+ /**
+ * Transform frontend metadata for a particular client into its {@link LeaderFrontendState} counterpart.
+ *
+ * @param shard parent shard
+ * @return Leader frontend state
+ */
+ @Nonnull LeaderFrontendState toLeaderState(@Nonnull final Shard shard) {
+ // Note: we have to make sure to *copy* all current state and not leak any views, otherwise leader/follower
+ // interactions would get intertwined leading to inconsistencies.
+ final Map<LocalHistoryIdentifier, LocalFrontendHistory> histories = new HashMap<>();
+ for (FrontendHistoryMetadataBuilder e : currentHistories.values()) {
+ if (e.getIdentifier().getHistoryId() != 0) {
+ final AbstractFrontendHistory state = e.toLeaderState(shard);
+ verify(state instanceof LocalFrontendHistory, "Unexpected state %s", state);
+ histories.put(e.getIdentifier(), (LocalFrontendHistory) state);
+ }
+ }
+
+ final AbstractFrontendHistory singleHistory;
+ final FrontendHistoryMetadataBuilder singleHistoryMeta = currentHistories.get(
+ new LocalHistoryIdentifier(identifier, 0));
+ if (singleHistoryMeta == null) {
+ final ShardDataTree tree = shard.getDataStore();
+ singleHistory = StandaloneFrontendHistory.create(shard.persistenceId(), getIdentifier(), tree);
+ } else {
+ singleHistory = singleHistoryMeta.toLeaderState(shard);
+ }
+
+ return new LeaderFrontendState(shard.persistenceId(), getIdentifier(), shard.getDataStore(),
+ purgedHistories.copy(), singleHistory, histories);
+ }
+
+ private FrontendHistoryMetadataBuilder getHistory(final TransactionIdentifier txId) {
+ LocalHistoryIdentifier historyId = txId.getHistoryId();
+ if (historyId.getHistoryId() == 0 && historyId.getCookie() != 0) {
+ // We are pre-creating the history for free-standing transactions with a zero cookie, hence our lookup
+ // needs to account for that.
+ LOG.debug("{}: looking up {} instead of {}", shardName, standaloneId, historyId);
+ historyId = standaloneId;
+ }
+
+ return currentHistories.get(historyId);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("identifier", identifier).add("current", currentHistories)
+ .add("purged", purgedHistories).toString();