voldemort.store.StoreUtils.java Source code

Java tutorial

Introduction

Here is the source code for voldemort.store.StoreUtils.java

Source

/*
 * Copyright 2008-2009 LinkedIn, Inc
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package voldemort.store;

import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import voldemort.cluster.Node;
import voldemort.routing.RoutingStrategy;
import voldemort.serialization.Serializer;
import voldemort.serialization.SerializerDefinition;
import voldemort.serialization.SerializerFactory;
import voldemort.store.metadata.MetadataStore;
import voldemort.utils.ByteArray;
import voldemort.utils.ClosableIterator;
import voldemort.utils.Pair;
import voldemort.versioning.Version;
import voldemort.versioning.Versioned;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * Group of store utilities
 * 
 */
public class StoreUtils {

    private static Logger logger = Logger.getLogger(StoreUtils.class);

    public static void assertValidKeys(Iterable<?> keys) {
        if (keys == null)
            throw new IllegalArgumentException("Keys cannot be null.");
        for (Object key : keys)
            assertValidKey(key);
    }

    public static <K> void assertValidKey(K key) {
        if (key == null)
            throw new IllegalArgumentException("Key cannot be null.");
    }

    /**
     * Implements get by delegating to getAll.
     */
    public static <K, V, T> List<Versioned<V>> get(Store<K, V, T> storageEngine, K key, T transform) {
        Map<K, List<Versioned<V>>> result = storageEngine.getAll(Collections.singleton(key),
                Collections.singletonMap(key, transform));
        if (result.size() > 0)
            return result.get(key);
        else
            return Collections.emptyList();
    }

    /**
     * Implements getAll by delegating to get.
     */
    public static <K, V, T> Map<K, List<Versioned<V>>> getAll(Store<K, V, T> storageEngine, Iterable<K> keys,
            Map<K, T> transforms) {
        Map<K, List<Versioned<V>>> result = newEmptyHashMap(keys);
        for (K key : keys) {
            List<Versioned<V>> value = storageEngine.get(key, transforms != null ? transforms.get(key) : null);
            if (!value.isEmpty())
                result.put(key, value);
        }
        return result;
    }

    /**
     * Returns an empty map with expected size matching the iterable size if
     * it's of type Collection. Otherwise, an empty map with the default size is
     * returned.
     */
    public static <K, V> HashMap<K, V> newEmptyHashMap(Iterable<?> iterable) {
        if (iterable instanceof Collection<?>)
            return Maps.newHashMapWithExpectedSize(((Collection<?>) iterable).size());
        return Maps.newHashMap();
    }

    /**
     * Closes a Closeable and logs a potential error instead of re-throwing the
     * exception. If {@code null} is passed, this method is a no-op.
     * 
     * This is typically used in finally blocks to prevent an exception thrown
     * during close from hiding an exception thrown inside the try.
     * 
     * @param c The Closeable to close, may be null.
     */
    public static void close(Closeable c) {
        if (c != null) {
            try {
                c.close();
            } catch (IOException e) {
                logger.error("Error closing stream", e);
            }
        }
    }

    /**
     * Check if the current node is part of routing request based on cluster.xml
     * or throw an exception.
     * 
     * @param key The key we are checking
     * @param routingStrategy The routing strategy
     * @param currentNode Current node
     */
    public static void assertValidMetadata(ByteArray key, RoutingStrategy routingStrategy, Node currentNode) {
        List<Node> nodes = routingStrategy.routeRequest(key.get());
        for (Node node : nodes) {
            if (node.getId() == currentNode.getId()) {
                return;
            }
        }

        throw new InvalidMetadataException("Client accessing key belonging to partitions "
                + routingStrategy.getPartitionList(key.get()) + " not present at " + currentNode);
    }

    /**
     * Check if the the nodeId is present in the cluster managed by the metadata store
     * or throw an exception.
     *
     * @param nodeId The nodeId to check existence of
     */
    public static void assertValidNode(MetadataStore metadataStore, Integer nodeId) {
        if (!metadataStore.getCluster().hasNodeWithId(nodeId)) {
            throw new InvalidMetadataException("NodeId " + nodeId + " is not or no longer in this cluster");
        }
    }

    public static <V> List<Version> getVersions(List<Versioned<V>> versioneds) {
        List<Version> versions = Lists.newArrayListWithCapacity(versioneds.size());
        for (Versioned<?> versioned : versioneds)
            versions.add(versioned.getVersion());
        return versions;
    }

    public static <K, V> ClosableIterator<K> keys(final ClosableIterator<Pair<K, V>> values) {
        return new ClosableIterator<K>() {

            public void close() {
                values.close();
            }

            public boolean hasNext() {
                return values.hasNext();
            }

            public K next() {
                Pair<K, V> value = values.next();
                if (value == null)
                    return null;
                return value.getFirst();
            }

            public void remove() {
                values.remove();
            }

        };
    }

    /**
     * This is a temporary measure until we have a type-safe solution for
     * retrieving serializers from a SerializerFactory. It avoids warnings all
     * over the codebase while making it easy to verify who calls it.
     */
    @SuppressWarnings("unchecked")
    public static <T> Serializer<T> unsafeGetSerializer(SerializerFactory serializerFactory,
            SerializerDefinition serializerDefinition) {
        return (Serializer<T>) serializerFactory.getSerializer(serializerDefinition);
    }

    /**
     * Get a store definition from the given list of store definitions
     * 
     * @param list A list of store definitions
     * @param name The name of the store
     * @return The store definition
     */
    public static StoreDefinition getStoreDef(List<StoreDefinition> list, String name) {
        for (StoreDefinition def : list)
            if (def.getName().equals(name))
                return def;
        return null;
    }

    /**
     * Get the list of store names from a list of store definitions
     * 
     * @param list
     * @param ignoreViews
     * @return list of store names
     */
    public static List<String> getStoreNames(List<StoreDefinition> list, boolean ignoreViews) {
        List<String> storeNameSet = new ArrayList<String>();
        for (StoreDefinition def : list)
            if (!def.isView() || !ignoreViews)
                storeNameSet.add(def.getName());
        return storeNameSet;
    }

    public static HashMap<String, StoreDefinition> getStoreDefsAsMap(List<StoreDefinition> storeDefs) {
        if (storeDefs == null)
            return null;

        HashMap<String, StoreDefinition> storeDefMap = new HashMap<String, StoreDefinition>();
        for (StoreDefinition def : storeDefs)
            storeDefMap.put(def.getName(), def);
        return storeDefMap;
    }
}