/* * Copyright 2012 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.nonblockingstore; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import org.apache.log4j.Level; import org.apache.log4j.Logger; import voldemort.VoldemortException; import voldemort.store.Store; import voldemort.store.StoreRequest; import voldemort.store.UnreachableStoreException; import voldemort.utils.ByteArray; import voldemort.utils.Time; import voldemort.utils.Utils; import voldemort.versioning.Version; import voldemort.versioning.Versioned; public class ThreadPoolBasedNonblockingStoreImpl implements NonblockingStore { private final ExecutorService executor; private final Store<ByteArray, byte[], byte[]> innerStore; private final Logger logger = Logger.getLogger(ThreadPoolBasedNonblockingStoreImpl.class); public ThreadPoolBasedNonblockingStoreImpl(ExecutorService executor, Store<ByteArray, byte[], byte[]> innerStore) { this.executor = Utils.notNull(executor); this.innerStore = Utils.notNull(innerStore); } public void submitGetAllRequest(final Iterable<ByteArray> keys, final Map<ByteArray, byte[]> transforms, final NonblockingStoreCallback callback, long timeoutMs) { submit(new StoreRequest<Map<ByteArray, List<Versioned<byte[]>>>>() { public Map<ByteArray, List<Versioned<byte[]>>> request(Store<ByteArray, byte[], byte[]> store) { return innerStore.getAll(keys, transforms); } }, callback, timeoutMs, "get all"); } public void submitGetRequest(final ByteArray key, final byte[] transforms, NonblockingStoreCallback callback, long timeoutMs) { submit(new StoreRequest<List<Versioned<byte[]>>>() { public List<Versioned<byte[]>> request(Store<ByteArray, byte[], byte[]> store) { return innerStore.get(key, transforms); } }, callback, timeoutMs, "get"); } public void submitGetVersionsRequest(final ByteArray key, NonblockingStoreCallback callback, long timeoutMs) { submit(new StoreRequest<List<Version>>() { public List<Version> request(Store<ByteArray, byte[], byte[]> store) { return innerStore.getVersions(key); } }, callback, timeoutMs, "submit"); } public void submitPutRequest(final ByteArray key, final Versioned<byte[]> value, final byte[] transforms, NonblockingStoreCallback callback, long timeoutMs) { submit(new StoreRequest<Void>() { public Void request(Store<ByteArray, byte[], byte[]> store) { innerStore.put(key, value, transforms); return null; } }, callback, timeoutMs, "put"); } public void submitDeleteRequest(final ByteArray key, final Version version, NonblockingStoreCallback callback, long timeoutMs) { submit(new StoreRequest<Boolean>() { public Boolean request(Store<ByteArray, byte[], byte[]> store) { return innerStore.delete(key, version); } }, callback, timeoutMs, "delete"); } private void submit(final StoreRequest<?> request, final NonblockingStoreCallback callback, final long timeoutMs, final String operationName) { executor.submit(new Runnable() { public void run() { long start = System.nanoTime(); final long timeoutNs = timeoutMs * Time.NS_PER_MS; try { Object result = request.request(innerStore); if(callback != null) { long diff = Utils.elapsedTimeNs(start, System.nanoTime()); if(diff <= timeoutNs) { try { callback.requestComplete(result, diff / Time.NS_PER_MS); } catch(Exception e) { if(logger.isEnabledFor(Level.WARN)) logger.warn(e, e); } } else { UnreachableStoreException ex = new UnreachableStoreException("Failure in " + operationName + ": time out exceeded"); try { callback.requestComplete(ex, diff / Time.NS_PER_MS); } catch(Exception e) { if(logger.isEnabledFor(Level.WARN)) logger.warn(e, e); } } } } catch(Exception e) { if(callback != null) { long diff = System.nanoTime() - start; try { callback.requestComplete(e, diff / Time.NS_PER_MS); } catch(Exception ex) { if(logger.isEnabledFor(Level.WARN)) logger.warn(ex, ex); } } } } }); } public void close() throws VoldemortException { innerStore.close(); } }