JUnit for IdManager
[vpnservice.git] / idmanager / idmanager-impl / src / main / java / org / opendaylight / idmanager / IdManager.java
1 /*
2  * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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
9 package org.opendaylight.idmanager;
10
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
16 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.yangtools.concepts.ListenerRegistration;
20 import org.opendaylight.yangtools.yang.binding.DataObject;
21 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
22 import org.opendaylight.yangtools.yang.common.RpcResult;
23 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.*;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.*;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.id.pool.*;
29
30 import java.math.BigInteger;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.concurrent.Future;
34
35
36 public class IdManager implements IdManagerService, AutoCloseable{
37     private static final Logger LOG = LoggerFactory.getLogger(IdManager.class);
38     private ListenerRegistration<DataChangeListener> listenerRegistration;
39     private final DataBroker broker;
40
41
42
43     @Override
44     public void close() throws Exception {
45         if (listenerRegistration != null) {
46             try {
47                 listenerRegistration.close();
48             } catch (final Exception e) {
49                 LOG.error("Error when cleaning up DataChangeListener.", e);
50             }
51             listenerRegistration = null;
52         }
53         LOG.info("IDManager Closed");
54     }
55
56     public IdManager(final DataBroker db) {
57         broker = db;
58     }
59
60     private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
61                                                     InstanceIdentifier<T> path) {
62
63         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
64
65         Optional<T> result = Optional.absent();
66         try {
67             result = tx.read(datastoreType, path).get();
68         } catch (Exception e) {
69             throw new RuntimeException(e);
70         }
71
72         return result;
73     }
74
75     protected  <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
76                                                    InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
77         WriteTransaction tx = broker.newWriteOnlyTransaction();
78         tx.put(datastoreType, path, data, true);
79         Futures.addCallback(tx.submit(), callback);
80     }
81
82     protected  <T extends DataObject> void asyncUpdate(LogicalDatastoreType datastoreType,
83                                                     InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
84         WriteTransaction tx = broker.newWriteOnlyTransaction();
85         tx.merge(datastoreType, path, data, true);
86         Futures.addCallback(tx.submit(), callback);
87     }
88
89     @Override
90     public Future<RpcResult<Void>> createIdPool(CreateIdPoolInput input)
91     {
92
93         String poolName = input.getPoolName();
94         long startIndx = input.getIdStart();
95         long poolSize = input.getPoolSize().longValue();
96         RpcResultBuilder<Void> rpcResultBuilder;
97
98         LOG.debug("poolName: {}, startIndx: {} , poolSize: {} ", poolName, startIndx,  poolSize);
99
100         try {
101             InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
102                     InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName));
103             InstanceIdentifier<IdPool> id = idBuilder.build();
104             Optional<IdPool> pool = read(LogicalDatastoreType.OPERATIONAL, id);
105             if (!pool.isPresent()) {
106                 LOG.debug("Creating a new global pool: {} ", poolName);
107                 IdPool newPool = getPoolInterface(poolName, startIndx, poolSize);
108                 LOG.debug("NewPool: {}", newPool);
109                 asyncWrite(LogicalDatastoreType.OPERATIONAL, id, newPool, DEFAULT_CALLBACK);
110
111             }
112
113             rpcResultBuilder = RpcResultBuilder.success();
114         }
115         catch(Exception e){
116             LOG.error("Creation of global pool {} failed due to {}" ,poolName, e);
117             rpcResultBuilder = RpcResultBuilder.failed();
118         }
119
120         return Futures.immediateFuture(rpcResultBuilder.build());
121     }
122
123
124     @Override
125     public Future<RpcResult<GetUniqueIdOutput>> getUniqueId(GetUniqueIdInput input){
126
127         String poolName = input.getPoolName();
128         String idKey = input.getIdKey();
129
130         LOG.debug("poolName: {} ,idKey: {}", poolName, idKey);
131         RpcResultBuilder<GetUniqueIdOutput> rpcResultBuilder;
132
133         try {
134             InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
135                     InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName));
136             InstanceIdentifier<IdPool> id = idBuilder.build();
137             Optional<IdPool> globalPool = read(LogicalDatastoreType.OPERATIONAL, id);
138             GetUniqueIdOutputBuilder output = new GetUniqueIdOutputBuilder();
139             Long newIdValue = null;
140             GeneratedIds newGenId = null;
141             if (globalPool.isPresent()) {
142                 IdPool pool = globalPool.get();
143                 List<GeneratedIds> generatedIds = pool.getGeneratedIds();
144
145                 if (generatedIds == null) {
146                     generatedIds = new ArrayList<GeneratedIds>();
147                 }
148                 if (!generatedIds.isEmpty()) {
149                     for (GeneratedIds genId : generatedIds) {
150                         if (genId.getIdKey().equals(idKey)) {
151                             newIdValue = genId.getIdValue();
152                             LOG.debug("Existing id {} for the key {} ", idKey, newIdValue);
153                         }
154
155                     }
156                 }
157                 synchronized (this) {
158                     if (newIdValue == null) {
159                         newIdValue = (long) generatedIds.size() + 1;
160                         LOG.debug("Creating a new id {} for the pool: {} ", newIdValue, poolName);
161                         newGenId = getIdsInterface(idKey, newIdValue);
162                         generatedIds.add(newGenId);
163                         pool = new IdPoolBuilder(pool).setGeneratedIds(generatedIds).build();
164                         asyncUpdate(LogicalDatastoreType.OPERATIONAL, id, pool, DEFAULT_CALLBACK);
165                     }
166                 }
167                 output.setIdValue(newIdValue);
168             }
169
170             rpcResultBuilder = RpcResultBuilder.success();
171             rpcResultBuilder.withResult(output.build());
172         }
173         catch(Exception e){
174             LOG.error("Creation of id for the key {} , global pool {} failed due to {}" ,idKey, poolName, e);
175             rpcResultBuilder = RpcResultBuilder.failed();
176         }
177         return Futures.immediateFuture(rpcResultBuilder.build());
178     }
179
180
181     private IdPool getPoolInterface(String poolName, long startIndx, long poolSize) {
182         BigInteger size = BigInteger.valueOf(poolSize);
183         return new IdPoolBuilder().setKey(new IdPoolKey(poolName)).setPoolName(poolName).setIdStart(startIndx)
184                 .setPoolSize(size).build();
185     }
186
187     private GeneratedIds getIdsInterface(String idKey, long newIdVal) {
188         return new GeneratedIdsBuilder().setKey(new GeneratedIdsKey(idKey)).setIdKey(idKey)
189                 .setIdValue(newIdVal).build();
190     }
191
192     private static final FutureCallback<Void> DEFAULT_CALLBACK =
193         new FutureCallback<Void>() {
194             public void onSuccess(Void result) {
195                 LOG.debug("Success in Datastore write operation");
196             }
197
198             public void onFailure(Throwable error) {
199                 LOG.error("Error in Datastore write operation", error);
200             }
201         };
202 }