Example #1
0
  private void finishCommit(
      @Nonnull final ActorRef sender,
      @Nonnull final String transactionID,
      @Nonnull final CohortEntry cohortEntry) {
    LOG.debug(
        "{}: Finishing commit for transaction {}", persistenceId(), cohortEntry.getTransactionID());

    try {
      cohortEntry.commit();

      sender.tell(CommitTransactionReply.INSTANCE.toSerializable(), getSelf());

      shardMBean.incrementCommittedTransactionCount();
      shardMBean.setLastCommittedTransactionTime(System.currentTimeMillis());

    } catch (Exception e) {
      sender.tell(new akka.actor.Status.Failure(e), getSelf());

      LOG.error(
          "{}, An exception occurred while committing transaction {}",
          persistenceId(),
          transactionID,
          e);
      shardMBean.incrementFailedTransactionsCount();
    } finally {
      commitCoordinator.currentTransactionComplete(transactionID, true);
    }
  }
Example #2
0
 private void commitWithNewTransaction(final Modification modification) {
   ReadWriteShardDataTreeTransaction tx =
       store.newReadWriteTransaction(modification.toString(), null);
   modification.apply(tx.getSnapshot());
   try {
     snapshotCohort.syncCommitTransaction(tx);
     shardMBean.incrementCommittedTransactionCount();
     shardMBean.setLastCommittedTransactionTime(System.currentTimeMillis());
   } catch (Exception e) {
     shardMBean.incrementFailedTransactionsCount();
     LOG.error("{}: Failed to commit", persistenceId(), e);
   }
 }
Example #3
0
  @Override
  protected void onLeaderChanged(String oldLeader, String newLeader) {
    shardMBean.incrementLeadershipChangeCount();

    if (hasLeader() && !isIsolatedLeader()) {
      messageRetrySupport.retryMessages();
    }
  }
Example #4
0
  protected Shard(AbstractBuilder<?, ?> builder) {
    super(
        builder.getId().toString(),
        builder.getPeerAddresses(),
        Optional.of(builder.getDatastoreContext().getShardRaftConfig()),
        DataStoreVersions.CURRENT_VERSION);

    this.name = builder.getId().toString();
    this.datastoreContext = builder.getDatastoreContext();
    this.restoreFromSnapshot = builder.getRestoreFromSnapshot();

    setPersistence(datastoreContext.isPersistent());

    LOG.info("Shard created : {}, persistent : {}", name, datastoreContext.isPersistent());

    store = new ShardDataTree(builder.getSchemaContext(), builder.getTreeType());

    shardMBean =
        ShardMBeanFactory.getShardStatsMBean(
            name.toString(), datastoreContext.getDataStoreMXBeanType());
    shardMBean.setShard(this);

    if (isMetricsCaptureEnabled()) {
      getContext().become(new MeteringBehavior(this));
    }

    commitCoordinator =
        new ShardCommitCoordinator(
            store,
            datastoreContext.getShardCommitQueueExpiryTimeoutInMillis(),
            datastoreContext.getShardTransactionCommitQueueCapacity(),
            LOG,
            this.name);

    setTransactionCommitTimeout();

    // create a notifier actor for each cluster member
    roleChangeNotifier = createRoleChangeNotifier(name.toString());

    appendEntriesReplyTracker =
        new MessageTracker(
            AppendEntriesReply.class,
            getRaftActorContext().getConfigParams().getIsolatedCheckIntervalInMillis());

    transactionActorFactory =
        new ShardTransactionActorFactory(
            store,
            datastoreContext,
            new Dispatchers(context().system().dispatchers())
                .getDispatcherPath(Dispatchers.DispatcherType.Transaction),
            self(),
            getContext(),
            shardMBean);

    snapshotCohort = new ShardSnapshotCohort(transactionActorFactory, store, LOG, this.name);

    messageRetrySupport = new ShardTransactionMessageRetrySupport(this);
  }
 private boolean checkClosed(AbstractShardDataTreeTransaction<?> transaction) {
   final boolean ret = transaction.isClosed();
   if (ret) {
     shardStats.incrementFailedReadTransactionsCount();
     getSender()
         .tell(
             new akka.actor.Status.Failure(new ReadFailedException("Transaction is closed")),
             getSelf());
   }
   return ret;
 }
Example #6
0
  @Override
  public void postStop() {
    LOG.info("Stopping Shard {}", persistenceId());

    super.postStop();

    messageRetrySupport.close();

    if (txCommitTimeoutCheckSchedule != null) {
      txCommitTimeoutCheckSchedule.cancel();
    }

    commitCoordinator.abortPendingTransactions("Transaction aborted due to shutdown.", this);

    shardMBean.unregisterMBean();
  }
Example #7
0
  private void finishCommit(@Nonnull final ActorRef sender, final @Nonnull String transactionID) {
    // With persistence enabled, this method is called via applyState by the leader strategy
    // after the commit has been replicated to a majority of the followers.

    CohortEntry cohortEntry = commitCoordinator.getCohortEntryIfCurrent(transactionID);
    if (cohortEntry == null) {
      // The transaction is no longer the current commit. This can happen if the transaction
      // was aborted prior, most likely due to timeout in the front-end. We need to finish
      // committing the transaction though since it was successfully persisted and replicated
      // however we can't use the original cohort b/c it was already preCommitted and may
      // conflict with the current commit or may have been aborted so we commit with a new
      // transaction.
      cohortEntry = commitCoordinator.getAndRemoveCohortEntry(transactionID);
      if (cohortEntry != null) {
        try {
          store.applyForeignCandidate(transactionID, cohortEntry.getCandidate());
        } catch (DataValidationFailedException e) {
          shardMBean.incrementFailedTransactionsCount();
          LOG.error("{}: Failed to re-apply transaction {}", persistenceId(), transactionID, e);
        }

        sender.tell(CommitTransactionReply.INSTANCE.toSerializable(), getSelf());
      } else {
        // This really shouldn't happen - it likely means that persistence or replication
        // took so long to complete such that the cohort entry was expired from the cache.
        IllegalStateException ex =
            new IllegalStateException(
                String.format(
                    "%s: Could not finish committing transaction %s - no CohortEntry found",
                    persistenceId(), transactionID));
        LOG.error(ex.getMessage());
        sender.tell(new akka.actor.Status.Failure(ex), getSelf());
      }
    } else {
      finishCommit(sender, transactionID, cohortEntry);
    }
  }
Example #8
0
 private void handleCommitTransaction(final CommitTransaction commit) {
   if (!commitCoordinator.handleCommit(commit.getTransactionID(), getSender(), this)) {
     shardMBean.incrementFailedTransactionsCount();
   }
 }
Example #9
0
  @Override
  public void onReceiveCommand(final Object message) throws Exception {

    MessageTracker.Context context = appendEntriesReplyTracker.received(message);

    if (context.error().isPresent()) {
      LOG.trace(
          "{} : AppendEntriesReply failed to arrive at the expected interval {}",
          persistenceId(),
          context.error());
    }

    try {
      if (CreateTransaction.SERIALIZABLE_CLASS.isInstance(message)) {
        handleCreateTransaction(message);
      } else if (BatchedModifications.class.isInstance(message)) {
        handleBatchedModifications((BatchedModifications) message);
      } else if (message instanceof ForwardedReadyTransaction) {
        handleForwardedReadyTransaction((ForwardedReadyTransaction) message);
      } else if (message instanceof ReadyLocalTransaction) {
        handleReadyLocalTransaction((ReadyLocalTransaction) message);
      } else if (CanCommitTransaction.SERIALIZABLE_CLASS.isInstance(message)) {
        handleCanCommitTransaction(CanCommitTransaction.fromSerializable(message));
      } else if (CommitTransaction.SERIALIZABLE_CLASS.isInstance(message)) {
        handleCommitTransaction(CommitTransaction.fromSerializable(message));
      } else if (AbortTransaction.SERIALIZABLE_CLASS.isInstance(message)) {
        handleAbortTransaction(AbortTransaction.fromSerializable(message));
      } else if (CloseTransactionChain.SERIALIZABLE_CLASS.isInstance(message)) {
        closeTransactionChain(CloseTransactionChain.fromSerializable(message));
      } else if (message instanceof RegisterChangeListener) {
        changeSupport.onMessage((RegisterChangeListener) message, isLeader(), hasLeader());
      } else if (message instanceof RegisterDataTreeChangeListener) {
        treeChangeSupport.onMessage(
            (RegisterDataTreeChangeListener) message, isLeader(), hasLeader());
      } else if (message instanceof UpdateSchemaContext) {
        updateSchemaContext((UpdateSchemaContext) message);
      } else if (message instanceof PeerAddressResolved) {
        PeerAddressResolved resolved = (PeerAddressResolved) message;
        setPeerAddress(resolved.getPeerId().toString(), resolved.getPeerAddress());
      } else if (message.equals(TX_COMMIT_TIMEOUT_CHECK_MESSAGE)) {
        commitCoordinator.checkForExpiredTransactions(transactionCommitTimeout, this);
      } else if (message instanceof DatastoreContext) {
        onDatastoreContext((DatastoreContext) message);
      } else if (message instanceof RegisterRoleChangeListener) {
        roleChangeNotifier.get().forward(message, context());
      } else if (message instanceof FollowerInitialSyncUpStatus) {
        shardMBean.setFollowerInitialSyncStatus(
            ((FollowerInitialSyncUpStatus) message).isInitialSyncDone());
        context().parent().tell(message, self());
      } else if (GET_SHARD_MBEAN_MESSAGE.equals(message)) {
        sender().tell(getShardMBean(), self());
      } else if (message instanceof GetShardDataTree) {
        sender().tell(store.getDataTree(), self());
      } else if (message instanceof ServerRemoved) {
        context().parent().forward(message, context());
      } else if (ShardTransactionMessageRetrySupport.TIMER_MESSAGE_CLASS.isInstance(message)) {
        messageRetrySupport.onTimerMessage(message);
      } else {
        super.onReceiveCommand(message);
      }
    } finally {
      context.done();
    }
  }