Package com.browseengine.bobo.geosearch.solo.index.impl

Source Code of com.browseengine.bobo.geosearch.solo.index.impl.GeoOnlyIndexer

package com.browseengine.bobo.geosearch.solo.index.impl;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.lucene.store.Directory;
import org.apache.lucene.store.Lock;
import org.apache.lucene.store.LockObtainFailedException;

import com.browseengine.bobo.geosearch.GeoVersion;
import com.browseengine.bobo.geosearch.IFieldNameFilterConverter;
import com.browseengine.bobo.geosearch.IGeoConverter;
import com.browseengine.bobo.geosearch.bo.GeoSearchConfig;
import com.browseengine.bobo.geosearch.bo.GeoSegmentInfo;
import com.browseengine.bobo.geosearch.index.bo.GeoCoordinate;
import com.browseengine.bobo.geosearch.index.bo.GeoCoordinateField;
import com.browseengine.bobo.geosearch.index.impl.GeoSegmentReader;
import com.browseengine.bobo.geosearch.index.impl.GeoSegmentWriter;
import com.browseengine.bobo.geosearch.solo.bo.IDGeoRecord;
import com.browseengine.bobo.geosearch.solo.bo.IndexTooLargeException;
import com.browseengine.bobo.geosearch.solo.impl.IDGeoRecordComparator;
import com.browseengine.bobo.geosearch.solo.impl.IDGeoRecordSerializer;

/**
*
* This class is NOT currently thread-safe. 
*
* @author gcooney
*/
public class GeoOnlyIndexer {
    GeoSearchConfig config;
    Directory directory;
    String indexName;
    Lock lock;
   
    IDGeoRecordComparator geoComparator = new IDGeoRecordComparator();
    IDGeoRecordSerializer geoRecordSerializer = new IDGeoRecordSerializer();
    TreeSet<IDGeoRecord> inMemoryIndex =  new TreeSet<IDGeoRecord>(new IDGeoRecordComparator());
    List<IDGeoRecord> newRecords = new LinkedList<IDGeoRecord>();
    Set<byte[]> removedRecords = new HashSet<byte[]>();

    public GeoOnlyIndexer(GeoSearchConfig config, Directory directory, String indexName) throws IOException {
        this.config = config;
        this.directory = directory;
        this.indexName = indexName;
       
        lock = directory.makeLock(indexName);
        if (!lock.obtain()) {
            throw new LockObtainFailedException("Index locked for write: " + indexName);
        }
    }
   
    /**
     * Adds a record to the geo only index
     * @param uuid
     * @param field
     */
    public void index(byte[] uuid, GeoCoordinateField field) {
        if (uuid.length != config.getBytesForId()) {
            throw new IllegalArgumentException("invalid uuid length: " + uuid.length
                    + ".  Expected uuid to be of length "
                    + config.getBytesForId() + ".");
        }
       
        IGeoConverter converter = config.getGeoConverter();
       
        GeoCoordinate geoCoordinate = field.getGeoCoordinate();
        IDGeoRecord geoRecord = converter.toIDGeoRecord(
                geoCoordinate.getLatitude(), geoCoordinate.getLongitude(), uuid);
        newRecords.add(geoRecord);
    }

    /**
     * Deletes all GeoRecords in the index that have a matching uuid.  Note that this
     * does not delete any records indexed but not yet flushed. 
     * @param uuid
     */
    public void delete(byte[] uuid) {
        removedRecords.add(uuid);
    }
   
    /**
     * Flushes any requested index updates to directory
     *
     * @throws IOException
     * @throws IndexTooLargeException If the size of the index is larger than the maximum size
     */
    public void flush() throws IOException, IndexTooLargeException {
        loadCurrentIndex();
       
        for (IDGeoRecord newRecord: newRecords) {
            inMemoryIndex.add(newRecord);
        }
       
        if (inMemoryIndex.size() > config.getMaxIndexSize()) {
            throw new IndexTooLargeException(indexName, inMemoryIndex.size(),
                    config.getMaxIndexSize());
        }
       
        flushInMemoryIndex();
    }

    /**
     * Closes this geoIndexer and releases any locks held
     * @throws IOException
     */
    public void close() throws IOException {
        lock.release();
    }
   
    private void flushInMemoryIndex() throws IOException {
        GeoSegmentWriter<IDGeoRecord> segmentWriter = getGeoSegmentWriter(inMemoryIndex);
       
        segmentWriter.close();
    }
   
    GeoSegmentWriter<IDGeoRecord> getGeoSegmentWriter(Set<IDGeoRecord> dataToFlush) throws IOException {
        String fileName = indexName + "." + config.getGeoFileExtension();
       
        return new GeoSegmentWriter<IDGeoRecord>(
                dataToFlush, directory, fileName,
                buildGeoSegmentInfo(indexName), geoRecordSerializer);
    }

    private void loadCurrentIndex() throws IOException {
        inMemoryIndex.clear();
       
        String fileName = indexName + "." + config.getGeoFileExtension();
        if (directory.fileExists(fileName)) {
            GeoSegmentReader<IDGeoRecord> currentIndex = getGeoSegmentReader();
            try {
                Iterator<IDGeoRecord> currentIndexIterator =
                    currentIndex.getIterator(IDGeoRecord.MIN_VALID_GEORECORD, IDGeoRecord.MAX_VALID_GEORECORD);
               
                while (currentIndexIterator.hasNext()) {
                    IDGeoRecord geoRecord = currentIndexIterator.next();
                   
                    if (!isDeleted(geoRecord.id)) {
                        inMemoryIndex.add(geoRecord);
                    }
                }
            } finally {
                currentIndex.close();
            }
        }
    }
   
    private boolean isDeleted(byte[] uuid) {
        for (byte[] deletedUUID : removedRecords) {
            if (Arrays.equals(uuid, deletedUUID)) {
                return true;
            }
        }
       
        return false;
    }
   
    GeoSegmentReader<IDGeoRecord> getGeoSegmentReader() throws IOException {
        String fileName = indexName + "." + config.getGeoFileExtension();
       
        return new GeoSegmentReader<IDGeoRecord>(
                directory, fileName, -1,
                config.getBufferSizePerGeoSegmentReader(), geoRecordSerializer,
                geoComparator);
    }
   
    private GeoSegmentInfo buildGeoSegmentInfo(String segmentName) throws IOException {
        IGeoConverter converter = config.getGeoConverter();
       
        //write version
        GeoSegmentInfo info = new GeoSegmentInfo();
        info.setGeoVersion(GeoVersion.CURRENT_GEOONLY_VERSION);

        info.setSegmentName(segmentName);
       
        info.setBytesPerRecord(IDGeoRecordSerializer.INTERLACE_BYTES + config.getBytesForId());
       
        //now write field -> filterByte mapping info
        IFieldNameFilterConverter fieldNameFilterConverter = converter.makeFieldNameFilterConverter();
        if (fieldNameFilterConverter != null) {
            info.setFieldNameFilterConverter(fieldNameFilterConverter);
        }
       
        return info;
    }
}
TOP

Related Classes of com.browseengine.bobo.geosearch.solo.index.impl.GeoOnlyIndexer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.