BUG 2762 : Compute rate limit based on a more lenient algorithm
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / ConfigurationImpl.java
1 /*
2  * Copyright (c) 2014 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
9 package org.opendaylight.controller.cluster.datastore;
10
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.ImmutableList;
14 import com.google.common.collect.ImmutableList.Builder;
15 import com.google.common.collect.ImmutableListMultimap;
16 import com.google.common.collect.ImmutableMap;
17 import com.google.common.collect.ImmutableSet;
18 import com.google.common.collect.ListMultimap;
19 import com.typesafe.config.Config;
20 import com.typesafe.config.ConfigFactory;
21 import com.typesafe.config.ConfigObject;
22 import java.io.File;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import org.opendaylight.controller.cluster.datastore.shardstrategy.DefaultShardStrategy;
30 import org.opendaylight.controller.cluster.datastore.shardstrategy.ModuleShardStrategy;
31 import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategy;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 public class ConfigurationImpl implements Configuration {
36
37     private final List<ModuleShard> moduleShards;
38
39     private final List<Module> modules;
40
41     private static final Logger
42         LOG = LoggerFactory.getLogger(DistributedDataStore.class);
43
44     // Look up maps to speed things up
45
46     // key = memberName, value = list of shardNames
47     private final Map<String, List<String>> memberShardNames = new HashMap<>();
48
49     // key = shardName, value = list of replicaNames (replicaNames are the same as memberNames)
50     private final Map<String, List<String>> shardReplicaNames = new HashMap<>();
51
52     private final ListMultimap<String, String> moduleNameToShardName;
53     private final Map<String, ShardStrategy> moduleNameToStrategy;
54     private final Map<String, String> namespaceToModuleName;
55     private final Set<String> allShardNames;
56
57     public ConfigurationImpl(final String moduleShardsConfigPath,
58
59         final String modulesConfigPath){
60
61         Preconditions.checkNotNull(moduleShardsConfigPath, "moduleShardsConfigPath should not be null");
62         Preconditions.checkNotNull(modulesConfigPath, "modulesConfigPath should not be null");
63
64
65         File moduleShardsFile = new File("./configuration/initial/" + moduleShardsConfigPath);
66         File modulesFile = new File("./configuration/initial/" + modulesConfigPath);
67
68         Config moduleShardsConfig = null;
69         if(moduleShardsFile.exists()) {
70             LOG.info("module shards config file exists - reading config from it");
71             moduleShardsConfig = ConfigFactory.parseFile(moduleShardsFile);
72         } else {
73             LOG.warn("module shards configuration read from resource");
74             moduleShardsConfig = ConfigFactory.load(moduleShardsConfigPath);
75         }
76
77         Config modulesConfig = null;
78         if(modulesFile.exists()) {
79             LOG.info("modules config file exists - reading config from it");
80             modulesConfig = ConfigFactory.parseFile(modulesFile);
81         } else {
82             LOG.warn("modules configuration read from resource");
83             modulesConfig = ConfigFactory.load(modulesConfigPath);
84         }
85
86         this.moduleShards = readModuleShards(moduleShardsConfig);
87         this.modules = readModules(modulesConfig);
88
89         this.allShardNames = createAllShardNames(moduleShards);
90         this.moduleNameToShardName = createModuleNameToShardName(moduleShards);
91         this.moduleNameToStrategy = createModuleNameToStrategy(modules);
92         this.namespaceToModuleName = createNamespaceToModuleName(modules);
93     }
94
95     private static Set<String> createAllShardNames(Iterable<ModuleShard> moduleShards) {
96         final com.google.common.collect.ImmutableSet.Builder<String> b = ImmutableSet.builder();
97         for(ModuleShard ms : moduleShards){
98             for(Shard s : ms.getShards()) {
99                 b.add(s.getName());
100             }
101         }
102         return b.build();
103     }
104
105     private static Map<String, ShardStrategy> createModuleNameToStrategy(Iterable<Module> modules) {
106         final com.google.common.collect.ImmutableMap.Builder<String, ShardStrategy> b = ImmutableMap.builder();
107         for (Module m : modules) {
108             b.put(m.getName(), m.getShardStrategy());
109         }
110         return b.build();
111     }
112
113     private static Map<String, String> createNamespaceToModuleName(Iterable<Module> modules) {
114         final com.google.common.collect.ImmutableMap.Builder<String, String> b = ImmutableMap.builder();
115         for (Module m : modules) {
116             b.put(m.getNameSpace(), m.getName());
117         }
118         return b.build();
119     }
120
121     private static ListMultimap<String, String> createModuleNameToShardName(Iterable<ModuleShard> moduleShards) {
122         final com.google.common.collect.ImmutableListMultimap.Builder<String, String> b = ImmutableListMultimap.builder();
123
124         for (ModuleShard m : moduleShards) {
125             for (Shard s : m.getShards()) {
126                 b.put(m.getModuleName(), s.getName());
127             }
128         }
129
130         return b.build();
131     }
132
133     @Override public List<String> getMemberShardNames(final String memberName){
134
135         Preconditions.checkNotNull(memberName, "memberName should not be null");
136
137         if(memberShardNames.containsKey(memberName)){
138             return memberShardNames.get(memberName);
139         }
140
141         List<String> shards = new ArrayList<>();
142         for(ModuleShard ms : moduleShards){
143             for(Shard s : ms.getShards()){
144                 for(String m : s.getReplicas()){
145                     if(memberName.equals(m)){
146                         shards.add(s.getName());
147                     }
148                 }
149             }
150         }
151
152         memberShardNames.put(memberName, shards);
153
154         return shards;
155
156     }
157
158     @Override
159     public Optional<String> getModuleNameFromNameSpace(final String nameSpace) {
160         Preconditions.checkNotNull(nameSpace, "nameSpace should not be null");
161         return Optional.fromNullable(namespaceToModuleName.get(nameSpace));
162     }
163
164     @Override
165     public Map<String, ShardStrategy> getModuleNameToShardStrategyMap() {
166         return moduleNameToStrategy;
167     }
168
169     @Override
170     public List<String> getShardNamesFromModuleName(final String moduleName) {
171         Preconditions.checkNotNull(moduleName, "moduleName should not be null");
172         return moduleNameToShardName.get(moduleName);
173     }
174
175     @Override public List<String> getMembersFromShardName(final String shardName) {
176
177         Preconditions.checkNotNull(shardName, "shardName should not be null");
178
179         if(shardReplicaNames.containsKey(shardName)){
180             return shardReplicaNames.get(shardName);
181         }
182
183         for(ModuleShard ms : moduleShards){
184             for(Shard s : ms.getShards()) {
185                 if(s.getName().equals(shardName)){
186                     List<String> replicas = s.getReplicas();
187                     shardReplicaNames.put(shardName, replicas);
188                     return replicas;
189                 }
190             }
191         }
192         shardReplicaNames.put(shardName, Collections.<String>emptyList());
193         return Collections.emptyList();
194     }
195
196     @Override
197     public Set<String> getAllShardNames() {
198         return allShardNames;
199     }
200
201     private List<Module> readModules(final Config modulesConfig) {
202         List<? extends ConfigObject> modulesConfigObjectList =
203             modulesConfig.getObjectList("modules");
204
205         final Builder<Module> b = ImmutableList.builder();
206         for(ConfigObject o : modulesConfigObjectList){
207             ConfigObjectWrapper w = new ConfigObjectWrapper(o);
208             b.add(new Module(w.stringValue("name"), w.stringValue(
209                 "namespace"), w.stringValue("shard-strategy")));
210         }
211
212         return b.build();
213     }
214
215     private static List<ModuleShard> readModuleShards(final Config moduleShardsConfig) {
216         List<? extends ConfigObject> moduleShardsConfigObjectList =
217             moduleShardsConfig.getObjectList("module-shards");
218
219         final Builder<ModuleShard> b = ImmutableList.builder();
220         for(ConfigObject moduleShardConfigObject : moduleShardsConfigObjectList){
221
222             String moduleName = moduleShardConfigObject.get("name").unwrapped().toString();
223
224             List<? extends ConfigObject> shardsConfigObjectList =
225                 moduleShardConfigObject.toConfig().getObjectList("shards");
226
227             List<Shard> shards = new ArrayList<>();
228
229             for(ConfigObject shard : shardsConfigObjectList){
230                 String shardName = shard.get("name").unwrapped().toString();
231                 List<String> replicas = shard.toConfig().getStringList("replicas");
232                 shards.add(new Shard(shardName, replicas));
233             }
234
235             b.add(new ModuleShard(moduleName, shards));
236         }
237
238         return b.build();
239     }
240
241     private static class ModuleShard {
242         private final String moduleName;
243         private final List<Shard> shards;
244
245         public ModuleShard(final String moduleName, final List<Shard> shards) {
246             this.moduleName = moduleName;
247             this.shards = shards;
248         }
249
250         public String getModuleName() {
251             return moduleName;
252         }
253
254         public List<Shard> getShards() {
255             return shards;
256         }
257     }
258
259     private static class Shard {
260         private final String name;
261         private final List<String> replicas;
262
263         Shard(final String name, final List<String> replicas) {
264             this.name = name;
265             this.replicas = replicas;
266         }
267
268         public String getName() {
269             return name;
270         }
271
272         public List<String> getReplicas() {
273             return replicas;
274         }
275     }
276
277     private class Module {
278
279         private final String name;
280         private final String nameSpace;
281         private final ShardStrategy shardStrategy;
282
283         Module(final String name, final String nameSpace, final String shardStrategy) {
284             this.name = name;
285             this.nameSpace = nameSpace;
286             if(ModuleShardStrategy.NAME.equals(shardStrategy)){
287                 this.shardStrategy = new ModuleShardStrategy(name, ConfigurationImpl.this);
288             } else {
289                 this.shardStrategy = DefaultShardStrategy.getInstance();
290             }
291         }
292
293         public String getName() {
294             return name;
295         }
296
297         public String getNameSpace() {
298             return nameSpace;
299         }
300
301         public ShardStrategy getShardStrategy() {
302             return shardStrategy;
303         }
304     }
305
306
307     private static class ConfigObjectWrapper{
308
309         private final ConfigObject configObject;
310
311         ConfigObjectWrapper(final ConfigObject configObject){
312             this.configObject = configObject;
313         }
314
315         public String stringValue(final String name){
316             return configObject.get(name).unwrapped().toString();
317         }
318     }
319 }