package com.bigdata.relation.rule.eval; import com.bigdata.relation.IMutableRelation; import com.bigdata.relation.IRelation; import com.bigdata.relation.accesspath.AbstractArrayBuffer; import com.bigdata.relation.accesspath.IBuffer; import com.bigdata.striterator.ChunkedArrayIterator; import com.bigdata.striterator.ChunkedResolvingIterator; import com.bigdata.striterator.IChunkedIterator; import com.bigdata.striterator.IChunkedOrderedIterator; /** * Base class for {@link IBuffer} whose target is a mutation (insert, delete, or * update) of some {@link IMutableRelation}. * * <strong>Note that this buffers chunks of {@link ISolution}s NOT relation * elements.</strong> * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ * * @param <R> * The generic type of the [R]elation elements. * * @see IMutableRelation */ abstract public class AbstractSolutionBuffer<R> extends AbstractArrayBuffer<ISolution<R>[]> { private final IMutableRelation<R> relation; protected IMutableRelation<R> getRelation() { return relation; } /** * @param capacity */ protected AbstractSolutionBuffer(final int capacity, final IMutableRelation<R> relation) { super(capacity, ISolution[].class, null/*filter*/); if (relation == null) throw new IllegalArgumentException(); this.relation = relation; } /** * Combines chunks of solutions together into a single chunk and then * delegates to {@link #flush(IChunkedOrderedIterator)}. * <p> * Note: Combining chunks together is a huge performance win if the source * chunks tend to be small (100). For example, this is true for scale-out * joins such as LUBM U1 EDS. There the performance gain is better than * 20:1. */ @Override final protected long flush(final int n, final ISolution<R>[][] a) { final IChunkedOrderedIterator<ISolution<R>> itr; /* * Combine the chunks together. */ // count #of elements in all chunks. int m = 0; for (int i = 0; i < n; i++) { m += a[i].length; } // allocate perfect fit array. final ISolution<R>[] b = new ISolution[m]; // combine all elements into a single chunk. int k = 0; for (int i = 0; i < n; i++) { final ISolution<R>[] tmp = a[i]; System.arraycopy(tmp, 0, b, k, tmp.length); k += tmp.length; } // iterator on that single combined chunk. itr = new ChunkedArrayIterator<ISolution<R>>(m, b, null/* keyOrder */); // /* // * Handle each chunk by itself. // */ // // itr = new ChunkConsumerIterator<ISolution<R>>( // new ArrayIterator<ISolution<R>[]>(n, a), null/* keyOrder(unknown) // */); return flush(itr); } // /** // * // * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> // * @version $Id$ // * @param <E> // */ // private static class ArrayIterator<E> implements ICloseableIterator<E> { // // private final int n; // private final E[] a; // // private int i = 0; // // public ArrayIterator(int n, E[] a) { // // this.n = n; // // this.a = a; // // } // // public void close() { // // NOP. // } // // public boolean hasNext() { // return i < n; // } // // public E next() { // return a[i++]; // } // // public void remove() { // throw new UnsupportedOperationException(); // } // // } /** * Concrete implementations must process the {@link ISolution}s, causing * the appropriate mutation on the target {@link IRelation}. * <p> * Note: The {@link ISolution}s generally appear in an arbitrary order. * They can either be resolved to {@link IRelation} elements or be sorted * into ordered {@link ISolution} chunks using a {@link SolutionComparator}. * * @param itr * The iterator (the order of the elements is unknown). * * @return The #of elements that were modified in the backing relation when * the buffer was flushed */ abstract protected long flush(IChunkedOrderedIterator<ISolution<R>> itr); /** * Buffer writes on {@link IMutableRelation#insert(IChunkedIterator)} when it is * {@link #flush() flushed}. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ * @param <E> */ public static class InsertSolutionBuffer<E> extends AbstractSolutionBuffer<E> { /** * @param capacity * @param relation */ public InsertSolutionBuffer(int capacity, IMutableRelation<E> relation) { super(capacity, relation); } @Override protected long flush(IChunkedOrderedIterator<ISolution<E>> itr) { final IChunkedOrderedIterator<E> itr2 = new ChunkedResolvingIterator<E, ISolution<E>>( itr) { @Override protected E resolve(ISolution<E> e) { return e.get(); } }; return getRelation().insert(itr2); } } /** * Buffer writes on {@link IMutableRelation#delete(IChunkedOrderedIterator)} when it is * {@link #flush() flushed}. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ * @param <E> */ public static class DeleteSolutionBuffer<E> extends AbstractSolutionBuffer<E> { /** * @param capacity * @param relation */ public DeleteSolutionBuffer(int capacity, IMutableRelation<E> relation) { super(capacity,relation); } @Override protected long flush(IChunkedOrderedIterator<ISolution<E>> itr) { // final IChunkedOrderedIterator<E> itr2 = new ChunkedOrderedStriterator( // itr) // .addFilter(new com.bigdata.striterator.Resolver<Iterator<ISolution<E>>, ISolution<E>, E>() { // // protected E resolve(ISolution<E> e) { // // return e.get(); // // } // }); final IChunkedOrderedIterator<E> itr2 = new ChunkedResolvingIterator<E, ISolution<E>>( itr) { @Override protected E resolve(ISolution<E> e) { return e.get(); } }; return getRelation().delete( itr2 ); } } // /** // * Buffer writes on // * {@link IMutableRelation#update(IChunkedOrderedIterator, ITransform)} when it is // * {@link #flush() flushed}. // * // * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> // * @version $Id$ // * @param <E> // */ // public static class UpdateSolutionBuffer<E> extends // AbstractSolutionBuffer<E> { // // private final ITransform<E> transform; // // /** // * @param capacity // * @param relation // */ // public UpdateSolutionBuffer(int capacity, IMutableRelation<E> relation, // ITransform<E> transform) { // // super(capacity, relation); // // if (transform == null) // throw new IllegalArgumentException(); // // this.transform = transform; // // } // // @Override // protected long flush(IChunkedOrderedIterator<ISolution<E>> itr) { // // final IChunkedOrderedIterator<E> itr2 = new ChunkedResolvingIterator<E, ISolution<E>>( // itr) { // // @Override // protected E resolve(ISolution<E> e) { // // return e.get(); // // } // // }; // // return getRelation().update(itr2, transform); // // } // // } }