org.xcmis.search.lucene.index.LocalStorageIndexDataManager.java Source code

Java tutorial

Introduction

Here is the source code for org.xcmis.search.lucene.index.LocalStorageIndexDataManager.java

Source

/*
 * Copyright (C) 2009 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.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.MultiReader;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.xcmis.search.Startable;
import org.xcmis.search.config.IndexConfiguration;
import org.xcmis.search.config.IndexConfigurationException;
import org.xcmis.search.content.IndexModificationException;
import org.xcmis.search.lucene.index.merge.IndexAggregator;
import org.xcmis.spi.utils.Logger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * Created by The eXo Platform SAS.
 * 
 * @author <a href="mailto:Sergey.Kabashnyuk@gmail.com">Sergey Kabashnyuk</a>
 * @version $Id: LocalStorageIndexDataManager.java 2 2010-02-04 17:21:49Z andrew00x $
 */
public class LocalStorageIndexDataManager implements LuceneIndexDataManager, IndexAggregator, Startable {
    /**
      * 
      */
    private List<PersistedIndex> chains;

    /**
      * 
      */
    private final PersistentIndexDataKeeperFactory indexFactory;

    /**
     * Class logger.
     */
    private static final Logger LOG = Logger.getLogger(LocalStorageIndexDataManager.class);

    private final IndexConfiguration indexConfuguration;

    /**
     * @throws IndexConfigurationException
     * @throws IndexException
     * @throws IndexConfigurationException
     */
    public LocalStorageIndexDataManager(final IndexConfiguration indexConfuguration)
            throws IndexException, IndexConfigurationException {
        super();
        this.indexConfuguration = indexConfuguration;

        indexFactory = new PersistentIndexDataKeeperFactory(indexConfuguration);

    }

    public IndexTransactionModificationReport aggregate(final Collection<LuceneIndexDataManager> indexes)
            throws IndexException, IndexTransactionException {
        if (chains.size() == 0) {
            chains.add((PersistedIndex) indexFactory.merge(indexes));
        } else {
            IndexWriter writer = null;
            try {
                final PersistedIndex index = chains.get(0);

                writer = new IndexWriter(index.getDirectory(), new StandardAnalyzer(), MaxFieldLength.UNLIMITED);
                final List<Directory> dirs = new ArrayList<Directory>();
                for (final LuceneIndexDataManager luceneIndexDataManager : indexes) {
                    // TODO remove get reader
                    luceneIndexDataManager.getIndexReader();
                    dirs.add(luceneIndexDataManager.getDirectory());
                }
                final Directory[] dirsToMerge = new Directory[dirs.size()];
                writer.addIndexesNoOptimize(dirs.toArray(dirsToMerge));
                writer.optimize();
            } catch (final CorruptIndexException e) {
                throw new IndexException(e.getLocalizedMessage(), e);
            } catch (final LockObtainFailedException e) {
                throw new IndexException(e.getLocalizedMessage(), e);
            } catch (final IOException e) {
                throw new IndexException(e.getLocalizedMessage(), e);
            } finally {
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (CorruptIndexException e) {
                        throw new IndexException(e.getLocalizedMessage(), e);
                    } catch (IOException e) {
                        throw new IndexException(e.getLocalizedMessage(), e);
                    }
                }

            }
        }
        return null;
    }

    public Directory getDirectory() throws IndexException {
        if (chains.size() != 0) {
            return chains.get(0).getDirectory();
        }
        return null;
    }

    public long getDirectorySize(final boolean includeInherited) {
        return 0;
    }

    public Document getDocument(final String uuid) throws IndexException {
        Document doc = null;
        synchronized (chains) {
            for (int i = 0; i < chains.size(); i++) {
                doc = chains.get(i).getDocument(uuid);
                if (doc != null) {
                    break;
                }
            }
        }
        return doc;
    }

    public synchronized long getDocumentCount() {
        long result = 0;
        for (final PersistedIndex index : chains) {
            result += index.getDocumentCount();
        }
        return result;
    }

    public IndexReader getIndexReader() throws IndexException {
        IndexReader result = null;
        if (chains.size() > 0) {
            synchronized (chains) {
                if (chains.size() > 0) {
                    final List<IndexReader> readers = new ArrayList<IndexReader>(chains.size());
                    final Iterator<PersistedIndex> it = chains.iterator();

                    while (it.hasNext()) {
                        final LuceneIndexDataManager chain = it.next();

                        final IndexReader indexReader = chain.getIndexReader();
                        if (indexReader != null) {
                            readers.add(indexReader);
                        }

                    }
                    if (result != null) {
                        readers.add(result);
                    }
                    if (readers.size() > 1) {
                        final IndexReader[] indexReaders = new IndexReader[readers.size()];
                        result = new MultiReader(readers.toArray(indexReaders));
                    } else if (readers.size() == 1) {
                        result = readers.get(0);
                    } else {
                        throw new RuntimeException("No readers found");
                    }
                }
            }
            if (result == null) {
                throw new RuntimeException("No readers found");
            }
        }
        return result;
    }

    public long getLastModifedTime() {
        return 0;
    }

    public boolean isStarted() {
        return false;
    }

    public boolean isStoped() {
        return false;
    }

    public IndexTransactionModificationReport save(IndexTransaction<Document> changes)
            throws IndexException, IndexTransactionException {
        // notify all chains about changes
        synchronized (chains) {

            if (changes.hasModifacationsDocuments()) {

                // reverse order
                changes = processModifed(changes);

                if (changes.getRemovedDocuments().size() > 0) {
                    throw new IndexModificationException(
                            "Unable to remove item's with id's " + changes.getRemovedDocuments() + " from index");
                }

            }
            // take care about added modification
            processAdded(changes);

        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    public void start() {
        try {
            chains = indexFactory.init();
        } catch (final IndexException e) {
            throw new RuntimeException(e.getLocalizedMessage(), e);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void stop() {
        for (final PersistedIndex index : chains) {
            try {
                index.getDirectory().close();
            } catch (final IndexException e) {
                LOG.error(e.getMessage(), e);
            } catch (final IOException e) {
                LOG.error(e.getMessage(), e);
            }
        }

    }

    /**
     * Process add
     * 
     * @param changes
     * @throws IndexException
     * @throws IndexTransactionException
     */
    private void processAdded(final IndexTransaction<Document> changes)
            throws IndexException, IndexTransactionException {
        if (changes.getAddedDocuments().size() > 0) {
            synchronized (chains) {
                if (chains.size() == 0) {
                    final LuceneIndexDataManager indexDataKeeper = indexFactory.createNewIndexDataKeeper(changes);
                    indexDataKeeper.start();
                    chains.add((PersistedIndex) indexDataKeeper);
                } else {
                    final LuceneIndexDataManager indexDataKeeper = chains.get(0);
                    indexDataKeeper.save(changes);
                }

            }
        }
    }

    /**
     * Process remove and update
     * 
     * @param changes
     * @return
     * @throws IndexException
     * @throws IndexTransactionException
     */
    private IndexTransaction<Document> processModifed(IndexTransaction<Document> changes)
            throws IndexException, IndexTransactionException {
        synchronized (chains) {

            for (final Iterator<PersistedIndex> it = chains.iterator(); it.hasNext();) {
                final LuceneIndexDataManager chain = it.next();
                final IndexTransactionModificationReport report = chain.save(changes);

                if (report.isModifed()) {
                    changes = changes.apply(report);
                    if (chain.getDocumentCount() == 0) {
                        indexFactory.dispose(chain);
                        it.remove();
                    }
                }
                if (!changes.hasModifacationsDocuments()) {
                    break;
                }

            }
        }
        return changes;
    }
}