*/
package org.opendaylight.controller.cluster.datastore.shardmanager;
+import static java.util.Objects.requireNonNull;
+
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.serialization.Serialization;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
-import javax.annotation.Nullable;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.controller.cluster.datastore.DatastoreContext;
import org.opendaylight.controller.cluster.datastore.Shard;
import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
import org.opendaylight.controller.cluster.datastore.messages.PeerAddressResolved;
-import org.opendaylight.controller.cluster.datastore.messages.PeerDown;
-import org.opendaylight.controller.cluster.datastore.messages.PeerUp;
import org.opendaylight.controller.cluster.datastore.shardmanager.ShardManager.OnShardInitialized;
import org.opendaylight.controller.cluster.datastore.shardmanager.ShardManager.OnShardReady;
import org.opendaylight.controller.cluster.raft.RaftState;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.data.tree.api.ReadOnlyDataTree;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-final class ShardInformation {
+@VisibleForTesting
+public final class ShardInformation {
private static final Logger LOG = LoggerFactory.getLogger(ShardInformation.class);
private final Set<OnShardInitialized> onShardInitializedSet = new HashSet<>();
private final ShardPeerAddressResolver addressResolver;
private final ShardIdentifier shardId;
private final String shardName;
+
+ // This reference indirection is required to have the ability to update the SchemaContext
+ // inside actor props. Otherwise we would be keeping an old SchemaContext there, preventing
+ // it from becoming garbage.
+ private final AtomicShardContextProvider schemaContextProvider = new AtomicShardContextProvider();
private ActorRef actor;
- private Optional<DataTree> localShardDataTree;
+
+ private Optional<ReadOnlyDataTree> localShardDataTree;
private boolean leaderAvailable = false;
// flag that determines if the actor is ready for business
private DatastoreContext datastoreContext;
private Shard.AbstractBuilder<?, ?> builder;
- private boolean isActiveMember = true;
+ private boolean activeMember = true;
- ShardInformation(String shardName, ShardIdentifier shardId,
- Map<String, String> initialPeerAddresses, DatastoreContext datastoreContext,
- Shard.AbstractBuilder<?, ?> builder, ShardPeerAddressResolver addressResolver) {
+ ShardInformation(final String shardName, final ShardIdentifier shardId,
+ final Map<String, String> initialPeerAddresses, final DatastoreContext datastoreContext,
+ final Shard.AbstractBuilder<?, ?> builder, final ShardPeerAddressResolver addressResolver) {
this.shardName = shardName;
this.shardId = shardId;
this.initialPeerAddresses = initialPeerAddresses;
this.addressResolver = addressResolver;
}
- Props newProps(SchemaContext schemaContext) {
- Preconditions.checkNotNull(builder);
- Props props = builder.id(shardId).peerAddresses(initialPeerAddresses).datastoreContext(datastoreContext).
- schemaContext(schemaContext).props();
+ Props newProps() {
+ Props props = requireNonNull(builder).id(shardId).peerAddresses(initialPeerAddresses)
+ .datastoreContext(datastoreContext).schemaContextProvider(schemaContextProvider).props();
builder = null;
return props;
}
return shardName;
}
- @Nullable
- ActorRef getActor(){
+ @VisibleForTesting
+ @Nullable public ActorRef getActor() {
return actor;
}
- void setActor(ActorRef actor) {
+ void setActor(final ActorRef actor) {
this.actor = actor;
}
return shardId;
}
- void setLocalDataTree(Optional<DataTree> localShardDataTree) {
- this.localShardDataTree = localShardDataTree;
+ void setLocalDataTree(final Optional<ReadOnlyDataTree> dataTree) {
+ localShardDataTree = dataTree;
}
- Optional<DataTree> getLocalShardDataTree() {
+ Optional<ReadOnlyDataTree> getLocalShardDataTree() {
return localShardDataTree;
}
return datastoreContext;
}
- void setDatastoreContext(DatastoreContext datastoreContext, ActorRef sender) {
- this.datastoreContext = datastoreContext;
+ void setDatastoreContext(final DatastoreContext newDatastoreContext, final ActorRef sender) {
+ datastoreContext = newDatastoreContext;
if (actor != null) {
LOG.debug("Sending new DatastoreContext to {}", shardId);
- actor.tell(this.datastoreContext, sender);
+ actor.tell(datastoreContext, sender);
}
}
- void updatePeerAddress(String peerId, String peerAddress, ActorRef sender){
+ void updatePeerAddress(final String peerId, final String peerAddress, final ActorRef sender) {
LOG.info("updatePeerAddress for peer {} with address {}", peerId, peerAddress);
- if(actor != null) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("Sending PeerAddressResolved for peer {} with address {} to {}",
- peerId, peerAddress, actor.path());
- }
+ if (actor != null) {
+ LOG.debug("Sending PeerAddressResolved for peer {} with address {} to {}", peerId,
+ peerAddress, actor.path());
actor.tell(new PeerAddressResolved(peerId, peerAddress), sender);
}
notifyOnShardInitializedCallbacks();
}
- void peerDown(String memberName, String peerId, ActorRef sender) {
- if(actor != null) {
- actor.tell(new PeerDown(memberName, peerId), sender);
- }
- }
-
- void peerUp(String memberName, String peerId, ActorRef sender) {
- if(actor != null) {
- actor.tell(new PeerUp(memberName, peerId), sender);
- }
- }
-
boolean isShardReady() {
return !RaftState.Candidate.name().equals(role) && !Strings.isNullOrEmpty(role);
}
boolean isShardReadyWithLeaderId() {
- return leaderAvailable && isShardReady() && !RaftState.IsolatedLeader.name().equals(role) &&
- (isLeader() || addressResolver.resolve(leaderId) != null);
+ return leaderAvailable && isShardReady() && !RaftState.IsolatedLeader.name().equals(role)
+ && !RaftState.PreLeader.name().equals(role)
+ && (isLeader() || addressResolver.resolve(leaderId) != null);
}
boolean isShardInitialized() {
}
boolean isLeader() {
- return Objects.equal(leaderId, shardId.toString());
+ return Objects.equals(leaderId, shardId.toString());
}
String getSerializedLeaderActor() {
- if(isLeader()) {
- return Serialization.serializedActorPath(getActor());
- } else {
- return addressResolver.resolve(leaderId);
- }
+ return isLeader() ? Serialization.serializedActorPath(getActor()) : addressResolver.resolve(leaderId);
}
void setActorInitialized() {
LOG.debug("Shard {} is initialized", shardId);
- this.actorInitialized = true;
+ actorInitialized = true;
notifyOnShardInitializedCallbacks();
}
private void notifyOnShardInitializedCallbacks() {
- if(onShardInitializedSet.isEmpty()) {
+ if (onShardInitializedSet.isEmpty()) {
return;
}
- boolean ready = isShardReadyWithLeaderId();
-
- LOG.debug("Shard {} is {} - notifying {} OnShardInitialized callbacks", shardId,
- ready ? "ready" : "initialized", onShardInitializedSet.size());
+ final boolean ready = isShardReadyWithLeaderId();
+ final String readyStr = ready ? "ready" : "initialized";
+ LOG.debug("Shard {} is {} - notifying {} OnShardInitialized callbacks", shardId, readyStr,
+ onShardInitializedSet.size());
Iterator<OnShardInitialized> iter = onShardInitializedSet.iterator();
- while(iter.hasNext()) {
+ while (iter.hasNext()) {
OnShardInitialized onShardInitialized = iter.next();
if (!(onShardInitialized instanceof OnShardReady) || ready) {
iter.remove();
}
}
- void addOnShardInitialized(OnShardInitialized onShardInitialized) {
+ void addOnShardInitialized(final OnShardInitialized onShardInitialized) {
onShardInitializedSet.add(onShardInitialized);
}
- void removeOnShardInitialized(OnShardInitialized onShardInitialized) {
+ void removeOnShardInitialized(final OnShardInitialized onShardInitialized) {
onShardInitializedSet.remove(onShardInitialized);
}
- void setRole(String newRole) {
- this.role = newRole;
+ void setRole(final String newRole) {
+ role = newRole;
notifyOnShardInitializedCallbacks();
}
- void setFollowerSyncStatus(boolean syncStatus){
- this.followerSyncStatus = syncStatus;
+ String getRole() {
+ return role;
+ }
+
+ void setFollowerSyncStatus(final boolean syncStatus) {
+ followerSyncStatus = syncStatus;
}
- boolean isInSync(){
- if(RaftState.Follower.name().equals(this.role)){
+ boolean isInSync() {
+ if (RaftState.Follower.name().equals(role)) {
return followerSyncStatus;
- } else if(RaftState.Leader.name().equals(this.role)){
+ } else if (RaftState.Leader.name().equals(role)) {
return true;
}
return false;
}
- boolean setLeaderId(String leaderId) {
- boolean changed = !Objects.equal(this.leaderId, leaderId);
- this.leaderId = leaderId;
- if(leaderId != null) {
- this.leaderAvailable = true;
+ boolean setLeaderId(final String newLeaderId) {
+ final boolean changed = !Objects.equals(leaderId, newLeaderId);
+ leaderId = newLeaderId;
+ if (newLeaderId != null) {
+ leaderAvailable = true;
}
notifyOnShardInitializedCallbacks();
return leaderId;
}
- void setLeaderAvailable(boolean leaderAvailable) {
+ void setLeaderAvailable(final boolean leaderAvailable) {
this.leaderAvailable = leaderAvailable;
- if(leaderAvailable) {
+ if (leaderAvailable) {
notifyOnShardInitializedCallbacks();
}
}
return leaderVersion;
}
- void setLeaderVersion(short leaderVersion) {
+ void setLeaderVersion(final short leaderVersion) {
this.leaderVersion = leaderVersion;
}
boolean isActiveMember() {
- return isActiveMember;
+ return activeMember;
+ }
+
+ void setActiveMember(final boolean isActiveMember) {
+ activeMember = isActiveMember;
+ }
+
+ EffectiveModelContext getSchemaContext() {
+ return schemaContextProvider.getEffectiveModelContext();
}
- void setActiveMember(boolean isActiveMember) {
- this.isActiveMember = isActiveMember;
+ void setSchemaContext(final EffectiveModelContext schemaContext) {
+ schemaContextProvider.set(requireNonNull(schemaContext));
}
-}
\ No newline at end of file
+
+ @VisibleForTesting
+ Shard.AbstractBuilder<?, ?> getBuilder() {
+ return builder;
+ }
+
+ @Override
+ public String toString() {
+ return "ShardInformation [shardId=" + shardId + ", leaderAvailable=" + leaderAvailable + ", actorInitialized="
+ + actorInitialized + ", followerSyncStatus=" + followerSyncStatus + ", role=" + role + ", leaderId="
+ + leaderId + ", activeMember=" + activeMember + "]";
+ }
+
+
+}