Bump odlparent/yangtools/mdsal
[controller.git] / opendaylight / md-sal / sal-distributed-eos / src / main / java / org / opendaylight / controller / cluster / 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.entityownership;
9
10 import static org.opendaylight.controller.cluster.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         // Hidden on purpose
36     }
37
38     @Override
39     public void onDataTreeChanged(final Collection<DataTreeCandidate> changes) {
40         for (DataTreeCandidate change : changes) {
41             DataTreeCandidateNode changeRoot = change.getRootNode();
42             LeafNode<?> ownerLeaf = (LeafNode<?>) changeRoot.getDataAfter().get();
43             String entityType = entityTypeFromEntityPath(change.getRootPath());
44             String newOwner = extractOwner(ownerLeaf);
45             if (!Strings.isNullOrEmpty(newOwner)) {
46                 updateStatistics(entityType, newOwner, 1);
47             }
48
49             Optional<NormalizedNode> dataBefore = changeRoot.getDataBefore();
50             if (dataBefore.isPresent()) {
51                 String origOwner = extractOwner((LeafNode<?>) changeRoot.getDataBefore().get());
52                 if (!Strings.isNullOrEmpty(origOwner)) {
53                     updateStatistics(entityType, origOwner, -1);
54                 }
55             }
56         }
57     }
58
59     Map<String, Map<String, Long>> all() {
60         Map<String, Map<String, Long>> snapshot = new HashMap<>();
61         for (String entityType : statistics.immutableSnapshot().keySet()) {
62             snapshot.put(entityType, byEntityType(entityType));
63         }
64         return snapshot;
65     }
66
67     Map<String, Long> byEntityType(final String entityType) {
68         if (statistics.get(entityType) != null) {
69             return statistics.get(entityType).immutableSnapshot();
70         }
71         return new HashMap<>();
72     }
73
74     private void updateStatistics(final String entityType, final String candidateName, final long count) {
75         TrieMap<String, Long> map = statistics.get(entityType);
76         if (map == null) {
77             map = TrieMap.create();
78             map.put(candidateName, count);
79             statistics.put(entityType, map);
80         } else {
81             map.merge(candidateName, count, (ownedEntities, addedEntities) -> ownedEntities + addedEntities);
82         }
83     }
84 }