/* * Copyright 2012-2013 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 org.apache.log4j.Logger; import voldemort.VoldemortException; import voldemort.store.InvalidMetadataException; import voldemort.store.Store; import voldemort.store.system.SystemStoreConstants; import voldemort.versioning.InconsistentDataException; import voldemort.versioning.VectorClock; import voldemort.versioning.Version; import voldemort.versioning.Versioned; /** * A client interface for interacting with System stores (managed by the * cluster). The naming convention is kept consistent with SocketStore (which is * also a client interface). * * @author csoman * * @param <K> Type of Key * @param <V> Type of Value */ public class SystemStoreClient<K, V> { private final Logger logger = Logger.getLogger(SystemStoreClient.class); private final String storeName; private volatile Store<K, V, Object> sysStore; /** * Constructor that creates a system store client which can be used to * interact with the system stores managed by the cluster * * @param storeName Name of the system store * @param systemStore The socket store used to interact with the system * stores on the individual server nodes */ public SystemStoreClient(String storeName, Store<K, V, Object> systemStore) { String prefix = storeName.substring(0, SystemStoreConstants.NAME_PREFIX.length()); if(!SystemStoreConstants.NAME_PREFIX.equals(prefix)) { throw new VoldemortException("Illegal system store : " + storeName); } this.storeName = storeName; try { this.sysStore = systemStore; } catch(Exception e) { logger.debug("Error while creating a system store client for store : " + this.storeName); } } public Version putSysStore(K key, V value) { Version version = null; try { if(logger.isDebugEnabled()) { logger.debug("Invoking Put for key : " + key + " on store name : " + this.storeName); } Versioned<V> versioned = getSysStore(key); if(versioned == null) versioned = Versioned.value(value, new VectorClock()); else versioned.setObject(value); this.sysStore.put(key, versioned, null); version = versioned.getVersion(); } catch(Exception e) { if(logger.isDebugEnabled()) { logger.debug("Exception caught during putSysStore: " + e); } } return version; } public Version putSysStore(K key, Versioned<V> value) { Version version = null; try { if(logger.isDebugEnabled()) { logger.debug("Invoking Put for key : " + key + " on store name : " + this.storeName); } this.sysStore.put(key, value, null); version = value.getVersion(); } catch(Exception e) { if(logger.isDebugEnabled()) { logger.debug("Exception caught during putSysStore: " + e); } logger.info("Exception during put", e); } return version; } public boolean deleteSysStore(K key) { try { if(logger.isDebugEnabled()) { logger.debug("Invoking Delete for key : " + key + " on store name : " + this.storeName); } Versioned<V> versioned = getSysStore(key); if(versioned == null) { // Nothing to delete return true; } return this.sysStore.delete(key, versioned.getVersion()); } catch(Exception e) { if(logger.isDebugEnabled()) { logger.debug("Exception caught during deleteSysStore: " + e); } logger.info("Exception during delete", e); return false; } } public Versioned<V> getSysStore(K key) { logger.debug("Invoking Get for key : " + key + " on store name : " + this.storeName); Versioned<V> versioned = null; try { List<Versioned<V>> items = this.sysStore.get(key, null); if(items.size() == 1) versioned = items.get(0); else if(items.size() > 1) throw new InconsistentDataException("Unresolved versions returned from get(" + key + ") = " + items, items); if(versioned != null) logger.debug("Value for key : " + key + " = " + versioned.getValue() + " on store name : " + this.storeName); else logger.debug("Got null value"); } catch(InvalidMetadataException e) { throw e; } catch(Exception e) { if(logger.isDebugEnabled()) { logger.debug("Exception caught during getSysStore: " + e); } } return versioned; } public V getValueSysStore(K key) { V value = null; try { logger.debug("Invoking Get for key : " + key + " on store name : " + this.storeName); Versioned<V> versioned = getSysStore(key); if(versioned != null) { logger.debug("Value for key : " + key + " = " + versioned.getValue() + " on store name : " + this.storeName); value = versioned.getValue(); } } catch(Exception e) { if(logger.isDebugEnabled()) { logger.debug("Exception caught during getSysStore: " + e); } } return value; } }