/* * Copyright 2008-2011 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.client; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import org.apache.log4j.Logger; import voldemort.VoldemortException; import voldemort.cluster.Node; import voldemort.versioning.ObsoleteVersionException; import voldemort.versioning.Version; import voldemort.versioning.Versioned; /** * A {@link StoreClient} with lazy initialization. This is useful existing codes * that initializes clients at service deployment time, when the servers may or * may not be available * */ public class LazyStoreClient<K, V> implements StoreClient<K, V> { private final Logger logger = Logger.getLogger(LazyStoreClient.class); private final Callable<StoreClient<K, V>> storeClientThunk; private StoreClient<K, V> storeClient; public LazyStoreClient(Callable<StoreClient<K, V>> storeClientThunk) { this(storeClientThunk, false); } /** * A Hybrid store client which tries to do immediate bootstrap. In case of * an exception, we fallback to the lazy way of doing initialization. * * @param storeClientThunk The callback invoked for doing the actual * bootstrap * @param instantInit A boolean flag when set indicates that we should try * to immediately bootstrap */ public LazyStoreClient(Callable<StoreClient<K, V>> storeClientThunk, boolean wrapsRESTClient) { this.storeClientThunk = storeClientThunk; try { storeClient = initStoreClient(); } catch(Exception e) { storeClient = null; logger.info(e.getMessage()); if(wrapsRESTClient) { logger.info("D2 client might not have been completely initialized. Trying on the next call ..."); } else { logger.info("Could not bootstrap right away. Trying on the next call ... "); } } } public synchronized StoreClient<K, V> getStoreClient() { if(storeClient == null) storeClient = initStoreClient(); return storeClient; } protected StoreClient<K, V> initStoreClient() { try { return storeClientThunk.call(); } catch(VoldemortException ve) { throw ve; } catch(Exception e) { // Callable's type signature includes checked exceptions throw new VoldemortException("Unexpected exception during initialization", e); } } public V getValue(K key) { return getStoreClient().getValue(key); } public V getValue(K key, V defaultValue) { return getStoreClient().getValue(key, defaultValue); } public Versioned<V> get(K key) { return getStoreClient().get(key); } public Versioned<V> get(K key, Object transforms) { return getStoreClient().get(key, transforms); } public Map<K, Versioned<V>> getAll(Iterable<K> keys) { return getStoreClient().getAll(keys); } public Map<K, Versioned<V>> getAll(Iterable<K> keys, Map<K, Object> transforms) { return getStoreClient().getAll(keys, transforms); } public Versioned<V> get(K key, Versioned<V> defaultValue) { return getStoreClient().get(key, defaultValue); } public Version put(K key, V value) { return getStoreClient().put(key, value); } public Version put(K key, V value, Object transforms) { return getStoreClient().put(key, value, transforms); } public Version put(K key, Versioned<V> versioned) throws ObsoleteVersionException { return getStoreClient().put(key, versioned); } public boolean putIfNotObsolete(K key, Versioned<V> versioned) { return getStoreClient().putIfNotObsolete(key, versioned); } public boolean applyUpdate(UpdateAction<K, V> action) { return getStoreClient().applyUpdate(action); } public boolean applyUpdate(UpdateAction<K, V> action, int maxTries) { return getStoreClient().applyUpdate(action, maxTries); } public boolean delete(K key) { return getStoreClient().delete(key); } public boolean delete(K key, Version version) { return getStoreClient().delete(key, version); } public List<Node> getResponsibleNodes(K key) { return getStoreClient().getResponsibleNodes(key); } }