*/
package org.opendaylight.controller.cluster.datastore;
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.Range;
+import com.google.common.collect.RangeSet;
+import com.google.common.collect.TreeRangeSet;
+import com.google.common.primitives.UnsignedLong;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier;
import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
final class FrontendHistoryMetadataBuilder implements Builder<FrontendHistoryMetadata>,
Identifiable<LocalHistoryIdentifier> {
+
+ private final Map<UnsignedLong, Boolean> closedTransactions;
+ private final RangeSet<UnsignedLong> purgedTransactions;
private final LocalHistoryIdentifier identifier;
- private long nextTransaction;
private boolean closed;
FrontendHistoryMetadataBuilder(final LocalHistoryIdentifier identifier) {
- this.identifier = Preconditions.checkNotNull(identifier);
+ this.identifier = requireNonNull(identifier);
+ this.purgedTransactions = TreeRangeSet.create();
+ this.closedTransactions = new HashMap<>(2);
}
FrontendHistoryMetadataBuilder(final ClientIdentifier clientId, final FrontendHistoryMetadata meta) {
identifier = new LocalHistoryIdentifier(clientId, meta.getHistoryId(), meta.getCookie());
- nextTransaction = meta.getNextTransaction();
+ closedTransactions = new HashMap<>(meta.getClosedTransactions());
+ purgedTransactions = TreeRangeSet.create(meta.getPurgedTransactions());
closed = meta.isClosed();
}
@Override
public FrontendHistoryMetadata build() {
- return new FrontendHistoryMetadata(identifier.getHistoryId(), identifier.getCookie(), nextTransaction, closed);
+ return new FrontendHistoryMetadata(identifier.getHistoryId(), identifier.getCookie(), closed,
+ closedTransactions, purgedTransactions);
}
void onHistoryClosed() {
+ checkState(identifier.getHistoryId() != 0);
closed = true;
}
+ void onTransactionAborted(final TransactionIdentifier txId) {
+ closedTransactions.put(UnsignedLong.fromLongBits(txId.getTransactionId()), Boolean.FALSE);
+ }
+
void onTransactionCommitted(final TransactionIdentifier txId) {
- nextTransaction = txId.getTransactionId() + 1;
+ closedTransactions.put(UnsignedLong.fromLongBits(txId.getTransactionId()), Boolean.TRUE);
+ }
+
+ void onTransactionPurged(final TransactionIdentifier txId) {
+ final UnsignedLong id = UnsignedLong.fromLongBits(txId.getTransactionId());
+ closedTransactions.remove(id);
+ purgedTransactions.add(Range.closedOpen(id, UnsignedLong.ONE.plus(id)));
+ }
+
+ /**
+ * Transform frontend metadata for a particular client history into its {@link LocalFrontendHistory} counterpart.
+ *
+ * @param shard parent shard
+ * @return Leader history state
+ */
+ @NonNull AbstractFrontendHistory toLeaderState(final @NonNull Shard shard) {
+ if (identifier.getHistoryId() == 0) {
+ return StandaloneFrontendHistory.recreate(shard.persistenceId(), identifier.getClientId(),
+ shard.getDataStore(), closedTransactions, purgedTransactions);
+ }
+
+ return LocalFrontendHistory.recreate(shard.persistenceId(), shard.getDataStore(),
+ shard.getDataStore().recreateTransactionChain(identifier, closed), closedTransactions, purgedTransactions);
}
}