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