Bug 4992: Removed old leader's candidates on leader change
[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 import com.google.common.base.Optional;
13 import com.google.common.base.Strings;
14 import com.romix.scala.collection.concurrent.TrieMap;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.Map;
18 import javax.annotation.Nonnull;
19 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
20 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
22 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
23
24 /**
25  * EntityOwnershipStatistics is a utility class that keeps track of ownership statistics for the candidates and
26  * caches it for quick count queries.
27  * <p>
28  * While the entity ownership model does maintain the information about which entity is owned by which candidate
29  * finding out how many entities of a given type are owned by a given candidate is not an efficient query.
30  */
31 class EntityOwnershipStatistics extends AbstractEntityOwnerChangeListener {
32
33     private TrieMap<String, TrieMap<String, Long>> statistics = new TrieMap<>();
34
35     EntityOwnershipStatistics(){
36     }
37
38     @Override
39     public void onDataTreeChanged(@Nonnull 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.readOnlySnapshot().keySet()) {
62             snapshot.put(entityType, byEntityType(entityType));
63         }
64         return snapshot;
65     }
66
67     Map<String, Long> byEntityType(String entityType){
68         if(statistics.get(entityType) != null) {
69             return statistics.get(entityType).readOnlySnapshot();
70         }
71         return new HashMap<>();
72     }
73
74     private void updateStatistics(String entityType, String candidateName, long count){
75         Map<String, Long> m = statistics.get(entityType);
76         if(m == null){
77             m = new TrieMap<>();
78             m.put(candidateName, count);
79             statistics.put(entityType, m);
80         } else {
81             Long candidateOwnedEntities = m.get(candidateName);
82             if(candidateOwnedEntities == null){
83                 m.put(candidateName, count);
84             } else {
85                 m.put(candidateName, candidateOwnedEntities + count);
86             }
87         }
88     }
89 }