Switch default stream output to Magnesium
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / entityownership / EntityOwnershipStatistics.java
1 /*
2  * Copyright (c) 2015 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 package org.opendaylight.controller.cluster.datastore.entityownership;
9
10 import static org.opendaylight.controller.cluster.datastore.entityownership.EntityOwnersModel.entityTypeFromEntityPath;
11
12 import com.google.common.base.Strings;
13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.Map;
16 import java.util.Optional;
17 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
18 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
19 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
20 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
21 import tech.pantheon.triemap.TrieMap;
22
23 /**
24  * EntityOwnershipStatistics is a utility class that keeps track of ownership statistics for the candidates and
25  * caches it for quick count queries.
26  * <p/>
27  * While the entity ownership model does maintain the information about which entity is owned by which candidate
28  * finding out how many entities of a given type are owned by a given candidate is not an efficient query.
29  */
30 class EntityOwnershipStatistics extends AbstractEntityOwnerChangeListener {
31
32     private final TrieMap<String, TrieMap<String, Long>> statistics = TrieMap.create();
33
34     EntityOwnershipStatistics(){
35     }
36
37     @Override
38     public void onDataTreeChanged(final Collection<DataTreeCandidate> changes) {
39         for (DataTreeCandidate change : changes) {
40             DataTreeCandidateNode changeRoot = change.getRootNode();
41             LeafNode<?> ownerLeaf = (LeafNode<?>) changeRoot.getDataAfter().get();
42             String entityType = entityTypeFromEntityPath(change.getRootPath());
43             String newOwner = extractOwner(ownerLeaf);
44             if (!Strings.isNullOrEmpty(newOwner)) {
45                 updateStatistics(entityType, newOwner, 1);
46             }
47
48             Optional<NormalizedNode<?, ?>> dataBefore = changeRoot.getDataBefore();
49             if (dataBefore.isPresent()) {
50                 String origOwner = extractOwner((LeafNode<?>) changeRoot.getDataBefore().get());
51                 if (!Strings.isNullOrEmpty(origOwner)) {
52                     updateStatistics(entityType, origOwner, -1);
53                 }
54             }
55         }
56     }
57
58     Map<String, Map<String, Long>> all() {
59         Map<String, Map<String, Long>> snapshot = new HashMap<>();
60         for (String entityType : statistics.immutableSnapshot().keySet()) {
61             snapshot.put(entityType, byEntityType(entityType));
62         }
63         return snapshot;
64     }
65
66     Map<String, Long> byEntityType(final String entityType) {
67         if (statistics.get(entityType) != null) {
68             return statistics.get(entityType).immutableSnapshot();
69         }
70         return new HashMap<>();
71     }
72
73     private void updateStatistics(final String entityType, final String candidateName, final long count) {
74         TrieMap<String, Long> map = statistics.get(entityType);
75         if (map == null) {
76             map = TrieMap.create();
77             map.put(candidateName, count);
78             statistics.put(entityType, map);
79         } else {
80             map.merge(candidateName, count, (ownedEntities, addedEntities) -> ownedEntities + addedEntities);
81         }
82     }
83 }