*/
package org.opendaylight.controller.cluster.datastore;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verify;
+import static com.google.common.base.Verify.verifyNotNull;
+import static java.util.Objects.requireNonNull;
+
import akka.actor.ActorRef;
import akka.util.Timeout;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
-import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.OptionalLong;
import java.util.Queue;
import java.util.SortedSet;
import java.util.concurrent.TimeUnit;
long lastAccess;
CommitEntry(final SimpleShardDataTreeCohort cohort, final long now) {
- this.cohort = Preconditions.checkNotNull(cohort);
+ this.cohort = requireNonNull(cohort);
lastAccess = now;
}
final ShardDataTreeChangeListenerPublisher treeChangeListenerPublisher,
final String logContext,
final ShardDataTreeMetadata<?>... metadata) {
- this.dataTree = Preconditions.checkNotNull(dataTree);
+ this.dataTree = requireNonNull(dataTree);
updateSchemaContext(schemaContext);
- this.shard = Preconditions.checkNotNull(shard);
- this.treeChangeListenerPublisher = Preconditions.checkNotNull(treeChangeListenerPublisher);
- this.logContext = Preconditions.checkNotNull(logContext);
+ this.shard = requireNonNull(shard);
+ this.treeChangeListenerPublisher = requireNonNull(treeChangeListenerPublisher);
+ this.logContext = requireNonNull(logContext);
this.metadata = ImmutableList.copyOf(metadata);
tip = dataTree;
}
@VisibleForTesting
public ShardDataTree(final Shard shard, final SchemaContext schemaContext, final TreeType treeType) {
- this(shard, schemaContext, treeType, YangInstanceIdentifier.EMPTY,
+ this(shard, schemaContext, treeType, YangInstanceIdentifier.empty(),
new DefaultShardDataTreeChangeListenerPublisher(""), "");
}
void updateSchemaContext(final SchemaContext newSchemaContext) {
dataTree.setSchemaContext(newSchemaContext);
- this.schemaContext = Preconditions.checkNotNull(newSchemaContext);
+ this.schemaContext = requireNonNull(newSchemaContext);
this.dataSchemaContext = DataSchemaContextTree.from(newSchemaContext);
}
* @return A state snapshot
*/
@NonNull ShardDataTreeSnapshot takeStateSnapshot() {
- final NormalizedNode<?, ?> rootNode = dataTree.takeSnapshot().readNode(YangInstanceIdentifier.EMPTY).get();
+ final NormalizedNode<?, ?> rootNode = dataTree.takeSnapshot().readNode(YangInstanceIdentifier.empty()).get();
final Builder<Class<? extends ShardDataTreeSnapshotMetadata<?>>, ShardDataTreeSnapshotMetadata<?>> metaBuilder =
ImmutableMap.builder();
final DataTreeModification mod = wrapper.apply(dataTree.takeSnapshot().newModification());
// delete everything first
- mod.delete(YangInstanceIdentifier.EMPTY);
+ mod.delete(YangInstanceIdentifier.empty());
- final java.util.Optional<NormalizedNode<?, ?>> maybeNode = snapshot.getRootNode();
+ final Optional<NormalizedNode<?, ?>> maybeNode = snapshot.getRootNode();
if (maybeNode.isPresent()) {
// Add everything from the remote node back
- mod.write(YangInstanceIdentifier.EMPTY, maybeNode.get());
+ mod.write(YangInstanceIdentifier.empty(), maybeNode.get());
}
mod.ready();
}
@SuppressWarnings("checkstyle:IllegalCatch")
- private void applyRecoveryCandidate(final DataTreeCandidate candidate) {
+ private void applyRecoveryCandidate(final CommitTransactionPayload payload) throws IOException {
+ final Entry<TransactionIdentifier, DataTreeCandidate> entry = payload.getCandidate();
+
final PruningDataTreeModification mod = wrapWithPruning(dataTree.takeSnapshot().newModification());
- DataTreeCandidates.applyToModification(mod, candidate);
+ DataTreeCandidates.applyToModification(mod, entry.getValue());
mod.ready();
final DataTreeModification unwrapped = mod.delegate();
"%s: Failed to apply recovery payload. Modification data was written to file %s",
logContext, file), e);
}
+
+ allMetadataCommittedTransaction(entry.getKey());
}
/**
*/
void applyRecoveryPayload(final @NonNull Payload payload) throws IOException {
if (payload instanceof CommitTransactionPayload) {
- final Entry<TransactionIdentifier, DataTreeCandidate> e =
- ((CommitTransactionPayload) payload).getCandidate();
- applyRecoveryCandidate(e.getValue());
- allMetadataCommittedTransaction(e.getKey());
+ applyRecoveryCandidate((CommitTransactionPayload) payload);
} else if (payload instanceof AbortTransactionPayload) {
allMetadataAbortedTransaction(((AbortTransactionPayload) payload).getIdentifier());
} else if (payload instanceof PurgeTransactionPayload) {
}
}
- private void applyReplicatedCandidate(final TransactionIdentifier identifier, final DataTreeCandidate foreign)
- throws DataValidationFailedException {
+ private void applyReplicatedCandidate(final CommitTransactionPayload payload)
+ throws DataValidationFailedException, IOException {
+ final Entry<TransactionIdentifier, DataTreeCandidate> entry = payload.getCandidate();
+ final TransactionIdentifier identifier = entry.getKey();
LOG.debug("{}: Applying foreign transaction {}", logContext, identifier);
final DataTreeModification mod = dataTree.takeSnapshot().newModification();
- DataTreeCandidates.applyToModification(mod, foreign);
+ DataTreeCandidates.applyToModification(mod, entry.getValue());
mod.ready();
LOG.trace("{}: Applying foreign modification {}", logContext, mod);
*/
if (payload instanceof CommitTransactionPayload) {
if (identifier == null) {
- final Entry<TransactionIdentifier, DataTreeCandidate> e =
- ((CommitTransactionPayload) payload).getCandidate();
- applyReplicatedCandidate(e.getKey(), e.getValue());
+ applyReplicatedCandidate((CommitTransactionPayload) payload);
} else {
- Verify.verify(identifier instanceof TransactionIdentifier);
+ verify(identifier instanceof TransactionIdentifier);
payloadReplicationComplete((TransactionIdentifier) identifier);
}
} else if (payload instanceof AbortTransactionPayload) {
final boolean closed) {
final ShardDataTreeTransactionChain ret = new ShardDataTreeTransactionChain(historyId, this);
final ShardDataTreeTransactionChain existing = transactionChains.putIfAbsent(historyId, ret);
- Preconditions.checkState(existing == null, "Attempted to recreate chain %s, but %s already exists", historyId,
- existing);
+ checkState(existing == null, "Attempted to recreate chain %s, but %s already exists", historyId, existing);
return ret;
}
}
Optional<DataTreeCandidate> readCurrentData() {
- final java.util.Optional<NormalizedNode<?, ?>> currentState =
- dataTree.takeSnapshot().readNode(YangInstanceIdentifier.EMPTY);
- return currentState.isPresent() ? Optional.of(DataTreeCandidates.fromNormalizedNode(
- YangInstanceIdentifier.EMPTY, currentState.get())) : Optional.<DataTreeCandidate>absent();
+ return dataTree.takeSnapshot().readNode(YangInstanceIdentifier.empty())
+ .map(state -> DataTreeCandidates.fromNormalizedNode(YangInstanceIdentifier.empty(), state));
}
public void registerTreeChangeListener(final YangInstanceIdentifier path, final DOMDataTreeChangeListener listener,
@Override
ShardDataTreeCohort finishTransaction(final ReadWriteShardDataTreeTransaction transaction,
- final java.util.Optional<SortedSet<String>> participatingShardNames) {
+ final Optional<SortedSet<String>> participatingShardNames) {
final DataTreeModification snapshot = transaction.getSnapshot();
+ final TransactionIdentifier id = transaction.getIdentifier();
+ LOG.debug("{}: readying transaction {}", logContext, id);
snapshot.ready();
+ LOG.debug("{}: transaction {} ready", logContext, id);
return createReadyCohort(transaction.getIdentifier(), snapshot, participatingShardNames);
}
}
public Optional<NormalizedNode<?, ?>> readNode(final YangInstanceIdentifier path) {
- return Optional.fromJavaUtil(dataTree.takeSnapshot().readNode(path));
+ return dataTree.takeSnapshot().readNode(path);
}
DataTreeSnapshot takeSnapshot() {
// For debugging purposes, allow dumping of the modification. Coupled with the above
// precondition log, it should allow us to understand what went on.
- LOG.debug("{}: Store Tx {}: modifications: {} tree: {}", logContext, cohort.getIdentifier(),
- modification, dataTree);
+ LOG.debug("{}: Store Tx {}: modifications: {}", logContext, cohort.getIdentifier(), modification);
+ LOG.trace("{}: Current tree: {}", logContext, dataTree);
cause = new TransactionCommitFailedException("Data did not pass validation for path " + e.getPath(), e);
} catch (Exception e) {
LOG.warn("{}: Unexpected failure in validation phase", logContext, e);
tempStack.forEach(queue::addFirst);
}
- private Collection<String> extractPrecedingShardNames(
- final java.util.Optional<SortedSet<String>> participatingShardNames) {
+ private Collection<String> extractPrecedingShardNames(final Optional<SortedSet<String>> participatingShardNames) {
return participatingShardNames.map((Function<SortedSet<String>, Collection<String>>)
set -> set.headSet(shard.getShardName())).orElse(Collections.<String>emptyList());
}
@SuppressWarnings("checkstyle:IllegalCatch")
void startPreCommit(final SimpleShardDataTreeCohort cohort) {
final CommitEntry entry = pendingTransactions.peek();
- Preconditions.checkState(entry != null, "Attempted to pre-commit of %s when no transactions pending", cohort);
+ checkState(entry != null, "Attempted to pre-commit of %s when no transactions pending", cohort);
final SimpleShardDataTreeCohort current = entry.cohort;
- Verify.verify(cohort.equals(current), "Attempted to pre-commit %s while %s is pending", cohort, current);
+ verify(cohort.equals(current), "Attempted to pre-commit %s while %s is pending", cohort, current);
- LOG.debug("{}: Preparing transaction {}", logContext, current.getIdentifier());
+ final TransactionIdentifier currentId = current.getIdentifier();
+ LOG.debug("{}: Preparing transaction {}", logContext, currentId);
final DataTreeCandidateTip candidate;
try {
candidate = tip.prepare(cohort.getDataTreeModification());
- } catch (RuntimeException e) {
+ LOG.debug("{}: Transaction {} candidate ready", logContext, currentId);
+ } catch (DataValidationFailedException | RuntimeException e) {
failPreCommit(e);
return;
}
@Override
public void onSuccess(final Void noop) {
// Set the tip of the data tree.
- tip = Verify.verifyNotNull(candidate);
+ tip = verifyNotNull(candidate);
entry.lastAccess = readTime();
pendingTransactions.remove();
pendingCommits.add(entry);
- LOG.debug("{}: Transaction {} prepared", logContext, current.getIdentifier());
+ LOG.debug("{}: Transaction {} prepared", logContext, currentId);
cohort.successfulPreCommit(candidate);
void startCommit(final SimpleShardDataTreeCohort cohort, final DataTreeCandidate candidate) {
final CommitEntry entry = pendingCommits.peek();
- Preconditions.checkState(entry != null, "Attempted to start commit of %s when no transactions pending", cohort);
+ checkState(entry != null, "Attempted to start commit of %s when no transactions pending", cohort);
final SimpleShardDataTreeCohort current = entry.cohort;
if (!cohort.equals(current)) {
@Override
ShardDataTreeCohort createReadyCohort(final TransactionIdentifier txId, final DataTreeModification mod,
- final java.util.Optional<SortedSet<String>> participatingShardNames) {
+ final Optional<SortedSet<String>> participatingShardNames) {
SimpleShardDataTreeCohort cohort = new SimpleShardDataTreeCohort(this, mod, txId,
cohortRegistry.createCohort(schemaContext, txId, shard::executeInSelf,
COMMIT_STEP_TIMEOUT), participatingShardNames);
// Exposed for ShardCommitCoordinator so it does not have deal with local histories (it does not care), this mimics
// the newReadWriteTransaction()
ShardDataTreeCohort newReadyCohort(final TransactionIdentifier txId, final DataTreeModification mod,
- final java.util.Optional<SortedSet<String>> participatingShardNames) {
+ final Optional<SortedSet<String>> participatingShardNames) {
if (txId.getHistoryId().getHistoryId() == 0) {
return createReadyCohort(txId, mod, participatingShardNames);
}
@SuppressFBWarnings(value = "DB_DUPLICATE_SWITCH_CLAUSES", justification = "See inline comments below.")
void checkForExpiredTransactions(final long transactionCommitTimeoutMillis,
- final Function<SimpleShardDataTreeCohort, Optional<Long>> accessTimeUpdater) {
+ final Function<SimpleShardDataTreeCohort, OptionalLong> accessTimeUpdater) {
final long timeout = TimeUnit.MILLISECONDS.toNanos(transactionCommitTimeoutMillis);
final long now = readTime();
return;
}
- final Optional<Long> updateOpt = accessTimeUpdater.apply(currentTx.cohort);
+ final OptionalLong updateOpt = accessTimeUpdater.apply(currentTx.cohort);
if (updateOpt.isPresent()) {
- final long newAccess = updateOpt.get().longValue();
+ final long newAccess = updateOpt.getAsLong();
final long newDelta = now - newAccess;
if (newDelta < delta) {
LOG.debug("{}: Updated current transaction {} access time", logContext,
@SuppressWarnings("checkstyle:IllegalCatch")
private void rebaseTransactions(final Iterator<CommitEntry> iter, final @NonNull DataTreeTip newTip) {
- tip = Preconditions.checkNotNull(newTip);
+ tip = requireNonNull(newTip);
while (iter.hasNext()) {
final SimpleShardDataTreeCohort cohort = iter.next().cohort;
if (cohort.getState() == State.CAN_COMMIT_COMPLETE) {