8dece75e57a475632e4a351fbfe5765bc10f362f
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / dao / ClusterDAOService.java
1 /*
2  * Copyright (c) 2013 Contextream, 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
9 package org.opendaylight.lispflowmapping.implementation.dao;
10
11 import java.lang.reflect.ParameterizedType;
12 import java.util.EnumSet;
13 import java.util.HashMap;
14 import java.util.Iterator;
15 import java.util.Map;
16 import java.util.concurrent.ConcurrentMap;
17 import java.util.concurrent.Executors;
18 import java.util.concurrent.ScheduledExecutorService;
19 import java.util.concurrent.TimeUnit;
20
21 import org.opendaylight.controller.clustering.services.CacheConfigException;
22 import org.opendaylight.controller.clustering.services.CacheExistException;
23 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
24 import org.opendaylight.controller.clustering.services.IClusterServices;
25 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
26 import org.opendaylight.lispflowmapping.interfaces.dao.ILispTypeConverter;
27 import org.opendaylight.lispflowmapping.interfaces.dao.IQueryAll;
28 import org.opendaylight.lispflowmapping.interfaces.dao.IRowVisitor;
29 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
30 import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceRLOC;
31 import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceValue;
32 import org.opendaylight.lispflowmapping.interfaces.dao.MappingValueKey;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 public class ClusterDAOService implements ILispDAO, IQueryAll {
37
38     protected static final Logger logger = LoggerFactory.getLogger(ClusterDAOService.class);
39     private IClusterContainerServices clusterContainerService = null;
40     private ConcurrentMap<Class<?>, Map<Object, Map<String, Object>>> typeToKeysToValues;
41     private final String CACHE_NAME = "mappingServiceCache";
42     private TimeUnit timeUnit = TimeUnit.SECONDS;
43     private int recordTimeOut = 240;
44     private int cleanInterval = 10;
45     private ScheduledExecutorService scheduler;
46
47     void setClusterContainerService(IClusterContainerServices s) {
48         this.clusterContainerService = s;
49         allocateCache();
50         retrieveCache();
51         scheduler = Executors.newScheduledThreadPool(1);
52         scheduler.scheduleAtFixedRate(new Runnable() {
53
54             public void run() {
55                 cleanOld();
56             }
57         }, 0, cleanInterval, timeUnit);
58     }
59
60     void unsetClusterContainerService(IClusterContainerServices s) {
61         logger.debug("Cluster Service unset");
62         if (this.clusterContainerService == s) {
63             this.clusterContainerService = null;
64         }
65         scheduler.shutdownNow();
66     }
67
68     @SuppressWarnings("deprecation")
69     private void allocateCache() {
70         if (this.clusterContainerService == null) {
71             logger.error("un-initialized clusterContainerService, can't create cache");
72             return;
73         }
74         logger.debug("Creating Cache for ClusterDAOService");
75         try {
76             this.clusterContainerService.createCache(CACHE_NAME, EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
77         } catch (CacheConfigException cce) {
78             logger.error("Cache couldn't be created for ClusterDAOService -  check cache mode");
79         } catch (CacheExistException cce) {
80             logger.error("Cache for ClusterDAOService already exists, destroy and recreate");
81         }
82         logger.debug("Cache successfully created for ClusterDAOService");
83     }
84
85     @SuppressWarnings({ "unchecked", "deprecation" })
86     private void retrieveCache() {
87         if (this.clusterContainerService == null) {
88             logger.error("un-initialized clusterContainerService, can't retrieve cache");
89             return;
90         }
91         logger.debug("Retrieving cache for ClusterDAOService");
92         typeToKeysToValues = (ConcurrentMap<Class<?>, Map<Object, Map<String, Object>>>) this.clusterContainerService.getCache(CACHE_NAME);
93         if (typeToKeysToValues == null) {
94             logger.error("Cache couldn't be retrieved for ClusterDAOService");
95         }
96         logger.debug("Cache was successfully retrieved for ClusterDAOService");
97     }
98
99     public void getAll(IRowVisitor visitor) {
100         for (Map.Entry<Class<?>, Map<Object, Map<String, Object>>> typeEntry : typeToKeysToValues.entrySet()) {
101             for (Map.Entry<Object, Map<String, Object>> keyEntry : typeEntry.getValue().entrySet()) {
102                 for (Map.Entry<String, Object> valueEntry : keyEntry.getValue().entrySet()) {
103                     visitor.visitRow(typeEntry.getKey(), keyEntry.getKey(), valueEntry.getKey(), valueEntry.getValue());
104                 }
105             }
106         }
107     }
108
109     public <K> void put(K key, MappingEntry<?>... values) {
110         Map<Object, Map<String, Object>> keysToValues = getTypeMap(key);
111         Map<String, Object> keyToValues = new HashMap<String, Object>();
112         for (MappingEntry<?> entry : values) {
113             keyToValues.put(entry.getKey(), entry.getValue());
114         }
115         keysToValues.put(key, keyToValues);
116     }
117
118     private <K> Map<Object, Map<String, Object>> getTypeMap(K key) {
119         if (key == null) {
120             throw new IllegalArgumentException("Illegal null key.");
121         }
122         Map<Object, Map<String, Object>> keysToValues = typeToKeysToValues.get(key.getClass());
123         if (keysToValues == null) {
124             throw new IllegalArgumentException("Unknown key type " + key.getClass() + ". must register with IConverter first.");
125         }
126         return keysToValues;
127     }
128
129     @SuppressWarnings("unchecked")
130     public <K, V> V getSpecific(K key, MappingValueKey<V> valueKey) {
131         Map<Object, Map<String, Object>> keysToValues = getTypeMap(key);
132         Map<String, Object> keyToValues = keysToValues.get(key);
133         if (keyToValues == null) {
134             return null;
135         }
136         return (V) keyToValues.get(valueKey.getKey());
137     }
138
139     public void cleanOld() {
140         getAll(new IRowVisitor() {
141             public void visitRow(Class<?> keyType, Object keyId, String valueKey, Object value) {
142                 if (value instanceof MappingServiceValue) {
143                     MappingServiceValue msv = (MappingServiceValue) value;
144                     for (Iterator<MappingServiceRLOC> it = msv.getRlocs().iterator(); it.hasNext();) {
145                         MappingServiceRLOC rloc = it.next();
146                         if (isExpired(rloc)) {
147                             it.remove();
148                         }
149                     }
150                     if (msv.getKey() == null && msv.getRlocs().size() == 0) {
151                         remove(keyId);
152                     }
153                 }
154             }
155
156             private boolean isExpired(MappingServiceRLOC rloc) {
157                 return System.currentTimeMillis() - rloc.getRegisterdDate().getTime() > TimeUnit.MILLISECONDS.convert(recordTimeOut, timeUnit);
158             }
159         });
160     }
161
162     public <K> Object getSpecific(K key, String valueKey) {
163         return getSpecific(key, new MappingValueKey<Object>(valueKey));
164     }
165
166     public <K> Map<String, ?> get(K key) {
167         Map<Object, Map<String, Object>> keysToValues = getTypeMap(key);
168         return keysToValues.get(key);
169     }
170
171     public <K> boolean remove(K key) {
172         Map<Object, Map<String, Object>> keysToValues = getTypeMap(key);
173         return keysToValues.remove(key) != null;
174     }
175
176     public <UserType, DbType> void register(Class<? extends ILispTypeConverter<UserType, DbType>> userType) {
177         Class<?> eidType = (Class<?>) ((ParameterizedType) userType.getGenericInterfaces()[0]).getActualTypeArguments()[0];
178         typeToKeysToValues.put(eidType, new HashMap<Object, Map<String, Object>>());
179     }
180
181     public void clearAll() {
182         typeToKeysToValues.clear();
183     }
184
185     public TimeUnit getTimeUnit() {
186         return timeUnit;
187     }
188
189     public void setRecordTimeOut(int recordTimeOut) {
190         this.recordTimeOut = recordTimeOut;
191     }
192
193     public int getRecordTimeOut() {
194         return recordTimeOut;
195     }
196
197     public void setTimeUnit(TimeUnit timeUnit) {
198         this.timeUnit = timeUnit;
199     }
200
201     public int getCleanInterval() {
202         return cleanInterval;
203     }
204
205     public void setCleanInterval(int cleanInterval) {
206         this.cleanInterval = cleanInterval;
207     }
208
209 }