BUG-9043: Remove use of CheckedFuture from YANG components
[yangtools.git] / yang / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / repo / util / InMemorySchemaSourceCache.java
index ad594e422116463671bb760fd75945ff647f0660..947e06f2c2f91e08e31e49fdca3c0c602795c687 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
@@ -7,16 +8,17 @@
 package org.opendaylight.yangtools.yang.model.repo.util;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
+import com.google.common.base.FinalizablePhantomReference;
+import com.google.common.base.FinalizableReferenceQueue;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.RemovalListener;
-import com.google.common.cache.RemovalNotification;
-import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
-
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource.Costs;
@@ -24,51 +26,67 @@ import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
 
 @Beta
-public class InMemorySchemaSourceCache<T extends SchemaSourceRepresentation> extends AbstractSchemaSourceCache<T> {
-    private static final class CacheEntry<T extends SchemaSourceRepresentation> {
-        private final SchemaSourceRegistration<T> reg;
-        private final T source;
-
-        public CacheEntry(final T source, final SchemaSourceRegistration<T> reg) {
-            this.source = Preconditions.checkNotNull(source);
-            this.reg = Preconditions.checkNotNull(reg);
-        }
-    }
+public class InMemorySchemaSourceCache<T extends SchemaSourceRepresentation> extends AbstractSchemaSourceCache<T>
+        implements AutoCloseable {
+    private final List<FinalizablePhantomReference<T>> regs = Collections.synchronizedList(new ArrayList<>());
+    private final FinalizableReferenceQueue queue = new FinalizableReferenceQueue();
+    private final Cache<SourceIdentifier, T> cache;
 
-    private static final RemovalListener<SourceIdentifier, CacheEntry<?>> LISTENER = new RemovalListener<SourceIdentifier, CacheEntry<?>>() {
-        @Override
-        public void onRemoval(final RemovalNotification<SourceIdentifier, CacheEntry<?>> notification) {
-            notification.getValue().reg.close();
-        }
-    };
-
-    private final Cache<SourceIdentifier, CacheEntry<T>> cache;
-
-    protected InMemorySchemaSourceCache(final SchemaSourceRegistry consumer, final Class<T> representation, final CacheBuilder<Object, Object> builder) {
+    protected InMemorySchemaSourceCache(final SchemaSourceRegistry consumer, final Class<T> representation,
+            final CacheBuilder<Object, Object> builder) {
         super(consumer, representation, Costs.IMMEDIATE);
-        cache = builder.removalListener(LISTENER).build();
+        cache = builder.build();
     }
 
-    public static <R extends SchemaSourceRepresentation> InMemorySchemaSourceCache<R> createSoftCache(final SchemaSourceRegistry consumer, final Class<R> representation) {
+    public static <R extends SchemaSourceRepresentation> InMemorySchemaSourceCache<R> createSoftCache(
+            final SchemaSourceRegistry consumer, final Class<R> representation) {
         return new InMemorySchemaSourceCache<>(consumer, representation, CacheBuilder.newBuilder().softValues());
     }
 
+    public static <R extends SchemaSourceRepresentation> InMemorySchemaSourceCache<R> createSoftCache(
+            final SchemaSourceRegistry consumer, final Class<R> representation, final long lifetime,
+            final TimeUnit units) {
+        return new InMemorySchemaSourceCache<>(consumer, representation, CacheBuilder.newBuilder().softValues()
+                .expireAfterAccess(lifetime, units));
+    }
+
     @Override
-    public CheckedFuture<? extends T, SchemaSourceException> getSource(final SourceIdentifier sourceIdentifier) {
-        final CacheEntry<T> present = cache.getIfPresent(sourceIdentifier);
+    public ListenableFuture<? extends T> getSource(final SourceIdentifier sourceIdentifier) {
+        final T present = cache.getIfPresent(sourceIdentifier);
         if (present != null) {
-            return Futures.immediateCheckedFuture(present.source);
+            return Futures.immediateFuture(present);
         }
 
-        return Futures.<T, SchemaSourceException>immediateFailedCheckedFuture(new MissingSchemaSourceException("Source not found", sourceIdentifier));
+        return Futures.immediateFailedFuture(new MissingSchemaSourceException("Source not found", sourceIdentifier));
     }
 
     @Override
     protected void offer(final T source) {
-        final CacheEntry<T> present = cache.getIfPresent(source.getIdentifier());
+        final T present = cache.getIfPresent(source.getIdentifier());
         if (present == null) {
+            cache.put(source.getIdentifier(), source);
+
             final SchemaSourceRegistration<T> reg = register(source.getIdentifier());
-            cache.put(source.getIdentifier(), new CacheEntry<T>(source, reg));
+            final FinalizablePhantomReference<T> ref = new FinalizablePhantomReference<T>(source, queue) {
+                @Override
+                public void finalizeReferent() {
+                    reg.close();
+                    regs.remove(this);
+                }
+            };
+
+            regs.add(ref);
+        }
+    }
+
+    @Override
+    public void close() {
+        while (!regs.isEmpty()) {
+            final FinalizablePhantomReference<?> ref = regs.get(0);
+            ref.finalizeReferent();
         }
+
+        cache.invalidateAll();
+        queue.close();
     }
 }