BUG-5280: handle TransactionPurgeRequest replay
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / databroker / actors / dds / LocalReadOnlyProxyTransaction.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 com.google.common.base.Verify;
12 import java.util.function.Consumer;
13 import javax.annotation.concurrent.NotThreadSafe;
14 import org.opendaylight.controller.cluster.access.commands.AbortLocalTransactionRequest;
15 import org.opendaylight.controller.cluster.access.commands.CommitLocalTransactionRequest;
16 import org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequest;
17 import org.opendaylight.controller.cluster.access.commands.PersistenceProtocol;
18 import org.opendaylight.controller.cluster.access.commands.TransactionPurgeRequest;
19 import org.opendaylight.controller.cluster.access.commands.TransactionRequest;
20 import org.opendaylight.controller.cluster.access.concepts.Response;
21 import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
22 import org.opendaylight.controller.cluster.datastore.util.AbstractDataTreeModificationCursor;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
25 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
27 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * A read-only specialization of {@link LocalProxyTransaction}.
33  *
34  * @author Robert Varga
35  */
36 @NotThreadSafe
37 final class LocalReadOnlyProxyTransaction extends LocalProxyTransaction {
38     private static final Logger LOG = LoggerFactory.getLogger(LocalReadOnlyProxyTransaction.class);
39
40     private final DataTreeSnapshot snapshot;
41
42     LocalReadOnlyProxyTransaction(final ProxyHistory parent, final TransactionIdentifier identifier,
43         final DataTreeSnapshot snapshot) {
44         super(parent, identifier);
45         this.snapshot = Preconditions.checkNotNull(snapshot);
46     }
47
48     @Override
49     boolean isSnapshotOnly() {
50         return true;
51     }
52
53     @Override
54     DataTreeSnapshot readOnlyView() {
55         return snapshot;
56     }
57
58     @Override
59     void doDelete(final YangInstanceIdentifier path) {
60         throw new UnsupportedOperationException("Read-only snapshot");
61     }
62
63     @Override
64     void doMerge(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
65         throw new UnsupportedOperationException("Read-only snapshot");
66     }
67
68     @Override
69     void doWrite(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
70         throw new UnsupportedOperationException("Read-only snapshot");
71     }
72
73     @Override
74     CommitLocalTransactionRequest commitRequest(final boolean coordinated) {
75         throw new UnsupportedOperationException("Read-only snapshot");
76     }
77
78     @Override
79     void doSeal() {
80         // No-op
81     }
82
83     @Override
84     void flushState(final AbstractProxyTransaction successor) {
85         // No-op
86     }
87
88     @Override
89     void applyModifyTransactionRequest(final ModifyTransactionRequest request,
90             final Consumer<Response<?, ?>> callback) {
91         Verify.verify(request.getModifications().isEmpty());
92
93         final PersistenceProtocol protocol = request.getPersistenceProtocol().get();
94         Verify.verify(protocol == PersistenceProtocol.ABORT);
95         abort();
96     }
97
98     @Override
99     void forwardToRemote(final RemoteProxyTransaction successor, final TransactionRequest<?> request,
100             final Consumer<Response<?, ?>> callback) {
101         if (request instanceof CommitLocalTransactionRequest) {
102             final CommitLocalTransactionRequest req = (CommitLocalTransactionRequest) request;
103             final DataTreeModification mod = req.getModification();
104
105             LOG.debug("Applying modification {} to successor {}", mod, successor);
106             mod.applyToCursor(new AbstractDataTreeModificationCursor() {
107                 @Override
108                 public void write(final PathArgument child, final NormalizedNode<?, ?> data) {
109                     successor.write(current().node(child), data);
110                 }
111
112                 @Override
113                 public void merge(final PathArgument child, final NormalizedNode<?, ?> data) {
114                     successor.merge(current().node(child), data);
115                 }
116
117                 @Override
118                 public void delete(final PathArgument child) {
119                     successor.delete(current().node(child));
120                 }
121             });
122
123             successor.ensureSealed();
124
125             final ModifyTransactionRequest successorReq = successor.commitRequest(req.isCoordinated());
126             successor.sendRequest(successorReq, callback);
127         } else if (request instanceof AbortLocalTransactionRequest) {
128             LOG.debug("Forwarding abort {} to successor {}", request, successor);
129             successor.abort();
130         } else if (request instanceof TransactionPurgeRequest) {
131             LOG.debug("Forwarding purge {} to successor {}", request, successor);
132             successor.purge();
133         } else {
134             throw new IllegalArgumentException("Unhandled request" + request);
135         }
136     }
137 }