BUG-5280: implement backend message handling
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / AbstractFrontendHistory.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 java.util.HashMap;
12 import java.util.Map;
13 import java.util.Optional;
14 import javax.annotation.Nullable;
15 import org.opendaylight.controller.cluster.access.commands.CommitLocalTransactionRequest;
16 import org.opendaylight.controller.cluster.access.commands.OutOfOrderRequestException;
17 import org.opendaylight.controller.cluster.access.commands.TransactionRequest;
18 import org.opendaylight.controller.cluster.access.commands.TransactionSuccess;
19 import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
20 import org.opendaylight.controller.cluster.access.concepts.RequestEnvelope;
21 import org.opendaylight.controller.cluster.access.concepts.RequestException;
22 import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
23 import org.opendaylight.yangtools.concepts.Identifiable;
24 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * Abstract class for providing logical tracking of frontend local histories. This class is specialized for
30  * standalone transactions and chained transactions.
31  *
32  * @author Robert Varga
33  */
34 abstract class AbstractFrontendHistory implements Identifiable<LocalHistoryIdentifier> {
35     private static final Logger LOG = LoggerFactory.getLogger(AbstractFrontendHistory.class);
36     private static final OutOfOrderRequestException UNSEQUENCED_START = new OutOfOrderRequestException(0);
37
38     private final Map<TransactionIdentifier, FrontendTransaction> transactions = new HashMap<>();
39     private final String persistenceId;
40
41     AbstractFrontendHistory(final String persistenceId) {
42         this.persistenceId = Preconditions.checkNotNull(persistenceId);
43     }
44
45     final String persistenceId() {
46         return persistenceId;
47     }
48
49     final @Nullable TransactionSuccess<?> handleTransactionRequest(final TransactionRequest<?> request,
50             final RequestEnvelope envelope) throws RequestException {
51
52         // FIXME: handle purging of transactions
53
54         final TransactionIdentifier id = request.getTarget();
55         FrontendTransaction tx = transactions.get(id);
56         if (tx == null) {
57             // The transaction does not exist and we are about to create it, check sequence number
58             if (request.getSequence() != 0) {
59                 LOG.debug("{}: no transaction state present, unexpected request {}", persistenceId(), request);
60                 throw UNSEQUENCED_START;
61             }
62
63             if (request instanceof CommitLocalTransactionRequest) {
64                 tx = createReadyTransaction(id, ((CommitLocalTransactionRequest) request).getModification());
65                 LOG.debug("{}: allocated new ready transaction {}", persistenceId(), id);
66             } else {
67                 tx = createOpenTransaction(id);
68                 LOG.debug("{}: allocated new open transaction {}", persistenceId(), id);
69             }
70
71             transactions.put(id, tx);
72         } else {
73             final Optional<TransactionSuccess<?>> replay = tx.replaySequence(request.getSequence());
74             if (replay.isPresent()) {
75                 return replay.get();
76             }
77         }
78
79         return tx.handleRequest(request, envelope);
80     }
81
82     abstract FrontendTransaction createOpenTransaction(TransactionIdentifier id) throws RequestException;
83
84     abstract FrontendTransaction createReadyTransaction(TransactionIdentifier id, DataTreeModification mod)
85         throws RequestException;
86
87     abstract ShardDataTreeCohort createReadyCohort(final TransactionIdentifier id, final DataTreeModification mod);
88 }