You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ch...@apache.org on 2015/05/21 17:26:46 UTC
svn commit: r1680903 [2/2] - in /jackrabbit/oak/trunk/oak-lucene/src:
main/java/org/apache/jackrabbit/oak/plugins/index/lucene/
test/java/org/apache/jackrabbit/oak/plugins/index/lucene/
Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopierTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopierTest.java?rev=1680903&r1=1680902&r2=1680903&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopierTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopierTest.java Thu May 21 15:26:46 2015
@@ -20,25 +20,35 @@
package org.apache.jackrabbit.oak.plugins.index.lucene;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
import javax.management.openmbean.TabularData;
+import com.google.common.base.StandardSystemProperty;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ForwardingListeningExecutorService;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
+import org.apache.commons.io.FileUtils;
import org.apache.jackrabbit.oak.commons.IOUtils;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -47,19 +57,21 @@ import org.apache.lucene.store.IOContext
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.store.RAMDirectory;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Sets.newHashSet;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_COUNT;
import static org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
public class IndexCopierTest {
private Random rnd = new Random();
@@ -79,7 +91,7 @@ public class IndexCopierTest {
IndexCopier c1 = new RAMIndexCopier(baseDir, sameThreadExecutor(), getWorkDir());
Directory remote = new RAMDirectory();
- Directory wrapped = c1.wrap("/foo" , defn, remote);
+ Directory wrapped = c1.wrapForRead("/foo", defn, remote);
byte[] t1 = writeFile(remote , "t1");
byte[] t2 = writeFile(remote , "t2");
@@ -104,7 +116,7 @@ public class IndexCopierTest {
IndexCopier c1 = new IndexCopier(sameThreadExecutor(), getWorkDir());
Directory remote = new RAMDirectory();
- Directory wrapped = c1.wrap("/foo" , defn, remote);
+ Directory wrapped = c1.wrapForRead("/foo", defn, remote);
byte[] t1 = writeFile(remote, "t1");
byte[] t2 = writeFile(remote , "t2");
@@ -128,16 +140,16 @@ public class IndexCopierTest {
assertEquals(1, td.size());
}
- @Ignore("OAK-2722") //FIXME test fails on windows
@Test
public void deleteOldPostReindex() throws Exception{
+ assumeNotWindows();
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
IndexCopier c1 = new IndexCopier(sameThreadExecutor(), getWorkDir());
Directory remote = new CloseSafeDir();
- Directory w1 = c1.wrap("/foo" , defn, remote);
+ Directory w1 = c1.wrapForRead("/foo", defn, remote);
- byte[] t1 = writeFile(remote , "t1");
+ byte[] t1 = writeFile(remote, "t1");
byte[] t2 = writeFile(remote , "t2");
readAndAssert(w1, "t1", t1);
@@ -154,7 +166,7 @@ public class IndexCopierTest {
//Close old version
w1.close();
//Get a new one with updated reindexCount
- Directory w2 = c1.wrap("/foo" , defn, remote);
+ Directory w2 = c1.wrapForRead("/foo", defn, remote);
readAndAssert(w2, "t1", t1);
@@ -174,7 +186,7 @@ public class IndexCopierTest {
IndexCopier c1 = new RAMIndexCopier(baseDir, executor, getWorkDir());
TestRAMDirectory remote = new TestRAMDirectory();
- Directory wrapped = c1.wrap("/foo", defn, remote);
+ Directory wrapped = c1.wrapForRead("/foo", defn, remote);
byte[] t1 = writeFile(remote , "t1");
@@ -237,7 +249,7 @@ public class IndexCopierTest {
super.copy(to, src, dest, context);
}
};
- Directory wrapped = c1.wrap("/foo", defn, remote);
+ Directory wrapped = c1.wrapForRead("/foo", defn, remote);
byte[] t1 = writeFile(remote , "t1");
@@ -281,7 +293,7 @@ public class IndexCopierTest {
IndexCopier c1 = new RAMIndexCopier(baseDir, sameThreadExecutor(), getWorkDir());
TestRAMDirectory remote = new TestRAMDirectory();
- Directory wrapped = c1.wrap("/foo" , defn, remote);
+ Directory wrapped = c1.wrapForRead("/foo", defn, remote);
byte[] t1 = writeFile(remote, "t1");
@@ -290,7 +302,7 @@ public class IndexCopierTest {
assertEquals(1, remote.openedFiles.size());
//2. Reuse the testDir and read again
- Directory wrapped2 = c1.wrap("/foo", defn, remote);
+ Directory wrapped2 = c1.wrapForRead("/foo", defn, remote);
remote.reset();
//3. Now read should be served from local
@@ -298,7 +310,7 @@ public class IndexCopierTest {
assertEquals(0, remote.openedFiles.size());
//Now check if local file gets corrupted then read from remote
- Directory wrapped3 = c1.wrap("/foo" , defn, remote);
+ Directory wrapped3 = c1.wrapForRead("/foo", defn, remote);
remote.reset();
//4. Corrupt the local copy
@@ -323,7 +335,7 @@ public class IndexCopierTest {
};
String fileName = "failed.txt";
- Directory wrapped = c1.wrap("/foo" , defn, remote);
+ Directory wrapped = c1.wrapForRead("/foo", defn, remote);
byte[] t1 = writeFile(remote , fileName);
@@ -351,10 +363,10 @@ public class IndexCopierTest {
Directory r1 = new RAMDirectory();
- byte[] t1 = writeFile(r1 , "t1");
+ byte[] t1 = writeFile(r1, "t1");
byte[] t2 = writeFile(r1 , "t2");
- Directory w1 = c1.wrap("/foo" , defn, r1);
+ Directory w1 = c1.wrapForRead("/foo", defn, r1);
readAndAssert(w1, "t1", t1);
readAndAssert(w1, "t2", t2);
@@ -366,7 +378,7 @@ public class IndexCopierTest {
copy(r1, r2);
r2.deleteFile("t1");
- Directory w2 = c1.wrap("/foo" , defn, r2);
+ Directory w2 = c1.wrapForRead("/foo", defn, r2);
//Close would trigger removal of file which are not present in remote
w2.close();
@@ -397,7 +409,7 @@ public class IndexCopierTest {
byte[] t1 = writeFile(r1, "t1");
byte[] t2 = writeFile(r1 , "t2");
- Directory w1 = c1.wrap("/foo" , defn, r1);
+ Directory w1 = c1.wrapForRead("/foo", defn, r1);
readAndAssert(w1, "t1", t1);
readAndAssert(w1, "t2", t2);
@@ -409,7 +421,7 @@ public class IndexCopierTest {
copy(r1, r2);
r2.deleteFile("t1");
- Directory w2 = c1.wrap("/foo" , defn, r2);
+ Directory w2 = c1.wrapForRead("/foo", defn, r2);
//Close would trigger removal of file which are not present in remote
testFiles.add("t1");
@@ -422,14 +434,14 @@ public class IndexCopierTest {
assertEquals(IOUtils.humanReadableByteCount(t1.length), c1.getGarbageSize());
assertEquals(1, c1.getGarbageDetails().length);
- Directory w3 = c1.wrap("/foo" , defn, r2);
+ Directory w3 = c1.wrapForRead("/foo", defn, r2);
w3.close();
assertEquals(2, testFile.getDeleteAttemptCount());
//Now let the file to be deleted
testFiles.clear();
- Directory w4 = c1.wrap("/foo" , defn, r2);
+ Directory w4 = c1.wrapForRead("/foo", defn, r2);
w4.close();
//No pending deletes left
@@ -447,14 +459,14 @@ public class IndexCopierTest {
Directory remote1 = new RAMDirectory();
byte[] t1 = writeFile(remote1, "t1");
- Directory local1 = copier.wrap("/foo", defn, remote1);
+ Directory local1 = copier.wrapForRead("/foo", defn, remote1);
readAndAssert(local1, "t1", t1);
//While local1 is open , open another local2 and read t2
Directory remote2 = new RAMDirectory();
byte[] t2 = writeFile(remote2, "t2");
- Directory local2 = copier.wrap("/foo", defn, remote2);
+ Directory local2 = copier.wrapForRead("/foo", defn, remote2);
readAndAssert(local2, "t2", t2);
//Close local1
@@ -464,6 +476,345 @@ public class IndexCopierTest {
readAndAssert(local2, "t2", t2);
}
+ @Test
+ public void wrapForWriteWithoutIndexPath() throws Exception{
+ assumeNotWindows();
+ Directory remote = new CloseSafeDir();
+
+ IndexCopier copier = new IndexCopier(sameThreadExecutor(), getWorkDir());
+
+ IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ Directory dir = copier.wrapForWrite(defn, remote, false);
+
+ byte[] t1 = writeFile(dir, "t1");
+
+ dir.close();
+
+ readAndAssert(remote, "t1", t1);
+ //Work dir must be empty post close
+ assertArrayEquals(FileUtils.EMPTY_FILE_ARRAY, copier.getIndexWorkDir().listFiles());
+ }
+
+ @Test
+ public void wrapForWriteWithIndexPath() throws Exception{
+ assumeNotWindows();
+ Directory remote = new CloseSafeDir();
+
+ IndexCopier copier = new IndexCopier(sameThreadExecutor(), getWorkDir());
+
+ builder.setProperty(LuceneIndexConstants.INDEX_PATH, "foo");
+ IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ Directory dir = copier.wrapForWrite(defn, remote, false);
+
+ byte[] t1 = writeFile(dir, "t1");
+
+ dir.close();
+
+ readAndAssert(remote, "t1", t1);
+ //Work dir must be empty post close
+ List<File> files = new ArrayList<File>(FileUtils.listFiles(copier.getIndexRootDir(), null, true));
+ assertEquals(1, files.size());
+ assertEquals("t1", files.get(0).getName());
+ }
+
+ @Test
+ public void copyOnWriteBasics() throws Exception{
+ Directory baseDir = new CloseSafeDir();
+ IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ IndexCopier copier = new RAMIndexCopier(baseDir, sameThreadExecutor(), getWorkDir());
+
+ Directory remote = new RAMDirectory();
+ byte[] t1 = writeFile(remote, "t1");
+
+ //State of remote directory should set before wrapping as later
+ //additions would not be picked up given COW assume remote directory
+ //to be read only
+ Directory local = copier.wrapForWrite(defn, remote, false);
+
+ assertEquals(newHashSet("t1"), newHashSet(local.listAll()));
+ assertEquals(t1.length, local.fileLength("t1"));
+
+ byte[] t2 = writeFile(local, "t2");
+ assertEquals(newHashSet("t1", "t2"), newHashSet(local.listAll()));
+ assertEquals(t2.length, local.fileLength("t2"));
+
+ assertTrue(local.fileExists("t1"));
+ assertTrue(local.fileExists("t2"));
+
+ assertTrue("t2 should be copied to remote", remote.fileExists("t2"));
+
+ readAndAssert(local, "t1", t1);
+ readAndAssert(local, "t2", t2);
+
+ local.deleteFile("t1");
+ assertEquals(newHashSet("t2"), newHashSet(local.listAll()));
+
+ local.deleteFile("t2");
+ assertEquals(newHashSet(), newHashSet(local.listAll()));
+
+
+ try {
+ local.fileLength("nonExistentFile");
+ fail();
+ } catch (FileNotFoundException ignore) {
+
+ }
+
+ try {
+ local.openInput("nonExistentFile", IOContext.DEFAULT);
+ fail();
+ } catch (FileNotFoundException ignore) {
+
+ }
+
+ local.close();
+ assertFalse(baseDir.fileExists("t2"));
+ }
+
+ /**
+ * Checks for the case where if the file exist local before writer starts
+ * then those files do not get deleted even if deleted by writer via
+ * indexing process from 'baseDir' as they might be in use by existing open
+ * indexes
+ */
+ @Test
+ public void cowExistingLocalFileNotDeleted() throws Exception{
+ Directory baseDir = new CloseSafeDir();
+ IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ IndexCopier copier = new RAMIndexCopier(baseDir, sameThreadExecutor(), getWorkDir());
+
+ Directory remote = new CloseSafeDir();
+ byte[] t1 = writeFile(remote, "t1");
+ byte[] t2 = writeFile(remote, "t2");
+ Directory local = copier.wrapForWrite(defn, remote, false);
+ assertEquals(newHashSet("t1", "t2"), newHashSet(local.listAll()));
+
+ byte[] t3 = writeFile(local, "t3");
+
+ //Now pull in the file t1 via CopyOnRead in baseDir
+ Directory localForRead = copier.wrapForRead("/foo", defn, remote);
+ readAndAssert(localForRead, "t1", t1);
+
+ //File which was copied from remote should not be deleted from baseDir
+ //upon delete from local
+ assertTrue(baseDir.fileExists("t1"));
+ local.deleteFile("t1");
+ assertFalse("t1 should be deleted from remote", remote.fileExists("t1"));
+ assertFalse("t1 should be deleted from 'local' view also", local.fileExists("t1"));
+ assertTrue("t1 should not be deleted from baseDir", baseDir.fileExists("t1"));
+
+ //File which was created only via local SHOULD get removed from
+ //baseDir only upon close
+ assertTrue(baseDir.fileExists("t3"));
+ local.deleteFile("t3");
+ assertFalse("t1 should be deleted from remote", local.fileExists("t3"));
+ assertTrue("t1 should NOT be deleted from remote", baseDir.fileExists("t3"));
+
+ local.close();
+ assertFalse("t3 should also be deleted from local", baseDir.fileExists("t3"));
+ }
+
+ @Test
+ public void cowReadDoneFromLocalIfFileExist() throws Exception{
+ final Set<String> readLocal = newHashSet();
+ Directory baseDir = new CloseSafeDir(){
+ @Override
+ public IndexInput openInput(String name, IOContext context) throws IOException {
+ readLocal.add(name);
+ return super.openInput(name, context);
+ }
+ };
+ IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ IndexCopier copier = new RAMIndexCopier(baseDir, sameThreadExecutor(), getWorkDir());
+
+ final Set<String> readRemotes = newHashSet();
+ Directory remote = new RAMDirectory() {
+ @Override
+ public IndexInput openInput(String name, IOContext context) throws IOException {
+ readRemotes.add(name);
+ return super.openInput(name, context);
+ }
+ };
+ byte[] t1 = writeFile(remote, "t1");
+ Directory local = copier.wrapForWrite(defn, remote, false);
+
+ //Read should be served from remote
+ readRemotes.clear();readLocal.clear();
+ readAndAssert(local, "t1", t1);
+ assertEquals(newHashSet("t1"), readRemotes);
+ assertEquals(newHashSet(), readLocal);
+
+ //Now pull in the file t1 via CopyOnRead in baseDir
+ Directory localForRead = copier.wrapForRead("/foo", defn, remote);
+ readAndAssert(localForRead, "t1", t1);
+
+ //Read should be served from local
+ readRemotes.clear();readLocal.clear();
+ readAndAssert(local, "t1", t1);
+ assertEquals(newHashSet(), readRemotes);
+ assertEquals(newHashSet("t1"), readLocal);
+
+ local.close();
+ }
+
+ @Test
+ public void cowCopyDoneOnClose() throws Exception{
+ final CollectingExecutor executor = new CollectingExecutor();
+ Directory baseDir = new CloseSafeDir();
+ IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ IndexCopier copier = new RAMIndexCopier(baseDir, executor, getWorkDir());
+
+ Directory remote = new CloseSafeDir();
+
+ final Directory local = copier.wrapForWrite(defn, remote, false);
+ byte[] t1 = writeFile(local, "t1");
+
+ assertTrue(local.fileExists("t1"));
+ assertFalse("t1 should NOT be copied to remote", remote.fileExists("t1"));
+
+ //Execute all job
+ executor.executeAll();
+
+ assertTrue("t1 should now be copied to remote", remote.fileExists("t1"));
+
+ byte[] t2 = writeFile(local, "t2");
+ assertFalse("t2 should NOT be copied to remote", remote.fileExists("t2"));
+
+ final ExecutorService executorService = Executors.newFixedThreadPool(4);
+ final CountDownLatch copyLatch = new CountDownLatch(1);
+ Future<?> copyTasks = executorService.submit(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ copyLatch.await();
+ //the executor to a proper one as it might happen that
+ //STOP task is added post CountingExecutor has executed. Then there
+ //would be none to process the STOP. Having a proper executor would
+ //handle that case
+ executor.setForwardingExecutor(executorService);
+ executor.executeAll();
+ return null;
+ }
+ });
+
+ final CountDownLatch closeLatch = new CountDownLatch(1);
+ Future<?> closeTasks = executorService.submit(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ closeLatch.await();
+ local.close();
+ return null;
+ }
+ });
+
+ closeLatch.countDown();
+ assertFalse("t2 should NOT be copied to remote", remote.fileExists("t2"));
+
+ //Let copy to proceed
+ copyLatch.countDown();
+
+ //Now wait for close to finish
+ closeTasks.get();
+ assertTrue("t2 should now be copied to remote", remote.fileExists("t2"));
+
+ executorService.shutdown();
+ }
+
+ @Test
+ public void cowCopyDoneOnCloseExceptionHandling() throws Exception{
+ final CollectingExecutor executor = new CollectingExecutor();
+ Directory baseDir = new CloseSafeDir();
+ IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ IndexCopier copier = new RAMIndexCopier(baseDir, executor, getWorkDir());
+
+ Directory remote = new CloseSafeDir();
+
+ final Directory local = copier.wrapForWrite(defn, remote, false);
+ byte[] t1 = writeFile(local, "t1");
+
+ assertTrue(local.fileExists("t1"));
+ assertFalse("t1 should NOT be copied to remote", remote.fileExists("t1"));
+
+ //Execute all job
+ executor.executeAll();
+
+ assertTrue("t1 should now be copied to remote", remote.fileExists("t1"));
+
+ byte[] t2 = writeFile(local, "t2");
+ assertFalse("t2 should NOT be copied to remote", remote.fileExists("t2"));
+
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ final CountDownLatch copyLatch = new CountDownLatch(1);
+ Future<?> copyTasks = executorService.submit(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ copyLatch.await();
+ executor.executeAll();
+ executor.enableImmediateExecution();
+ return null;
+ }
+ });
+
+ final CountDownLatch closeLatch = new CountDownLatch(1);
+ Future<?> closeTasks = executorService.submit(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ closeLatch.await();
+ local.close();
+ return null;
+ }
+ });
+
+ closeLatch.countDown();
+ assertFalse("t2 should NOT be copied to remote", remote.fileExists("t2"));
+
+ //Let copy to proceed
+ copyLatch.countDown();
+
+ //Now wait for close to finish
+ closeTasks.get();
+ assertTrue("t2 should now be copied to remote", remote.fileExists("t2"));
+
+ executorService.shutdown();
+ }
+
+ @Test
+ public void cowFailureInCopy() throws Exception{
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ Directory baseDir = new CloseSafeDir();
+ IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ IndexCopier copier = new RAMIndexCopier(baseDir, executorService, getWorkDir());
+
+ final Set<String> toFail = Sets.newHashSet();
+ Directory remote = new CloseSafeDir() {
+ @Override
+ public IndexOutput createOutput(String name, IOContext context) throws IOException {
+ if (toFail.contains(name)){
+ throw new RuntimeException("Failing copy for "+name);
+ }
+ return super.createOutput(name, context);
+ }
+ };
+
+ final Directory local = copier.wrapForWrite(defn, remote, false);
+ toFail.add("t2");
+ byte[] t1 = writeFile(local, "t1");
+ byte[] t2 = writeFile(local, "t2");
+
+ try {
+ local.close();
+ fail();
+ } catch (IOException ignore){
+
+ }
+
+ executorService.shutdown();
+ }
+
+ @Test
+ public void cowIndexPathNotDefined() throws Exception{
+
+ }
+
private byte[] writeFile(Directory dir, String name) throws IOException {
byte[] data = randomBytes(rnd.nextInt(maxFileSize) + 1);
IndexOutput o = dir.createOutput(name, IOContext.DEFAULT);
@@ -498,13 +849,18 @@ public class IndexCopierTest {
private class RAMIndexCopier extends IndexCopier {
final Directory baseDir;
- public RAMIndexCopier(Directory baseDir, Executor executor, File indexRootDir) {
+ public RAMIndexCopier(Directory baseDir, Executor executor, File indexRootDir) throws IOException {
super(executor, indexRootDir);
this.baseDir = baseDir;
}
@Override
- protected Directory createLocalDir(String indexPath, IndexDefinition definition) throws IOException {
+ protected Directory createLocalDirForIndexReader(String indexPath, IndexDefinition definition) throws IOException {
+ return baseDir;
+ }
+
+ @Override
+ protected Directory createLocalDirForIndexWriter(IndexDefinition definition) throws IOException {
return baseDir;
}
}
@@ -531,18 +887,44 @@ public class IndexCopierTest {
}
private static class CollectingExecutor implements Executor {
- final List<Runnable> commands = newArrayList();
+ final BlockingQueue<Runnable> commands = new LinkedBlockingQueue<Runnable>();
+ private boolean immediateExecution = false;
+ private volatile Executor forwardingExecutor;
@Override
public void execute(Runnable command) {
- commands.add(command);
+ if (forwardingExecutor != null){
+ forwardingExecutor.execute(command);
+ return;
+ }
+ if (immediateExecution){
+ command.run();
+ } else {
+ commands.add(command);
+ }
}
void executeAll(){
- for (Runnable c : commands) {
+ Runnable c;
+ while ((c = commands.poll()) != null){
c.run();
}
}
+
+ void enableImmediateExecution(){
+ immediateExecution = true;
+ }
+
+ void enableDelayedExecution(){
+ immediateExecution = false;
+ }
+
+ void setForwardingExecutor(Executor forwardingExecutor){
+ this.forwardingExecutor = forwardingExecutor;
+ }
}
+ private static void assumeNotWindows() {
+ assumeTrue(!StandardSystemProperty.OS_NAME.value().toLowerCase().contains("windows"));
+ }
}
Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexProviderServiceTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexProviderServiceTest.java?rev=1680903&r1=1680902&r2=1680903&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexProviderServiceTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexProviderServiceTest.java Thu May 21 15:26:46 2015
@@ -22,16 +22,20 @@ package org.apache.jackrabbit.oak.plugin
import java.util.HashMap;
import java.util.Map;
+import org.apache.jackrabbit.oak.plugins.index.IndexEditorProvider;
import org.apache.jackrabbit.oak.spi.commit.BackgroundObserver;
import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
+import org.apache.lucene.util.InfoStream;
import org.apache.sling.testing.mock.osgi.MockOsgi;
import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class LuceneIndexProviderServiceTest {
@@ -50,10 +54,16 @@ public class LuceneIndexProviderServiceT
assertNotNull(context.getService(QueryIndexProvider.class));
assertNotNull(context.getService(Observer.class));
+ assertNotNull(context.getService(IndexEditorProvider.class));
- assertNotNull("CopyOnRead should be enabled by default",context.getService(CopyOnReadStatsMBean.class));
+ LuceneIndexEditorProvider editorProvider =
+ (LuceneIndexEditorProvider) context.getService(IndexEditorProvider.class);
+ assertNull(editorProvider.getIndexCopier());
+
+ assertNotNull("CopyOnRead should be enabled by default", context.getService(CopyOnReadStatsMBean.class));
assertTrue(context.getService(Observer.class) instanceof BackgroundObserver);
+ assertEquals(InfoStream.NO_OUTPUT, InfoStream.getDefault());
MockOsgi.deactivate(service);
}
@@ -69,6 +79,31 @@ public class LuceneIndexProviderServiceT
MockOsgi.deactivate(service);
}
+ @Test
+ public void enableCopyOnWrite() throws Exception{
+ Map<String,Object> config = getDefaultConfig();
+ config.put("enableCopyOnWriteSupport", true);
+ MockOsgi.activate(service, context.bundleContext(), config);
+
+ LuceneIndexEditorProvider editorProvider =
+ (LuceneIndexEditorProvider) context.getService(IndexEditorProvider.class);
+
+ assertNotNull(editorProvider);
+ assertNotNull(editorProvider.getIndexCopier());
+
+ MockOsgi.deactivate(service);
+ }
+
+ @Test
+ public void debugLogging() throws Exception{
+ Map<String,Object> config = getDefaultConfig();
+ config.put("debug", true);
+ MockOsgi.activate(service, context.bundleContext(), config);
+
+ assertEquals(LoggingInfoStream.INSTANCE, InfoStream.getDefault());
+ MockOsgi.deactivate(service);
+ }
+
private Map<String,Object> getDefaultConfig(){
Map<String,Object> config = new HashMap<String, Object>();
config.put("localIndexDir", folder.getRoot().getAbsolutePath());
Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java?rev=1680903&r1=1680902&r2=1680903&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java Thu May 21 15:26:46 2015
@@ -108,6 +108,7 @@ import org.junit.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+@SuppressWarnings("ConstantConditions")
public class LuceneIndexTest {
private static final EditorHook HOOK = new EditorHook(
@@ -341,7 +342,7 @@ public class LuceneIndexTest {
}
private void purgeDeletedDocs(NodeBuilder idx, IndexDefinition definition) throws IOException {
- IndexWriter writer = new IndexWriter(newIndexDirectory(definition, idx), getIndexWriterConfig(definition));
+ IndexWriter writer = new IndexWriter(newIndexDirectory(definition, idx), getIndexWriterConfig(definition, true));
writer.forceMergeDeletes();
writer.close();
}
Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java?rev=1680903&r1=1680902&r2=1680903&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java Thu May 21 15:26:46 2015
@@ -20,12 +20,15 @@
package org.apache.jackrabbit.oak.plugins.index.lucene;
import java.io.InputStream;
+import java.io.IOException;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import javax.annotation.Nonnull;
import javax.jcr.PropertyType;
@@ -59,7 +62,10 @@ import org.apache.jackrabbit.oak.spi.com
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
import org.apache.jackrabbit.util.ISO8601;
+import org.junit.After;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
import static com.google.common.collect.ImmutableSet.of;
import static java.util.Arrays.asList;
@@ -95,6 +101,11 @@ public class LucenePropertyIndexTest ext
*/
static final int NUMBER_OF_NODES = LucenePropertyIndex.LUCENE_QUERY_BATCH_SIZE * 2;
+ private ExecutorService executorService = Executors.newFixedThreadPool(2);
+
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
@Override
protected void createTestIndexNode() throws Exception {
setTraversalEnabled(false);
@@ -108,12 +119,25 @@ public class LucenePropertyIndexTest ext
.with(new OpenSecurityProvider())
.with((QueryIndexProvider) provider)
.with((Observer) provider)
- .with(new LuceneIndexEditorProvider())
+ .with(new LuceneIndexEditorProvider(createIndexCopier()))
.with(new PropertyIndexEditorProvider())
.with(new NodeTypeIndexProvider())
.createContentRepository();
}
+ private IndexCopier createIndexCopier() {
+ try {
+ return new IndexCopier(executorService, temporaryFolder.getRoot());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @After
+ public void shutdownExecutor(){
+ executorService.shutdown();
+ }
+
@Test
public void fulltextSearchWithCustomAnalyzer() throws Exception {
Tree idx = createFulltextIndex(root.getTree("/"), "test");