*/
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.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;
import org.opendaylight.controller.cluster.datastore.persisted.FrontendHistoryMetadata;
+import org.opendaylight.controller.cluster.datastore.utils.MutableUnsignedLongSet;
+import org.opendaylight.controller.cluster.datastore.utils.UnsignedLongBitmap;
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.concepts.Identifiable;
-final class FrontendHistoryMetadataBuilder implements Builder<FrontendHistoryMetadata>, Identifiable<LocalHistoryIdentifier> {
- private final LocalHistoryIdentifier identifier;
+final class FrontendHistoryMetadataBuilder implements Builder<FrontendHistoryMetadata>,
+ Identifiable<LocalHistoryIdentifier> {
+
+ private final @NonNull Map<UnsignedLong, Boolean> closedTransactions;
+ private final @NonNull MutableUnsignedLongSet purgedTransactions;
+ private final @NonNull LocalHistoryIdentifier identifier;
- private long nextTransaction;
private boolean closed;
FrontendHistoryMetadataBuilder(final LocalHistoryIdentifier identifier) {
- this.identifier = Preconditions.checkNotNull(identifier);
+ this.identifier = requireNonNull(identifier);
+ purgedTransactions = MutableUnsignedLongSet.of();
+ closedTransactions = new HashMap<>(2);
}
FrontendHistoryMetadataBuilder(final ClientIdentifier clientId, final FrontendHistoryMetadata meta) {
identifier = new LocalHistoryIdentifier(clientId, meta.getHistoryId(), meta.getCookie());
- nextTransaction = meta.getNextTransaction();
+ closedTransactions = meta.getClosedTransactions().mutableCopy();
+ purgedTransactions = meta.getPurgedTransactions().mutableCopy();
closed = meta.isClosed();
}
@Override
public FrontendHistoryMetadata build() {
- return new FrontendHistoryMetadata(identifier.getHistoryId(), identifier.getCookie(), nextTransaction, closed);
+ return new FrontendHistoryMetadata(identifier.getHistoryId(), identifier.getCookie(), closed,
+ UnsignedLongBitmap.copyOf(closedTransactions), purgedTransactions.immutableCopy());
}
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 long txidBits = txId.getTransactionId();
+ closedTransactions.remove(UnsignedLong.fromLongBits(txidBits));
+ purgedTransactions.add(txidBits);
+ }
+
+ /**
+ * 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);
}
}