Declare SuppressFBWarnings in imports
[transportpce.git] / common / src / main / java / org / opendaylight / transportpce / common / network / RequestProcessor.java
1 /*
2  * Copyright © 2017 Orange, 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.transportpce.common.network;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.util.concurrent.FluentFuture;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
15 import java.util.HashMap;
16 import java.util.Map;
17 import java.util.Optional;
18 import java.util.concurrent.locks.Lock;
19 import java.util.concurrent.locks.ReentrantReadWriteLock;
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.opendaylight.mdsal.binding.api.DataBroker;
22 import org.opendaylight.mdsal.binding.api.ReadTransaction;
23 import org.opendaylight.mdsal.binding.api.WriteTransaction;
24 import org.opendaylight.mdsal.common.api.CommitInfo;
25 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
26 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
27 import org.opendaylight.yangtools.yang.binding.DataObject;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 @SuppressFBWarnings(value = "UL_UNRELEASED_LOCK_EXCEPTION_PATH",
33     justification = "This appears to be doing exactly the right thing with the finally-clause to release the lock")
34 public class RequestProcessor {
35
36     private static final Logger LOG = LoggerFactory.getLogger(RequestProcessor.class);
37
38     private final DataBroker dataBroker;
39     private final ReentrantReadWriteLock rwL = new ReentrantReadWriteLock();
40     private final Lock readL = rwL.readLock();
41     private final Lock writeL = rwL.writeLock();
42     private Map<String, WriteTransaction> writeTrMap = new HashMap<>();
43
44
45     public RequestProcessor(DataBroker dataBroker) {
46         this.dataBroker = requireNonNull(dataBroker);
47         LOG.info("RequestProcessor instantiated");
48     }
49
50     public <T extends DataObject> ListenableFuture<Optional<T>> read(LogicalDatastoreType store,
51             InstanceIdentifier<T> path) {
52         ReadTransaction readTx = dataBroker.newReadOnlyTransaction();
53         String thread = Thread.currentThread().getName();
54         readL.lock();
55         LOG.debug("read locked {} by {}", store, thread);
56         try {
57             return readTx.read(store, path);
58         }
59         finally {
60             readTx.close();
61             readL.unlock();
62             LOG.debug("read after unlock - {}", thread);
63         }
64     }
65
66     public <T extends DataObject> void delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
67         String thread = Thread.currentThread().getName();
68         LOG.debug("delete - store, thread = {} - {}", store, thread);
69         writeL.lock();
70         LOG.debug("delete locked by {}", thread);
71         try {
72             if (!writeTrMap.containsKey(thread)) {
73                 writeTrMap.put(thread, dataBroker.newWriteOnlyTransaction());
74             }
75             writeTrMap.get(thread).delete(store, path);
76         }
77         finally {
78             LOG.debug("delete before unlock - {}", thread);
79             writeL.unlock();
80             LOG.debug("delete after unlock1 - {}", Thread.currentThread().getName());
81             LOG.debug("delete after unlock2 - {}", thread);
82         }
83     }
84
85     public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
86         String thread = Thread.currentThread().getName();
87         writeL.lock();
88         LOG.debug("put locked {} by {}", store, thread);
89         try {
90             if (!writeTrMap.containsKey(thread)) {
91                 writeTrMap.put(thread, dataBroker.newWriteOnlyTransaction());
92             }
93             writeTrMap.get(thread).put(store, path, data);
94         }
95         finally {
96             writeL.unlock();
97             LOG.debug("put after unlock - {}", thread);
98         }
99     }
100
101     public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
102         String thread = Thread.currentThread().getName();
103         writeL.lock();
104         LOG.debug("merge locked {} by {}", store, thread);
105         try {
106             if (!writeTrMap.containsKey(thread)) {
107                 writeTrMap.put(thread, dataBroker.newWriteOnlyTransaction());
108             }
109             writeTrMap.get(thread).merge(store, path, data);
110         }
111         finally {
112             writeL.unlock();
113             LOG.debug("merge after unlock - {}", thread);
114         }
115     }
116
117     public FluentFuture<? extends @NonNull CommitInfo> commit() {
118         String thread = Thread.currentThread().getName();
119         writeL.lock();
120         LOG.debug("commit locked by {}", thread);
121         try {
122             if (writeTrMap.containsKey(thread)) {
123                 return writeTrMap.get(thread).commit();
124             } else {
125                 LOG.warn("No write transaction available for thread {}", thread);
126                 return FluentFutures.immediateNullFluentFuture();
127             }
128         }
129         finally {
130             writeTrMap.remove(thread);
131             writeL.unlock();
132             LOG.debug("commit after unlock - {}", thread);
133         }
134     }
135
136     /**
137      * Return the dataBroker related to RequestProcessor.
138      * @return the dataBroker
139      */
140     public DataBroker getDataBroker() {
141         return dataBroker;
142     }
143 }