/* * Copyright 2008-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.store; import java.util.List; import voldemort.VoldemortException; import voldemort.server.storage.KeyLockHandle; import voldemort.utils.ClosableIterator; import voldemort.utils.Pair; import voldemort.versioning.Versioned; /** * A base storage class which is actually responsible for data persistence. This * interface implies all the usual responsibilities of a Store implementation, * and in addition * <ol> * <li>The implementation MUST throw an ObsoleteVersionException if the user * attempts to put a version which is strictly before an existing version * (concurrent is okay)</li> * <li>The implementation MUST increment this version number when the value is * stored.</li> * <li>The implementation MUST contain an ID identifying it as part of the * cluster</li> * </ol> * * A hash value can be produced for known subtrees of a StorageEngine * * * @param <K> The type of the key being stored * @param <V> The type of the value being stored * @param <T> The type of the transforms * */ public interface StorageEngine<K, V, T> extends Store<K, V, T> { /** * Get an iterator over pairs of entries in the store. The key is the first * element in the pair and the versioned value is the second element. * * Note that the iterator need not be threadsafe, and that it must be * manually closed after use. * * @return An iterator over the entries in this StorageEngine. */ public ClosableIterator<Pair<K, Versioned<V>>> entries(); /** * Get an iterator over keys in the store. * * Note that the iterator need not be threadsafe, and that it must be * manually closed after use. * * @return An iterator over the keys in this StorageEngine. */ public ClosableIterator<K> keys(); /** * Get an iterator over pairs of entries in a store's partition. The key is * the first element in the pair and the versioned value is the second * element. * * Note that the iterator need not be threadsafe, and that it must be * manually closed after use. * * @param partition partition whose entries are to be fetched * @return An iterator over the entries in this StorageEngine. */ public ClosableIterator<Pair<K, Versioned<V>>> entries(int partition); /** * Get an iterator over keys in the store's partition * * Note that the iterator need not be threadsafe, and that it must be * manually closed after use. * * @param partition partition whose keys are to be fetched * @return An iterator over the keys in this StorageEngine. */ public ClosableIterator<K> keys(int partition); /** * Truncate all entries in the store */ public void truncate(); /** * Are partitions persisted in distinct files? In other words is the data * stored on disk on a per-partition basis? This is really for the read-only * use case in which each partition is stored in a distinct file. * * @return Boolean indicating if partitions are persisted in distinct files * (read-only use case). */ public boolean isPartitionAware(); /** * Does the storage engine support efficient scanning of a single partition? * * @return true if the storage engine implements the capability. false * otherwise */ public boolean isPartitionScanSupported(); /** * A lot of storage engines support efficient methods for performing large * number of writes (puts/deletes) against the data source. This method puts * the storage engine in this batch write mode * * @return true if the storage engine took successful action to switch to * 'batch-write' mode */ public boolean beginBatchModifications(); /** * Atomically update storage with the list of versioned values for the given * key, to improve storage efficiency. * * @param key Key to write * @param values List of versioned values to be written atomically. * @return list of obsolete versions that were rejected */ public List<Versioned<V>> multiVersionPut(K key, List<Versioned<V>> values); /** * Returns the list of versions stored for the key, at the same time locking * the key for any writes until * {@link StorageEngine#putAndUnlock(Object, KeyLockHandle)} or * {@link StorageEngine#releaseLock(KeyLockHandle)} is called with the same * lock handle. The idea here is to facilitate custom atomic * Read-Modify-Write logic outside the storage engine * * NOTE : An invocation of getAndLock should be followed by EXACTLY ONE call * to either putAndLock or releaseLock, for resources to be freed properly * * @param key * @return */ public KeyLockHandle<V> getAndLock(K key); /** * Takes the handle issued from a prior * {@link StorageEngine#getAndLock(Object)} call, and update the key with * the set of values provided in the handle, also releasing the lock held on * the key. * * @param key * @param handle handle object with new list of versions to be stored */ public void putAndUnlock(K key, KeyLockHandle<V> handle); /** * Release any lock held by a prior * {@link AbstractStorageEngine#getAndLock(Object)} call. Helpful for * exception handling during a read-modify-cycle * * @param handle */ public void releaseLock(KeyLockHandle<V> handle); /** * * @return true if the storage engine successfully returned to normal mode */ public boolean endBatchModifications(); }