/**
* Copyright (C) 2010 eXo Platform SAS.
*
* 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.xcmis.search.lucene.index;
import org.apache.lucene.document.Document;
import org.xcmis.search.config.IndexConfiguration;
import org.xcmis.search.config.IndexConfigurationException;
import org.xcmis.search.lucene.IndexRecoveryTool;
import org.xcmis.spi.utils.Logger;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by The eXo Platform SAS.
*
* @author <a href="mailto:Sergey.Kabashnyuk@gmail.com">Sergey Kabashnyuk</a>
* @version $Id: StartableJcrIndexingService.java 2 2010-02-04 17:21:49Z
* andrew00x $
*/
public class StartableIndexingService extends LuceneIndexingService
{
/**
* File name. If this file exists, that means reindex was interrupted, so
* need new reindex.
*/
private static final String REINDEX_RUN = "reindexProcessing";
/** ChangesLog Buffer (used for saves before start). */
private List<IndexTransaction<Document>> changesLogBuffer = new ArrayList<IndexTransaction<Document>>();
/** The index dir. */
private final File indexDir;
/** The index restore service. */
private final IndexRecoveryTool indexRecoveryTool;
/** Is started flag. */
private boolean isStarted = false;
/** Class logger. */
private static final Logger LOG = Logger.getLogger(StartableIndexingService.class);
/**
* @param configuration
* @throws IndexConfigurationException
* @throws IndexException
*/
public StartableIndexingService(IndexConfiguration configuration, IndexRecoveryTool indexRecoveryTool)
throws IndexConfigurationException, IndexException
{
super(configuration, indexRecoveryTool);
this.indexRecoveryTool = indexRecoveryTool;
this.indexDir = new File(configuration.getIndexDir());
if (!indexDir.exists() && !indexDir.mkdirs())
{
throw new IndexException("Fail to create index directory : " + indexDir.getAbsolutePath());
}
}
/**
* @see org.xcmis.search.lucene.index.TransactionableIndexDataManager#save(org.xcmis.search.lucene.index.IndexTransaction)
*/
@Override
public IndexTransactionModificationReport save(IndexTransaction<Document> changes) throws IndexException,
IndexTransactionException
{
if (isStarted)
{
return super.save(changes);
}
changesLogBuffer.add(changes);
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void start()
{
super.start();
// save buffered logs
isStarted = true;
try
{
for (final IndexTransaction<Document> bufferedChangesLog : changesLogBuffer)
{
super.save(bufferedChangesLog);
}
if (needIndexRestore())
{
// need restore index;
try
{
restoreIndex();
}
catch (final IOException e)
{
LOG.error("Restore IOException occurs " + e.getMessage(), e);
}
}
}
catch (IndexException e)
{
LOG.error(e.getMessage(), e);
}
changesLogBuffer.clear();
changesLogBuffer = null;
}
/**
* {@inheritDoc}
*/
@Override
public void stop()
{
super.stop();
}
/**
* Do we need restore index.
*
* @return <code>true</code> if index not exist or restore was interrupted.
* @throws IndexException
* if index read exception occurs.
*/
private boolean needIndexRestore() throws IndexException
{
if (getDocumentCount() == 0)
{
return true;
}
final File flag = new File(indexDir, StartableIndexingService.REINDEX_RUN);
return flag.exists();
}
/**
* Restore Index from full repository content.
*
* @throws IOException
* if reindex flag file was not created or was'nt removed.
* @throws IndexException
*/
private void restoreIndex() throws IOException, IndexException
{
if (LOG.isDebugEnabled())
{
LOG.info("Restore index started.");
}
final File flag = new File(indexDir, StartableIndexingService.REINDEX_RUN);
if (!flag.exists())
{
if (!flag.createNewFile())
{
throw new IOException("Reindex flag file was not created.");
}
}
// clean persisted index
softCleanIndex();
indexRecoveryTool.recoverAll();
if (!flag.delete())
{
throw new IOException("Can't remove reindex flag.");
}
// clean changesLogBuffer
// all states in changesLogBuffer already indexed by IndexRestoreVisitor,
// so it contains duplicated data
changesLogBuffer.clear();
if (LOG.isDebugEnabled())
{
LOG.info("Restore index finished.");
}
}
}