File Source: IndexManagerImpl.java

         /* 
    P/P   *  Method: org.apache.roller.weblogger.business.search.IndexManagerImpl$1__static_init
          */
     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   *  contributor license agreements.  The ASF licenses this file to You
     4   * under the Apache License, Version 2.0 (the "License"); you may not
     5   * use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.  For additional information regarding
    15   * copyright in this work, please see the NOTICE file in the top level
    16   * directory of this distribution.
    17   */
    18  
    19  package org.apache.roller.weblogger.business.search;
    20  
    21  import java.io.File;
    22  import java.io.IOException;
    23  
    24  import org.apache.commons.logging.Log;
    25  import org.apache.commons.logging.LogFactory;
    26  import org.apache.lucene.analysis.Analyzer;
    27  import org.apache.lucene.analysis.standard.StandardAnalyzer;
    28  import org.apache.lucene.index.IndexReader;
    29  import org.apache.lucene.index.IndexWriter;
    30  import org.apache.lucene.store.Directory;
    31  import org.apache.lucene.store.FSDirectory;
    32  import org.apache.lucene.store.RAMDirectory;
    33  import org.apache.roller.weblogger.WebloggerException;
    34  import org.apache.roller.weblogger.business.*;
    35  import org.apache.roller.weblogger.business.search.operations.AddEntryOperation;
    36  import org.apache.roller.weblogger.business.search.operations.IndexOperation;
    37  import org.apache.roller.weblogger.business.search.operations.ReIndexEntryOperation;
    38  import org.apache.roller.weblogger.business.search.operations.RebuildWebsiteIndexOperation;
    39  import org.apache.roller.weblogger.business.search.operations.RemoveEntryOperation;
    40  import org.apache.roller.weblogger.business.search.operations.RemoveWebsiteIndexOperation;
    41  import org.apache.roller.weblogger.business.search.operations.WriteToIndexOperation;
    42  import org.apache.roller.weblogger.pojos.WeblogEntry;
    43  import org.apache.roller.weblogger.pojos.Weblog;
    44  
    45  import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
    46  import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock;
    47  import org.apache.roller.weblogger.config.WebloggerConfig;
    48  import org.apache.commons.lang.StringUtils;
    49  
    50  
    51  /**
    52   * Lucene implementation of IndexManager. This is the central entry point 
    53   * into the Lucene searching API.
    54   * @author Mindaugas Idzelis (min@idzelis.com)
    55   * @author mraible (formatting and making indexDir configurable)
    56   */
    57  @com.google.inject.Singleton
    58  public class IndexManagerImpl implements IndexManager {
    59      //~ Static fields/initializers
    60      // =============================================
    61      
    62      private IndexReader reader;
    63      private final Weblogger roller;
    64      
             /* 
    P/P       *  Method: org.apache.roller.weblogger.business.search.IndexManagerImpl__static_init
              * 
              *  Presumptions:
              *    org.apache.commons.logging.LogFactory:getFactory(...)@65 != null
              * 
              *  Postconditions:
              *    init'ed(mLogger)
              */
    65      static Log mLogger = LogFactory.getFactory().getInstance(
    66              IndexManagerImpl.class);
    67      
    68      //~ Instance fields
    69      // ========================================================
    70      
    71      private boolean searchEnabled = true;
    72      
    73      File indexConsistencyMarker;
    74      
    75      private boolean useRAMIndex = false;
    76      
    77      private RAMDirectory fRAMindex;
    78      
    79      private String indexDir = null;
    80      
    81      private boolean inconsistentAtStartup = false;
    82      
    83      private ReadWriteLock rwl = new WriterPreferenceReadWriteLock();
    84      
    85      //~ Constructors
    86      // ===========================================================
    87      
    88      /**
    89       * Creates a new lucene index manager. This should only be created once.
    90       * Creating the index manager more than once will definately result in
    91       * errors. The preferred way of getting an index is through the
    92       * RollerContext.
    93       *
    94       * @param indexDir -
    95       *            the path to the index directory
    96       */
    97      @com.google.inject.Inject
             /* 
    P/P       *  Method: void org.apache.roller.weblogger.business.search.IndexManagerImpl(Weblogger)
              * 
              *  Preconditions:
              *    mLogger != null
              *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
              *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
              * 
              *  Presumptions:
              *    init'ed(java.io.File.separator)
              *    init'ed(java.io.File.separatorChar)
              * 
              *  Postconditions:
              *    this.inconsistentAtStartup == 0
              *    this.useRAMIndex == 0
              *    this.indexConsistencyMarker == &new File(IndexManagerImpl#5)
              *    this.indexDir != null
              *    this.roller == roller
              *    init'ed(this.roller)
              *    this.rwl == &new WriterPreferenceReadWriteLock(IndexManagerImpl#1)
              *    init'ed(this.searchEnabled)
              *    new File(IndexManagerImpl#5) num objects == 1
              *    new WriterPreferenceReadWriteLock(IndexManagerImpl#1) num objects == 1
              * 
              *  Test Vectors:
              *    java.lang.String:equalsIgnoreCase(...)@103: {0}, {1}
              */
    98      protected IndexManagerImpl(Weblogger roller) {
    99          this.roller = roller;
   100  
   101          // check config to see if the internal search is enabled
   102          String enabled = WebloggerConfig.getProperty("search.enabled");
   103          if("false".equalsIgnoreCase(enabled))
   104              this.searchEnabled = false;
   105          
   106          // we also need to know what our index directory is
   107          // Note: system property expansion is now handled by WebloggerConfig
   108          String searchIndexDir = WebloggerConfig.getProperty("search.index.dir");
+  109          this.indexDir = searchIndexDir.replace('/', File.separatorChar);
   110          
   111          // a little debugging
   112          mLogger.info("search enabled: " + this.searchEnabled);
   113          mLogger.info("index dir: " + this.indexDir);
   114          
   115          String test = indexDir + File.separator + ".index-inconsistent";
   116          indexConsistencyMarker = new File(test);
   117      }
   118      
   119      
   120      /**
   121       * @inheritDoc
   122       */
   123      public void initialize() throws InitializationException {
   124          
   125          // only initialize the index if search is enabled
                 /* 
    P/P           *  Method: void initialize()
                  * 
                  *  Preconditions:
                  *    init'ed(this.searchEnabled)
                  *    (soft) mLogger != null
                  *    (soft) init'ed(this.inconsistentAtStartup)
                  *    (soft) this.indexConsistencyMarker != null
                  *    (soft) init'ed(this.indexDir)
                  *    (soft) this.roller != null
                  *    (soft) this.roller.threadManager != null
                  *    (soft) this.roller.threadManager.serviceScheduler != null
                  *    (soft) init'ed(this.useRAMIndex)
                  * 
                  *  Postconditions:
                  *    this.fRAMindex == One-of{old this.fRAMindex, &new RAMDirectory(initialize#2), &new RAMDirectory(initialize#3)}
                  *    (soft) init'ed(this.inconsistentAtStartup)
                  *    new RAMDirectory(initialize#2) num objects <= 1
                  *    new RAMDirectory(initialize#3) num objects <= 1
                  * 
                  *  Test Vectors:
                  *    this.searchEnabled: {0}, {1}
                  *    this.useRAMIndex: {0}, {1}
                  *    java.io.File:exists(...)@133: {0}, {1}
                  *    java.io.File:exists(...)@139: {1}, {0}
                  *    org.apache.lucene.index.IndexReader:indexExists(...)@288: {0}, {1}
                  */
   126          if (this.searchEnabled) {
   127              
   128              // 1. If inconsistency marker exists.
   129              //     Delete index
   130              // 2. if we're using RAM index
   131              //     load ram index wrapper around index
   132              //
   133              if (indexConsistencyMarker.exists()) {
   134                  getFSDirectory(true);
   135                  inconsistentAtStartup = true;
   136              } else {
   137                  try {
   138                      File makeIndexDir = new File(indexDir);
   139                      if (!makeIndexDir.exists()) {
   140                          makeIndexDir.mkdirs();
   141                          inconsistentAtStartup = true;
   142                      }
   143                      indexConsistencyMarker.createNewFile();
   144                  } catch (IOException e) {
   145                      mLogger.error(e);
   146                  }
   147              }
   148              
   149              if (indexExists()) {
   150                  if (useRAMIndex) {
   151                      Directory filesystem = getFSDirectory(false);
   152                      
   153                      try {
   154                          fRAMindex = new RAMDirectory(filesystem);
   155                      } catch (IOException e) {
   156                          mLogger.error("Error creating in-memory index", e);
   157                      }
   158                  }
   159              } else {
   160                  if (useRAMIndex) {
   161                      fRAMindex = new RAMDirectory();
   162                      createIndex(fRAMindex);
   163                  } else {
   164                      createIndex(getFSDirectory(true));
   165                  }
   166              }
   167              
   168              if (isInconsistentAtStartup()) {
   169                  mLogger.info(
   170                          "Index was inconsistent. Rebuilding index in the background...");
   171                  try {
   172                      rebuildWebsiteIndex();
   173                  } catch (WebloggerException e) {
   174                      mLogger.error("ERROR: scheduling re-index operation");
   175                  }
   176              }
   177          }
   178          
   179      }
   180      
   181      
   182      //~ Methods
   183      // ================================================================
   184      
   185      public void rebuildWebsiteIndex() throws WebloggerException {
                 /* 
    P/P           *  Method: void rebuildWebsiteIndex()
                  * 
                  *  Preconditions:
                  *    (soft) mLogger != null
                  *    (soft) this.roller != null
                  *    (soft) this.roller.threadManager != null
                  *    (soft) this.roller.threadManager.serviceScheduler != null
                  *    (soft) init'ed(this.searchEnabled)
                  */
   186          scheduleIndexOperation(
   187                  new RebuildWebsiteIndexOperation(roller, this, null));
   188      }
   189      
   190      public void rebuildWebsiteIndex(Weblog website) throws WebloggerException {
                 /* 
    P/P           *  Method: void rebuildWebsiteIndex(Weblog)
                  * 
                  *  Preconditions:
                  *    (soft) mLogger != null
                  *    (soft) this.roller != null
                  *    (soft) this.roller.threadManager != null
                  *    (soft) this.roller.threadManager.serviceScheduler != null
                  *    (soft) init'ed(this.searchEnabled)
                  */
   191          scheduleIndexOperation(
   192                  new RebuildWebsiteIndexOperation(roller, this, website));
   193      }
   194      
   195      public void removeWebsiteIndex(Weblog website) throws WebloggerException {
                 /* 
    P/P           *  Method: void removeWebsiteIndex(Weblog)
                  * 
                  *  Preconditions:
                  *    (soft) mLogger != null
                  *    (soft) this.roller != null
                  *    (soft) this.roller.threadManager != null
                  *    (soft) this.roller.threadManager.serviceScheduler != null
                  *    (soft) init'ed(this.searchEnabled)
                  */
   196          scheduleIndexOperation(
   197                  new RemoveWebsiteIndexOperation(roller, this, website));
   198      }
   199      
   200      public void addEntryIndexOperation(WeblogEntry entry) throws WebloggerException {
                 /* 
    P/P           *  Method: void addEntryIndexOperation(WeblogEntry)
                  * 
                  *  Preconditions:
                  *    (soft) mLogger != null
                  *    (soft) this.roller != null
                  *    (soft) this.roller.threadManager != null
                  *    (soft) this.roller.threadManager.serviceScheduler != null
                  *    (soft) init'ed(this.searchEnabled)
                  */
   201          AddEntryOperation addEntry = new AddEntryOperation(roller, this, entry);
   202          scheduleIndexOperation(addEntry);
   203      }
   204      
   205      public void addEntryReIndexOperation(WeblogEntry entry) throws WebloggerException {
                 /* 
    P/P           *  Method: void addEntryReIndexOperation(WeblogEntry)
                  * 
                  *  Preconditions:
                  *    (soft) mLogger != null
                  *    (soft) this.roller != null
                  *    (soft) this.roller.threadManager != null
                  *    (soft) this.roller.threadManager.serviceScheduler != null
                  *    (soft) init'ed(this.searchEnabled)
                  */
   206          ReIndexEntryOperation reindex = new ReIndexEntryOperation(roller, this, entry);
   207          scheduleIndexOperation(reindex);
   208      }
   209      
   210      public void removeEntryIndexOperation(WeblogEntry entry) throws WebloggerException {
                 /* 
    P/P           *  Method: void removeEntryIndexOperation(WeblogEntry)
                  * 
                  *  Preconditions:
                  *    (soft) mLogger != null
                  *    (soft) this.roller != null
                  *    (soft) this.roller.threadManager != null
                  *    (soft) this.roller.threadManager.serviceScheduler != null
                  *    (soft) init'ed(this.searchEnabled)
                  */
   211          RemoveEntryOperation removeOp = new RemoveEntryOperation(roller, this, entry);
   212          executeIndexOperationNow(removeOp);
   213      }
   214      
   215      public ReadWriteLock getReadWriteLock() {
                 /* 
    P/P           *  Method: ReadWriteLock getReadWriteLock()
                  * 
                  *  Preconditions:
                  *    init'ed(this.rwl)
                  * 
                  *  Postconditions:
                  *    return_value == this.rwl
                  *    init'ed(return_value)
                  */
   216          return rwl;
   217      }
   218      
   219      public boolean isInconsistentAtStartup() {
                 /* 
    P/P           *  Method: bool isInconsistentAtStartup()
                  * 
                  *  Preconditions:
                  *    init'ed(this.inconsistentAtStartup)
                  * 
                  *  Postconditions:
                  *    return_value == this.inconsistentAtStartup
                  *    init'ed(return_value)
                  */
   220          return inconsistentAtStartup;
   221      }
   222      
   223      /**
   224       * This is the analyzer that will be used to tokenize comment text.
   225       *
   226       * @return Analyzer to be used in manipulating the database.
   227       */
   228      public static final Analyzer getAnalyzer() {
                 /* 
    P/P           *  Method: Analyzer getAnalyzer()
                  * 
                  *  Postconditions:
                  *    return_value == &new StandardAnalyzer(getAnalyzer#1)
                  *    new StandardAnalyzer(getAnalyzer#1) num objects == 1
                  */
   229          return new StandardAnalyzer();
   230      }
   231      
   232      private void scheduleIndexOperation(final IndexOperation op) {
   233          try {
   234              // only if search is enabled
                     /* 
    P/P               *  Method: void scheduleIndexOperation(IndexOperation)
                      * 
                      *  Preconditions:
                      *    (soft) mLogger != null
                      *    (soft) op != null
                      *    (soft) this.roller != null
                      *    (soft) this.roller.threadManager != null
                      *    (soft) this.roller.threadManager.serviceScheduler != null
                      *    (soft) init'ed(this.searchEnabled)
                      * 
                      *  Presumptions:
                      *    java.lang.Object:getClass(...)@236 != null
                      * 
                      *  Test Vectors:
                      *    this.searchEnabled: {0}, {1}
                      */
   235              if(this.searchEnabled) {
   236                  mLogger.debug("Starting scheduled index operation: "+op.getClass().getName());
   237                  roller.getThreadManager().executeInBackground(op);
   238              }
   239          } catch (InterruptedException e) {
   240              mLogger.error("Error executing operation", e);
   241          }
   242      }
   243      
   244      /**
   245       * @param search
   246       */
   247      public void executeIndexOperationNow(final IndexOperation op) {
   248          try {
   249              // only if search is enabled
                     /* 
    P/P               *  Method: void executeIndexOperationNow(IndexOperation)
                      * 
                      *  Preconditions:
                      *    (soft) mLogger != null
                      *    (soft) op != null
                      *    (soft) this.roller != null
                      *    (soft) this.roller.threadManager != null
                      *    (soft) this.roller.threadManager.serviceScheduler != null
                      *    (soft) init'ed(this.searchEnabled)
                      * 
                      *  Presumptions:
                      *    java.lang.Object:getClass(...)@251 != null
                      * 
                      *  Test Vectors:
                      *    this.searchEnabled: {0}, {1}
                      */
   250              if(this.searchEnabled) {
   251                  mLogger.debug("Executing index operation now: "+op.getClass().getName());
   252                  roller.getThreadManager().executeInForeground(op);
   253              }
   254          } catch (InterruptedException e) {
   255              mLogger.error("Error executing operation", e);
   256          }
   257      }
   258      
   259      public synchronized void resetSharedReader() {
                 /* 
    P/P           *  Method: void resetSharedReader()
                  * 
                  *  Postconditions:
                  *    this.reader == null
                  */
   260          reader = null;
   261      }
   262      public synchronized IndexReader getSharedIndexReader() {
                 /* 
    P/P           *  Method: IndexReader getSharedIndexReader()
                  * 
                  *  Preconditions:
                  *    init'ed(this.reader)
                  *    (soft) mLogger != null
                  *    (soft) init'ed(this.fRAMindex)
                  *    (soft) init'ed(this.indexDir)
                  *    (soft) init'ed(this.useRAMIndex)
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  *    this.reader == return_value
                  * 
                  *  Test Vectors:
                  *    this.reader: Inverse{null}, Addr_Set{null}
                  */
   263          if (reader == null) {
   264              try {
   265                  reader = IndexReader.open(getIndexDirectory());
   266              } catch (IOException e) {
   267              }
   268          }
   269          return reader;
   270      }
   271      
   272      /**
   273       * Get the directory that is used by the lucene index. This method will
   274       * return null if there is no index at the directory location. If we are
   275       * using a RAM index, the directory will be a ram directory.
   276       *
   277       * @return Directory The directory containing the index, or null if error.
   278       */
   279      public Directory getIndexDirectory() {
                 /* 
    P/P           *  Method: Directory getIndexDirectory()
                  * 
                  *  Preconditions:
                  *    init'ed(this.useRAMIndex)
                  *    (soft) mLogger != null
                  *    (soft) init'ed(this.fRAMindex)
                  *    (soft) init'ed(this.indexDir)
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    this.useRAMIndex: {0}, {1}
                  */
   280          if (useRAMIndex) {
   281              return fRAMindex;
   282          } else {
   283              return getFSDirectory(false);
   284          }
   285      }
   286      
   287      private boolean indexExists() {
                 /* 
    P/P           *  Method: bool indexExists()
                  * 
                  *  Preconditions:
                  *    init'ed(this.indexDir)
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   288          return IndexReader.indexExists(indexDir);
   289      }
   290      
   291      Directory getFSDirectory(boolean delete) {
                 /* 
    P/P           *  Method: Directory getFSDirectory(bool)
                  * 
                  *  Preconditions:
                  *    (soft) mLogger != null
                  *    (soft) init'ed(this.indexDir)
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   292          Directory directory = null;
   293          
   294          try {
   295              directory = FSDirectory.getDirectory(indexDir, delete);
   296          } catch (IOException e) {
   297              mLogger.error("Problem accessing index directory", e);
   298          }
   299          
   300          return directory;
   301      }
   302      
   303      private void createIndex(Directory dir) {
                 /* 
    P/P           *  Method: void createIndex(Directory)
                  * 
                  *  Preconditions:
                  *    (soft) mLogger != null
                  */
   304          IndexWriter writer = null;
   305          
   306          try {
   307              writer = new IndexWriter(dir, IndexManagerImpl.getAnalyzer(), true);
   308          } catch (IOException e) {
   309              mLogger.error("Error creating index", e);
   310          } finally {
   311              try {
   312                  if (writer != null) {
   313                      writer.close();
   314                  }
   315              } catch (IOException e) {
   316              }
   317          }
   318      }
   319      
   320      private IndexOperation getSaveIndexOperation() {
                 /* 
    P/P           *  Method: IndexOperation getSaveIndexOperation()
                  * 
                  *  Postconditions:
                  *    return_value == &new IndexManagerImpl$1(getSaveIndexOperation#1)
                  *    new IndexManagerImpl$1(getSaveIndexOperation#1) num objects == 1
                  *    return_value.manager == this
                  *    return_value.manager != null
                  */
   321          return new WriteToIndexOperation(this) {
   322              public void doRun() {
                         /* 
    P/P                   *  Method: void doRun()
                          * 
                          *  Preconditions:
                          *    init'ed(this.useRAMIndex)
                          *    (soft) org/apache/roller/weblogger/business/search/IndexManagerImpl.mLogger != null
                          *    (soft) init'ed(this.fRAMindex)
                          *    (soft) this.indexConsistencyMarker != null
                          *    (soft) init'ed(this.indexDir)
                          */
   323                  Directory dir = getIndexDirectory();
   324                  Directory fsdir = getFSDirectory(true);
   325                  
   326                  IndexWriter writer = null;
   327                  
   328                  try {
   329                      writer = new IndexWriter(fsdir, IndexManagerImpl
   330                              .getAnalyzer(), true);
   331                      
   332                      writer.addIndexes(new Directory[] { dir });
   333                      indexConsistencyMarker.delete();
   334                  } catch (IOException e) {
   335                      mLogger.error("Problem saving index to disk", e);
   336                      
   337                      // Delete the directory, since there was a problem saving
   338                      // the RAM contents
   339                      getFSDirectory(true);
   340                  } finally {
   341                      try {
   342                          if (writer != null)
   343                              writer.close();
   344                      } catch (IOException e1) {
   345                          mLogger.warn("Unable to close IndexWriter.");
   346                      }
   347                  }
   348                  
   349              }
   350          };
   351      }
   352      
   353      public void release() {
   354          // no-op
             /* 
    P/P       *  Method: void release()
              */
   355      }
   356      
   357      public void shutdown() {
                 /* 
    P/P           *  Method: void shutdown()
                  * 
                  *  Preconditions:
                  *    init'ed(this.useRAMIndex)
                  *    (soft) mLogger != null
                  *    (soft) this.indexConsistencyMarker != null
                  *    (soft) init'ed(this.reader)
                  *    (soft) this.roller != null
                  *    (soft) this.roller.threadManager != null
                  *    (soft) this.roller.threadManager.serviceScheduler != null
                  *    (soft) init'ed(this.searchEnabled)
                  * 
                  *  Test Vectors:
                  *    this.reader: Addr_Set{null}, Inverse{null}
                  *    this.useRAMIndex: {0}, {1}
                  */
   358          if (useRAMIndex) {
   359              scheduleIndexOperation(getSaveIndexOperation());
   360          } else {
   361              indexConsistencyMarker.delete();
   362          }
   363          
   364          try {
   365              if (reader != null)
   366                  reader.close();
   367          } catch (IOException e) {
   368              // won't happen, since it was
   369          }
   370      }
   371  
   372  }








SofCheck Inspector Build Version : 2.18479
IndexManagerImpl.java 2009-Jan-02 14:25:20
IndexManagerImpl.class 2009-Sep-04 03:12:32
IndexManagerImpl$1.class 2009-Sep-04 03:12:32