use of org.apache.cassandra.db.RowPosition in project eiger by wlloyd.
the class ClientLibrary method get_range_slices.
public List<KeySlice> get_range_slices(ColumnParent column_parent, SlicePredicate predicate, KeyRange range) throws Exception {
//if (logger.isTraceEnabled()) {
// logger.trace("get_range_slices(column_parent = {}, predicate = {}, range = {})", new Object[]{column_parent, predicate, range});
//}
//turn the KeyRange into AbstractBounds that are easier to reason about
AbstractBounds<Token> requestedRange;
if (range.start_key == null) {
Token.TokenFactory tokenFactory = partitioner.getTokenFactory();
Token left = tokenFactory.fromString(range.start_token);
Token right = tokenFactory.fromString(range.end_token);
requestedRange = new Bounds<Token>(left, right, partitioner);
} else {
AbstractBounds<RowPosition> rowPositionBounds = new Bounds<RowPosition>(RowPosition.forKey(range.start_key, partitioner), RowPosition.forKey(range.end_key, partitioner));
requestedRange = rowPositionBounds.toTokenBounds();
}
//Split up into one request for each server in the local cluster
Map<Cassandra.AsyncClient, List<Range<Token>>> asyncClientToRanges = new HashMap<Cassandra.AsyncClient, List<Range<Token>>>();
for (Entry<Range<Token>, InetAddress> entry : ringCache.getRangeMap().entries()) {
Range<Token> serverRange = entry.getKey();
InetAddress addr = entry.getValue();
Cassandra.AsyncClient asyncClient = addressToAsyncClient.get(addr);
if (asyncClient == null) {
//this addr is not in the local datacenter
continue;
}
// We want to restrict the range we ask for from each server to be
// the intersection of its range and the requested range
serverRange = intersect(serverRange, requestedRange);
if (serverRange == null) {
//no intersection, so nothing to request from this server
continue;
}
if (!asyncClientToRanges.containsKey(asyncClient)) {
asyncClientToRanges.put(asyncClient, new ArrayList<Range<Token>>());
}
asyncClientToRanges.get(asyncClient).add(serverRange);
}
//Need to merge the adjacent ranges into a single keyRange to request from each local server
Map<Cassandra.AsyncClient, KeyRange> asyncClientToKeyRange = new HashMap<Cassandra.AsyncClient, KeyRange>();
for (Entry<Cassandra.AsyncClient, List<Range<Token>>> entry : asyncClientToRanges.entrySet()) {
Cassandra.AsyncClient asyncClient = entry.getKey();
List<Range<Token>> rangeList = entry.getValue();
List<AbstractBounds<Token>> normalizedBounds = AbstractBounds.normalize(rangeList);
assert normalizedBounds.size() == 1 : "All parts of a server ranges should be adjacent : " + normalizedBounds;
AbstractBounds<Token<String>> serverRange = new Bounds<Token<String>>(normalizedBounds.get(0).left, normalizedBounds.get(0).right, partitioner);
//WL TODO: Should be a more elegant way to extract tokens
String leftToken = serverRange.left.toString();
String rightToken = serverRange.right.toString();
//Remove brackets from tokens (they only show up when we have the ByteOrderPartitioner I think)
if (leftToken.indexOf("[") != -1) {
leftToken = leftToken.substring(leftToken.indexOf("[") + 1, leftToken.indexOf("]"));
rightToken = rightToken.substring(rightToken.indexOf("[") + 1, rightToken.indexOf("]"));
}
KeyRange rangeForThisClient = new KeyRange();
rangeForThisClient.setStart_token(leftToken);
rangeForThisClient.setEnd_token(rightToken);
asyncClientToKeyRange.put(asyncClient, rangeForThisClient);
}
Queue<BlockingQueueCallback<get_range_slices_call>> callbacks = new LinkedList<BlockingQueueCallback<get_range_slices_call>>();
for (Entry<Cassandra.AsyncClient, KeyRange> entry : asyncClientToKeyRange.entrySet()) {
Cassandra.AsyncClient asyncClient = entry.getKey();
KeyRange rangeForThisClient = entry.getValue();
BlockingQueueCallback<get_range_slices_call> callback = new BlockingQueueCallback<get_range_slices_call>();
callbacks.add(callback);
asyncClient.get_range_slices(column_parent, predicate, rangeForThisClient, consistencyLevel, LamportClock.sendTimestamp(), callback);
}
List<KeySlice> combinedResults = new ArrayList<KeySlice>();
for (BlockingQueueCallback<get_range_slices_call> callback : callbacks) {
GetRangeSlicesResult result = callback.getResponseNoInterruption().getResult();
LamportClock.updateTime(result.lts);
for (KeySlice keySlice : result.value) {
ByteBuffer key = keySlice.key;
List<ColumnOrSuperColumn> coscList = keySlice.columns;
for (Iterator<ColumnOrSuperColumn> cosc_it = coscList.iterator(); cosc_it.hasNext(); ) {
ColumnOrSuperColumn cosc = cosc_it.next();
try {
clientContext.addDep(key, cosc);
} catch (NotFoundException nfe) {
//remove deleted results, it's okay for all result to be removed
cosc_it.remove();
}
}
}
combinedResults.addAll(result.value);
}
//}
return combinedResults;
}
use of org.apache.cassandra.db.RowPosition in project eiger by wlloyd.
the class ClientLibrary method transactional_get_range_slices.
public List<KeySlice> transactional_get_range_slices(ColumnParent column_parent, SlicePredicate predicate, KeyRange range) throws Exception {
//if (logger.isTraceEnabled()) {
// logger.trace("transactional_get_range_slices(column_parent = {}, predicate = {}, range = {})", new Object[]{column_parent, predicate, range});
//}
//turn the KeyRange into AbstractBounds that are easier to reason about
AbstractBounds<Token> requestedRange;
if (range.start_key == null) {
Token.TokenFactory tokenFactory = partitioner.getTokenFactory();
Token left = tokenFactory.fromString(range.start_token);
Token right = tokenFactory.fromString(range.end_token);
requestedRange = new Bounds<Token>(left, right, partitioner);
} else {
AbstractBounds<RowPosition> rowPositionBounds = new Bounds<RowPosition>(RowPosition.forKey(range.start_key, partitioner), RowPosition.forKey(range.end_key, partitioner));
requestedRange = rowPositionBounds.toTokenBounds();
}
//Split up into one request for each server in the local cluster
Map<Cassandra.AsyncClient, List<Range<Token>>> asyncClientToRanges = new HashMap<Cassandra.AsyncClient, List<Range<Token>>>();
for (Entry<Range<Token>, InetAddress> entry : ringCache.getRangeMap().entries()) {
Range<Token> serverRange = entry.getKey();
InetAddress addr = entry.getValue();
Cassandra.AsyncClient asyncClient = addressToAsyncClient.get(addr);
if (asyncClient == null) {
//this addr is not in the local datacenter
continue;
}
// We want to restrict the range we ask for from each server to be
// the intersection of its range and the requested range
serverRange = intersect(serverRange, requestedRange);
if (serverRange == null) {
//no intersection, so nothing to request from this server
continue;
}
if (!asyncClientToRanges.containsKey(asyncClient)) {
asyncClientToRanges.put(asyncClient, new ArrayList<Range<Token>>());
}
asyncClientToRanges.get(asyncClient).add(serverRange);
}
//Need to merge the adjacent ranges into a single keyRange to request from each local server
Map<Cassandra.AsyncClient, KeyRange> asyncClientToKeyRange = new HashMap<Cassandra.AsyncClient, KeyRange>();
for (Entry<Cassandra.AsyncClient, List<Range<Token>>> entry : asyncClientToRanges.entrySet()) {
Cassandra.AsyncClient asyncClient = entry.getKey();
List<Range<Token>> rangeList = entry.getValue();
List<AbstractBounds<Token>> normalizedBounds = AbstractBounds.normalize(rangeList);
assert normalizedBounds.size() == 1 : "All parts of a server ranges should be adjacent : " + normalizedBounds;
AbstractBounds<Token<String>> serverRange = new Bounds<Token<String>>(normalizedBounds.get(0).left, normalizedBounds.get(0).right, partitioner);
//WL TODO: Should be a more elegant way to extract tokens
String leftToken = serverRange.left.toString();
String rightToken = serverRange.right.toString();
//Remove brackets from tokens (they only show up when we have the ByteOrderPartitioner I think)
if (leftToken.indexOf("[") != -1) {
leftToken = leftToken.substring(leftToken.indexOf("[") + 1, leftToken.indexOf("]"));
rightToken = rightToken.substring(rightToken.indexOf("[") + 1, rightToken.indexOf("]"));
}
KeyRange rangeForThisClient = new KeyRange();
rangeForThisClient.setStart_token(leftToken);
rangeForThisClient.setEnd_token(rightToken);
asyncClientToKeyRange.put(asyncClient, rangeForThisClient);
}
Queue<BlockingQueueCallback<get_range_slices_call>> firstRoundCallbacks = new LinkedList<BlockingQueueCallback<get_range_slices_call>>();
for (Entry<Cassandra.AsyncClient, KeyRange> entry : asyncClientToKeyRange.entrySet()) {
Cassandra.AsyncClient asyncClient = entry.getKey();
KeyRange rangeForThisClient = entry.getValue();
BlockingQueueCallback<get_range_slices_call> callback = new BlockingQueueCallback<get_range_slices_call>();
firstRoundCallbacks.add(callback);
asyncClient.get_range_slices(column_parent, predicate, rangeForThisClient, consistencyLevel, LamportClock.sendTimestamp(), callback);
}
//Gather responses, track both max_evt and min_lvt
long overallMaxEvt = Long.MIN_VALUE;
long overallMinLvt = Long.MAX_VALUE;
//keyToColumns should be in sorted order, clients (at least some of my testing code) assumes this
SortedMap<ByteBuffer, List<ColumnOrSuperColumn>> keyToColumns = new TreeMap<ByteBuffer, List<ColumnOrSuperColumn>>();
Map<ByteBuffer, Set<Dep>> keyToDeps = new HashMap<ByteBuffer, Set<Dep>>();
//WL TODO Add support for doing queries to secondary indices
NavigableMap<Long, List<ByteBuffer>> lvtToKeys = new TreeMap<Long, List<ByteBuffer>>();
for (BlockingQueueCallback<get_range_slices_call> callback : firstRoundCallbacks) {
GetRangeSlicesResult result = callback.getResponseNoInterruption().getResult();
LamportClock.updateTime(result.lts);
for (KeySlice keySlice : result.value) {
ByteBuffer key = keySlice.key;
List<ColumnOrSuperColumn> coscList = keySlice.columns;
//find the evt and lvt for the entire row
EvtAndLvt evtAndLvt = ColumnOrSuperColumnHelper.extractEvtAndLvt(coscList);
if (!lvtToKeys.containsKey(evtAndLvt.getLatestValidTime())) {
lvtToKeys.put(evtAndLvt.getLatestValidTime(), new LinkedList<ByteBuffer>());
}
lvtToKeys.get(evtAndLvt.getLatestValidTime()).add(key);
//if (logger.isTraceEnabled()) { logger.trace("round 1 response for " + printKey(key) + " evt: " + evtAndLvt.getEarliestValidTime() + " lvt: " + evtAndLvt.getLatestValidTime()); }
overallMaxEvt = Math.max(overallMaxEvt, evtAndLvt.getEarliestValidTime());
overallMinLvt = Math.min(overallMinLvt, evtAndLvt.getLatestValidTime());
ClientContext tmpContext = new ClientContext();
for (Iterator<ColumnOrSuperColumn> cosc_it = coscList.iterator(); cosc_it.hasNext(); ) {
ColumnOrSuperColumn cosc = cosc_it.next();
try {
tmpContext.addDep(key, cosc);
} catch (NotFoundException nfe) {
//remove deleted results, it's okay for all result to be removed
cosc_it.remove();
}
}
keyToColumns.put(key, coscList);
keyToDeps.put(key, tmpContext.getDeps());
}
}
//Execute 2nd round if necessary
if (overallMinLvt < overallMaxEvt) {
//get the smallest lvt > maxEvt
long chosenTime = lvtToKeys.navigableKeySet().higher(overallMaxEvt);
List<ByteBuffer> secondRoundKeys = new LinkedList<ByteBuffer>();
for (List<ByteBuffer> keyList : lvtToKeys.headMap(chosenTime).values()) {
secondRoundKeys.addAll(keyList);
}
//invalid all results for second round keys (sanity check, not strictly necessary)
for (ByteBuffer key : secondRoundKeys) {
keyToColumns.remove(key);
keyToDeps.remove(key);
}
Set<ByteBuffer> allKnownKeys = keyToColumns.keySet();
Map<Cassandra.AsyncClient, List<ByteBuffer>> asyncClientToKnownKeys = partitionByAsyncClients(allKnownKeys);
Queue<BlockingQueueCallback<get_range_slices_by_time_call>> secondRoundCallbacks = new LinkedList<BlockingQueueCallback<get_range_slices_by_time_call>>();
for (Entry<Cassandra.AsyncClient, KeyRange> entry : asyncClientToKeyRange.entrySet()) {
Cassandra.AsyncClient asyncClient = entry.getKey();
KeyRange rangeForThisClient = entry.getValue();
BlockingQueueCallback<get_range_slices_by_time_call> callback = new BlockingQueueCallback<get_range_slices_by_time_call>();
secondRoundCallbacks.add(callback);
List<ByteBuffer> knownKeys = asyncClientToKnownKeys.get(asyncClient);
if (knownKeys == null) {
//knownKeys can't be null for thrift encoding
knownKeys = new LinkedList<ByteBuffer>();
}
asyncClient.get_range_slices_by_time(column_parent, predicate, rangeForThisClient, knownKeys, consistencyLevel, chosenTime, LamportClock.sendTimestamp(), callback);
}
for (BlockingQueueCallback<get_range_slices_by_time_call> callback : secondRoundCallbacks) {
GetRangeSlicesResult result = callback.getResponseNoInterruption().getResult();
LamportClock.updateTime(result.lts);
for (KeySlice keySlice : result.value) {
ByteBuffer key = keySlice.key;
List<ColumnOrSuperColumn> coscList = keySlice.columns;
ClientContext tmpContext = new ClientContext();
for (Iterator<ColumnOrSuperColumn> cosc_it = coscList.iterator(); cosc_it.hasNext(); ) {
ColumnOrSuperColumn cosc = cosc_it.next();
try {
tmpContext.addDep(key, cosc);
} catch (NotFoundException nfe) {
//remove deleted results, it's okay for all result to be removed
cosc_it.remove();
}
}
keyToColumns.put(key, coscList);
keyToDeps.put(key, tmpContext.getDeps());
}
}
}
//Add dependencies from counts we return
for (Set<Dep> deps : keyToDeps.values()) {
clientContext.addDeps(deps);
}
List<KeySlice> combinedResults = new ArrayList<KeySlice>();
for (Entry<ByteBuffer, List<ColumnOrSuperColumn>> entry : keyToColumns.entrySet()) {
ByteBuffer key = entry.getKey();
List<ColumnOrSuperColumn> coscList = entry.getValue();
combinedResults.add(new KeySlice(key, coscList));
}
return combinedResults;
}
Aggregations