FileDocCategorySizeDatePackage
StorageBuffer.javaAPI DocApache Lucene 2.1.011562Wed Feb 14 10:46:04 GMT 2007org.apache.lucene.gdata.storage.lucenestorage

StorageBuffer

public class StorageBuffer extends Object
The StorageBuffer is used to buffer incoming updates, deletes and inserts to the storage. The storage uses an lucene index to store the enries. As modifying the index all the time an altering request comes in is not efficent. The entries will be added to the buffer to be available for incoming storage queries. If the loadfactor for the {@link org.apache.lucene.gdata.storage.lucenestorage.StorageModifier} is reached the modifier will perform a batch update on the index. Each entry will be associated with a feed id inside a associative datastructure to return a requested entry efficiently.

This implementation uses {@link java.util.concurrent.locks.ReadWriteLock}. The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.

The entry and feed ID's must not be a composite key. The entry and feed ID must be unique.

see
java.util.concurrent.locks.ReentrantReadWriteLock
see
org.apache.lucene.gdata.storage.lucenestorage.StorageModifier
see
org.apache.lucene.gdata.storage.lucenestorage.StorageCoreController
author
Simon Willnauer

Fields Summary
private static final Log
LOG
private final Map
bufferMap
private final Map
modifiyMap
private final List
excludeList
private final ReadWriteLock
lock
private final Lock
readLock
private final Lock
writeLock
private final int
bufferSize
protected static final int
DEFAULT_BUFFER_COUNT
Constructors Summary
protected StorageBuffer(int expectedBufferCount)
Constructs a new StorageBuffer.

The expectedBufferCount sould be higher than the maximum of entries added to the buffer, resizing the buffer is very efficient. For detailed infomation {@link HashMap} as this is used inside the buffer

param
expectedBufferCount - the expected size of the buffer


                                                                     
        
        this.bufferSize = expectedBufferCount < DEFAULT_BUFFER_COUNT ? DEFAULT_BUFFER_COUNT
                : expectedBufferCount;
        this.bufferMap = new HashMap<String, Map<String, StorageEntryWrapper>>(
                this.bufferSize);
        this.excludeList = new ArrayList<String>(this.bufferSize);
        this.modifiyMap = new HashMap<String, Long>(this.bufferSize);
    
Methods Summary
public voidaddDeleted(java.lang.String entryId, java.lang.String feedId)
Adds a deleted entry to the buffer.

param
entryId - the deleted entry id
param
feedId - the feed of the entry

        this.writeLock.lock();
        try {
            Map<String, StorageEntryWrapper> tempMap = this.bufferMap
                    .get(feedId);
            if (tempMap != null) {
                tempMap.remove(entryId);
                this.addLastModified(feedId, new Long(System
                        .currentTimeMillis()));
            }
            /*
             * add to exclude from searches
             */
            if (!this.excludeList.contains(entryId))
                this.excludeList.add(entryId);
        } finally {

            this.writeLock.unlock();

        }

    
public voidaddEntry(StorageEntryWrapper wrapper)
Adds a {@link StorageEntryWrapper} to the buffer. If a wrapper representing the same entry are already in the buffer the wrapper will be replaced.

This method does ignore already delted entries. This should before the entry is added to the buffer.

param
wrapper - the wrapper to buffer

        this.writeLock.lock();
        try {
            if (LOG.isInfoEnabled())
                LOG.info(" Buffering wrapper - " + wrapper.getOperation()
                        + " ID: " + wrapper.getEntryId() + " FeedID: "
                        + wrapper.getFeedId());
            if (wrapper.getOperation().equals(StorageOperation.DELETE))
                return;
            String feedId = wrapper.getFeedId();
            if (this.bufferMap.containsKey(feedId))
                this.bufferMap.get(feedId).put(wrapper.getEntryId(), wrapper);
            else {
                Map<String, StorageEntryWrapper> newFeedMap = new HashMap<String, StorageEntryWrapper>(
                        20);
                newFeedMap.put(wrapper.getEntryId(), wrapper);
                this.bufferMap.put(feedId, newFeedMap);

            }
            addLastModified(wrapper.getFeedId(), wrapper.getTimestamp());
            /*
             * add to exclude from searches doc will be available via the buffer
             * if the entry is not already in the buffer
             */
            if (!this.excludeList.contains(wrapper.getEntryId()))
                this.excludeList.add(wrapper.getEntryId());
        } finally {
            this.writeLock.unlock();
        }
    
private voidaddLastModified(java.lang.String feedId, java.lang.Long timestamp)

        this.writeLock.lock();
        try {
            if (this.modifiyMap.containsKey(feedId))
                this.modifiyMap.remove(feedId);
            this.modifiyMap.put(feedId, timestamp);
        } finally {
            this.writeLock.unlock();
        }

    
private voidclearBuffer()


        this.bufferMap.clear();
        this.excludeList.clear();
        this.modifiyMap.clear();

    
public voidclose()
clears the buffer -

        this.writeLock.lock();
        try {
            clearBuffer();
        } finally {
            this.writeLock.unlock();
        }

    
public intgetBufferSize()

return
Returns the bufferSize.

        return this.bufferSize;
    
public StorageEntryWrappergetEntry(java.lang.String entryId, java.lang.String feedId)
Returns an entry for the given entry id in the feed context spezified by the feed id;

param
entryId - the id of the entry to return
param
feedId - the feed containing the entry
return
- the entry or null if the corresponding entry is not in the buffer.

        this.readLock.lock();
        try {

            if (this.bufferMap.containsKey(feedId))
                return this.bufferMap.get(feedId).get(entryId);
            return null;

        } finally {
            this.readLock.unlock();
        }
    
public java.lang.String[]getExculdList()
The buffer contains updated and delete entries. These entries are already available in the lucene index but should not be found during search.

This list contains all entries should not be found by the index searcher. This method creates a copy of the current list to prevent concurrent modification exceptions while iteration over the collection.

see
ModifiedEntryFilter
return
- a String array of entries to be omitted from a lucene index search

        this.readLock.lock();
        try {
            return this.excludeList
                    .toArray(new String[this.excludeList.size()]);
        } finally {
            this.readLock.unlock();
        }
    
protected java.lang.LonggetFeedLastModified(java.lang.String feedId)
the timestamp of the last modification for the given feed id

param
feedId - feed id
return
timestamp

        this.readLock.lock();
        try {
            return this.modifiyMap.get(feedId);
        } finally {
            this.readLock.unlock();
        }
    
protected java.util.SetgetLastModified()

        return this.modifiyMap.entrySet();
    
public java.util.ListgetSortedEntries(java.lang.String feedId)
Returns all entries for the given feed id sorted by the update timestamp desc.

param
feedId - the feed id
return
a {@link List} of all {@link StorageEntryWrapper} object buffered in this buffer or an empty list if not entry has been buffered for the given feed

        this.readLock.lock();
        try {
            if (!this.bufferMap.containsKey(feedId))
                return null;
            Map<String, StorageEntryWrapper> tempMap = this.bufferMap
                    .get(feedId);
            if (tempMap == null)
                return null;
            Collection<StorageEntryWrapper> col = tempMap.values();
            List<StorageEntryWrapper> returnList = new ArrayList<StorageEntryWrapper>(
                    col);
            Collections.sort(returnList);
            return returnList;

        } finally {
            this.readLock.unlock();
        }