001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify it under the
005: * terms of the GNU Lesser General Public License as published by the Free
006: * Software Foundation; either version 2 of the License, or (at your option) any
007: * later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful, but WITHOUT ANY
010: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
011: * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012: * details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software Foundation, Inc., 59
016: * Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: */
019:
020: package de.schlund.pfixcore.lucefix;
021:
022: import java.io.File;
023: import java.io.IOException;
024: import java.util.Collection;
025: import java.util.Iterator;
026: import java.util.Set;
027: import java.util.TreeSet;
028:
029: import org.apache.log4j.Logger;
030: import org.apache.lucene.document.DateField;
031: import org.apache.lucene.document.Document;
032: import org.apache.lucene.index.IndexReader;
033:
034: import de.schlund.pfixcore.editor2.core.dom.IncludePartThemeVariant;
035: import de.schlund.pfixcore.editor2.core.dom.Project;
036: import de.schlund.pfixcore.editor2.core.spring.ProjectFactoryService;
037: import de.schlund.pfixcore.editor2.frontend.util.SpringBeanLocator;
038: import de.schlund.pfixxml.XMLException;
039: import de.schlund.pfixxml.config.GlobalConfig;
040:
041: /**
042: * @author schuppi
043: * @date Jun 24, 2005
044: */
045: public class PfixReadjustment {
046:
047: private static PfixReadjustment _instance = new PfixReadjustment();
048:
049: private final static Logger LOG = Logger
050: .getLogger(PfixReadjustment.class);
051:
052: public static final String LUCENE_DATA = PfixQueueManager.lucene_data_path;
053:
054: /**
055: * @param idletime
056: * @throws XMLException
057: */
058: private PfixReadjustment() {
059: }
060:
061: /**
062: * Checks list of include parts for changes and updates search index.
063: */
064: public void readjust() {
065: Collection<Tripel> partsKnownByPustefix = getUsedTripels();
066: IndexReader reader = null;
067: PfixQueueManager queue;
068: boolean jobDone;
069: long startLoop, stopLoop, startCollect, stopCollect, startIndexLoop, stopIndexLoop, startAddLoop, stopAddLoop;
070:
071: long collectTime = 0;
072:
073: int knownDocsSize, newDocs, deleteDocs, numDocs;
074:
075: startLoop = stopLoop = startCollect = stopCollect = startIndexLoop = stopIndexLoop = startAddLoop = stopAddLoop = 0;
076: newDocs = knownDocsSize = deleteDocs = numDocs = 0;
077:
078: startLoop = System.currentTimeMillis();
079: Set<Tripel> tripelsToIndex = new TreeSet<Tripel>();
080:
081: queue = PfixQueueManager.getInstance(null);
082: try {
083: jobDone = false;
084: startCollect = System.currentTimeMillis();
085: partsKnownByPustefix = getUsedTripels();
086: stopCollect = System.currentTimeMillis();
087: collectTime = stopCollect - startCollect;
088: knownDocsSize = partsKnownByPustefix.size();
089:
090: try {
091: reader = IndexReader.open(LUCENE_DATA);
092: } catch (IOException ioe) {
093: LOG
094: .warn("broken or nonexistant database -> will queue ALL known parts");
095:
096: for (Iterator<Tripel> iter = partsKnownByPustefix
097: .iterator(); iter.hasNext();) {
098: Tripel element = iter.next();
099: element.setType(Tripel.Type.INSERT);
100: newDocs++;
101: if (!tripelsToIndex.add(element)) {
102: LOG.debug("duplicated insert");
103: }
104: }
105: jobDone = true;
106: }
107: if (!jobDone) {
108: numDocs = reader.numDocs();
109: startIndexLoop = System.currentTimeMillis();
110: docloop: for (int i = 0; i < numDocs; i++) {
111:
112: Document currentdoc;
113: try {
114: currentdoc = reader.document(i);
115: } catch (RuntimeException e) {
116: // this happens if we want to access a deleted
117: // document -> continue
118: continue docloop;
119: }
120:
121: // check if needed
122: String path = currentdoc.get(PreDoc.PATH);
123: Tripel pfixTripel = new Tripel(path, null);
124:
125: if (partsKnownByPustefix.contains(pfixTripel)) {
126:
127: // checkTs
128: File f = new File(GlobalConfig.getDocroot(),
129: currentdoc.get(PreDoc.FILENAME));
130: if (f.lastModified() != DateField
131: .stringToTime(currentdoc
132: .get(PreDoc.LASTTOUCH))) {
133: // ts differs
134: pfixTripel.setType(Tripel.Type.INSERT);
135: LOG.debug("TS differs: " + pfixTripel);
136: newDocs++;
137: if (!tripelsToIndex.add(pfixTripel)) {
138: LOG.debug("duplicated insert "
139: + pfixTripel);
140: }
141: }
142: partsKnownByPustefix.remove(pfixTripel);
143: } else {
144: // part not needed anymore
145: Tripel newTripel = new Tripel(currentdoc
146: .get(PreDoc.PATH), Tripel.Type.DELETE);
147: deleteDocs++;
148: queue.queue(newTripel);
149: }
150:
151: }
152: stopIndexLoop = System.currentTimeMillis();
153:
154: // now partsKnownByPustefix only contains parts which are NOT indexed...
155: startAddLoop = System.currentTimeMillis();
156: for (Iterator<Tripel> iter = partsKnownByPustefix
157: .iterator(); iter.hasNext();) {
158: Tripel element = iter.next();
159: element.setType(Tripel.Type.INSERT);
160: // LOG.debug("adding " + element + " to queue
161: // (INDEX)");
162: newDocs++;
163: if (!tripelsToIndex.add(element)) {
164: LOG.debug("duplicated insert " + element);
165: }
166: // queue.queue(element);
167: }
168:
169: stopAddLoop = System.currentTimeMillis();
170: }
171: } catch (IOException ioe) {
172: LOG.fatal("error reading index", ioe);
173: }
174:
175: // its a treeset, it is already sorted :)
176: // Collections.sort(tripelsToIndex);
177: // Collections.
178: for (Tripel tripel : tripelsToIndex) {
179: queue.queue(tripel);
180: }
181:
182: stopLoop = System.currentTimeMillis();
183: long needed = stopLoop - startLoop;
184: if (newDocs != 0 || deleteDocs != 0) {
185: LOG.debug(needed + "ms (getUsedTripels(): " + collectTime
186: + "ms (" + knownDocsSize + "u) indexloop: "
187: + (stopIndexLoop - startIndexLoop) + "|"
188: + (stopAddLoop - startAddLoop) + "ms (" + numDocs
189: + "u), added " + newDocs + "+" + deleteDocs
190: + " queueitems");
191: }
192:
193: try {
194: if (reader != null) {
195: reader.close();
196: reader = null;
197: }
198: } catch (IOException e) {
199: LOG.error("error while closing reader", e);
200: }
201: }
202:
203: private Set<Tripel> getUsedTripels() {
204: Set<Tripel> retval = new TreeSet<Tripel>();
205:
206: ProjectFactoryService projectFactory = SpringBeanLocator
207: .getProjectFactoryService();
208: for (Iterator<Project> i = projectFactory.getProjects()
209: .iterator(); i.hasNext();) {
210: Project currentproject = i.next();
211: for (Iterator<IncludePartThemeVariant> i2 = currentproject
212: .getAllIncludeParts().iterator(); i2.hasNext();) {
213: IncludePartThemeVariant element = i2.next();
214: String filename = element.getIncludePart()
215: .getIncludeFile().getPath();
216: String incname = element.getIncludePart().getName();
217: String prodname = element.getTheme().getName();
218: retval.add(new Tripel(prodname, incname, filename));
219: }
220: }
221:
222: return retval;
223: }
224:
225: /**
226: * Returns singleton which must have been initialized ealier.
227: *
228: * @return Instance of PfixReadjustment
229: * @throws RuntimeException
230: * if singleton has not been initialized yet
231: */
232: public static synchronized PfixReadjustment getInstance() {
233: if (_instance == null) {
234: throw new RuntimeException(
235: "PfixReadjustment has to be initialized first!");
236: }
237: return _instance;
238: }
239:
240: }
|