X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-distributed-datastore%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fdatastore%2Fentityownership%2FEntityOwnershipShard.java;h=30fafbbb10f4e78b1a09f0a5c6ec2559a4d88bf3;hb=e04c7f93b0b614580c45318585f7709192465757;hp=ba7512830ea1b8b65a5343946c6098095bf363f0;hpb=077b0b3a083c96c72f32116491158a930ff770d2;p=controller.git diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnershipShard.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnershipShard.java index ba7512830e..30fafbbb10 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnershipShard.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnershipShard.java @@ -80,6 +80,7 @@ class EntityOwnershipShard extends Shard { private final Map peerIdToMemberNames = new HashMap<>(); private final EntityOwnerSelectionStrategyConfig strategyConfig; private final Map entityToScheduledOwnershipTask = new HashMap<>(); + private final EntityOwnershipStatistics entityOwnershipStatistics; private static DatastoreContext noPersistenceDatastoreContext(DatastoreContext datastoreContext) { return DatastoreContext.newBuilderFrom(datastoreContext).persistent(false).build(); @@ -91,6 +92,8 @@ class EntityOwnershipShard extends Shard { this.commitCoordinator = new EntityOwnershipShardCommitCoordinator(builder.localMemberName, LOG); this.listenerSupport = new EntityOwnershipListenerSupport(getContext(), persistenceId()); this.strategyConfig = builder.ownerSelectionStrategyConfig; + this.entityOwnershipStatistics = new EntityOwnershipStatistics(); + this.entityOwnershipStatistics.init(getDataStore()); for(String peerId: getRaftActorContext().getPeerIds()) { ShardIdentifier shardId = ShardIdentifier.builder().fromShardIdString(peerId).build(); @@ -139,7 +142,9 @@ class EntityOwnershipShard extends Shard { private void onSelectOwner(SelectOwner selectOwner) { String currentOwner = getCurrentOwner(selectOwner.getEntityPath()); if(Strings.isNullOrEmpty(currentOwner)) { + String entityType = EntityOwnersModel.entityTypeFromEntityPath(selectOwner.getEntityPath()); writeNewOwner(selectOwner.getEntityPath(), newOwner(selectOwner.getAllCandidates(), + entityOwnershipStatistics.byEntityType(entityType), selectOwner.getOwnerSelectionStrategy())); Cancellable cancellable = entityToScheduledOwnershipTask.get(selectOwner.getEntityPath()); @@ -239,17 +244,23 @@ class EntityOwnershipShard extends Shard { protected void onStateChanged() { super.onStateChanged(); - commitCoordinator.onStateChanged(this, isLeader()); + boolean isLeader = isLeader(); + if(LOG.isDebugEnabled()) { + LOG.debug("{}: onStateChanged: isLeader: {}, hasLeader: {}", persistenceId(), isLeader, hasLeader()); + } + + commitCoordinator.onStateChanged(this, isLeader); } @Override protected void onLeaderChanged(String oldLeader, String newLeader) { super.onLeaderChanged(oldLeader, newLeader); + boolean isLeader = isLeader(); LOG.debug("{}: onLeaderChanged: oldLeader: {}, newLeader: {}, isLeader: {}", persistenceId(), oldLeader, - newLeader, isLeader()); + newLeader, isLeader); - if(isLeader()) { + if(isLeader) { // We were just elected leader. If the old leader is down, select new owners for the entities // owned by the down leader. @@ -260,6 +271,11 @@ class EntityOwnershipShard extends Shard { if(downPeerMemberNames.contains(oldLeaderMemberName)) { selectNewOwnerForEntitiesOwnedBy(oldLeaderMemberName); } + } else { + // The leader changed - notify the coordinator to check if pending modifications need to be sent. + // While onStateChanged also does this, this method handles the case where the shard hears from a + // leader and stays in the follower state. In that case no behavior state change occurs. + commitCoordinator.onStateChanged(this, isLeader); } } @@ -268,9 +284,11 @@ class EntityOwnershipShard extends Shard { if(isLeader()) { String currentOwner = getCurrentOwner(message.getEntityPath()); - if(message.getRemovedCandidate().equals(currentOwner)){ + if(message.getRemovedCandidate().equals(currentOwner) || message.getRemainingCandidates().size() == 0){ + String entityType = EntityOwnersModel.entityTypeFromEntityPath(message.getEntityPath()); writeNewOwner(message.getEntityPath(), - newOwner(message.getRemainingCandidates(), getEntityOwnerElectionStrategy(message.getEntityPath()))); + newOwner(message.getRemainingCandidates(), entityOwnershipStatistics.byEntityType(entityType), + getEntityOwnerElectionStrategy(message.getEntityPath()))); } } else { // We're not the leader. If the removed candidate is our local member then check if we actually @@ -310,7 +328,9 @@ class EntityOwnershipShard extends Shard { EntityOwnerSelectionStrategy strategy = getEntityOwnerElectionStrategy(message.getEntityPath()); if(Strings.isNullOrEmpty(currentOwner)){ if(strategy.getSelectionDelayInMillis() == 0L) { - writeNewOwner(message.getEntityPath(), newOwner(message.getAllCandidates(), strategy)); + String entityType = EntityOwnersModel.entityTypeFromEntityPath(message.getEntityPath()); + writeNewOwner(message.getEntityPath(), newOwner(message.getAllCandidates(), + entityOwnershipStatistics.byEntityType(entityType), strategy)); } else { scheduleOwnerSelection(message.getEntityPath(), message.getAllCandidates(), strategy); } @@ -332,6 +352,11 @@ class EntityOwnershipShard extends Shard { peerIdToMemberNames.put(peerUp.getPeerId(), peerUp.getMemberName()); downPeerMemberNames.remove(peerUp.getMemberName()); + + // Notify the coordinator to check if pending modifications need to be sent. We do this here + // to handle the case where the leader's peer address isn't now yet when a prior state or + // leader change occurred. + commitCoordinator.onStateChanged(this, isLeader()); } private void selectNewOwnerForEntitiesOwnedBy(String owner) { @@ -344,7 +369,11 @@ class EntityOwnershipShard extends Shard { node(entityTypeNode.getIdentifier()).node(ENTITY_NODE_ID).node(entityNode.getIdentifier()). node(ENTITY_OWNER_NODE_ID).build(); - Object newOwner = newOwner(getCandidateNames(entityNode), getEntityOwnerElectionStrategy(entityPath)); + String entityType = EntityOwnersModel.entityTypeFromEntityPath(entityPath); + + Object newOwner = newOwner(getCandidateNames(entityNode), + entityOwnershipStatistics.byEntityType(entityType), + getEntityOwnerElectionStrategy(entityPath)); LOG.debug("{}: Found entity {}, writing new owner {}", persistenceId(), entityPath, newOwner); @@ -422,7 +451,7 @@ class EntityOwnershipShard extends Shard { } } - private Collection getCandidateNames(MapEntryNode entity) { + private static Collection getCandidateNames(MapEntryNode entity) { Collection candidates = ((MapNode) entity.getChild(CANDIDATE_NODE_ID).get()).getValue(); Collection candidateNames = new ArrayList<>(candidates.size()); for(MapEntryNode candidate: candidates) { @@ -459,12 +488,12 @@ class EntityOwnershipShard extends Shard { entityToScheduledOwnershipTask.put(entityPath, lastScheduledTask); } - private String newOwner(Collection candidates, EntityOwnerSelectionStrategy ownerSelectionStrategy) { + private String newOwner(Collection candidates, Map statistics, EntityOwnerSelectionStrategy ownerSelectionStrategy) { Collection viableCandidates = getViableCandidates(candidates); if(viableCandidates.size() == 0){ return ""; } - return ownerSelectionStrategy.newOwner(viableCandidates); + return ownerSelectionStrategy.newOwner(viableCandidates, statistics); } private Collection getViableCandidates(Collection candidates) {