com.bigdata.service.MetadataService 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 Mar 17, 2007
*/
package com.bigdata.service;
import java.io.IOException;
import java.util.Arrays;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import com.bigdata.btree.IRangeQuery;
import com.bigdata.btree.ITuple;
import com.bigdata.btree.ITupleIterator;
import com.bigdata.btree.IndexMetadata;
import com.bigdata.io.SerializerUtil;
import com.bigdata.journal.AbstractTask;
import com.bigdata.journal.ConcurrencyManager;
import com.bigdata.journal.IConcurrencyManager;
import com.bigdata.journal.IResourceManager;
import com.bigdata.journal.ITx;
import com.bigdata.journal.IndexExistsException;
import com.bigdata.journal.NoSuchIndexException;
import com.bigdata.mdi.LocalPartitionMetadata;
import com.bigdata.mdi.MetadataIndex;
import com.bigdata.mdi.PartitionLocator;
import com.bigdata.resources.ResourceManager;
import com.bigdata.util.BytesUtil;
/**
* Implementation of a metadata service for a named scale-out index.
*
* @author Bryan Thompson
* @version $Id$
*/
abstract public class MetadataService extends DataService implements
IMetadataService {
/**
* Error message when a request is made to register a scale-out index but
* delete markers are not enabled for that index.
*/
protected static final String ERR_DELETE_MARKERS = "Delete markers not enabled";
/**
* Return the name of the metadata index.
*
* @param name
* The name of the scale-out index.
*
* @return The name of the corresponding {@link MetadataIndex} that is used
* to manage the partitions in the named scale-out index.
*
* @see DataService#getIndexPartitionName(String, int)
*/
public static String getMetadataIndexName(String name) {
return METADATA_INDEX_NAMESPACE + name;
}
/**
* The namespace for the metadata indices.
*/
public static final String METADATA_INDEX_NAMESPACE = "metadata-";
/**
* Options for the {@link MetadataService}.
*
* @author Bryan Thompson
* @version $Id$
*/
public static interface Options extends DataService.Options {
}
/**
* @param properties
*/
protected MetadataService(Properties properties) {
super(properties);
}
public MetadataService start() {
return (MetadataService) super.start();
}
/**
* Note: You SHOULD NOT be running arbitrary tasks on a
* {@link MetadataService}. They are specialized for the index partition
* locator information and SHOULD NOT be overloaded for other purposes.
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Override
public Future extends Object> submit(Callable extends Object> task) {
// throw new UnsupportedOperationException();
return super.submit(task);
}
public int nextPartitionId(String name) throws IOException, InterruptedException, ExecutionException {
setupLoggingContext();
try {
final AbstractTask task = new NextPartitionIdTask(
getConcurrencyManager(), getMetadataIndexName(name));
final Integer partitionId = (Integer) getConcurrencyManager().submit(
task).get();
if (log.isInfoEnabled())
log.info("Assigned partitionId=" + partitionId + ", name="
+ name);
return partitionId.intValue();
} finally {
clearLoggingContext();
}
}
public PartitionLocator get(String name, long timestamp, final byte[] key)
throws InterruptedException, ExecutionException, IOException {
setupLoggingContext();
try {
if (timestamp == ITx.UNISOLATED) {
/*
* This is a read-only operation so run as read committed rather
* than unisolated.
*/
timestamp = ITx.READ_COMMITTED;
}
final AbstractTask task = new GetTask(getConcurrencyManager(),
timestamp, getMetadataIndexName(name), key);
return (PartitionLocator) getConcurrencyManager().submit(task).get();
} finally {
clearLoggingContext();
}
}
/**
* Task for {@link MetadataService#get(String, long, byte[])}.
*
* @author Bryan Thompson
* @version $Id$
*/
static private final class GetTask extends AbstractTask {
private final byte[] key;
public GetTask(IConcurrencyManager concurrencyManager, long timestamp,
String resource, byte[] key) {
super(concurrencyManager, timestamp, resource);
this.key = key;
}
@Override
protected Object doTask() throws Exception {
MetadataIndex ndx = (MetadataIndex) getIndex(getOnlyResource());
return ndx.get(key);
}
}
public PartitionLocator find(String name, long timestamp, final byte[] key)
throws InterruptedException, ExecutionException, IOException {
setupLoggingContext();
try {
if (timestamp == ITx.UNISOLATED) {
/*
* This is a read-only operation so run as read committed rather
* than unisolated.
*/
timestamp = ITx.READ_COMMITTED;
}
final AbstractTask task = new FindTask(getConcurrencyManager(),
timestamp, getMetadataIndexName(name), key);
return (PartitionLocator) getConcurrencyManager().submit(task).get();
} finally {
clearLoggingContext();
}
}
/**
* Task for {@link MetadataService#find(String, long, byte[])}.
*
* @author Bryan Thompson
* @version $Id$
*/
static private final class FindTask extends AbstractTask {
private final byte[] key;
public FindTask(IConcurrencyManager concurrencyManager, long timestamp,
String resource, byte[] key) {
super(concurrencyManager, timestamp, resource);
this.key = key;
}
@Override
protected Object doTask() throws Exception {
MetadataIndex ndx = (MetadataIndex) getIndex(getOnlyResource());
return ndx.find(key);
}
}
public void splitIndexPartition(String name, PartitionLocator oldLocator,
PartitionLocator newLocators[]) throws IOException,
InterruptedException, ExecutionException {
setupLoggingContext();
try {
final AbstractTask task = new SplitIndexPartitionTask(
getConcurrencyManager(), getMetadataIndexName(name),
oldLocator, newLocators);
getConcurrencyManager().submit(task).get();
} finally {
clearLoggingContext();
}
}
public void joinIndexPartition(String name, PartitionLocator[] oldLocators,
PartitionLocator newLocator) throws IOException,
InterruptedException, ExecutionException {
setupLoggingContext();
try {
final AbstractTask task = new JoinIndexPartitionTask(
getConcurrencyManager(), getMetadataIndexName(name),
oldLocators, newLocator);
getConcurrencyManager().submit(task).get();
} finally {
clearLoggingContext();
}
}
public void moveIndexPartition(String name, PartitionLocator oldLocator,
PartitionLocator newLocator) throws IOException,
InterruptedException, ExecutionException {
setupLoggingContext();
try {
final AbstractTask task = new MoveIndexPartitionTask(
getConcurrencyManager(), getMetadataIndexName(name),
oldLocator, newLocator);
getConcurrencyManager().submit(task).get();
} finally {
clearLoggingContext();
}
}
/**
* @todo if if exits already? (and has consistent/inconsistent metadata)?
*/
public UUID registerScaleOutIndex(final IndexMetadata metadata,
final byte[][] separatorKeys, final UUID[] dataServices)
throws IOException, InterruptedException, ExecutionException {
setupLoggingContext();
try {
if (metadata.getName() == null) {
throw new IllegalArgumentException(
"No name assigned to index in metadata template.");
}
/*
* Note: This automatically turns on delete markers since they are
* required for a scale-out index.
*/
if(!metadata.getDeleteMarkers()) {
metadata.setDeleteMarkers(true);
if (log.isInfoEnabled())
log.info("Enabling delete markers: "+metadata.getName());
}
// if (!metadata.getDeleteMarkers()) {
//
// throw new IllegalArgumentException(ERR_DELETE_MARKERS);
//
// }
final String scaleOutIndexName = metadata.getName();
// Note: We need this in order to assert a lock on this resource!
final String metadataIndexName = MetadataService
.getMetadataIndexName(scaleOutIndexName);
final AbstractTask task = new RegisterScaleOutIndexTask(getFederation(),
getConcurrencyManager(), getResourceManager(), metadataIndexName,
metadata, separatorKeys, dataServices);
final UUID managedIndexUUID = (UUID) getConcurrencyManager()
.submit(task).get();
return managedIndexUUID;
} finally {
clearLoggingContext();
}
}
public void dropScaleOutIndex(final String name) throws IOException,
InterruptedException, ExecutionException {
setupLoggingContext();
try {
final AbstractTask task = new DropScaleOutIndexTask(
getFederation(), getConcurrencyManager(),
getMetadataIndexName(name));
getConcurrencyManager().submit(task).get();
} finally {
clearLoggingContext();
}
}
/*
* Tasks.
*/
/**
* Task assigns the next partition identifier for a registered scale-out
* index in a restart-safe manner.
*/
static protected class NextPartitionIdTask extends AbstractTask {
/**
* @param concurrencyManager
* @param resource
*/
protected NextPartitionIdTask(IConcurrencyManager concurrencyManager, String resource) {
super(concurrencyManager, ITx.UNISOLATED, resource);
}
/**
* @return The next partition identifier as an {@link Integer}.
*/
@Override
protected Object doTask() throws Exception {
final MetadataIndex ndx = (MetadataIndex)getIndex(getOnlyResource());
final int partitionId = ndx.incrementAndGetNextPartitionId();
assert ndx.needsCheckpoint();
// final int counter = (int) ndx.getCounter().incrementAndGet();
return partitionId;
}
}
/**
* Atomic operation removes the pre-existing entry for specified index
* partition and replaces it with N new entries giving the locators for the
* N new index partitions created when that index partition was split.
*
* @author Bryan Thompson
* @version $Id$
*/
static protected class SplitIndexPartitionTask extends AbstractTask {
protected final PartitionLocator oldLocator;
protected final PartitionLocator newLocators[];
/**
* @param concurrencyManager
* @param resource
* @param oldLocator
* @param newLocators
*/
protected SplitIndexPartitionTask(
IConcurrencyManager concurrencyManager, String resource,
PartitionLocator oldLocator,
PartitionLocator newLocators[]) {
super(concurrencyManager, ITx.UNISOLATED, resource);
if (oldLocator == null)
throw new IllegalArgumentException();
if (newLocators == null)
throw new IllegalArgumentException();
this.oldLocator = oldLocator;
this.newLocators = newLocators;
}
@Override
protected Object doTask() throws Exception {
if (log.isInfoEnabled())
log.info("name=" + getOnlyResource() + ", oldLocator="
+ oldLocator + ", locators="
+ Arrays.toString(newLocators));
final MetadataIndex mdi = (MetadataIndex)getIndex(getOnlyResource());
final PartitionLocator pmd = (PartitionLocator) SerializerUtil
.deserialize(mdi.remove(oldLocator.getLeftSeparatorKey()));
if (pmd == null) {
throw new RuntimeException("No such locator: name="
+ getOnlyResource() + ", locator=" + oldLocator);
}
if(!oldLocator.equals(pmd)) {
/*
* Sanity check failed - old locator not equal to the locator
* found under that key in the metadata index.
*/
throw new RuntimeException("Expected different locator: name="
+ getOnlyResource() + ", oldLocator=" + oldLocator
+ ", but actual=" + pmd);
}
final byte[] leftSeparator = oldLocator.getLeftSeparatorKey();
/*
* Sanity check the first locator. It's leftSeparator MUST be the
* leftSeparator of the index partition that was split.
*/
if(!BytesUtil.bytesEqual(leftSeparator,newLocators[0].getLeftSeparatorKey())) {
throw new RuntimeException("locators[0].leftSeparator does not agree.");
}
/*
* Sanity check the last locator. It's rightSeparator MUST be the
* rightSeparator of the index partition that was split. For the
* last index partition, the right separator is always null.
*/
{
final long indexOf = mdi.indexOf(leftSeparator);
byte[] rightSeparator;
try {
// The key for the next index partition.
rightSeparator = mdi.keyAt(indexOf + 1);
} catch (IndexOutOfBoundsException ex) {
// The rightSeparator for the last index partition is null.
rightSeparator = null;
}
final PartitionLocator locator = newLocators[newLocators.length - 1];
if (rightSeparator == null) {
if (locator.getRightSeparatorKey() != null) {
throw new RuntimeException("locators["
+ newLocators.length
+ "].rightSeparator should be null.");
}
} else {
if (!BytesUtil.bytesEqual(rightSeparator, locator
.getRightSeparatorKey())) {
throw new RuntimeException("locators["
+ newLocators.length
+ "].rightSeparator does not agree.");
}
}
}
/*
* Sanity check the partition identifers. They must be distinct from
* one another and distinct from the old partition identifier.
*/
for(int i=0; iBryan Thompson
* @version $Id$
*/
static protected class JoinIndexPartitionTask extends AbstractTask {
protected final PartitionLocator oldLocators[];
protected final PartitionLocator newLocator;
/**
* @param concurrencyManager
* @param resource
* @param oldLocators
* @param newLocator
*/
protected JoinIndexPartitionTask(
IConcurrencyManager concurrencyManager, String resource,
PartitionLocator oldLocators[],
PartitionLocator newLocator) {
super(concurrencyManager, ITx.UNISOLATED, resource);
if (oldLocators == null)
throw new IllegalArgumentException();
if (newLocator == null)
throw new IllegalArgumentException();
this.oldLocators = oldLocators;
this.newLocator = newLocator;
}
@Override
protected Object doTask() throws Exception {
if (log.isInfoEnabled())
log.info("name=" + getOnlyResource() + ", oldLocators="
+ Arrays.toString(oldLocators) + ", newLocator="
+ newLocator);
MetadataIndex mdi = (MetadataIndex)getIndex(getOnlyResource());
/*
* Sanity check the partition identifers. They must be distinct from
* one another and distinct from the old partition identifier.
*/
for(int i=0; iBryan Thompson
* @version $Id$
*/
static protected class MoveIndexPartitionTask extends AbstractTask {
protected final PartitionLocator oldLocator;
protected final PartitionLocator newLocator;
/**
* @param concurrencyManager
* @param resource
* @param oldLocator
* @param newLocator
*/
protected MoveIndexPartitionTask(
IConcurrencyManager concurrencyManager, String resource,
PartitionLocator oldLocator,
PartitionLocator newLocator) {
super(concurrencyManager, ITx.UNISOLATED, resource);
if (oldLocator == null)
throw new IllegalArgumentException();
if (newLocator == null)
throw new IllegalArgumentException();
this.oldLocator = oldLocator;
this.newLocator = newLocator;
}
@Override
protected Object doTask() throws Exception {
if (log.isInfoEnabled())
log.info("name=" + getOnlyResource() + ", oldLocator="
+ oldLocator + ", newLocator=" + newLocator);
final MetadataIndex mdi = (MetadataIndex) getIndex(getOnlyResource());
// remove the old locators from the metadata index.
final PartitionLocator pmd = (PartitionLocator) SerializerUtil
.deserialize(mdi.remove(oldLocator.getLeftSeparatorKey()));
if (pmd == null) {
throw new RuntimeException("No such locator: name="
+ getOnlyResource() + ", locator=" + oldLocator);
}
if (!oldLocator.equals(pmd)) {
/*
* Sanity check failed - old locator not equal to the locator
* found under that key in the metadata index.
*
* @todo differences in just the data service failover chain are
* probably not important and might be ignored.
*/
throw new RuntimeException("Expected oldLocator=" + oldLocator
+ ", but actual=" + pmd);
}
/*
* FIXME validate that the newLocator is a perfect fit replacement
* for the oldLocators in terms of the key range spanned and that
* there are no gaps. Add an API constaint that the oldLocators are
* in key order by their leftSeparator key.
*/
// add the new locator to the metadata index.
mdi.insert(newLocator.getLeftSeparatorKey(), SerializerUtil
.serialize(newLocator));
return null;
}
}
/**
* Registers a metadata index for a named scale-out index and statically
* partition the index using the given separator keys and data services.
*
* @todo this does not attempt to handle errors on data services when
* attempting to register the index partitions. it should failover
* rather than just dying.
*
* @todo an error during execution can result in the task aborting but any
* registered index partitions will already exist on the various data
* servers. that will make it impossible to re-register the scale-out
* index until those index partitions have been cleaned up, which is a
* more than insignificant pain (they could be cleaned up by a
* bottom-up index rebuild followed by dropping the rebuilt index).
*
* @author Bryan Thompson
* @version $Id$
*/
static protected class RegisterScaleOutIndexTask extends AbstractTask {
/** The federation. */
final private IBigdataFederation fed;
/** The name of the scale-out index. */
final private String scaleOutIndexName;
/** The metadata template for the scale-out index. */
final private IndexMetadata metadata;
/** The #of index partitions to create. */
final private int npartitions;
/** The separator keys for those index partitions. */
final private byte[][] separatorKeys;
/** The service UUIDs of the data services on which to create those index partitions. */
final private UUID[] dataServiceUUIDs;
/** The data services on which to create those index partitions. */
final private IDataService[] dataServices;
/**
* Create and statically partition a scale-out index.
*
* @param metadataIndexName
* The name of the metadata index (the resource on which the
* task must have a lock).
* @param separatorKeys
* The array of separator keys. Each separator key is
* interpreted as an unsigned byte[]. The first
* entry MUST be an empty byte[]. The entries MUST be in
* sorted order.
* @param dataServiceUUIDs
* The array of data services onto which each partition
* defined by a separator key will be mapped (optional). The
* #of entries in this array MUST agree with the #of entries
* in the separatorKeys array. When null
,
* the index paritions will be auto-assigned to data
* services.
*/
public RegisterScaleOutIndexTask(
final IBigdataFederation fed,
final ConcurrencyManager concurrencyManager,
final IResourceManager resourceManager,
final String metadataIndexName,
final IndexMetadata metadata,
final byte[][] separatorKeys,
UUID[] dataServiceUUIDs
) {
super(concurrencyManager, ITx.UNISOLATED, metadataIndexName);
if (fed == null)
throw new IllegalArgumentException();
if (metadata == null)
throw new IllegalArgumentException();
if (separatorKeys == null)
throw new IllegalArgumentException();
if (separatorKeys.length == 0)
throw new IllegalArgumentException();
if (dataServiceUUIDs != null) {
if (dataServiceUUIDs.length == 0)
throw new IllegalArgumentException();
if (separatorKeys.length != dataServiceUUIDs.length)
throw new IllegalArgumentException();
} else {
/*
* Auto-assign the index partitions to data services.
*/
try {
// discover under-utilized data service UUIDs.
dataServiceUUIDs = fed.getLoadBalancerService().getUnderUtilizedDataServices(
separatorKeys.length, // minCount
separatorKeys.length, // maxCount
null// exclude
);
} catch(Exception ex) {
throw new RuntimeException(ex);
}
}
this.fed = fed;
this.scaleOutIndexName = metadata.getName();
this.metadata = metadata;
this.npartitions = separatorKeys.length;
this.separatorKeys = separatorKeys;
this.dataServiceUUIDs = dataServiceUUIDs;
this.dataServices = new IDataService[dataServiceUUIDs.length];
if( separatorKeys[0] == null )
throw new IllegalArgumentException();
if (separatorKeys[0].length != 0)
throw new IllegalArgumentException(
"The first separatorKey must be an empty byte[].");
for (int i = 0; i < npartitions; i++) {
final byte[] separatorKey = separatorKeys[i];
if (separatorKey == null) {
throw new IllegalArgumentException();
}
if (i > 0) {
if(BytesUtil.compareBytes(separatorKey, separatorKeys[i-1])<0) {
throw new IllegalArgumentException(
"Separator keys out of order at index=" + i);
}
}
final UUID uuid = dataServiceUUIDs[i];
if (uuid == null) {
throw new IllegalArgumentException();
}
final IDataService dataService = fed.getDataService(uuid);
if (dataService == null) {
throw new IllegalArgumentException(
"Unknown data service: uuid=" + uuid);
}
dataServices[i] = dataService;
}
}
/**
* Create and statically partition the scale-out index.
*
* @return The UUID assigned to the managed index.
*/
protected Object doTask() throws Exception {
// the name of the metadata index itself.
final String metadataName = getOnlyResource();
// make sure there is no metadata index for that btree.
try {
getIndex(metadataName);
throw new IndexExistsException(metadataName);
} catch(NoSuchIndexException ex) {
// ignore expected exception
}
/*
* Note: there are two UUIDs here - the UUID for the metadata index
* describing the partitions of the named scale-out index and the
* UUID of the named scale-out index. The metadata index UUID MUST
* be used by all B+Tree objects having data for the metadata index
* (its mutable btrees on journals and its index segments) while the
* managed named index UUID MUST be used by all B+Tree objects
* having data for the named index (its mutable btrees on journals
* and its index segments).
*/
final UUID metadataIndexUUID = UUID.randomUUID();
/*
* Create the metadata index.
*/
final MetadataIndex mdi = MetadataIndex.create(getJournal(),
metadataIndexUUID, metadata);
/*
* Map the partitions onto the data services.
*/
final PartitionLocator[] partitions = new PartitionLocator[npartitions];
for (int i = 0; i < npartitions; i++) {
final byte[] leftSeparator = separatorKeys[i];
final byte[] rightSeparator = i + 1 < npartitions ? separatorKeys[i + 1]
: null;
final PartitionLocator pmd = new PartitionLocator(//
mdi.incrementAndGetNextPartitionId(),//
dataServiceUUIDs[i],
leftSeparator,
rightSeparator
);
if (log.isInfoEnabled())
log.info("name=" + scaleOutIndexName + ", pmd=" + pmd);
/*
* Map the initial partition onto that data service. This
* requires us to compute the left and right separator keys. The
* right separator key is just the separator key for the next
* partition in order and null iff this is the last partition.
*/
final IndexMetadata md = metadata.clone();
// override the partition metadata.
md.setPartitionMetadata(new LocalPartitionMetadata(
pmd.getPartitionId(),//
-1, // we are creating a new index, not moving an index partition.
leftSeparator,//
rightSeparator,//
/*
* Note: By setting this to null we are indicating to
* the RegisterIndexTask on the data service that it
* needs to set the resourceMetadata[] when the index is
* actually registered based on the live journal as of
* the when the task actually executes on the data
* service.
*/
null, // [resources] Signal to the RegisterIndexTask.
null // [cause] Signal to RegisterIndexTask
// /*
// * History.
// */
// ,"createScaleOutIndex(name="+scaleOutIndexName+") "
));
dataServices[i].registerIndex(DataService
.getIndexPartitionName(scaleOutIndexName, pmd.getPartitionId()), md);
partitions[i] = pmd;
}
/*
* Record each partition in the metadata index.
*/
for (int i = 0; i < npartitions; i++) {
// mdi.put(separatorKeys[i], partitions[i]);
mdi.insert(separatorKeys[i], SerializerUtil.serialize(partitions[i]));
}
/*
* Register the metadata index with the metadata service. This
* registration will not be restart safe until the task commits.
*/
getJournal().registerIndex(metadataName, mdi);
// Done.
return mdi.getScaleOutIndexMetadata().getIndexUUID();
}
}
/**
* Drops a scale-out index.
*
* Since this task is unisolated, it basically has a lock on the writable
* version of the metadata index. It drops each index partition and finally
* drops the metadata index itself.
*
* Historical reads against the metadata index will continue to succeed both
* during and after this operation has completed successfully. However,
* {@link ITx#READ_COMMITTED} operations will succeed only until this
* operation completes at which point the scale-out index will no longer be
* visible.
*
* The data comprising the scale-out index will remain available for
* historical reads until it is released by whatever policy is in effect for
* the {@link ResourceManager}s for the {@link DataService}s on which that
* data resides.
*
* @todo This does not try to handle errors gracefully. E.g., if there is a
* problem with one of the data services hosting an index partition it
* does not fail over to the next data service for that index
* partition.
*/
static public class DropScaleOutIndexTask extends AbstractTask {
private final IBigdataFederation fed;
/**
* @parma fed
* @param concurrencyManager
* @param name
* The name of the metadata index for some scale-out index.
*/
protected DropScaleOutIndexTask(IBigdataFederation fed,
ConcurrencyManager concurrencyManager, String name) {
super(concurrencyManager, ITx.UNISOLATED, name);
if (fed == null)
throw new IllegalArgumentException();
this.fed = fed;
}
/**
* Drops the index partitions and then drops the metadata index as well.
*
* @return The {@link Integer} #of index partitions that were dropped.
*/
@Override
protected Object doTask() throws Exception {
final MetadataIndex ndx;
try {
ndx = (MetadataIndex) getIndex(getOnlyResource());
} catch (ClassCastException ex) {
throw new UnsupportedOperationException(
"Not a scale-out index?", ex);
}
// name of the scale-out index.
final String name = ndx.getScaleOutIndexMetadata().getName();
if (log.isInfoEnabled())
log.info("Will drop index partitions for " + name);
// final ChunkedLocalRangeIterator itr = new ChunkedLocalRangeIterator(
// ndx, null, null, 0/* capacity */, IRangeQuery.VALS, null/* filter */);
final ITupleIterator itr = ndx.rangeIterator(null, null,
0/* capacity */, IRangeQuery.VALS, null/* filter */);
int ndropped = 0;
while(itr.hasNext()) {
final ITuple tuple = itr.next();
// FIXME There is still (5/30/08) a problem with using getValueStream() here!
final PartitionLocator pmd = (PartitionLocator) SerializerUtil
.deserialize(tuple.getValue());
// .deserialize(tuple.getValueStream());
/*
* Drop the index partition.
*/
{
final int partitionId = pmd.getPartitionId();
final UUID serviceUUID = pmd.getDataServiceUUID();
final IDataService dataService = fed
.getDataService(serviceUUID);
if (log.isInfoEnabled())
log.info("Dropping index partition: partitionId="
+ partitionId + ", dataService=" + dataService);
dataService.dropIndex(DataService.getIndexPartitionName(
name, partitionId));
}
ndropped++;
}
// // flush all delete requests.
// itr.flush();
if (log.isInfoEnabled())
log.info("Dropped " + ndropped + " index partitions for "
+ name);
// drop the metadata index as well.
getJournal().dropIndex(getOnlyResource());
return ndropped;
}
}
}