Search in sources :

Example 1 with RowPosition

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;
}
Also used : RowPosition(org.apache.cassandra.db.RowPosition) ByteBuffer(java.nio.ByteBuffer) AsyncClient.get_range_slices_call(org.apache.cassandra.thrift.Cassandra.AsyncClient.get_range_slices_call) InetAddress(java.net.InetAddress)

Example 2 with RowPosition

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;
}
Also used : AsyncClient.get_range_slices_call(org.apache.cassandra.thrift.Cassandra.AsyncClient.get_range_slices_call) InetAddress(java.net.InetAddress) AsyncClient.get_range_slices_by_time_call(org.apache.cassandra.thrift.Cassandra.AsyncClient.get_range_slices_by_time_call) EvtAndLvt(org.apache.cassandra.utils.ColumnOrSuperColumnHelper.EvtAndLvt) RowPosition(org.apache.cassandra.db.RowPosition) ByteBuffer(java.nio.ByteBuffer)

Aggregations

InetAddress (java.net.InetAddress)2 ByteBuffer (java.nio.ByteBuffer)2 RowPosition (org.apache.cassandra.db.RowPosition)2 AsyncClient.get_range_slices_call (org.apache.cassandra.thrift.Cassandra.AsyncClient.get_range_slices_call)2 AsyncClient.get_range_slices_by_time_call (org.apache.cassandra.thrift.Cassandra.AsyncClient.get_range_slices_by_time_call)1 EvtAndLvt (org.apache.cassandra.utils.ColumnOrSuperColumnHelper.EvtAndLvt)1