summaryrefslogtreecommitdiff
path: root/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java
diff options
context:
space:
mode:
Diffstat (limited to 'hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java')
-rw-r--r--hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java168
1 files changed, 168 insertions, 0 deletions
diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java
new file mode 100644
index 0000000000..6ae45b6d08
--- /dev/null
+++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.hadoop.ozone.container.common.utils;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.collections.MapIterator;
+import org.apache.commons.collections.map.LRUMap;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.ozone.OzoneConfigKeys;
+import org.apache.hadoop.utils.MetadataStore;
+import org.apache.hadoop.utils.MetadataStoreBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * container cache is a LRUMap that maintains the DB handles.
+ */
+public final class ContainerCache extends LRUMap {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(ContainerCache.class);
+ private final Lock lock = new ReentrantLock();
+ private static ContainerCache cache;
+ private static final float LOAD_FACTOR = 0.75f;
+ /**
+ * Constructs a cache that holds DBHandle references.
+ */
+ private ContainerCache(int maxSize, float loadFactor, boolean
+ scanUntilRemovable) {
+ super(maxSize, loadFactor, scanUntilRemovable);
+ }
+
+ /**
+ * Return a singleton instance of {@link ContainerCache}
+ * that holds the DB handlers.
+ *
+ * @param conf - Configuration.
+ * @return A instance of {@link ContainerCache}.
+ */
+ public synchronized static ContainerCache getInstance(Configuration conf) {
+ if (cache == null) {
+ int cacheSize = conf.getInt(OzoneConfigKeys.OZONE_CONTAINER_CACHE_SIZE,
+ OzoneConfigKeys.OZONE_CONTAINER_CACHE_DEFAULT);
+ cache = new ContainerCache(cacheSize, LOAD_FACTOR, true);
+ }
+ return cache;
+ }
+
+ /**
+ * Closes a db instance.
+ *
+ * @param container - name of the container to be closed.
+ * @param db - db instance to close.
+ */
+ private void closeDB(String container, MetadataStore db) {
+ if (db != null) {
+ try {
+ db.close();
+ } catch (IOException e) {
+ LOG.error("Error closing DB. Container: " + container, e);
+ }
+ }
+ }
+
+ /**
+ * Closes all the db instances and resets the cache.
+ */
+ public void shutdownCache() {
+ lock.lock();
+ try {
+ // iterate the cache and close each db
+ MapIterator iterator = cache.mapIterator();
+ while (iterator.hasNext()) {
+ iterator.next();
+ MetadataStore db = (MetadataStore) iterator.getValue();
+ closeDB(iterator.getKey().toString(), db);
+ }
+ // reset the cache
+ cache.clear();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean removeLRU(LinkEntry entry) {
+ lock.lock();
+ try {
+ MetadataStore db = (MetadataStore) entry.getValue();
+ closeDB(entry.getKey().toString(), db);
+ } finally {
+ lock.unlock();
+ }
+ return true;
+ }
+
+ /**
+ * Returns a DB handle if available, create the handler otherwise.
+ *
+ * @param containerName - Name of the container.
+ * @return MetadataStore.
+ */
+ public MetadataStore getDB(String containerName, String containerDBPath)
+ throws IOException {
+ Preconditions.checkNotNull(containerName);
+ Preconditions.checkState(!containerName.isEmpty());
+ lock.lock();
+ try {
+ MetadataStore db = (MetadataStore) this.get(containerName);
+
+ if (db == null) {
+ db = MetadataStoreBuilder.newBuilder()
+ .setDbFile(new File(containerDBPath))
+ .setCreateIfMissing(false)
+ .build();
+ this.put(containerName, db);
+ }
+ return db;
+ } catch (Exception e) {
+ LOG.error("Error opening DB. Container:{} ContainerPath:{}",
+ containerName, containerDBPath, e);
+ throw e;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Remove a DB handler from cache.
+ *
+ * @param containerName - Name of the container.
+ */
+ public void removeDB(String containerName) {
+ Preconditions.checkNotNull(containerName);
+ Preconditions.checkState(!containerName.isEmpty());
+ lock.lock();
+ try {
+ MetadataStore db = (MetadataStore)this.get(containerName);
+ closeDB(containerName, db);
+ this.remove(containerName);
+ } finally {
+ lock.unlock();
+ }
+ }
+}