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

com.bigdata.service.ndx.AbstractScaleOutClientIndexView2 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 Apr 1, 2009
 */

package com.bigdata.service.ndx;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import com.bigdata.btree.IndexMetadata;
import com.bigdata.btree.proc.AbstractKeyArrayIndexProcedureConstructor;
import com.bigdata.btree.proc.IKeyArrayIndexProcedure;
import com.bigdata.btree.proc.IKeyRangeIndexProcedure;
import com.bigdata.btree.proc.IParallelizableIndexProcedure;
import com.bigdata.btree.proc.IResultHandler;
import com.bigdata.btree.proc.ISimpleIndexProcedure;
import com.bigdata.journal.ITx;
import com.bigdata.mdi.IMetadataIndex;
import com.bigdata.mdi.PartitionLocator;
import com.bigdata.resources.StaleLocatorException;
import com.bigdata.service.AbstractScaleOutFederation;
import com.bigdata.service.Split;

/**
 * Abstract class encapsulating MOST of the logic for executing tasks
 * corresponding to client index operations. {@link StaleLocatorException}s are
 * handled by the recursive application of the various submit()
 * methods.
 * 

* A concrete subclass must implement {@link #runTasks(boolean, ArrayList)}. * * @author Bryan Thompson */ abstract public class AbstractScaleOutClientIndexView2 extends AbstractScaleOutClientIndexView { /** * Create a view on a scale-out index. * * @param fed * The federation containing the index. * @param name * The index name. * @param timestamp * A transaction identifier, {@link ITx#UNISOLATED} for the * unisolated index view, {@link ITx#READ_COMMITTED}, or * timestamp for a historical view no later than * the specified timestamp. * @param metadataIndex * The {@link IMetadataIndex} for the named scale-out index as of * that timestamp. Note that the {@link IndexMetadata} on this * object contains the template {@link IndexMetadata} for the * scale-out index partitions. */ public AbstractScaleOutClientIndexView2(AbstractScaleOutFederation fed, String name, long timestamp, IMetadataIndex metadataIndex) { super(fed, name, timestamp, metadataIndex); } /** * * @see #getRecursionDepth() */ final private ThreadLocal recursionDepth = new ThreadLocal() { protected synchronized AtomicInteger initialValue() { return new AtomicInteger(); } }; final public AtomicInteger getRecursionDepth() { return recursionDepth.get(); } /** * Runs set of tasks. * * @param parallel * true iff the tasks MAY be run in parallel. * @param tasks * The tasks to be executed. */ abstract protected void runTasks(final boolean parallel, final ArrayList tasks); /** * Variant uses the caller's timestamp. * * @param ts * @param key * @param proc * @return */ protected Object submit(final long ts, final byte[] key, final ISimpleIndexProcedure proc) { // Find the index partition spanning that key. final PartitionLocator locator = fed.getMetadataIndex(name, ts).find( key); /* * Submit procedure to that data service. */ try { if (log.isInfoEnabled()) { log.info("Submitting " + proc.getClass() + " to partition" + locator); } // required to get the result back from the procedure. final IResultHandler resultHandler = new IdentityHandler(); final SimpleDataServiceProcedureTask task = new SimpleDataServiceProcedureTask( this, key, ts, new Split(locator, 0, 0), proc, resultHandler); // submit procedure and await completion. getThreadPool().submit(task).get(taskTimeout, TimeUnit.MILLISECONDS); // the singleton result. final Object result = resultHandler.getResult(); return result; } catch (Exception ex) { throw new RuntimeException(ex); } } /** * Variant uses the caller's timestamp. * * @param ts * @param fromKey * @param toKey * @param proc * @param resultHandler */ protected void submit(final long ts, final byte[] fromKey, final byte[] toKey, final IKeyRangeIndexProcedure proc, final IResultHandler resultHandler) { // true iff the procedure is known to be parallelizable. final boolean parallel = proc instanceof IParallelizableIndexProcedure; if (log.isInfoEnabled()) log.info("Procedure " + proc.getClass().getName() + " will be mapped across index partitions in " + (parallel ? "parallel" : "sequence")); final int poolSize = ((ThreadPoolExecutor) getThreadPool()) .getCorePoolSize(); final int maxTasksPerRequest = fed.getClient() .getMaxParallelTasksPerRequest(); // max #of tasks to queue at once. final int maxTasks = poolSize == 0 ? maxTasksPerRequest : Math.min( poolSize, maxTasksPerRequest); // verify positive or the loop below will fail to progress. assert maxTasks > 0 : "maxTasks=" + maxTasks + ", poolSize=" + poolSize + ", maxTasksPerRequest=" + maxTasksPerRequest; /* * Scan visits index partition locators in key order. * * Note: We are using the caller's timestamp. */ final Iterator itr = locatorScan(ts, fromKey, toKey, false/* reverseScan */); long nparts = 0; while (itr.hasNext()) { /* * Process the remaining locators a "chunk" at a time. The chunk * size is choosen to be the configured size of the client thread * pool. This lets us avoid overwhelming the thread pool queue when * mapping a procedure across a very large #of index partitions. * * The result is an ordered list of the tasks to be executed. The * order of the tasks is determined by the natural order of the * index partitions - that is, we submit the tasks in key order so * that a non-parallelizable procedure will be mapped in the correct * sequence. */ final ArrayList tasks = new ArrayList( maxTasks); for (int i = 0; i < maxTasks && itr.hasNext(); i++) { final PartitionLocator locator = itr.next(); final Split split = new Split(locator, 0/* fromIndex */, 0/* toIndex */); tasks.add(new KeyRangeDataServiceProcedureTask(this, fromKey, toKey, ts, split, proc, resultHandler)); nparts++; } runTasks(parallel, tasks); } // next (chunk of) locators. if (log.isInfoEnabled()) log.info("Procedure " + proc.getClass().getName() + " mapped across " + nparts + " index partitions in " + (parallel ? "parallel" : "sequence")); } /** * Variant uses the caller's timestamp. * * @param ts * @param fromIndex * @param toIndex * @param keys * @param vals * @param ctor * @param aggregator */ protected void submit(final long ts, final int fromIndex, final int toIndex, final byte[][] keys, final byte[][] vals, final AbstractKeyArrayIndexProcedureConstructor ctor, final IResultHandler aggregator) { /* * Break down the data into a series of "splits", each of which will be * applied to a different index partition. * * Note: We are using the caller's timestamp here so this will have * read-consistent semantics! */ final LinkedList splits = splitKeys(ts, fromIndex, toIndex, keys); final int nsplits = splits.size(); /* * Create the instances of the procedure for each split. */ final ArrayList tasks = new ArrayList( nsplits); final Iterator itr = splits.iterator(); boolean parallel = false; while (itr.hasNext()) { final Split split = itr.next(); final IKeyArrayIndexProcedure proc = ctor.newInstance(this, split.fromIndex, split.toIndex, keys, vals); if (proc instanceof IParallelizableIndexProcedure) { parallel = true; } tasks.add(new KeyArrayDataServiceProcedureTask(this, keys, vals, ts, split, proc, aggregator, ctor)); } if (log.isInfoEnabled()) log.info("Procedures created by " + ctor.getClass().getName() + " will run on " + nsplits + " index partitions in " + (parallel ? "parallel" : "sequence")); runTasks(parallel, tasks); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy