26b03e39b092c57d00876b030df15d1aeda015e8
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / databroker / actors / dds / ClientLocalHistory.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.annotations.Beta;
11 import com.google.common.base.Preconditions;
12 import org.opendaylight.controller.cluster.access.client.AbstractClientConnection;
13 import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
14 import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
15
16 /**
17  * Client-side view of a local history. This class tracks all state related to a particular history and routes
18  * frontend requests towards the backend.
19  *
20  * <p>
21  * This interface is used by the world outside of the actor system and in the actor system it is manifested via
22  * its client actor. That requires some state transfer with {@link AbstractDataStoreClientBehavior}. In order to
23  * reduce request latency, all messages are carbon-copied (and enqueued first) to the client actor.
24  *
25  * @author Robert Varga
26  */
27 @Beta
28 public final class ClientLocalHistory extends AbstractClientHistory implements AutoCloseable {
29     ClientLocalHistory(final AbstractDataStoreClientBehavior client, final LocalHistoryIdentifier historyId) {
30         super(client, historyId);
31     }
32
33     @Override
34     public void close() {
35         final State local = state();
36         if (local != State.CLOSED) {
37             Preconditions.checkState(local == State.IDLE, "Local history %s has an open transaction", this);
38             updateState(local, State.CLOSED);
39         }
40     }
41
42     private State ensureIdleState() {
43         final State local = state();
44         Preconditions.checkState(local == State.IDLE, "Local history %s state is %s", this, local);
45         return local;
46     }
47
48     @Override
49     ClientSnapshot doCreateSnapshot() {
50         ensureIdleState();
51         return new ClientSnapshot(this, new TransactionIdentifier(getIdentifier(), nextTx()));
52     }
53
54     @Override
55     ClientTransaction doCreateTransaction() {
56         updateState(ensureIdleState(), State.TX_OPEN);
57         return new ClientTransaction(this, new TransactionIdentifier(getIdentifier(), nextTx()));
58     }
59
60     @Override
61     void onTransactionAbort(final AbstractClientHandle<?> snap) {
62         if (snap instanceof ClientTransaction) {
63             final State local = state();
64             if (local == State.TX_OPEN) {
65                 updateState(local, State.IDLE);
66             }
67         }
68
69         super.onTransactionAbort(snap);
70     }
71
72     @Override
73     AbstractTransactionCommitCohort onTransactionReady(final ClientTransaction tx,
74             final AbstractTransactionCommitCohort cohort) {
75
76         final State local = state();
77         switch (local) {
78             case CLOSED:
79                 return super.onTransactionReady(tx, cohort);
80             case IDLE:
81                 throw new IllegalStateException(String.format("Local history %s is idle when readying transaction %s",
82                     this, tx.getIdentifier()));
83             case TX_OPEN:
84                 updateState(local, State.IDLE);
85                 return super.onTransactionReady(tx, cohort);
86             default:
87                 throw new IllegalStateException(String.format("Local history %s in unhandled state %s", this, local));
88
89         }
90     }
91
92     @Override
93     ProxyHistory createHistoryProxy(final LocalHistoryIdentifier historyId,
94             final AbstractClientConnection<ShardBackendInfo> connection) {
95         return ProxyHistory.createClient(connection, historyId);
96     }
97 }