BUG-5280: add FrontendMetadata
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / TransactionContextCleanup.java
1 /*
2  * Copyright (c) 2015 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.datastore;
9
10 import com.google.common.base.FinalizablePhantomReference;
11 import com.google.common.base.FinalizableReferenceQueue;
12 import java.util.Map;
13 import java.util.concurrent.ConcurrentHashMap;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 /**
18  * A PhantomReference that closes remote transactions for a TransactionContext when it's
19  * garbage collected. This is used for read-only transactions as they're not explicitly closed
20  * by clients. So the only way to detect that a transaction is no longer in use and it's safe
21  * to clean up is when it's garbage collected. It's inexact as to when an instance will be GC'ed
22  * but TransactionProxy instances should generally be short-lived enough to avoid being moved
23  * to the old generation space and thus should be cleaned up in a timely manner as the GC
24  * runs on the young generation (eden, swap1...) space much more frequently.
25  */
26 final class TransactionContextCleanup extends FinalizablePhantomReference<TransactionProxy> {
27     private static final Logger LOG = LoggerFactory.getLogger(TransactionContextCleanup.class);
28     /**
29      * Used to enqueue the PhantomReferences for read-only TransactionProxy instances. The
30      * FinalizableReferenceQueue is safe to use statically in an OSGi environment as it uses some
31      * trickery to clean up its internal thread when the bundle is unloaded.
32      */
33     private static final FinalizableReferenceQueue QUEUE = new FinalizableReferenceQueue();
34
35     /**
36      * This stores the TransactionProxyCleanupPhantomReference instances statically, This is
37      * necessary because PhantomReferences need a hard reference so they're not garbage collected.
38      * Once finalized, the TransactionProxyCleanupPhantomReference removes itself from this map
39      * and thus becomes eligible for garbage collection.
40      */
41     private static final Map<TransactionContext, TransactionContextCleanup> CACHE = new ConcurrentHashMap<>();
42
43     private final TransactionContext cleanup;
44
45     private TransactionContextCleanup(TransactionProxy referent, TransactionContext cleanup) {
46         super(referent, QUEUE);
47         this.cleanup = cleanup;
48     }
49
50     static void track(final TransactionProxy referent, final TransactionContext cleanup) {
51         final TransactionContextCleanup ret = new TransactionContextCleanup(referent, cleanup);
52         CACHE.put(cleanup, ret);
53     }
54
55     @Override
56     public void finalizeReferent() {
57         LOG.trace("Cleaning up {} Tx actors {}", cleanup);
58
59         if (CACHE.remove(cleanup) != null) {
60             cleanup.closeTransaction();
61         }
62     }
63
64     static void untrack(final TransactionContext cleanup) {
65         CACHE.remove(cleanup);
66     }
67 }