BUG-5280: fix problems identified by integration tests
[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     @Override
43     ClientTransaction doCreateTransaction() {
44         final State local = state();
45         Preconditions.checkState(local == State.IDLE, "Local history %s state is %s", this, local);
46         updateState(local, State.TX_OPEN);
47
48         return new ClientTransaction(this, new TransactionIdentifier(getIdentifier(), nextTx()));
49     }
50
51     @Override
52     void onTransactionAbort(final TransactionIdentifier txId) {
53         final State local = state();
54         if (local == State.TX_OPEN) {
55             updateState(local, State.IDLE);
56         }
57
58         super.onTransactionAbort(txId);
59     }
60
61     @Override
62     AbstractTransactionCommitCohort onTransactionReady(final TransactionIdentifier txId,
63             final AbstractTransactionCommitCohort cohort) {
64         final State local = state();
65         switch (local) {
66             case CLOSED:
67                 return super.onTransactionReady(txId, cohort);
68             case IDLE:
69                 throw new IllegalStateException(String.format("Local history %s is idle when readying transaction %s",
70                     this, txId));
71             case TX_OPEN:
72                 updateState(local, State.IDLE);
73                 return super.onTransactionReady(txId, cohort);
74             default:
75                 throw new IllegalStateException(String.format("Local history %s in unhandled state %s", this, local));
76
77         }
78     }
79
80     @Override
81     ProxyHistory createHistoryProxy(final LocalHistoryIdentifier historyId,
82             final AbstractClientConnection<ShardBackendInfo> connection) {
83         return ProxyHistory.createClient(connection, historyId);
84     }
85 }