Repository: incubator-geode Updated Branches: refs/heads/develop 384d379ae -> 3f356594e
GEODE-11: Adding a tool to dump the lucene index files Adding a function that will dump all of the files for the lucene index to disk, for examination with external tools like Luke. Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/3f356594 Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/3f356594 Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/3f356594 Branch: refs/heads/develop Commit: 3f356594e63c8a601330b558bbc7023d6d7653c6 Parents: 384d379 Author: Dan Smith <[email protected]> Authored: Fri May 27 11:55:26 2016 -0700 Committer: Dan Smith <[email protected]> Committed: Tue May 31 17:05:49 2016 -0700 ---------------------------------------------------------------------- .../gemfire/test/junit/rules/DiskDirRule.java | 8 ++ .../lucene/internal/LuceneServiceImpl.java | 2 + .../internal/directory/DumpDirectoryFiles.java | 111 ++++++++++++++++ .../cache/lucene/internal/filesystem/File.java | 19 ++- .../lucene/internal/filesystem/FileSystem.java | 17 +++ .../internal/repository/IndexRepository.java | 12 +- .../repository/IndexRepositoryImpl.java | 5 + .../DumpDirectoryFilesIntegrationTest.java | 87 +++++++++++++ .../directory/DumpDirectoryFilesJUnitTest.java | 127 +++++++++++++++++++ .../filesystem/FileSystemJUnitTest.java | 32 +++++ 10 files changed, 417 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f356594/geode-junit/src/main/java/com/gemstone/gemfire/test/junit/rules/DiskDirRule.java ---------------------------------------------------------------------- diff --git a/geode-junit/src/main/java/com/gemstone/gemfire/test/junit/rules/DiskDirRule.java b/geode-junit/src/main/java/com/gemstone/gemfire/test/junit/rules/DiskDirRule.java index 184619f..7ce8bbc 100644 --- a/geode-junit/src/main/java/com/gemstone/gemfire/test/junit/rules/DiskDirRule.java +++ b/geode-junit/src/main/java/com/gemstone/gemfire/test/junit/rules/DiskDirRule.java @@ -24,6 +24,10 @@ import java.nio.file.Files; import org.junit.rules.ExternalResource; +/** + * A rule that creates a temporary directory and + * cleans it up after the test. + */ public class DiskDirRule extends ExternalResource { private File diskDir; @@ -32,6 +36,10 @@ public class DiskDirRule extends ExternalResource { } @Override protected void after() { + if(!diskDir.exists()) { + return; + } + try { Files.walk(diskDir.toPath()).forEach((path) -> { try { http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f356594/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java index ecade52..f9bb8ba 100644 --- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java +++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java @@ -33,6 +33,7 @@ import com.gemstone.gemfire.cache.RegionAttributes; import com.gemstone.gemfire.cache.execute.FunctionService; import com.gemstone.gemfire.cache.lucene.LuceneIndex; import com.gemstone.gemfire.cache.lucene.LuceneQueryFactory; +import com.gemstone.gemfire.cache.lucene.internal.directory.DumpDirectoryFiles; import com.gemstone.gemfire.cache.lucene.internal.distributed.EntryScore; import com.gemstone.gemfire.cache.lucene.internal.distributed.LuceneFunction; import com.gemstone.gemfire.cache.lucene.internal.distributed.LuceneFunctionContext; @@ -80,6 +81,7 @@ public class LuceneServiceImpl implements InternalLuceneService { this.cache = gfc; FunctionService.registerFunction(new LuceneFunction()); + FunctionService.registerFunction(new DumpDirectoryFiles()); registerDataSerializables(); } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f356594/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFiles.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFiles.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFiles.java new file mode 100644 index 0000000..0d7b859 --- /dev/null +++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFiles.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.gemstone.gemfire.cache.lucene.internal.directory; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; + +import com.gemstone.gemfire.cache.Region; +import com.gemstone.gemfire.cache.execute.Function; +import com.gemstone.gemfire.cache.execute.FunctionAdapter; +import com.gemstone.gemfire.cache.execute.FunctionContext; +import com.gemstone.gemfire.cache.execute.FunctionException; +import com.gemstone.gemfire.cache.execute.RegionFunctionContext; +import com.gemstone.gemfire.cache.execute.ResultSender; +import com.gemstone.gemfire.cache.lucene.LuceneQueryProvider; +import com.gemstone.gemfire.cache.lucene.LuceneService; +import com.gemstone.gemfire.cache.lucene.LuceneServiceProvider; +import com.gemstone.gemfire.cache.lucene.internal.InternalLuceneIndex; +import com.gemstone.gemfire.cache.lucene.internal.LuceneServiceImpl; +import com.gemstone.gemfire.cache.lucene.internal.distributed.CollectorManager; +import com.gemstone.gemfire.cache.lucene.internal.distributed.LuceneFunctionContext; +import com.gemstone.gemfire.cache.lucene.internal.distributed.TopEntriesCollector; +import com.gemstone.gemfire.cache.lucene.internal.distributed.TopEntriesCollectorManager; +import com.gemstone.gemfire.cache.lucene.internal.filesystem.FileSystem; +import com.gemstone.gemfire.cache.lucene.internal.repository.IndexRepository; +import com.gemstone.gemfire.cache.lucene.internal.repository.IndexRepositoryImpl; +import com.gemstone.gemfire.cache.lucene.internal.repository.IndexResultCollector; +import com.gemstone.gemfire.cache.lucene.internal.repository.RepositoryManager; +import com.gemstone.gemfire.cache.query.QueryException; +import com.gemstone.gemfire.internal.InternalEntity; +import com.gemstone.gemfire.internal.cache.BucketNotFoundException; +import com.gemstone.gemfire.internal.logging.LogService; + +import org.apache.logging.log4j.Logger; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.search.Query; +import org.apache.lucene.store.Directory; + +public class DumpDirectoryFiles implements Function, InternalEntity { + private static final long serialVersionUID = 1L; + + private static final Logger logger = LogService.getLogger(); + + @Override + public void execute(FunctionContext context) { + RegionFunctionContext ctx = (RegionFunctionContext) context; + + if(!(context.getArguments() instanceof String[])) { + throw new IllegalArgumentException("Arguments should be a string array"); + } + String[] args = (String[]) context.getArguments(); + if(args.length != 2) { + throw new IllegalArgumentException("Expected 2 arguments: exportLocation, indexName"); + } + + + String exportLocation =args[0]; + String indexName =args[1]; + + final Region<Object, Object> region = ctx.getDataSet(); + LuceneService service = LuceneServiceProvider.get(ctx.getDataSet().getCache()); + InternalLuceneIndex index = (InternalLuceneIndex) service.getIndex(indexName, region.getFullPath()); + if(index == null) { + throw new IllegalStateException("Index not found for region " + region + " index " + indexName); + } + + final RepositoryManager repoManager = index.getRepositoryManager(); + try { + final Collection<IndexRepository> repositories = repoManager.getRepositories(ctx); + repositories.stream().forEach(repo -> { + final IndexWriter writer = repo.getWriter(); + RegionDirectory directory = (RegionDirectory) writer.getDirectory(); + FileSystem fs = directory.getFileSystem(); + + String bucketName = index.getName() + "_" + repo.getRegion().getFullPath(); + bucketName = bucketName.replace("/", "_"); + File bucketDirectory = new File(exportLocation, bucketName); + bucketDirectory.mkdirs(); + fs.export(bucketDirectory); + }); + context.getResultSender().lastResult(null); + } + catch (BucketNotFoundException e) { + throw new FunctionException(e); + } + } + + @Override + public boolean optimizeForWrite() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f356594/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/File.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/File.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/File.java index 2937af5..d27717e 100644 --- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/File.java +++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/File.java @@ -25,9 +25,11 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; +import java.nio.file.Files; import java.util.UUID; import com.gemstone.gemfire.DataSerializer; +import com.gemstone.gemfire.InternalGemFireError; import com.gemstone.gemfire.internal.DataSerializableFixedID; import com.gemstone.gemfire.internal.Version; @@ -150,6 +152,19 @@ public class File implements DataSerializableFixedID { long low = in.readLong(); id = new UUID(high, low); } - - + + + /** + * Export this to a {@link java.io.File} + */ + public void export(final java.io.File exportLocation) + { + java.io.File targetFile = new java.io.File(exportLocation, getName()); + try { + Files.copy(getInputStream(), targetFile.toPath()); + } + catch (IOException e) { + throw new InternalGemFireError("Could not export file " + getName(), e); + } + } } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f356594/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/FileSystem.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/FileSystem.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/FileSystem.java index fdafcbe..5f5218a 100644 --- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/FileSystem.java +++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/FileSystem.java @@ -167,4 +167,21 @@ public class FileSystem { public ConcurrentMap<ChunkKey, byte[]> getChunkRegion() { return chunkRegion; } + + /** + * Export all of the files in the filesystem to the provided directory + */ + public void export(final java.io.File exportLocation) { + + listFileNames().stream().forEach(fileName-> { + try { + getFile(fileName).export(exportLocation); + } + catch (FileNotFoundException e) { + //ignore this, it was concurrently removed + } + + }); + } + } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f356594/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepository.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepository.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepository.java index f1e63e0..fab2c2a 100644 --- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepository.java +++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepository.java @@ -21,6 +21,9 @@ package com.gemstone.gemfire.cache.lucene.internal.repository; import java.io.IOException; +import com.gemstone.gemfire.cache.Region; + +import org.apache.lucene.index.IndexWriter; import org.apache.lucene.search.Query; /** @@ -64,11 +67,18 @@ public interface IndexRepository { * @throws IOException */ void commit() throws IOException; - + + Region<?, ?> getRegion(); + /** * Check to see if this repository is closed due to * underlying resources being closed or destroyed * @return true if this repository is closed. */ public boolean isClosed(); + + /** + * For debugging purposes, return the underlying IndexWriter + */ + IndexWriter getWriter(); } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f356594/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepositoryImpl.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepositoryImpl.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepositoryImpl.java index 3dbbc94..47e43b5 100644 --- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepositoryImpl.java +++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepositoryImpl.java @@ -135,6 +135,11 @@ public class IndexRepositoryImpl implements IndexRepository { return writer; } + @Override + public Region<?, ?> getRegion() { + return region; + } + public LuceneSerializer getSerializer() { return serializer; } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f356594/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFilesIntegrationTest.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFilesIntegrationTest.java b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFilesIntegrationTest.java new file mode 100644 index 0000000..9f02f2b --- /dev/null +++ b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFilesIntegrationTest.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gemstone.gemfire.cache.lucene.internal.directory; + +import static com.gemstone.gemfire.cache.lucene.test.LuceneTestUtilities.*; +import static org.junit.Assert.*; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; + +import com.gemstone.gemfire.cache.PartitionAttributes; +import com.gemstone.gemfire.cache.PartitionAttributesFactory; +import com.gemstone.gemfire.cache.Region; +import com.gemstone.gemfire.cache.RegionShortcut; +import com.gemstone.gemfire.cache.execute.FunctionService; +import com.gemstone.gemfire.cache.execute.ResultCollector; +import com.gemstone.gemfire.cache.lucene.LuceneIndex; +import com.gemstone.gemfire.cache.lucene.LuceneIntegrationTest; +import com.gemstone.gemfire.cache.lucene.LuceneQuery; +import com.gemstone.gemfire.cache.lucene.test.TestObject; +import com.gemstone.gemfire.test.junit.categories.IntegrationTest; +import com.gemstone.gemfire.test.junit.rules.DiskDirRule; + +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.MatchAllDocsQuery; +import org.apache.lucene.search.TopDocs; +import org.apache.lucene.store.FSDirectory; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +@Category(IntegrationTest.class) +public class DumpDirectoryFilesIntegrationTest extends LuceneIntegrationTest { + @Rule + public DiskDirRule diskDirRule = new DiskDirRule(); + + @Test + public void shouldDumpReadableLuceneIndexFile() throws Exception { + luceneService.createIndex(INDEX_NAME, REGION_NAME, "title", "description"); + + Region region = createRegion(REGION_NAME, RegionShortcut.PARTITION); + region.put(0, new TestObject("title 1", "hello world")); + region.put(1 * 113, new TestObject("title 2", "this will not match")); + region.put(2 * 113, new TestObject("title 3", "hello world")); + region.put(3 * 113, new TestObject("hello world", "hello world")); + + LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); + + index.waitUntilFlushed(60000); + + ResultCollector resultCollector= FunctionService + .onRegion(region) + .withArgs(new String[] {diskDirRule.get().getAbsolutePath(), INDEX_NAME}) + .execute(new DumpDirectoryFiles().getId()); + resultCollector.getResult(); + + //Find the directory for the first bucket + File bucket0 = diskDirRule.get().listFiles(file -> file.getName().endsWith("_0"))[0]; + + //Test that we can read the lucene index from the dump + final FSDirectory directory = FSDirectory.open(bucket0.toPath()); + IndexReader reader = DirectoryReader.open(directory); + IndexSearcher searcher = new IndexSearcher(reader); + final TopDocs results = searcher.search(new MatchAllDocsQuery(), 1000); + assertEquals(4, results.totalHits); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f356594/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFilesJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFilesJUnitTest.java b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFilesJUnitTest.java new file mode 100644 index 0000000..f6f91bf --- /dev/null +++ b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/directory/DumpDirectoryFilesJUnitTest.java @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gemstone.gemfire.cache.lucene.internal.directory; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.io.File; +import java.util.Collections; + +import com.gemstone.gemfire.cache.Region; +import com.gemstone.gemfire.cache.execute.RegionFunctionContext; +import com.gemstone.gemfire.cache.execute.ResultSender; +import com.gemstone.gemfire.cache.lucene.LuceneService; +import com.gemstone.gemfire.cache.lucene.internal.InternalLuceneIndex; +import com.gemstone.gemfire.cache.lucene.internal.InternalLuceneService; +import com.gemstone.gemfire.cache.lucene.internal.filesystem.FileSystem; +import com.gemstone.gemfire.cache.lucene.internal.repository.IndexRepository; +import com.gemstone.gemfire.cache.lucene.internal.repository.RepositoryManager; +import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem; +import com.gemstone.gemfire.internal.cache.BucketNotFoundException; +import com.gemstone.gemfire.internal.cache.GemFireCacheImpl; +import com.gemstone.gemfire.test.fake.Fakes; +import com.gemstone.gemfire.test.junit.categories.UnitTest; + +import org.apache.lucene.index.IndexWriter; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; + +@Category(UnitTest.class) +public class DumpDirectoryFilesJUnitTest { + + private RegionFunctionContext context; + private String indexName = "index"; + private String directoryName = "directory"; + private String bucketName = "bucket"; + private FileSystem fileSystem; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Before + public void createMocks() throws BucketNotFoundException { + + GemFireCacheImpl cache = Fakes.cache(); + context = mock(RegionFunctionContext.class); + ResultSender sender = mock(ResultSender.class); + Region region = mock(Region.class); + InternalLuceneService service = mock(InternalLuceneService.class); + InternalLuceneIndex index = mock(InternalLuceneIndex.class); + RepositoryManager repoManager = mock(RepositoryManager.class); + IndexRepository repo = mock(IndexRepository.class); + IndexWriter writer = mock(IndexWriter.class); + RegionDirectory directory = mock(RegionDirectory.class); + fileSystem = mock(FileSystem.class); + Region bucket = mock(Region.class); + when(bucket.getFullPath()).thenReturn(bucketName); + + when(context.getArguments()).thenReturn(new String[] {directoryName, indexName}); + when(context.getResultSender()).thenReturn(sender); + when(context.getDataSet()).thenReturn(region); + when(region.getCache()).thenReturn(cache); + when(cache.getService(any())).thenReturn(service); + when(repoManager.getRepositories(eq(context))).thenReturn(Collections.singleton(repo)); + when(index.getRepositoryManager()).thenReturn(repoManager); + when(index.getName()).thenReturn(indexName); + when(service.getIndex(eq(indexName), any())).thenReturn(index); + when(directory.getFileSystem()).thenReturn(fileSystem); + when(writer.getDirectory()).thenReturn(directory); + when(repo.getWriter()).thenReturn(writer); + when(repo.getRegion()).thenReturn(bucket); + } + + @Test + public void shouldInvokeExportOnBuckets() throws BucketNotFoundException { + DumpDirectoryFiles dump = new DumpDirectoryFiles(); + dump.execute(context); + + File expectedDir = new File(directoryName, indexName + "_" + bucketName); + verify(fileSystem).export(eq(expectedDir)); + } + + @Test + public void shouldThrowIllegalStateWhenMissingIndex() throws BucketNotFoundException { + DumpDirectoryFiles dump = new DumpDirectoryFiles(); + when(context.getArguments()).thenReturn(new String[] {"badDirectory", "badIndex"}); + expectedException.expect(IllegalStateException.class); + dump.execute(context); + } + + @Test + public void shouldThrowIllegalArgumentWhenGivenBadArguments() throws BucketNotFoundException { + DumpDirectoryFiles dump = new DumpDirectoryFiles(); + when(context.getArguments()).thenReturn(new Object()); + expectedException.expect(IllegalArgumentException.class); + dump.execute(context); + } + + @Test + public void shouldThrowIllegalArgumentWhenMissingArgument() throws BucketNotFoundException { + DumpDirectoryFiles dump = new DumpDirectoryFiles(); + when(context.getArguments()).thenReturn(new String[] {"not enough args"}); + expectedException.expect(IllegalArgumentException.class); + dump.execute(context); + } + + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f356594/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/FileSystemJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/FileSystemJUnitTest.java b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/FileSystemJUnitTest.java index 1d936ca..78bf1de 100644 --- a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/FileSystemJUnitTest.java +++ b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/filesystem/FileSystemJUnitTest.java @@ -20,18 +20,23 @@ package com.gemstone.gemfire.cache.lucene.internal.filesystem; import static org.junit.Assert.*; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; +import java.nio.file.Files; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.mockito.Mockito; @@ -40,6 +45,7 @@ import org.mockito.stubbing.Answer; import com.gemstone.gemfire.cache.CacheClosedException; import com.gemstone.gemfire.test.junit.categories.UnitTest; +import com.gemstone.gemfire.test.junit.rules.DiskDirRule; @Category(UnitTest.class) public class FileSystemJUnitTest { @@ -52,6 +58,9 @@ public class FileSystemJUnitTest { private ConcurrentHashMap<String, File> fileRegion; private ConcurrentHashMap<ChunkKey, byte[]> chunkRegion; + @Rule + public DiskDirRule dirRule = new DiskDirRule(); + @Before public void setUp() { fileRegion = new ConcurrentHashMap<String, File>(); @@ -465,6 +474,29 @@ public class FileSystemJUnitTest { } } + @Test + public void testExport() throws IOException { + String name1 = "testFile1"; + File file1= system.createFile(name1); + byte[] file1Data = writeRandomBytes(file1); + + String name2 = "testFile2"; + File file2= system.createFile(name2); + byte[] file2Data = writeRandomBytes(file2); + + java.io.File parentDir = dirRule.get(); + system.export(dirRule.get()); + assertArrayEquals(new String[] {"testFile1", "testFile2"}, parentDir.list()); + + assertExportedFileContents(file1Data, new java.io.File(parentDir, "testFile1")); + assertExportedFileContents(file2Data, new java.io.File(parentDir, "testFile2")); + } + + private void assertExportedFileContents(final byte[] expected, final java.io.File exportedFile) throws IOException { + byte[] actual = Files.readAllBytes(exportedFile.toPath()); + assertArrayEquals(expected, actual); + } + private void assertContents(byte[] data, File file) throws IOException { assertEquals(data.length, file.getLength());
