Search in sources :

Example 1 with KeyType

use of com.cinchapi.concourse.validate.Keys.KeyType in project concourse by cinchapi.

the class Stores method select.

/**
 * Select all of the {@code keys} from {@code record} at {@code timestamp}
 * within {@code store}.
 * <p>
 * This method contains optimizations to efficiently select multiple keys
 * from a record with as few lookups as possible; especially if there are
 * multiple {@link KeyType#NAVIGATION_KEY navigation keys}.
 * </p>
 *
 * @param store
 * @param keys
 * @param record
 * @param timestamp
 * @return a mapping from each of the {@code keys} to the data held for it
 *         in {@code record} at {@code timestamp} within {@code store}
 */
public static Map<String, Set<TObject>> select(Store store, Collection<String> keys, long record, long timestamp) {
    if (keys.isEmpty()) {
        return ImmutableMap.of();
    } else {
        Map<String, Set<TObject>> data = new HashMap<>(keys.size());
        Map<String, Set<TObject>> stored = null;
        Node root = null;
        int count = 1;
        for (String key : keys) {
            Key metadata = Keys.parse(key);
            KeyType type = metadata.type();
            if (type == KeyType.NAVIGATION_KEY) {
                // Generate a single Graph containing all of the stops in
                // each of the navigation keys.
                root = root == null ? Node.root(record) : root;
                Node node = root;
                String[] stops = metadata.data();
                for (String stop : stops) {
                    node = node.next(stop);
                    ++count;
                }
                node.end();
            } else {
                Set<TObject> values;
                if (type == KeyType.WRITABLE_KEY && keys.size() == 1) {
                    // efficient lookup source.
                    return ImmutableMap.of(key, lookupWithStrategy(store, key, record, timestamp));
                } else if (type == KeyType.WRITABLE_KEY) {
                    // @formatter:off
                    stored = stored == null ? (timestamp == Time.NONE ? store.select(record) : store.select(record, timestamp)) : stored;
                    // @formatter:on
                    values = stored.get(key);
                    if (values == null) {
                        values = ImmutableSet.of();
                    }
                } else if (type == KeyType.IDENTIFIER_KEY) {
                    values = ImmutableSet.of(Convert.javaToThrift(record));
                } else if (type == KeyType.FUNCTION_KEY) {
                    Function function = metadata.data();
                    String method = Calculations.alias(function.operation()) + "KeyRecordAtomic";
                    Number value = Reflection.callStatic(Operations.class, method, function.key(), record, timestamp, store);
                    values = value != null ? ImmutableSet.of(Convert.javaToThrift(value)) : ImmutableSet.of();
                } else {
                    values = ImmutableSet.of();
                }
                data.put(key, values);
            }
        }
        if (root != null) {
            // Iterate through the graph, in a breadth-first manner, to
            // perform bulk selection at each Junctions.
            Queue<Node> queue = new ArrayDeque<>(count);
            queue.add(root);
            while (!queue.isEmpty()) {
                Node node = queue.poll();
                Collection<Node> successors = node.successors();
                if (successors.isEmpty()) {
                    data.put(node.path, node.values());
                } else {
                    queue.addAll(successors);
                    Collection<Long> links = node.links();
                    for (long link : links) {
                        Map<String, Set<TObject>> intermediate = null;
                        if (successors.size() > 1) {
                            // Bypassing the Strategy framework is
                            // acceptable here because we know that there
                            // are multiple keys that need to be selected
                            // from each record, so it makes sense to select
                            // the entire record from the Engine, once
                            intermediate = timestamp == Time.NONE ? store.select(link) : store.select(link, timestamp);
                        }
                        for (Node successor : successors) {
                            String stop = successor.stop;
                            if (intermediate == null) {
                                // This means there is only 1 successor, so
                                // the lookup should defer to the Strategy
                                // framework
                                intermediate = ImmutableMap.of(stop, lookupWithStrategy(store, stop, link, timestamp));
                            }
                            Set<TObject> values = intermediate.get(stop);
                            if (values != null) {
                                successor.store(values);
                            } else if (stop.equals(Constants.JSON_RESERVED_IDENTIFIER_NAME)) {
                                successor.store(Convert.javaToThrift(link));
                            }
                        }
                    }
                }
            }
        }
        return data.size() > 1 ? new OrderImposingMap<>(keys, data) : data;
    }
}
Also used : TObject(com.cinchapi.concourse.thrift.TObject) AbstractSet(java.util.AbstractSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) KeyType(com.cinchapi.concourse.validate.Keys.KeyType) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayDeque(java.util.ArrayDeque) Function(com.cinchapi.ccl.type.Function) IndexFunction(com.cinchapi.ccl.type.function.IndexFunction) TemporalFunction(com.cinchapi.ccl.type.function.TemporalFunction) KeyConditionFunction(com.cinchapi.ccl.type.function.KeyConditionFunction) KeyRecordsFunction(com.cinchapi.ccl.type.function.KeyRecordsFunction) Key(com.cinchapi.concourse.validate.Keys.Key)

Aggregations

Function (com.cinchapi.ccl.type.Function)1 IndexFunction (com.cinchapi.ccl.type.function.IndexFunction)1 KeyConditionFunction (com.cinchapi.ccl.type.function.KeyConditionFunction)1 KeyRecordsFunction (com.cinchapi.ccl.type.function.KeyRecordsFunction)1 TemporalFunction (com.cinchapi.ccl.type.function.TemporalFunction)1 TObject (com.cinchapi.concourse.thrift.TObject)1 Key (com.cinchapi.concourse.validate.Keys.Key)1 KeyType (com.cinchapi.concourse.validate.Keys.KeyType)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 AbstractSet (java.util.AbstractSet)1 ArrayDeque (java.util.ArrayDeque)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 Set (java.util.Set)1