Added support for "maps" cli command that displays meta information for various …
…consistent maps in the system Change-Id: I63e590a8520ac9d1238efe4ad0033dcba939e472
Showing
10 changed files
with
214 additions
and
0 deletions
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.cli.net; | ||
17 | + | ||
18 | +import java.util.List; | ||
19 | + | ||
20 | +import org.apache.karaf.shell.commands.Command; | ||
21 | +import org.onosproject.cli.AbstractShellCommand; | ||
22 | +import org.onosproject.store.service.MapInfo; | ||
23 | +import org.onosproject.store.service.StorageAdminService; | ||
24 | + | ||
25 | +import com.fasterxml.jackson.databind.JsonNode; | ||
26 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
27 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
28 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
29 | + | ||
30 | +/** | ||
31 | + * Command to list the various maps in the system. | ||
32 | + */ | ||
33 | +@Command(scope = "onos", name = "maps", | ||
34 | + description = "Lists information about consistent maps in the system") | ||
35 | +public class MapsListCommand extends AbstractShellCommand { | ||
36 | + | ||
37 | + // TODO: Add support to display different eventually | ||
38 | + // consistent maps as well. | ||
39 | + | ||
40 | + private static final String FMT = "%-20s %8s"; | ||
41 | + | ||
42 | + /** | ||
43 | + * Displays map info as text. | ||
44 | + * | ||
45 | + * @param mapInfo map descriptions | ||
46 | + */ | ||
47 | + private void displayMaps(List<MapInfo> mapInfo) { | ||
48 | + print("------------------------------"); | ||
49 | + print(FMT, "Name", "Size"); | ||
50 | + print("------------------------------"); | ||
51 | + | ||
52 | + | ||
53 | + for (MapInfo info : mapInfo) { | ||
54 | + print(FMT, info.name(), info.size()); | ||
55 | + } | ||
56 | + if (mapInfo.size() > 0) { | ||
57 | + print("------------------------------"); | ||
58 | + } | ||
59 | + } | ||
60 | + | ||
61 | + /** | ||
62 | + * Converts list of map info into a JSON object. | ||
63 | + * | ||
64 | + * @param mapInfo map descriptions | ||
65 | + */ | ||
66 | + private JsonNode json(List<MapInfo> mapInfo) { | ||
67 | + ObjectMapper mapper = new ObjectMapper(); | ||
68 | + ArrayNode maps = mapper.createArrayNode(); | ||
69 | + | ||
70 | + // Create a JSON node for each map | ||
71 | + mapInfo.stream() | ||
72 | + .forEach(info -> { | ||
73 | + ObjectNode map = mapper.createObjectNode(); | ||
74 | + map.put("name", info.name()) | ||
75 | + .put("size", info.size()); | ||
76 | + maps.add(map); | ||
77 | + }); | ||
78 | + | ||
79 | + return maps; | ||
80 | + } | ||
81 | + | ||
82 | + @Override | ||
83 | + protected void execute() { | ||
84 | + StorageAdminService storageAdminService = get(StorageAdminService.class); | ||
85 | + List<MapInfo> mapInfo = storageAdminService.getMapInfo(); | ||
86 | + if (outputJson()) { | ||
87 | + print("%s", json(mapInfo)); | ||
88 | + } else { | ||
89 | + displayMaps(mapInfo); | ||
90 | + } | ||
91 | + } | ||
92 | +} |
... | @@ -230,6 +230,9 @@ | ... | @@ -230,6 +230,9 @@ |
230 | <action class="org.onosproject.cli.net.PartitionsListCommand"/> | 230 | <action class="org.onosproject.cli.net.PartitionsListCommand"/> |
231 | </command> | 231 | </command> |
232 | <command> | 232 | <command> |
233 | + <action class="org.onosproject.cli.net.MapsListCommand"/> | ||
234 | + </command> | ||
235 | + <command> | ||
233 | <action class="org.onosproject.cli.net.ClusterDevicesCommand"/> | 236 | <action class="org.onosproject.cli.net.ClusterDevicesCommand"/> |
234 | <completers> | 237 | <completers> |
235 | <ref component-id="clusterIdCompleter"/> | 238 | <ref component-id="clusterIdCompleter"/> | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.store.service; | ||
17 | + | ||
18 | +/** | ||
19 | + * Metadata information for a consistent map. | ||
20 | + */ | ||
21 | +public class MapInfo { | ||
22 | + private final String name; | ||
23 | + private final int size; | ||
24 | + | ||
25 | + public MapInfo(String name, int size) { | ||
26 | + this.name = name; | ||
27 | + this.size = size; | ||
28 | + } | ||
29 | + | ||
30 | + /** | ||
31 | + * Returns the name of the map. | ||
32 | + * | ||
33 | + * @return map name | ||
34 | + */ | ||
35 | + public String name() { | ||
36 | + return name; | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * Returns the number of entries in the map. | ||
41 | + * | ||
42 | + * @return map size | ||
43 | + */ | ||
44 | + public int size() { | ||
45 | + return size; | ||
46 | + } | ||
47 | +} |
... | @@ -28,4 +28,11 @@ public interface StorageAdminService { | ... | @@ -28,4 +28,11 @@ public interface StorageAdminService { |
28 | * @return list of partition information | 28 | * @return list of partition information |
29 | */ | 29 | */ |
30 | List<PartitionInfo> getPartitionInfo(); | 30 | List<PartitionInfo> getPartitionInfo(); |
31 | + | ||
32 | + /** | ||
33 | + * Returns information about all the consistent maps in the system. | ||
34 | + * | ||
35 | + * @return list of map information | ||
36 | + */ | ||
37 | + List<MapInfo> getMapInfo(); | ||
31 | } | 38 | } | ... | ... |
... | @@ -44,7 +44,9 @@ import org.onosproject.store.cluster.impl.NodeInfo; | ... | @@ -44,7 +44,9 @@ import org.onosproject.store.cluster.impl.NodeInfo; |
44 | import org.onosproject.store.cluster.messaging.ClusterCommunicationService; | 44 | import org.onosproject.store.cluster.messaging.ClusterCommunicationService; |
45 | import org.onosproject.store.ecmap.EventuallyConsistentMapBuilderImpl; | 45 | import org.onosproject.store.ecmap.EventuallyConsistentMapBuilderImpl; |
46 | import org.onosproject.store.service.ConsistentMapBuilder; | 46 | import org.onosproject.store.service.ConsistentMapBuilder; |
47 | +import org.onosproject.store.service.ConsistentMapException; | ||
47 | import org.onosproject.store.service.EventuallyConsistentMapBuilder; | 48 | import org.onosproject.store.service.EventuallyConsistentMapBuilder; |
49 | +import org.onosproject.store.service.MapInfo; | ||
48 | import org.onosproject.store.service.PartitionInfo; | 50 | import org.onosproject.store.service.PartitionInfo; |
49 | import org.onosproject.store.service.StorageAdminService; | 51 | import org.onosproject.store.service.StorageAdminService; |
50 | import org.onosproject.store.service.StorageService; | 52 | import org.onosproject.store.service.StorageService; |
... | @@ -58,8 +60,10 @@ import java.util.Map; | ... | @@ -58,8 +60,10 @@ import java.util.Map; |
58 | import java.util.Set; | 60 | import java.util.Set; |
59 | import java.util.concurrent.CompletableFuture; | 61 | import java.util.concurrent.CompletableFuture; |
60 | import java.util.concurrent.CountDownLatch; | 62 | import java.util.concurrent.CountDownLatch; |
63 | +import java.util.concurrent.ExecutionException; | ||
61 | import java.util.concurrent.Executors; | 64 | import java.util.concurrent.Executors; |
62 | import java.util.concurrent.TimeUnit; | 65 | import java.util.concurrent.TimeUnit; |
66 | +import java.util.concurrent.TimeoutException; | ||
63 | import java.util.stream.Collectors; | 67 | import java.util.stream.Collectors; |
64 | 68 | ||
65 | import static org.slf4j.LoggerFactory.getLogger; | 69 | import static org.slf4j.LoggerFactory.getLogger; |
... | @@ -80,6 +84,7 @@ public class DatabaseManager implements StorageService, StorageAdminService { | ... | @@ -80,6 +84,7 @@ public class DatabaseManager implements StorageService, StorageAdminService { |
80 | private static final int DATABASE_STARTUP_TIMEOUT_SEC = 60; | 84 | private static final int DATABASE_STARTUP_TIMEOUT_SEC = 60; |
81 | private static final int RAFT_ELECTION_TIMEOUT = 3000; | 85 | private static final int RAFT_ELECTION_TIMEOUT = 3000; |
82 | private static final int RAFT_HEARTBEAT_TIMEOUT = 1500; | 86 | private static final int RAFT_HEARTBEAT_TIMEOUT = 1500; |
87 | + private static final int DATABASE_OPERATION_TIMEOUT_MILLIS = 5000; | ||
83 | 88 | ||
84 | private ClusterCoordinator coordinator; | 89 | private ClusterCoordinator coordinator; |
85 | private PartitionedDatabase partitionedDatabase; | 90 | private PartitionedDatabase partitionedDatabase; |
... | @@ -294,4 +299,33 @@ public class DatabaseManager implements StorageService, StorageAdminService { | ... | @@ -294,4 +299,33 @@ public class DatabaseManager implements StorageService, StorageAdminService { |
294 | public <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder() { | 299 | public <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder() { |
295 | return new DefaultConsistentMapBuilder<>(inMemoryDatabase, partitionedDatabase); | 300 | return new DefaultConsistentMapBuilder<>(inMemoryDatabase, partitionedDatabase); |
296 | } | 301 | } |
302 | + | ||
303 | + @Override | ||
304 | + public List<MapInfo> getMapInfo() { | ||
305 | + List<MapInfo> maps = Lists.newArrayList(); | ||
306 | + maps.addAll(getMapInfo(inMemoryDatabase)); | ||
307 | + maps.addAll(getMapInfo(partitionedDatabase)); | ||
308 | + return maps; | ||
309 | + } | ||
310 | + | ||
311 | + private List<MapInfo> getMapInfo(Database database) { | ||
312 | + return complete(database.tableNames()) | ||
313 | + .stream() | ||
314 | + .map(name -> new MapInfo(name, complete(database.size(name)))) | ||
315 | + .filter(info -> info.size() > 0) | ||
316 | + .collect(Collectors.toList()); | ||
317 | + } | ||
318 | + | ||
319 | + private static <T> T complete(CompletableFuture<T> future) { | ||
320 | + try { | ||
321 | + return future.get(DATABASE_OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); | ||
322 | + } catch (InterruptedException e) { | ||
323 | + Thread.currentThread().interrupt(); | ||
324 | + throw new ConsistentMapException.Interrupted(); | ||
325 | + } catch (TimeoutException e) { | ||
326 | + throw new ConsistentMapException.Timeout(); | ||
327 | + } catch (ExecutionException e) { | ||
328 | + throw new ConsistentMapException(e.getCause()); | ||
329 | + } | ||
330 | + } | ||
297 | } | 331 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -30,6 +30,12 @@ import org.onosproject.store.service.Versioned; | ... | @@ -30,6 +30,12 @@ import org.onosproject.store.service.Versioned; |
30 | */ | 30 | */ |
31 | public interface DatabaseProxy<K, V> { | 31 | public interface DatabaseProxy<K, V> { |
32 | 32 | ||
33 | + /** | ||
34 | + * Returns a set of all tables names. | ||
35 | + * @return A completable future to be completed with the result once complete. | ||
36 | + */ | ||
37 | + CompletableFuture<Set<String>> tableNames(); | ||
38 | + | ||
33 | /** | 39 | /** |
34 | * Gets the table size. | 40 | * Gets the table size. |
35 | * | 41 | * | ... | ... |
... | @@ -44,6 +44,9 @@ public interface DatabaseState<K, V> { | ... | @@ -44,6 +44,9 @@ public interface DatabaseState<K, V> { |
44 | public void init(StateContext<DatabaseState<K, V>> context); | 44 | public void init(StateContext<DatabaseState<K, V>> context); |
45 | 45 | ||
46 | @Query | 46 | @Query |
47 | + Set<String> tableNames(); | ||
48 | + | ||
49 | + @Query | ||
47 | int size(String tableName); | 50 | int size(String tableName); |
48 | 51 | ||
49 | @Query | 52 | @Query | ... | ... |
... | @@ -61,6 +61,11 @@ public class DefaultDatabase extends AbstractResource<Database> implements Datab | ... | @@ -61,6 +61,11 @@ public class DefaultDatabase extends AbstractResource<Database> implements Datab |
61 | } | 61 | } |
62 | 62 | ||
63 | @Override | 63 | @Override |
64 | + public CompletableFuture<Set<String>> tableNames() { | ||
65 | + return checkOpen(() -> proxy.tableNames()); | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
64 | public CompletableFuture<Integer> size(String tableName) { | 69 | public CompletableFuture<Integer> size(String tableName) { |
65 | return checkOpen(() -> proxy.size(tableName)); | 70 | return checkOpen(() -> proxy.size(tableName)); |
66 | } | 71 | } | ... | ... |
... | @@ -19,6 +19,7 @@ package org.onosproject.store.consistent.impl; | ... | @@ -19,6 +19,7 @@ package org.onosproject.store.consistent.impl; |
19 | import java.util.Arrays; | 19 | import java.util.Arrays; |
20 | import java.util.Collection; | 20 | import java.util.Collection; |
21 | import java.util.HashMap; | 21 | import java.util.HashMap; |
22 | +import java.util.HashSet; | ||
22 | import java.util.List; | 23 | import java.util.List; |
23 | import java.util.Map; | 24 | import java.util.Map; |
24 | import java.util.Map.Entry; | 25 | import java.util.Map.Entry; |
... | @@ -71,6 +72,11 @@ public class DefaultDatabaseState<K, V> implements DatabaseState<K, V> { | ... | @@ -71,6 +72,11 @@ public class DefaultDatabaseState<K, V> implements DatabaseState<K, V> { |
71 | } | 72 | } |
72 | 73 | ||
73 | @Override | 74 | @Override |
75 | + public Set<String> tableNames() { | ||
76 | + return new HashSet<>(tables.keySet()); | ||
77 | + } | ||
78 | + | ||
79 | + @Override | ||
74 | public int size(String tableName) { | 80 | public int size(String tableName) { |
75 | return getTableMap(tableName).size(); | 81 | return getTableMap(tableName).size(); |
76 | } | 82 | } | ... | ... |
... | @@ -78,6 +78,17 @@ public class PartitionedDatabase implements Database { | ... | @@ -78,6 +78,17 @@ public class PartitionedDatabase implements Database { |
78 | } | 78 | } |
79 | 79 | ||
80 | @Override | 80 | @Override |
81 | + public CompletableFuture<Set<String>> tableNames() { | ||
82 | + checkState(isOpen.get(), DB_NOT_OPEN); | ||
83 | + Set<String> tableNames = Sets.newConcurrentHashSet(); | ||
84 | + return CompletableFuture.allOf(partitions | ||
85 | + .stream() | ||
86 | + .map(db -> db.tableNames().thenApply(tableNames::addAll)) | ||
87 | + .toArray(CompletableFuture[]::new)) | ||
88 | + .thenApply(v -> tableNames); | ||
89 | + } | ||
90 | + | ||
91 | + @Override | ||
81 | public CompletableFuture<Integer> size(String tableName) { | 92 | public CompletableFuture<Integer> size(String tableName) { |
82 | checkState(isOpen.get(), DB_NOT_OPEN); | 93 | checkState(isOpen.get(), DB_NOT_OPEN); |
83 | AtomicInteger totalSize = new AtomicInteger(0); | 94 | AtomicInteger totalSize = new AtomicInteger(0); | ... | ... |
-
Please register or login to post a comment