/** * Copyright 2014 Benjamin Lerer * * 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 io.horizondb.db.btree; import io.horizondb.db.metrics.CacheMetrics; import io.horizondb.db.metrics.Monitorable; import io.horizondb.db.metrics.PrefixFilter; import java.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import com.codahale.metrics.MetricRegistry; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; /** * Cache used by the <code>OnDiskNodeManagers</code> to reduce the number of disk read. * * @author Benjamin * */ public final class NodeCache<K extends Comparable<K>, V> implements Monitorable { /** * The cache used to reduce disk read. */ private final Cache<NodeProxy<K, V>, Node<K, V>> cache; /** * The name of this cache. */ private final String name; /** * @param name * @param cache */ public NodeCache(String name, int cacheSize) { this.name = name; this.cache = CacheBuilder.newBuilder() .maximumSize(cacheSize) .recordStats() .build(); } /** * {@inheritDoc} */ @Override public String getName() { return this.name; } /** * {@inheritDoc} */ @Override public void register(MetricRegistry registry) { registry.registerAll(new CacheMetrics(this.name, this.cache)); } /** * {@inheritDoc} */ @Override public void unregister(MetricRegistry registry) { registry.removeMatching(new PrefixFilter(getName())); } /** * Adds the specified node to the cache. * * @param proxy the proxy associated to the specified node * @param node the node */ void put(NodeProxy<K, V> proxy, Node<K, V> node) { this.cache.put(proxy, node); } /** * Returns the node associated to the specified proxy. * * @param proxy the node proxy * @param reader the reader used to retrieve the node if it is not already in memory * @return the node associated to the specified proxy * @throws IOException if an I/O problem occurs. */ Node<K, V> get(final NodeProxy<K, V> proxy, final NodeReader<K, V> reader) throws IOException { try { return this.cache.get(proxy, new Callable<Node<K,V>>() { /** * {@inheritDoc} */ @Override public Node<K, V> call() throws Exception { return reader.readNode(proxy.getBTree(), proxy.getPosition()); } }); } catch (ExecutionException e) { throw new IOException(e.getCause()); } } }