All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.relation.accesspath.UnsynchronizedUnboundedChunkBuffer Maven / Gradle / Ivy

/*

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/
/*
 * Created on Jun 20, 2008
 */

package com.bigdata.relation.accesspath;

import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

import com.bigdata.striterator.EmptyChunkedIterator;
import com.bigdata.striterator.IChunkedOrderedIterator;
import com.bigdata.striterator.IKeyOrder;

/**
 * An unsynchronized buffer backed by a fixed capacity array that migrates
 * references onto an internal {@link Queue}, which may be drained by an
 * {@link #iterator()}.
 * 

* This implementation is NOT thread-safe. * * @author Bryan Thompson * @version $Id$ * * @see TestUnsynchronizedUnboundedChunkBuffer */ public class UnsynchronizedUnboundedChunkBuffer extends AbstractUnsynchronizedArrayBuffer { /** * The queue onto which chunks are evicted by {@link #overflow()}. */ private final Queue queue; /** * The order of the elements as they are added to the buffer (iff known). */ private final IKeyOrder keyOrder; /** * From the first element visited. * * TODO This is probably no longer required since the component type of the * class is now declared in the constructor. */ private Class chunkClass = null; /** * @param capacity * The capacity of the backing buffer. * @param cls * The component type of the backing array. */ public UnsynchronizedUnboundedChunkBuffer(final int capacity, final Class cls) { this(capacity, cls, null/* filter */, null/* keyOrder */); } /** * @param capacity * The capacity of the backing buffer. * @param cls * The component type of the backing array. * @param filter * Filter to keep elements out of the buffer (optional). * @param keyOrder * The order of the elements in the chunks written onto the * buffer or null iff not known. */ public UnsynchronizedUnboundedChunkBuffer(final int capacity, final Class cls, final IElementFilter filter, final IKeyOrder keyOrder) { super(capacity, cls, filter); this.keyOrder = keyOrder; queue = new LinkedBlockingQueue(/* unbounded capacity */); } /** Add the chunk to the target buffer. */ final protected void handleChunk(final E[] chunk) { if (chunkClass == null) { // Note the Class of the chunk for the snapshot iterator. chunkClass = (Class) chunk.getClass(); } queue.add(chunk); } /** * Iterator drains chunks from a snapshot of the queue (shallow copy). * Chunks are drained in a FIFO basis. The internal buffer is flushed onto a * chunk on the queue before the snapshot is taken so that any buffered * elements will appear in the snapshot. */ public IChunkedOrderedIterator iterator() { overflow(); /* * Snapshot the queue state and wrap as an iterator visiting chunks of * elements. */ synchronized (queue) { if (queue.isEmpty()) { // Note: handles case where chunkClass is not defined. return new EmptyChunkedIterator(keyOrder); } assert chunkClass != null; final Iterator src = Arrays.asList( (E[][]) queue.toArray((E[][]) java.lang.reflect.Array .newInstance(chunkClass, 0/* size */))).iterator(); // wrap with the IChunkedOrderedIterator API. return new ListOfChunksIterator(src, keyOrder); } } /** * Drains chunks from a queue. Chunks are drained in a FIFO basis. * * @author Bryan Thompson * @version $Id$ */ static private class ListOfChunksIterator implements IChunkedOrderedIterator { private final Iterator src; private final IKeyOrder keyOrder; /** * * @param src * Iterator visiting dense chunks. * @param keyOrder * The order of the elements in the buffer or * null iff not known. */ public ListOfChunksIterator(final Iterator src, final IKeyOrder keyOrder) { this.src = src; this.keyOrder = keyOrder; } /** true iff open. */ private boolean open = true; /** Index of the next element to visit in the current chunk. */ private int i = 0; /** * The current chunk or null if another chunk should be read from the * queue. */ private E[] chunk; public boolean hasNext() { if (!open) return false; do { if (chunk != null && i >= chunk.length) { // chunk is exhausted. chunk = null; i = 0; } if (chunk == null) { if(!src.hasNext()) { // nothing left. return false; } // another chunk. chunk = src.next(); i = 0; } } while (chunk.length == 0); // skip empty chunks. return true; } public E next() { if (!hasNext()) throw new NoSuchElementException(); return chunk[i++]; } public E[] nextChunk() { if (!hasNext()) throw new NoSuchElementException(); final E[] ret; if (i == 0) { ret = chunk; } else { /* * Create and return a new chunk[] containing only the elements * remaining in the current iterator. */ final int remaining = chunk.length - i; /* * Dynamically instantiation an array of the same component type * as the objects that we are visiting. */ ret = (E[]) java.lang.reflect.Array.newInstance(chunk.getClass() .getComponentType(), remaining); System.arraycopy(chunk, i, ret, 0, remaining); } // indicate that all statements have been consumed. chunk = null; i = 0; return ret; } /** * @throws UnsupportedOperationException */ public void remove() { throw new UnsupportedOperationException(); } public void close() { open = false; } public IKeyOrder getKeyOrder() { return keyOrder; } public E[] nextChunk(final IKeyOrder keyOrder) { if (keyOrder == null) throw new IllegalArgumentException(); final E[] chunk = nextChunk(); if (!keyOrder.equals(getKeyOrder())) { /* * Sort into the required order. * * Note: Since this iterator is supposed to have snapshot * semantics the chunk is cloned so that the sort does not * disturb the source data. */ Arrays.sort(chunk.clone(), 0, chunk.length, keyOrder.getComparator()); } return chunk; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy