[infinispan-commits] Infinispan SVN: r1977 - in trunk/lucene-directory/src: test/java/org/infinispan/lucene and 2 other directories.

infinispan-commits at lists.jboss.org infinispan-commits at lists.jboss.org
Mon Jul 5 13:07:49 EDT 2010


Author: sannegrinovero
Date: 2010-07-05 13:07:48 -0400 (Mon, 05 Jul 2010)
New Revision: 1977

Added:
   trunk/lucene-directory/src/main/java/org/infinispan/lucene/FileReadLockKey.java
Modified:
   trunk/lucene-directory/src/main/java/org/infinispan/lucene/FileMetadata.java
   trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanDirectory.java
   trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanIndexInput.java
   trunk/lucene-directory/src/test/java/org/infinispan/lucene/DirectoryIntegrityCheck.java
   trunk/lucene-directory/src/test/java/org/infinispan/lucene/InfinispanDirectoryIOTest.java
   trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/IndexReadingStressTest.java
   trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/LuceneReaderThread.java
   trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/LuceneUserThread.java
   trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/PerformanceCompareStressTest.java
   trunk/lucene-directory/src/test/java/org/infinispan/lucene/testutils/LuceneSettings.java
Log:
[ISPN-526] (Implement Read-Locks for Lucene delete) (part of ISPN-501) - trunk

Modified: trunk/lucene-directory/src/main/java/org/infinispan/lucene/FileMetadata.java
===================================================================
--- trunk/lucene-directory/src/main/java/org/infinispan/lucene/FileMetadata.java	2010-07-05 15:11:05 UTC (rev 1976)
+++ trunk/lucene-directory/src/main/java/org/infinispan/lucene/FileMetadata.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -31,7 +31,7 @@
  * @author Lukasz Moren
  * @see org.infinispan.lucene.FileCacheKey
  */
-public class FileMetadata implements Serializable {
+final class FileMetadata implements Serializable {
 
    /** The serialVersionUID */
    private static final long serialVersionUID = -2605615719808221213L;
@@ -68,7 +68,7 @@
       if (this == o) {
          return true;
       }
-      if (o == null || getClass() != o.getClass()) {
+      if (o == null || FileMetadata.class != o.getClass()) {
          return false;
       }
       FileMetadata metadata = (FileMetadata) o;
@@ -86,4 +86,5 @@
    public String toString() {
       return "FileMetadata{" + "lastModified=" + lastModified + ", size=" + size + '}';
    }
+   
 }

Added: trunk/lucene-directory/src/main/java/org/infinispan/lucene/FileReadLockKey.java
===================================================================
--- trunk/lucene-directory/src/main/java/org/infinispan/lucene/FileReadLockKey.java	                        (rev 0)
+++ trunk/lucene-directory/src/main/java/org/infinispan/lucene/FileReadLockKey.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -0,0 +1,105 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.lucene;
+
+import java.io.Serializable;
+
+/**
+ * Lucene's index segment files are chunked, for safe deletion of elements a read lock is
+ * implemented so that all chunks are deleted only after the usage counter is decremented to zero.
+ * FileReadLockKey is used as a key for the reference counters; a special purpose key was needed to
+ * make atomic operation possible.
+ * 
+ * @author Sanne Grinovero
+ * @since 4.0
+ */
+final class FileReadLockKey implements Serializable, CacheKey {
+
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 7789410500198851940L;
+
+   private final String indexName;
+   private final String fileName;
+   private final int hashCode;
+
+   FileReadLockKey(String indexName, String fileName) {
+      if (indexName == null)
+         throw new IllegalArgumentException("indexName shall not be null");
+      if (fileName == null)
+         throw new IllegalArgumentException("fileName shall not be null");
+      this.indexName = indexName;
+      this.fileName = fileName;
+      this.hashCode = generateHashCode();
+   }
+
+   /**
+    * Get the indexName.
+    * 
+    * @return the indexName.
+    */
+   public String getIndexName() {
+      return indexName;
+   }
+
+   /**
+    * Get the fileName.
+    * 
+    * @return the fileName.
+    */
+   public String getFileName() {
+      return fileName;
+   }
+
+   @Override
+   public int hashCode() {
+      return hashCode;
+   }
+
+   private int generateHashCode() {
+      final int prime = 31;
+      int result = prime + fileName.hashCode();
+      result = prime * result + indexName.hashCode();
+      return result;
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (FileReadLockKey.class != obj.getClass())
+         return false;
+      FileReadLockKey other = (FileReadLockKey) obj;
+      if (!fileName.equals(other.fileName))
+         return false;
+      if (!indexName.equals(other.indexName))
+         return false;
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return "FileReadLockKey{fileName=" + fileName + ", indexName=" + indexName + "} ";
+   }
+
+}

Modified: trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanDirectory.java
===================================================================
--- trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanDirectory.java	2010-07-05 15:11:05 UTC (rev 1976)
+++ trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanDirectory.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -143,22 +143,15 @@
     */
    public void deleteFile(String name) throws IOException {
       checkIsOpen();
-      FileCacheKey key = new FileCacheKey(indexName, name);
-      // remove main file
-      cache.remove(key);
       Set<String> fileList = getFileList();
-      fileList.remove(name);
-      cache.put(fileListCacheKey, fileList);
-      // and all of its chunks
-      int i = 0;
-      Object removed;
-      ChunkCacheKey chunkKey = new ChunkCacheKey(indexName, name, i);
-      do {
-         removed = cache.remove(chunkKey);
-         chunkKey = new ChunkCacheKey(indexName, name, ++i);
-      } while (removed != null);
+      boolean deleted = fileList.remove(name);
+      if (deleted) {
+         cache.put(fileListCacheKey, fileList);
+      }
+      FileReadLockKey fileReadLockKey = new FileReadLockKey(indexName, name);
+      InfinispanIndexInput.releaseReadLock(fileReadLockKey, cache);
       if (log.isDebugEnabled()) {
-         log.debug("Removed file: {0} from index: {1}", key.getFileName(), indexName);
+         log.debug("Removed file: {0} from index: {1}", name, indexName);
       }
    }
 
@@ -216,6 +209,8 @@
       FileMetadata previous = (FileMetadata) cache.putIfAbsent(key, newFileMetadata);
       if (previous == null) {
          // creating new file
+         FileReadLockKey readLockKey = new FileReadLockKey(indexName, name);
+         cache.put(readLockKey, Integer.valueOf(1));
          Set<String> fileList = getFileList();
          fileList.add(name);
          cache.put(fileListCacheKey, fileList);

Modified: trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanIndexInput.java
===================================================================
--- trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanIndexInput.java	2010-07-05 15:11:05 UTC (rev 1976)
+++ trunk/lucene-directory/src/main/java/org/infinispan/lucene/InfinispanIndexInput.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -21,10 +21,12 @@
  */
 package org.infinispan.lucene;
 
+import java.io.FileNotFoundException;
 import java.io.IOException;
 
 import org.apache.lucene.store.IndexInput;
 import org.infinispan.AdvancedCache;
+import org.infinispan.context.Flag;
 import org.infinispan.util.logging.Log;
 import org.infinispan.util.logging.LogFactory;
 
@@ -45,29 +47,126 @@
    private final FileMetadata file;
    private final FileCacheKey fileKey;
    private final int chunkSize;
+   private final FileReadLockKey readLockKey;
 
    private int currentBufferSize;
    private byte[] buffer;
    private int bufferPosition;
    private int currentLoadedChunk = -1;
 
-   public InfinispanIndexInput(AdvancedCache<CacheKey, Object> cache, FileCacheKey fileKey, int chunkSize) throws IOException {
+   private boolean isClone;
+
+   public InfinispanIndexInput(AdvancedCache<CacheKey, Object> cache, FileCacheKey fileKey, int chunkSize) throws FileNotFoundException {
       this.cache = cache;
       this.fileKey = fileKey;
       this.chunkSize = chunkSize;
+      final String filename = fileKey.getFileName();
+      this.readLockKey = new FileReadLockKey(fileKey.getIndexName(), filename);
+      
+      boolean failure = true;
+      aquireReadLock();
+      try {
 
-      // get file header from file
-      this.file = (FileMetadata) cache.get(fileKey);
+         // get file header from file
+         this.file = (FileMetadata) cache.get(fileKey);
 
-      if (file == null) {
-         throw new IOException("Error loading medatada for index file: " + fileKey);
+         if (file == null) {
+            throw new FileNotFoundException("Error loading medatada for index file: " + fileKey);
+         }
+
+         if (log.isDebugEnabled()) {
+            log.debug("Opened new IndexInput for file:{0} in index: {1}", filename, fileKey.getIndexName());
+         }
+         failure = false;
+      } finally {
+         if (failure)
+            releaseReadLock();
       }
+   }
 
-      if (log.isDebugEnabled()) {
-         log.debug("Opened new IndexInput for file:{0} in index: {1}", fileKey.getFileName(), fileKey.getIndexName());
+   private void releaseReadLock() {
+      releaseReadLock(readLockKey, cache);
+   }
+   
+   /**
+    * Releases a read-lock for this file, so that if it was marked as deleted and
+    * no other {@link InfinispanIndexInput} instances are using it, then it will
+    * be effectively deleted.
+    * 
+    * @see #aquireReadLock()
+    * @see InfinispanDirectory#deleteFile(String)
+    * 
+    * @param readLockKey the key pointing to the reference counter value
+    * @param cache The cache containing the reference counter value
+    */
+   static void releaseReadLock(FileReadLockKey readLockKey, AdvancedCache<CacheKey, Object> cache) {
+      int newValue = 0;
+      // spinning as we currently don't mandate transactions, so no proper lock support available
+      boolean done = false;
+      while (done == false) {
+         Object lockValue = cache.get(readLockKey);
+         if (lockValue == null)
+            return; // no special locking for some core files
+         int refCount = (Integer) lockValue;
+         newValue = refCount - 1;
+         done = cache.replace(readLockKey, refCount, newValue);
       }
+      if (newValue == 0) {
+         realFileDelete(readLockKey, cache);
+      }
    }
+   
+   /**
+    * The {@link InfinispanDirectory#deleteFile(String)} is not deleting the elements from the cache
+    * but instead flagging the file as deletable.
+    * This method will really remove the elements from the cache; should be invoked only
+    * by {@link #releaseReadLock(FileReadLockKey, AdvancedCache)} after having verified that there
+    * are no users left in need to read these chunks.
+    * 
+    * @param readLockKey the key representing the values to be deleted
+    * @param cache the cache containing the elements to be deleted
+    */
+   static void realFileDelete(FileReadLockKey readLockKey, AdvancedCache<CacheKey, Object> cache) {
+      final String indexName = readLockKey.getIndexName();
+      final String filename = readLockKey.getFileName();
+      int i = 0;
+      Object removed;
+      ChunkCacheKey chunkKey = new ChunkCacheKey(indexName, filename, i);
+      do {
+         removed = cache.withFlags(Flag.SKIP_LOCKING).remove(chunkKey);
+         chunkKey = new ChunkCacheKey(indexName, filename, ++i);
+      } while (removed != null);
+      cache.startBatch();
+      cache.withFlags(Flag.SKIP_REMOTE_LOOKUP,Flag.SKIP_LOCKING).remove(readLockKey);
+      FileCacheKey key = new FileCacheKey(indexName, filename);
+      cache.withFlags(Flag.SKIP_REMOTE_LOOKUP,Flag.SKIP_LOCKING).remove(key);
+      cache.endBatch(true);
+   }
 
+   /**
+    * Acquires a readlock on all chunks for this file, to make sure chunks are not deleted while
+    * iterating on the group. This is needed to avoid an eager lock on all elements.
+    * 
+    * @see #releaseReadLock(FileReadLockKey, AdvancedCache)
+    */
+   private void aquireReadLock() throws FileNotFoundException {
+      // spinning as we currently don't mandate transactions, so no proper lock support is available
+      boolean done = false;
+      while (done == false) {
+         Object lockValue = cache.get(readLockKey);
+         if (lockValue == null)
+            return; // no special locking for some core files
+         int refCount = (Integer) lockValue;
+         if (refCount == 0) {
+            // too late: in case refCount==0 the delete process already triggered chunk deletion.
+            // safest reaction is to tell this file doesn't exist anymore.
+            throw new FileNotFoundException("segment file was deleted");
+         }
+         Integer newValue = Integer.valueOf(refCount + 1);
+         done = cache.replace(readLockKey, refCount, newValue);
+      }
+   }
+
    @Override
    public byte readByte() throws IOException {
       if (bufferPosition >= currentBufferSize) {
@@ -102,18 +201,20 @@
       bufferPosition = 0;
       currentLoadedChunk = -1;
       buffer = null;
+      if (isClone) return;
+      releaseReadLock();
       if (log.isDebugEnabled()) {
          log.debug("Closed IndexInput for file:{0} in index: {1}", fileKey.getFileName(), fileKey.getIndexName());
       }
    }
 
    public long getFilePointer() {
-      return ((long)currentLoadedChunk) * chunkSize + bufferPosition;
+      return ((long) currentLoadedChunk) * chunkSize + bufferPosition;
    }
 
    @Override
    public void seek(long pos) throws IOException {
-      bufferPosition = (int)( pos % chunkSize );
+      bufferPosition = (int) (pos % chunkSize);
       int targetChunk = (int) (pos / chunkSize);
       if (targetChunk != currentLoadedChunk) {
          currentLoadedChunk = targetChunk;
@@ -154,4 +255,14 @@
       return file.getSize();
    }
    
+   @Override
+   public Object clone() {
+      InfinispanIndexInput clone = (InfinispanIndexInput)super.clone();
+      // reference counting doesn't work properly: need to use isClone
+      // as in other Directory implementations. Apparently not all clones
+      // are cleaned up, but the original is (especially .tis files)
+      clone.isClone = true; 
+      return clone;
+    }
+
 }
\ No newline at end of file

Modified: trunk/lucene-directory/src/test/java/org/infinispan/lucene/DirectoryIntegrityCheck.java
===================================================================
--- trunk/lucene-directory/src/test/java/org/infinispan/lucene/DirectoryIntegrityCheck.java	2010-07-05 15:11:05 UTC (rev 1976)
+++ trunk/lucene-directory/src/test/java/org/infinispan/lucene/DirectoryIntegrityCheck.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -81,6 +81,15 @@
          } else if (key instanceof FileListCacheKey) {
             fileListCacheKeyInstances++;
             Assert.assertEquals(1, fileListCacheKeyInstances);
+         } else if (key instanceof FileReadLockKey) {
+            FileReadLockKey readLockKey = (FileReadLockKey) key;
+            Assert.assertEquals(readLockKey.getIndexName(), indexName);
+            Assert.assertTrue(fileList.contains(readLockKey.getFileName()), readLockKey + " should not have existed");
+            Object value = cache.get(readLockKey);
+            Assert.assertNotNull(value);
+            Assert.assertTrue(value instanceof Integer);
+            int readLockCount = (Integer) value;
+            Assert.assertEquals(readLockCount, 1, " for FileReadLockKey " + readLockKey);
          } else {
             Assert.fail("an unexpected key was found in the cache having key type " + key.getClass() + " toString:" + key);
          }

Modified: trunk/lucene-directory/src/test/java/org/infinispan/lucene/InfinispanDirectoryIOTest.java
===================================================================
--- trunk/lucene-directory/src/test/java/org/infinispan/lucene/InfinispanDirectoryIOTest.java	2010-07-05 15:11:05 UTC (rev 1976)
+++ trunk/lucene-directory/src/test/java/org/infinispan/lucene/InfinispanDirectoryIOTest.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -45,7 +45,7 @@
  * @author Davide Di Somma
  * @author Sanne Grinovero
  */
- at Test(groups = "functional", testName = "lucene.InfinispanDirectoryIOTest")
+ at Test(groups = "functional", testName = "lucene.InfinispanDirectoryIOTest", sequential = true)
 public class InfinispanDirectoryIOTest {
    
    private CacheContainer cacheManager;
@@ -410,6 +410,7 @@
       byte[] buf = new byte[9];
       IndexInput ii = dir.openInput("MyNewFile.txt");
       ii.readBytes(buf, 0, (int) ii.length());
+      ii.close();
 
       assert new String(new byte[] { 66, 69 }).equals(new String(buf).trim());
 
@@ -459,6 +460,7 @@
       byte[] buf = new byte[testTextAsBytes.length];
 
       ii.readBytes(buf, 0, testTextAsBytes.length);
+      ii.close();
 
       assert testText.equals(new String(buf).trim());
 

Modified: trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/IndexReadingStressTest.java
===================================================================
--- trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/IndexReadingStressTest.java	2010-07-05 15:11:05 UTC (rev 1976)
+++ trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/IndexReadingStressTest.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -32,7 +32,13 @@
 import org.apache.lucene.document.Field.Index;
 import org.apache.lucene.document.Field.Store;
 import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.FSDirectory;
 import org.apache.lucene.store.LockObtainFailedException;
@@ -58,11 +64,11 @@
  * @author Sanne Grinovero
  * @since 4.0
  */
- at Test(groups = "profiling", testName = "lucene.profiling.IndexReadingStressTest")
+ at Test(groups = "profiling", testName = "lucene.profiling.IndexReadingStressTest", sequential = true)
 public class IndexReadingStressTest {
 
    /** Concurrent IndexSearchers used during tests */
-   private static final int THREADS = 20;
+   private static final int THREADS = 5;
 
    /** Test duration **/
    private static final long DURATION_MS = 350000;
@@ -88,7 +94,7 @@
 
    @Test
    public void profileTestInfinispanDirectory() throws InterruptedException, IOException {
-      // theses default are not for performance settings but meant for problem detection:
+      // these defaults are not for performance settings but meant for problem detection:
       Cache<CacheKey, Object> cache = cacheFactory.createClusteredCache();
       InfinispanDirectory dir = new InfinispanDirectory(cache, "iname");
       testDirectory(dir, "InfinispanClustered");
@@ -110,7 +116,7 @@
       SharedState state = fillDirectory(dir);
       ExecutorService e = Executors.newFixedThreadPool(THREADS);
       for (int i = 0; i < THREADS; i++) {
-         e.execute(new LuceneReaderThread(dir, state));
+         e.execute(new IndependentLuceneReaderThread(dir, state, i, 1, TERMS_NUMBER));
       }
       e.shutdown();
       state.startWaitingThreads();
@@ -130,8 +136,14 @@
       for (int i = 0; i <= TERMS_NUMBER; i++) {
          Document doc = new Document();
          String term = String.valueOf(i);
-         state.addStringWrittenToIndex(term);
-         doc.add(new Field("main", term, Store.NO, Index.NOT_ANALYZED));
+         //For even values of i we add to "main" field
+         if (i % 2 == 0) {
+            doc.add(new Field("main", term, Store.NO, Index.NOT_ANALYZED));
+            state.addStringWrittenToIndex(term);
+         }
+         else {
+            doc.add(new Field("secondaryField", term, Store.NO, Index.NOT_ANALYZED));
+         }
          iwriter.addDocument(doc);
       }
       iwriter.commit();
@@ -148,5 +160,47 @@
    public static void afterTest() {
       cacheFactory.stop();
    }
+   
+   private static class IndependentLuceneReaderThread extends LuceneUserThread {
 
+      private final int startValue;
+      private final int increment;
+      private final int max;
+      private final IndexReader indexReader;
+      private final IndexSearcher searcher;
+
+      IndependentLuceneReaderThread(Directory dir, SharedState state, int startValue, int increment, int max) throws CorruptIndexException, IOException {
+         super(dir, state);
+         this.startValue = startValue;
+         this.increment = increment;
+         this.max = max;
+         indexReader = IndexReader.open(directory, true);
+         searcher = new IndexSearcher(indexReader);
+      }
+      
+      @Override
+      protected void testLoop() throws IOException {
+         Term t = new Term("main", "0");
+         for (int i = startValue; i <= max && state.needToQuit() == false; i += increment) {
+            Term termToQuery = t.createTerm(Integer.toString(i));
+            Query query = new TermQuery(termToQuery);
+            TopDocs docs = searcher.search(query, null, 1);
+            if (i % 2 == 0 && docs.totalHits != 1) {
+               //Even values should be found in the index
+               throw new RuntimeException("String '" + String.valueOf(i) + "' should exist but was not found in index");
+            } else if (i % 2 == 1 && docs.totalHits != 0) {
+               //Uneven values should not be found
+               throw new RuntimeException("String '" + String.valueOf(i) + "' should NOT exist but was found in index");
+            }
+            state.incrementIndexSearchesCount(1);
+         }
+      }
+
+      @Override
+      protected void cleanup() throws IOException {
+         indexReader.close();
+      }
+      
+   }
+      
 }

Modified: trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/LuceneReaderThread.java
===================================================================
--- trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/LuceneReaderThread.java	2010-07-05 15:11:05 UTC (rev 1976)
+++ trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/LuceneReaderThread.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -45,8 +45,8 @@
  */
 public class LuceneReaderThread extends LuceneUserThread {
 
-   private IndexSearcher searcher;
-   private IndexReader indexReader;
+   protected IndexSearcher searcher;
+   protected IndexReader indexReader;
 
    LuceneReaderThread(Directory dir, SharedState state) {
       super(dir, state);
@@ -70,17 +70,27 @@
       state.incrementIndexSearchesCount(numElements);
    }
 
-   private void refreshIndexReader() throws CorruptIndexException, IOException {
-      if (indexReader==null) {
+   protected void refreshIndexReader() throws CorruptIndexException, IOException {
+      if (indexReader == null) {
          indexReader = IndexReader.open(directory, true);
       }
       else {
+         IndexReader before = indexReader;
          indexReader = indexReader.reopen();
+         if (before != indexReader) {
+            before.close();
+         }
       }
-      if (searcher!=null) {
+      if (searcher != null) {
          searcher.close();
       }
-      searcher = new IndexSearcher(directory, true);
+      searcher = new IndexSearcher(indexReader);
    }
+   
+   @Override
+   protected void cleanup() throws IOException {
+      if (indexReader != null)
+         indexReader.close();
+   }
 
 }

Modified: trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/LuceneUserThread.java
===================================================================
--- trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/LuceneUserThread.java	2010-07-05 15:11:05 UTC (rev 1976)
+++ trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/LuceneUserThread.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -24,6 +24,9 @@
 import java.io.IOException;
 
 import org.apache.lucene.store.Directory;
+import org.infinispan.lucene.InfinispanDirectory;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
 
 /**
  * LuceneUserThread: base class to perform activities on the index, as searching, adding to index and
@@ -33,6 +36,8 @@
  * @since 4.0
  */
 public abstract class LuceneUserThread implements Runnable {
+   
+   private static final Log log = LogFactory.getLog(InfinispanDirectory.class);
 
    protected final Directory directory;
    protected final SharedState state;
@@ -54,11 +59,22 @@
          try {
             testLoop();
          } catch (Exception e) {
+            log.error("unexpected error", e);
             state.errorManage(e);
          }
       }
+      try {
+         cleanup();
+      } catch (IOException e) {
+         log.error("unexpected error", e);
+         state.errorManage(e);
+      }
    }
 
    protected abstract void testLoop() throws IOException;
+   
+   protected void cleanup() throws IOException {
+      // defaults to no operation
+   }
 
 }

Modified: trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/PerformanceCompareStressTest.java
===================================================================
--- trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/PerformanceCompareStressTest.java	2010-07-05 15:11:05 UTC (rev 1976)
+++ trunk/lucene-directory/src/test/java/org/infinispan/lucene/profiling/PerformanceCompareStressTest.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -33,9 +33,13 @@
 import org.infinispan.Cache;
 import org.infinispan.lucene.CacheKey;
 import org.infinispan.lucene.CacheTestSupport;
+import org.infinispan.lucene.DirectoryIntegrityCheck;
 import org.infinispan.lucene.InfinispanDirectory;
 import org.infinispan.lucene.testutils.ClusteredCacheFactory;
 import org.infinispan.manager.CacheContainer;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+import org.testng.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -51,12 +55,16 @@
  * @author Sanne Grinovero
  * @since 4.0
  */
- at Test(groups = "profiling", testName = "lucene.profiling.PerformanceCompareStressTest")
+ at Test(groups = "profiling", testName = "lucene.profiling.PerformanceCompareStressTest", sequential=true)
 public class PerformanceCompareStressTest {
    
+   private static final Log log = LogFactory.getLog(PerformanceCompareStressTest.class);
+   
    /** Concurrent Threads in tests */
-   private static final int THREADS = 8;
+   private static final int THREADS = 5;
    
+   private static final String indexName = "iname";
+   
    private static final long DURATION_MS = 100000;
    
    private static final ClusteredCacheFactory cacheFactory = new ClusteredCacheFactory(CacheTestSupport.createTestConfiguration());
@@ -79,8 +87,9 @@
    public void profileTestInfinispanDirectory() throws InterruptedException, IOException {
       //these default are not for performance settings but meant for problem detection:
       Cache<CacheKey,Object> cache = cacheFactory.createClusteredCache();
-      InfinispanDirectory dir = new InfinispanDirectory(cache, "iname");
+      InfinispanDirectory dir = new InfinispanDirectory(cache, indexName);
       testDirectory(dir, "InfinispanClustered");
+      DirectoryIntegrityCheck.verifyDirectoryStructure(cache, indexName);
    }
    
    @Test
@@ -88,8 +97,9 @@
       CacheContainer cacheContainer = CacheTestSupport.createLocalCacheManager();
       try {
          Cache<CacheKey, Object> cache = cacheContainer.getCache();
-         InfinispanDirectory dir = new InfinispanDirectory(cache, "iname");
+         InfinispanDirectory dir = new InfinispanDirectory(cache, indexName);
          testDirectory(dir, "InfinispanLocal");
+         DirectoryIntegrityCheck.verifyDirectoryStructure(cache, indexName);
       } finally {
          cacheContainer.stop();
       }
@@ -109,7 +119,8 @@
       long searchesCount = state.incrementIndexSearchesCount(0);
       long writerTaskCount = state.incrementIndexWriterTaskCount(0);
       state.quit();
-      e.awaitTermination(10, TimeUnit.SECONDS);
+      boolean terminatedCorrectly = e.awaitTermination(10, TimeUnit.SECONDS);
+      Assert.assertTrue(terminatedCorrectly);
       System.out.println(
                "Test " + testLabel +" run in " + DURATION_MS + "ms:\n\tSearches: " + searchesCount + "\n\t" + "Writes: " + writerTaskCount);
    }

Modified: trunk/lucene-directory/src/test/java/org/infinispan/lucene/testutils/LuceneSettings.java
===================================================================
--- trunk/lucene-directory/src/test/java/org/infinispan/lucene/testutils/LuceneSettings.java	2010-07-05 15:11:05 UTC (rev 1976)
+++ trunk/lucene-directory/src/test/java/org/infinispan/lucene/testutils/LuceneSettings.java	2010-07-05 17:07:48 UTC (rev 1977)
@@ -52,6 +52,7 @@
       IndexWriter iwriter = new IndexWriter(directory, LuceneSettings.analyzer, false, MaxFieldLength.UNLIMITED);
       iwriter.setMergeScheduler(mergeScheduler);
       iwriter.setMaxMergeDocs(maxMergeDocs);
+      iwriter.setUseCompoundFile(false);
       return iwriter;
    }
 



More information about the infinispan-commits mailing list