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

com.bigdata.rdf.spo.SPOIndexRemover Maven / Gradle / Ivy

package com.bigdata.rdf.spo;

import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.log4j.Logger;

import com.bigdata.btree.IIndex;
import com.bigdata.btree.proc.AbstractKeyArrayIndexProcedure.ResultBitBuffer;
import com.bigdata.btree.proc.AbstractKeyArrayIndexProcedure.ResultBitBufferHandler;
import com.bigdata.btree.proc.BatchRemove.BatchRemoveConstructor;
import com.bigdata.btree.proc.LongAggregator;
import com.bigdata.rdf.inf.Justification;

/**
 * Class writes on a statement index, removing the specified statements (batch
 * API, no truth maintenance). If the database uses {@link Justification}s for
 * truth maintenance then the caller is responsible for also removing the
 * {@link Justification}s for the statements being deleted using a
 * {@link JustificationRemover}.
 * 
 * @author Bryan Thompson
 * @version $Id$
 */
public class SPOIndexRemover implements Callable {

    protected static final Logger log = Logger.getLogger(SPOIndexRemover.class);

    /**
     * True iff the {@link #log} level is INFO or less.
     */
    final static protected boolean INFO = log.isInfoEnabled();

    /**
     * True iff the {@link #log} level is DEBUG or less.
     */
    final static protected boolean DEBUG = log.isDebugEnabled();

//    final AbstractTripleStore db;

    final private SPORelation spoRelation;
    
    final private SPOKeyOrder keyOrder;

	final private boolean primaryIndex;

    final private ISPO[] a;

    final private int numStmts;

    final private AtomicLong sortTime;

    final private AtomicLong writeTime;

    final private AtomicLong mutationCount;
    
    final private boolean reportMutations;
    
    public SPOIndexRemover(final SPORelation spoRelation, final ISPO[] stmts,
            final int numStmts, final SPOKeyOrder keyOrder,
			final boolean primaryIndex,
            final boolean clone, final AtomicLong sortTime,
            final AtomicLong writeTime,
            final AtomicLong mutationCount, 
            final boolean reportMutations) {

        if (spoRelation == null)
            throw new IllegalArgumentException();

        if (stmts == null)
            throw new IllegalArgumentException();

        if (numStmts <= 0)
            throw new IllegalArgumentException();

        if (keyOrder == null)
            throw new IllegalArgumentException();

        this.spoRelation = spoRelation;

        this.keyOrder = keyOrder;
		this.primaryIndex = primaryIndex;
        if (clone) {

            this.a = new ISPO[numStmts];

            System.arraycopy(stmts, 0, a, 0, numStmts);

        } else {

            this.a = stmts;

        }

        this.numStmts = numStmts;

        this.sortTime = sortTime;

        this.writeTime = writeTime;

        this.mutationCount = mutationCount;
        
        this.reportMutations = reportMutations;

    }

    /**
     * Remove the statements specified by the called from the statement indices.
     * 
     * @return The elapsed time.
     */
    public Long call() throws Exception {

        final long begin = System.currentTimeMillis();

//        // thread-local key builder.
//        final RdfKeyBuilder keyBuilder = db.getKeyBuilder();

        final IIndex ndx = spoRelation.getIndex(keyOrder);

        final SPOTupleSerializer tupleSer = (SPOTupleSerializer) ndx
                .getIndexMetadata().getTupleSerializer();
        
        // Place statements in index order.
        Arrays.sort(a, 0, numStmts, keyOrder.getComparator());

        final long beginWrite = System.currentTimeMillis();

        sortTime.addAndGet(beginWrite - begin);

        /*
         * Generate keys for batch operation.
         */

        final byte[][] keys = new byte[numStmts][];

        for (int i = 0; i < numStmts; i++) {

            final ISPO spo = a[i];

            if (DEBUG) {

                /*
                 * Note: the externalized terms will be NOT FOUND when removing
                 * a statement from a temp store since the term identifiers for
                 * the temp store are generally only stored in the database.
                 */

                log.debug("Removing " + spo.toString(/*db*/) + " from " + keyOrder);

            }

            keys[i] = tupleSer.serializeKey(spo);

        }

        final long writeCount;
        if (reportMutations) {
            
            /*
             * The IResultHandler obtains from the RPC an indication of each
             * statement whose state was changed by this operation. We use that
             * information to set the metadata on the corresponding ISPO in the
             * caller's array.
             */

            final ResultBitBufferHandler aggregator = new ResultBitBufferHandler(
                    numStmts);

            // batch remove.
            ndx.submit(//
                    0,// fromIndex,
                    numStmts, // toIndex,
                    keys,//
                    null, // vals
                    BatchRemoveConstructor.RETURN_BIT_MASK,//
                    aggregator // handler
                    );

            final ResultBitBuffer modified = aggregator.getResult();

            final boolean[] bits = modified.getResult();
            
            writeCount = modified.getOnCount();
            
            for (int i = 0; i < numStmts; i++) {

                if (bits[i]) {

                    /*
                     * Note: This only turns on the modified flag. It will not
                     * clear it if it is already set. The caller has to take
                     * responsibility for that. This way if the statement is
                     * written twice and the 2nd time the indices are not
                     * updated we still report the statement as modified since
                     * its flag has not been cleared (unless the caller
                     * explicitly cleared it in between those writes).
                     */
                    
                    a[i].setModified(ModifiedEnum.REMOVED);
                    
                }

            }

        } else {
            
            final LongAggregator aggregator = new LongAggregator();

            // batch remove.
            ndx.submit(//
                    0,// fromIndex,
                    numStmts, // toIndex,
                    keys,//
                    null, // vals
                    BatchRemoveConstructor.RETURN_MUTATION_COUNT,//
                    aggregator // handler
                    );

            writeCount = aggregator.getResult();

        }
        
		if (primaryIndex) {

            /*
             * Note: Only the task writing on the primary index takes
             * responsibility for reporting the #of statements that were removed
             * from the indices. This avoids double counting.
             */

            mutationCount.addAndGet(writeCount);

        }
        
        final long elapsed = System.currentTimeMillis() - beginWrite;

        writeTime.addAndGet(elapsed);

        return elapsed;

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy