BUG-5280: move proxy instantiation to AbstractClientHistory
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / databroker / actors / dds / AbstractClientHistory.java
1 /*
2  * Copyright (c) 2016 Cisco 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.databroker.actors.dds;
9
10 import com.google.common.base.Preconditions;
11 import java.util.Map;
12 import java.util.concurrent.ConcurrentHashMap;
13 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
14 import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
15 import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
16 import org.opendaylight.yangtools.concepts.Identifiable;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 /**
21  * Abstract base class for client view of a history. This class has two implementations, one for normal local histories
22  * and the other for single transactions.
23  *
24  * @author Robert Varga
25  */
26 abstract class AbstractClientHistory extends LocalAbortable implements Identifiable<LocalHistoryIdentifier> {
27     static enum State {
28         IDLE,
29         TX_OPEN,
30         CLOSED,
31     }
32
33     private static final Logger LOG = LoggerFactory.getLogger(AbstractClientHistory.class);
34     private static final AtomicReferenceFieldUpdater<AbstractClientHistory, State> STATE_UPDATER =
35             AtomicReferenceFieldUpdater.newUpdater(AbstractClientHistory.class, State.class, "state");
36
37     private final Map<Long, LocalHistoryIdentifier> histories = new ConcurrentHashMap<>();
38     private final DistributedDataStoreClientBehavior client;
39     private final LocalHistoryIdentifier identifier;
40
41     private volatile State state = State.IDLE;
42
43     AbstractClientHistory(final DistributedDataStoreClientBehavior client, final LocalHistoryIdentifier identifier) {
44         this.client = Preconditions.checkNotNull(client);
45         this.identifier = Preconditions.checkNotNull(identifier);
46         Preconditions.checkArgument(identifier.getCookie() == 0);
47     }
48
49     final State state() {
50         return state;
51     }
52
53     final void updateState(final State expected, final State next) {
54         final boolean success = STATE_UPDATER.compareAndSet(this, expected, next);
55         Preconditions.checkState(success, "Race condition detected, state changed from %s to %s", expected, state);
56     }
57
58     private LocalHistoryIdentifier getHistoryForCookie(final Long cookie) {
59         LocalHistoryIdentifier ret = histories.get(cookie);
60         if (ret == null) {
61             ret = new LocalHistoryIdentifier(identifier.getClientId(), identifier.getHistoryId(), cookie);
62             final LocalHistoryIdentifier existing = histories.putIfAbsent(cookie, ret);
63             if (existing != null) {
64                 ret = existing;
65             }
66         }
67
68         return ret;
69     }
70
71     @Override
72     public final LocalHistoryIdentifier getIdentifier() {
73         return identifier;
74     }
75
76     final DistributedDataStoreClientBehavior getClient() {
77         return client;
78     }
79
80     @Override
81     final void localAbort(final Throwable cause) {
82         LOG.debug("Force-closing history {}", getIdentifier(), cause);
83         state = State.CLOSED;
84     }
85
86     final AbstractProxyTransaction createTransactionProxy(final TransactionIdentifier transactionId, final Long shard) {
87         return AbstractProxyTransaction.create(client, getHistoryForCookie(shard),
88             transactionId.getTransactionId(), client.resolver().getFutureBackendInfo(shard));
89     }
90
91     /**
92      * Callback invoked from {@link ClientTransaction} when a transaction has been sub
93      *
94      * @param transaction Transaction handle
95      */
96     void onTransactionReady(final ClientTransaction transaction) {
97         client.transactionComplete(transaction);
98     }
99 }