KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > search > CmsIndexingThreadManager


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src/org/opencms/search/CmsIndexingThreadManager.java,v $
3  * Date : $Date: 2006/03/27 14:52:54 $
4  * Version: $Revision: 1.25 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software GmbH, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 package org.opencms.search;
33
34 import org.opencms.file.CmsObject;
35 import org.opencms.i18n.CmsMessageContainer;
36 import org.opencms.main.CmsLog;
37 import org.opencms.main.OpenCms;
38 import org.opencms.report.CmsLogReport;
39 import org.opencms.report.I_CmsReport;
40 import org.opencms.search.documents.I_CmsDocumentFactory;
41
42 import java.io.IOException JavaDoc;
43 import java.util.Map JavaDoc;
44
45 import org.apache.commons.logging.Log;
46 import org.apache.lucene.document.Document;
47 import org.apache.lucene.index.IndexWriter;
48
49 /**
50  * Implements the management of indexing threads.<p>
51  *
52  * @author Carsten Weinholz
53  * @author Alexander Kandzior
54  *
55  * @version $Revision: 1.25 $
56  *
57  * @since 6.0.0
58  */

59 public class CmsIndexingThreadManager extends Thread JavaDoc {
60
61     /** The log object for this class. */
62     private static final Log LOG = CmsLog.getLog(CmsIndexingThreadManager.class);
63
64     /** Number of threads abandoned. */
65     private int m_abandonedCounter;
66
67     /** Cache for extracted documents. */
68     private Map JavaDoc m_documentCache;
69
70     /** Overall number of threads started. */
71     private int m_fileCounter;
72
73     /** The report. */
74     private I_CmsReport m_report;
75
76     /** Number of thread returned. */
77     private int m_returnedCounter;
78
79     /** Timeout for abandoning threads. */
80     private long m_timeout;
81
82     /**
83      * Creates and starts a thread manager for indexing threads.<p>
84      * @param report the report to write out progress information
85      * @param timeout timeout after a thread is abandoned
86      * @param indexName the name of the index
87      * @param documentCache cache for storing indexed documents in (to avoid multiple text extraction)
88      */

89     public CmsIndexingThreadManager(I_CmsReport report, long timeout, String JavaDoc indexName, Map JavaDoc documentCache) {
90
91         super("OpenCms: Indexing thread manager for search index '" + indexName + "'");
92
93         m_report = report;
94         m_timeout = timeout;
95         m_fileCounter = 0;
96         m_abandonedCounter = 0;
97         m_returnedCounter = 0;
98         m_documentCache = documentCache;
99         this.start();
100     }
101
102     /**
103      * Caches the generated Document for the index resource to avoid multiple text extraction.<p>
104      *
105      * @param res the index resource to cache the Document for
106      * @param locale the locale to chache the Document fot
107      * @param doc the Document to cache
108      */

109     public synchronized void addDocument(A_CmsIndexResource res, String JavaDoc locale, Document doc) {
110
111         if (m_documentCache != null) {
112             m_documentCache.put(res.getId().toString().concat(locale), doc);
113         }
114     }
115
116     /**
117      * Creates and starts a new indexing thread for a resource.<p>
118      *
119      * After an indexing thread was started, the manager suspends itself
120      * and waits for an amount of time specified by the <code>timeout</code>
121      * value. If the timeout value is reached, the indexing thread is
122      * aborted by an interrupt signal.<p>
123      *
124      * @param cms the cms object
125      * @param writer the write to write the index
126      * @param res the resource
127      * @param index the index
128      */

129     public void createIndexingThread(CmsObject cms, IndexWriter writer, A_CmsIndexResource res, CmsSearchIndex index) {
130
131         I_CmsDocumentFactory factory = OpenCms.getSearchManager().getDocumentFactory(res);
132         if ((factory == null) || !index.getDocumenttypes(res.getRootPath()).contains(factory.getName())) {
133             // document type dos not match the ones configured for the index, skip document
134

135             m_fileCounter++;
136             m_returnedCounter++;
137             if (m_report != null) {
138                 m_report.println(
139                     org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_SKIPPED_0),
140                     I_CmsReport.FORMAT_NOTE);
141             }
142             if (LOG.isDebugEnabled()) {
143                 LOG.debug(Messages.get().getBundle().key(Messages.LOG_SKIPPED_1, res.getRootPath()));
144             }
145
146             // no need to continue
147
return;
148         }
149
150         Document cachedDoc;
151         if ((m_documentCache != null)
152             && ((cachedDoc = (Document)m_documentCache.get(res.getId().toString().concat(index.getLocale()))) != null)) {
153             // search document for the resource has already been cached, just re-use without extra Thread
154

155             m_fileCounter++;
156             m_returnedCounter++;
157             try {
158                 writer.addDocument(cachedDoc);
159                 if (m_report != null) {
160                     m_report.println(
161                         org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
162                         I_CmsReport.FORMAT_OK);
163                 }
164             } catch (IOException JavaDoc e) {
165                 if (m_report != null) {
166                     m_report.println();
167                     m_report.print(
168                         org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0),
169                         I_CmsReport.FORMAT_WARNING);
170                     m_report.println(e);
171
172                 }
173                 if (LOG.isWarnEnabled()) {
174                     LOG.warn(Messages.get().getBundle().key(
175                         Messages.ERR_INDEX_RESOURCE_FAILED_2,
176                         res.getRootPath(),
177                         index.getName()), e);
178                 }
179             }
180         } else {
181             // search document for the resource has not been found in cache,
182
// extract the information from the resource in a separate Thread
183

184             CmsIndexingThread thread = new CmsIndexingThread(cms, writer, res, factory, index, m_report, this);
185
186             try {
187                 m_fileCounter++;
188                 thread.start();
189                 thread.join(m_timeout);
190
191                 if (thread.isAlive()) {
192
193                     if (LOG.isWarnEnabled()) {
194                         LOG.warn(Messages.get().getBundle().key(Messages.LOG_INDEXING_TIMEOUT_1, res.getRootPath()));
195                     }
196                     m_report.println();
197                     m_report.print(
198                         org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0),
199                         I_CmsReport.FORMAT_WARNING);
200                     m_report.println(
201                         Messages.get().container(Messages.RPT_SEARCH_INDEXING_TIMEOUT_1, res.getRootPath()),
202                         I_CmsReport.FORMAT_WARNING);
203
204                     m_abandonedCounter++;
205                     thread.interrupt();
206                 }
207             } catch (InterruptedException JavaDoc exc) {
208                 // noop
209
}
210         }
211     }
212
213     /**
214      * Signals the thread manager that a thread has finished its job and will exit immediately.<p>
215      */

216     public synchronized void finished() {
217
218         m_returnedCounter++;
219     }
220
221     /**
222      * Gets the current thread (file) count.<p>
223      *
224      * @return the current thread count
225      */

226     public int getCounter() {
227
228         return m_fileCounter;
229     }
230
231     /**
232      * Returns if the indexing manager still have indexing threads.<p>
233      *
234      * @return true if the indexing manager still have indexing threads
235      */

236     public boolean isRunning() {
237
238         return (m_returnedCounter + m_abandonedCounter < m_fileCounter);
239     }
240
241     /**
242      * Writes statistical information to the report.<p>
243      *
244      * The method reports the total number of threads started
245      * (equals to the number of indexed files), the number of returned
246      * threads (equals to the number of successfully indexed files),
247      * and the number of abandoned threads (hanging threads reaching the timeout).
248      */

249     public void reportStatistics() {
250
251         CmsMessageContainer message = Messages.get().container(
252             Messages.RPT_SEARCH_INDEXING_STATS_4,
253             new Object JavaDoc[] {
254                 new Integer JavaDoc(m_fileCounter),
255                 new Integer JavaDoc(m_returnedCounter),
256                 new Integer JavaDoc(m_abandonedCounter),
257                 m_report.formatRuntime()});
258
259         if (m_report != null) {
260             m_report.println(message);
261         }
262         if (!(m_report instanceof CmsLogReport) && LOG.isInfoEnabled()) {
263             // only write to the log if report is not already a log report
264
LOG.info(message.key());
265         }
266     }
267
268     /**
269      * Starts the thread manager to look for non-terminated threads<p>
270      * The thread manager looks all 10 minutes if threads are not returned
271      * and reports the number to the log file.
272      *
273      * @see java.lang.Runnable#run()
274      */

275     public void run() {
276
277         int max = 20;
278
279         try {
280             // wait 30 seconds for the initial indexing
281
Thread.sleep(30000);
282
283             while (m_fileCounter > m_returnedCounter && max-- > 0) {
284
285                 Thread.sleep(30000);
286                 // wait 30 seconds before we start checking for "dead" index threads
287
if (LOG.isWarnEnabled()) {
288                     LOG.warn(Messages.get().getBundle().key(
289                         Messages.LOG_WAITING_ABANDONED_THREADS_2,
290                         new Integer JavaDoc(m_abandonedCounter),
291                         new Integer JavaDoc((m_fileCounter - m_returnedCounter))));
292                 }
293
294             }
295         } catch (Exception JavaDoc exc) {
296             // noop
297
}
298
299         if (max > 0) {
300             if (LOG.isInfoEnabled()) {
301                 LOG.info(Messages.get().getBundle().key(Messages.LOG_THREADS_FINISHED_0));
302             }
303         } else {
304             LOG.error(Messages.get().getBundle().key(
305                 Messages.LOG_THREADS_FINISHED_0,
306                 new Integer JavaDoc(m_fileCounter - m_returnedCounter)));
307         }
308     }
309 }
Popular Tags