/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/search/trunk/search-impl/impl/src/test/org/sakaiproject/search/indexer/impl/test/OptimizeOperationTest.java $ * $Id: OptimizeOperationTest.java 105078 2012-02-24 23:00:38Z ottenhoff@longsight.com $ *********************************************************************************** * * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009 The Sakai Foundation * * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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 org.sakaiproject.search.indexer.impl.test; import java.io.File; import java.util.List; import junit.framework.TestCase; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.lucene.search.IndexSearcher; import org.sakaiproject.search.index.impl.StandardAnalyzerFactory; import org.sakaiproject.search.indexer.impl.JournalManagerUpdateTransaction; import org.sakaiproject.search.indexer.impl.JournalStorageUpdateTransactionListener; import org.sakaiproject.search.indexer.impl.SearchBuilderQueueManager; import org.sakaiproject.search.indexer.impl.TransactionIndexManagerImpl; import org.sakaiproject.search.indexer.impl.TransactionalIndexWorker; import org.sakaiproject.search.journal.impl.DbJournalManager; import org.sakaiproject.search.journal.impl.IndexListenerCloser; import org.sakaiproject.search.journal.impl.JournalSettings; import org.sakaiproject.search.journal.impl.JournaledFSIndexStorage; import org.sakaiproject.search.journal.impl.JournaledFSIndexStorageUpdateTransactionListener; import org.sakaiproject.search.journal.impl.MergeUpdateManager; import org.sakaiproject.search.journal.impl.MergeUpdateOperation; import org.sakaiproject.search.journal.impl.SharedFilesystemJournalStorage; import org.sakaiproject.search.mock.MockSearchIndexBuilder; import org.sakaiproject.search.mock.MockSearchService; import org.sakaiproject.search.mock.MockServerConfigurationService; import org.sakaiproject.search.mock.MockThreadLocalManager; import org.sakaiproject.search.model.SearchBuilderItem; import org.sakaiproject.search.optimize.impl.OptimizableIndexImpl; import org.sakaiproject.search.optimize.impl.OptimizeIndexManager; import org.sakaiproject.search.optimize.impl.OptimizeIndexOperation; import org.sakaiproject.search.optimize.impl.OptimizeTransactionListenerImpl; import org.sakaiproject.search.transaction.impl.LocalTransactionSequenceImpl; import org.sakaiproject.search.transaction.impl.TransactionSequenceImpl; import org.sakaiproject.search.util.FileUtils; import org.sakaiproject.thread_local.api.ThreadLocalManager; /** * @author ieb */ public class OptimizeOperationTest extends TestCase { private static final Log log = LogFactory.getLog(OptimizeOperationTest.class); private File testBase; private TDataSource tds; private MergeUpdateOperation mu; private TransactionalIndexWorker tiw; private OptimizeIndexOperation oo; private File optimizeWork; private OptimizableIndexImpl optimizableIndex; private JournaledFSIndexStorage journaledFSIndexStorage; protected ThreadLocal<Object> inclose = new ThreadLocal<Object>(); protected ThreadLocal<Object> insearcherclose = new ThreadLocal<Object>(); private JournalSettings journalSettings; private ThreadLocalManager threadLocalManager; /** * @param name */ public OptimizeOperationTest(String name) { super(name); } /* * (non-Javadoc) * * @see junit.framework.TestCase#setUp() */ protected void setUp() throws Exception { super.setUp(); testBase = new File("target"); testBase = new File(testBase, "OptimizeOperationTest"); FileUtils.deleteAll(testBase); String localIndexBase = new File(testBase,"local").getAbsolutePath(); String sharedJournalBase = new File(testBase,"shared").getAbsolutePath(); threadLocalManager = new MockThreadLocalManager(); journalSettings = new JournalSettings(); journalSettings.setLocalIndexBase(localIndexBase); journalSettings.setSharedJournalBase(sharedJournalBase); journalSettings.setMinimumOptimizeSavePoints(5); journalSettings.setOptimizeMergeSize(5); journalSettings.setLocalMaxBufferedDocs(50); journalSettings.setLocalMaxMergeDocs(1000000); journalSettings.setLocalMaxMergeFactor(10); journalSettings.setSharedMaxBufferedDocs(50); journalSettings.setSharedMaxMergeDocs(1000000); journalSettings.setSharedMaxMergeFactor(10); journalSettings.setCreateMaxBufferedDocs(50); journalSettings.setCreateMaxMergeDocs(1000000); journalSettings.setCreateMaxMergeFactor(10); journalSettings.setSoakTest(true); tds = new TDataSource(5, false); mu = new MergeUpdateOperation(); journaledFSIndexStorage = new JournaledFSIndexStorage(); journaledFSIndexStorage.setThreadLocalManager(threadLocalManager); StandardAnalyzerFactory analyzerFactory = new StandardAnalyzerFactory(); DbJournalManager journalManager = new DbJournalManager(); MockServerConfigurationService serverConfigurationService = new MockServerConfigurationService(); MergeUpdateManager mergeUpdateManager = new MergeUpdateManager(); TransactionSequenceImpl sequence = new TransactionSequenceImpl(); SharedFilesystemJournalStorage sharedFilesystemJournalStorage = new SharedFilesystemJournalStorage(); JournaledFSIndexStorageUpdateTransactionListener journaledFSIndexStorageUpdateTransactionListener = new JournaledFSIndexStorageUpdateTransactionListener(); sequence.setDatasource(tds.getDataSource()); sequence.setName("TransactionalIndexWorkerTest"); journaledFSIndexStorageUpdateTransactionListener .setJournaledIndex(journaledFSIndexStorage); journaledFSIndexStorageUpdateTransactionListener .setJournalManager(journalManager); journaledFSIndexStorageUpdateTransactionListener .setJournalStorage(sharedFilesystemJournalStorage); sharedFilesystemJournalStorage.setJournalSettings(journalSettings); sequence.setDatasource(tds.getDataSource()); mergeUpdateManager .addTransactionListener(journaledFSIndexStorageUpdateTransactionListener); mergeUpdateManager.setSequence(sequence); journalManager.setDatasource(tds.getDataSource()); journalManager.setServerConfigurationService(serverConfigurationService); journaledFSIndexStorage.setAnalyzerFactory(analyzerFactory); journaledFSIndexStorage.setDatasource(tds.getDataSource()); journaledFSIndexStorage.setJournalManager(journalManager); journaledFSIndexStorage.setRecoverCorruptedIndex(false); journaledFSIndexStorage.setJournalSettings(journalSettings); journaledFSIndexStorage.setServerConfigurationService(serverConfigurationService); mu.setJournaledObject(journaledFSIndexStorage); optimizableIndex = new OptimizableIndexImpl(); optimizableIndex.setJournaledIndex(journaledFSIndexStorage); OptimizeTransactionListenerImpl otli = new OptimizeTransactionListenerImpl(); otli.setJournalSettings(journalSettings); otli.setOptimizableIndex(optimizableIndex); OptimizeIndexManager oum = new OptimizeIndexManager(); oum.setAnalyzerFactory(analyzerFactory); oum.setJournalSettings(journalSettings); oum.addTransactionListener(otli); oum.setSequence(new LocalTransactionSequenceImpl()); oo = new OptimizeIndexOperation(); oo.setJournaledObject(journaledFSIndexStorage); oo.setOptimizeUpdateManager(oum); mu.setMergeUpdateManager(mergeUpdateManager); mu.setOptimizeUpdateManager(oum); journaledFSIndexStorage.addIndexListener(new IndexListenerCloser()); // index updater JournalManagerUpdateTransaction journalManagerUpdateTransaction = new JournalManagerUpdateTransaction(); MockSearchIndexBuilder mockSearchIndexBuilder = new MockSearchIndexBuilder(); TransactionIndexManagerImpl transactionIndexManager = new TransactionIndexManagerImpl(); SearchBuilderQueueManager searchBuilderQueueManager = new SearchBuilderQueueManager(); TransactionSequenceImpl lockSequenceImpl = new TransactionSequenceImpl(); lockSequenceImpl.setDatasource(tds.getDataSource()); lockSequenceImpl.setName("queueManagerLock"); lockSequenceImpl.setMinValue(2000); lockSequenceImpl.setMaxValue(10000000); lockSequenceImpl.init(); searchBuilderQueueManager.setSequence(lockSequenceImpl); transactionIndexManager.setAnalyzerFactory(new StandardAnalyzerFactory()); transactionIndexManager.setJournalSettings(journalSettings); transactionIndexManager.setSequence(sequence); journalManagerUpdateTransaction.setJournalManager(journalManager); JournalStorageUpdateTransactionListener journalStorageUpdateTransactionListener = new JournalStorageUpdateTransactionListener(); journalStorageUpdateTransactionListener .setJournalStorage(sharedFilesystemJournalStorage); searchBuilderQueueManager.setDatasource(tds.getDataSource()); searchBuilderQueueManager.setSearchIndexBuilder(mockSearchIndexBuilder); transactionIndexManager.addTransactionListener(searchBuilderQueueManager); transactionIndexManager .addTransactionListener(journalStorageUpdateTransactionListener); transactionIndexManager.addTransactionListener(journalManagerUpdateTransaction); MockSearchService searchService = new MockSearchService(); searchService.setDatasource(tds.getDataSource()); searchService.setServerConfigurationService(new MockServerConfigurationService()); tiw = new TransactionalIndexWorker(); tiw.setSearchIndexBuilder(mockSearchIndexBuilder); tiw.setServerConfigurationService(serverConfigurationService); tiw.setTransactionIndexManager(transactionIndexManager); tiw.setSearchService(searchService); tiw.setThreadLocalManager(threadLocalManager); sequence.init(); searchBuilderQueueManager.init(); transactionIndexManager.init(); journalManager.init(); mu.init(); journaledFSIndexStorage.init(); tiw.init(); oo.init(); } /* * (non-Javadoc) * * @see junit.framework.TestCase#tearDown() */ protected void tearDown() throws Exception { super.tearDown(); } /** * Test method for * {@link org.sakaiproject.search.optimize.impl.OptimizeIndexOperation#runOnce()}. * * @throws Exception */ public final void testRunOnce() throws Exception { List<SearchBuilderItem> items = tds.populateDocuments(1000,"optimizeop"); int n = 0; int i = 0; while ((n = tiw.process(10)) > 0) { assertEquals( "Runaway Cyclic Indexing, should have completed processing by now ", true, i < 500); i++; } log.info("Indexing Complete at " + i + " with " + n); mu.runOnce(); assertEquals( "Index is not correct after a merge update operationadd items only ", 0, tds.checkIndexContents(items, journaledFSIndexStorage.getIndexSearcher())); items = tds.deleteSomeItems(items); while ((n = tiw.process(10)) > 0) { assertEquals( "Runaway Cyclic Indexing, should have completed processing by now ", true, i < 500); i++; } log.info("Indexing Complete at " + i + " with " + n); mu.runOnce(); // need to populate the index with some data first. assertEquals( "Index is not correct after a merge update operation with deleted items, delete processing is not working ", 0, tds.checkIndexContents(items, journaledFSIndexStorage .getIndexSearcher())); File[] optSegments = optimizableIndex.getOptimizableSegments(); for (File f : optSegments) { log.info("Segment at " + f.getPath()); } IndexSearcher s = journaledFSIndexStorage.getIndexSearcher(); log.info("Optimizing "); // Now perform an optimize operation oo.runOnce(); log.info("Done Optimizing "); optSegments = optimizableIndex.getOptimizableSegments(); log.info("Number of Temp Segments is " + optSegments.length); for (File f : optSegments) { log.info("Segment at " + f.getPath()); } log.info("Current Index is " + s); s = journaledFSIndexStorage.getIndexSearcher(); log.info("Reopening Index " + s); int errors = tds.checkIndexContents(items, s); assertEquals( "Check on index contents failed, Merge Index Failure on Local Node, please check logs ", 0, errors); // Generate a second set and do the process again List<SearchBuilderItem> items2 = tds.populateDocuments(1000,"set2"); int n2 = 0; int i2 = 0; while ((n2 = tiw.process(10)) > 0) { assertEquals( "Runaway Cyclic Indexing, should have completed processing by now ", true, i2 < 500); i2++; } log.info("Indexing Complete at " + i2 + " with " + n2); mu.runOnce(); assertEquals( "Index is not correct after a merge update operationadd items only ", 0, tds.checkIndexContents(items, journaledFSIndexStorage.getIndexSearcher())); assertEquals( "Index is not correct after a merge update operationadd items only ", 0, tds.checkIndexContents(items2, journaledFSIndexStorage.getIndexSearcher())); items2 = tds.deleteSomeItems(items2); while ((n2 = tiw.process(10)) > 0) { assertEquals( "Runaway Cyclic Indexing, should have completed processing by now ", true, i2 < 500); i2++; } log.info("Indexing Complete at " + i2 + " with " + n2); mu.runOnce(); // need to populate the index with some data first. assertEquals( "Index is not correct after a merge update operation with deleted items, delete processing is not working ", 0, tds.checkIndexContents(items, journaledFSIndexStorage .getIndexSearcher())); assertEquals( "Index is not correct after a merge update operation with deleted items, delete processing is not working ", 0, tds.checkIndexContents(items2, journaledFSIndexStorage .getIndexSearcher())); File[] optSegments2 = optimizableIndex.getOptimizableSegments(); for (File f : optSegments2) { log.info("Segment at " + f.getPath()); } IndexSearcher s2 = journaledFSIndexStorage.getIndexSearcher(); log.info("Optimizing "); // Now perform an optimize operation oo.runOnce(); log.info("Done Optimizing "); optSegments2 = optimizableIndex.getOptimizableSegments(); log.info("Number of Temp Segments is " + optSegments2.length); for (File f : optSegments2) { log.info("Segment at " + f.getPath()); } log.info("Current Index is " + s2); s2 = journaledFSIndexStorage.getIndexSearcher(); log.info("Reopening Index " + s2); int errors2 = tds.checkIndexContents(items, s2); errors2 += tds.checkIndexContents(items2, s2); log.info("Local "); FileUtils.listDirectory(new File(journalSettings.getLocalIndexBase())); log.info("shared "); FileUtils.listDirectory(new File(journalSettings.getSharedJournalBase())); s.close(); s2.close(); assertEquals( "Check on index contents failed, Merge Index Failure on Local Node, please check logs ", 0, errors2); } }