org.apache.lucene.index.LuceneSegmentsMerger.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.lucene.index.LuceneSegmentsMerger.java

Source

/*
 * Copyright 2004-2006 the original author or authors.
 * 
 * Licensed 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 org.apache.lucene.index;

import java.io.IOException;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.Lock;
import org.compass.core.lucene.engine.LuceneSearchEngineFactory;
import org.compass.core.lucene.engine.LuceneSettings;

/**
 * A helper class that can merge segments from a certain segment number till the
 * last.
 *
 * @author kimchy
 */
public class LuceneSegmentsMerger {

    private static final Log log = LogFactory.getLog(LuceneSegmentsMerger.class);

    private Directory directory; // where this index resides

    //private Analyzer analyzer; // how to analyze text

    //private Similarity similarity = Similarity.getDefault(); // how to

    private SegmentInfos segmentInfos = new SegmentInfos(); // the segments

    private Lock writeLock;

    private String newSegmentName;

    private Vector segmentsToDelete = new Vector();

    private boolean closeDir;

    private LuceneSettings luceneSettings;

    private SegmentInfos rollbackSegmentInfos; // segmentInfos we will fallback to if the commit fails

    private IndexFileDeleter deleter;

    public LuceneSegmentsMerger(Directory dir, boolean closeDir, LuceneSearchEngineFactory searchEngineFactory)
            throws IOException {
        this.closeDir = closeDir;
        this.directory = dir;
        this.luceneSettings = searchEngineFactory.getLuceneSettings();
        //this.analyzer = a;
        Lock writeLock = directory.makeLock(IndexWriter.WRITE_LOCK_NAME);
        if (!writeLock.obtain(luceneSettings.getTransactionLockTimout())) { // obtain write lock
            throw new IOException("Lock obtain failed: " + writeLock);
        }
        this.writeLock = writeLock; // save it
        segmentInfos.read(directory);
        rollbackSegmentInfos = (SegmentInfos) segmentInfos.clone();
        deleter = new IndexFileDeleter(directory,
                searchEngineFactory.getIndexDeletionPolicyManager().createIndexDeletionPolicy(dir), segmentInfos,
                null);
    }

    public void mergeFromSegment(int fromSegment) throws IOException {
        newSegmentName = newSegmentName();
        SegmentMerger merger = new SegmentMerger(directory, newSegmentName);

        for (int i = fromSegment; i < segmentInfos.size(); i++) {
            SegmentInfo si = segmentInfos.info(i);
            // TODO: expose this as a configurable parmeter (same as in TransReader)
            IndexReader reader = SegmentReader.get(si, 4096);
            merger.add(reader);
            segmentsToDelete.addElement(reader); // queue segment for deletion
        }
        int mergedDocCount = merger.merge();

        merger.closeReaders();
        segmentInfos.setSize(fromSegment); // pop old infos & add new
        SegmentInfo newSegmentInfo = new SegmentInfo(newSegmentName, mergedDocCount, directory, false, true);
        segmentInfos.addElement(newSegmentInfo);
        deleter.checkpoint(segmentInfos, false);
        if (luceneSettings.isUseCompoundFile()) {
            newSegmentInfo.setUseCompoundFile(true);
            merger.createCompoundFile(newSegmentName + ".cfs");
            deleter.checkpoint(segmentInfos, false);
        }
    }

    public void commit() throws IOException {
        segmentInfos.write(directory); // commit before deleting
        deleter.checkpoint(segmentInfos, true);
    }

    public void rollback() throws IOException {
        segmentInfos.clear();
        segmentInfos.addAll(rollbackSegmentInfos);
        rollbackSegmentInfos = null;

        // Ask deleter to locate unreferenced files we had
        // created & remove them:
        deleter.checkpoint(segmentInfos, false);

        deleter.refresh();

    }

    public void close() throws IOException {
        if (closeDir) {
            try {
                directory.close();
            } catch (IOException ex) {
                // swallow this one
                log.warn("Failed to close directory, ignoring", ex);
            }
            directory = null;
        }
        if (writeLock != null) {
            writeLock.release();
            writeLock = null;
        }
    }

    private final synchronized String newSegmentName() {
        return "_" + Integer.toString(segmentInfos.counter++, Character.MAX_RADIX);
    }

    protected void finalize() throws IOException {
        if (writeLock != null) {
            writeLock.release(); // release write lock
            writeLock = null;
        }
    }

}