7608556e6e8a0ad67d7c6a634c80dc2f70a4fa80
[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, AbstractProxyHistory> 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     @Override
59     public final LocalHistoryIdentifier getIdentifier() {
60         return identifier;
61     }
62
63     final DistributedDataStoreClientBehavior getClient() {
64         return client;
65     }
66
67     @Override
68     final void localAbort(final Throwable cause) {
69         LOG.debug("Force-closing history {}", getIdentifier(), cause);
70         state = State.CLOSED;
71     }
72
73     private AbstractProxyHistory createHistoryProxy(final Long shard) {
74         final LocalHistoryIdentifier historyId = new LocalHistoryIdentifier(identifier.getClientId(),
75             identifier.getHistoryId(), shard);
76         return AbstractProxyHistory.create(client, client.resolver().getFutureBackendInfo(shard), historyId);
77     }
78
79     final AbstractProxyTransaction createTransactionProxy(final TransactionIdentifier transactionId, final Long shard) {
80         final AbstractProxyHistory history = histories.computeIfAbsent(shard, this::createHistoryProxy);
81         return history.createTransactionProxy(transactionId);
82     }
83
84     /**
85      * Callback invoked from {@link ClientTransaction} when a transaction has been sub
86      *
87      * @param transaction Transaction handle
88      */
89     void onTransactionReady(final ClientTransaction transaction) {
90         client.transactionComplete(transaction);
91     }
92 }