BUG-5280: implement backend message handling
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / LocalFrontendHistory.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.datastore;
9
10 import com.google.common.base.Preconditions;
11 import org.opendaylight.controller.cluster.access.commands.DeadTransactionException;
12 import org.opendaylight.controller.cluster.access.commands.LocalHistorySuccess;
13 import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
14 import org.opendaylight.controller.cluster.access.concepts.RequestException;
15 import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
16 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20
21 /**
22  * Chained transaction specialization of {@link AbstractFrontendHistory}. It prevents concurrent open transactions.
23  *
24  * @author Robert Varga
25  */
26 final class LocalFrontendHistory extends AbstractFrontendHistory {
27     private enum State {
28         OPEN,
29         CLOSED,
30     }
31
32     private static final Logger LOG = LoggerFactory.getLogger(LocalFrontendHistory.class);
33
34     private final ShardDataTreeTransactionChain chain;
35
36     private Long lastSeenTransaction;
37     private State state = State.OPEN;
38
39     LocalFrontendHistory(final String persistenceId, final ShardDataTreeTransactionChain chain) {
40         super(persistenceId);
41         this.chain = Preconditions.checkNotNull(chain);
42     }
43
44     @Override
45     public LocalHistoryIdentifier getIdentifier() {
46         return chain.getIdentifier();
47     }
48
49     @Override
50     FrontendTransaction createOpenTransaction(final TransactionIdentifier id) throws RequestException {
51         checkDeadTransaction(id);
52         lastSeenTransaction = id.getTransactionId();
53         return FrontendTransaction.createOpen(this, chain.newReadWriteTransaction(id));
54     }
55
56     @Override
57     FrontendTransaction createReadyTransaction(final TransactionIdentifier id, final DataTreeModification mod)
58             throws RequestException {
59         checkDeadTransaction(id);
60         lastSeenTransaction = id.getTransactionId();
61         return FrontendTransaction.createReady(this, id, mod);
62     }
63
64     @Override
65     ShardDataTreeCohort createReadyCohort(final TransactionIdentifier id, final DataTreeModification mod) {
66         return chain.createReadyCohort(id, mod);
67     }
68
69     LocalHistorySuccess destroy(final long sequence) throws RequestException {
70         if (state != State.CLOSED) {
71             LOG.debug("{}: closing history {}", persistenceId(), getIdentifier());
72
73             // FIXME: add any finalization as needed
74             state = State.CLOSED;
75         }
76
77         // FIXME: record a DESTROY tombstone in the journal
78         return new LocalHistorySuccess(getIdentifier(), sequence);
79     }
80
81     boolean isDestroyed() {
82         return state == State.CLOSED;
83     }
84
85     private void checkDeadTransaction(final TransactionIdentifier id) throws RequestException {
86         // FIXME: check if this history is still open
87         // FIXME: check if the last transaction has been submitted
88
89         // Transaction identifiers within a local history have to have increasing IDs
90         if (lastSeenTransaction != null && Long.compareUnsigned(lastSeenTransaction, id.getTransactionId()) >= 0) {
91             throw new DeadTransactionException(lastSeenTransaction);
92         }
93     }
94 }