/**
   * Destroys the RecoveryCoordinatorImpl object.
   *
   * @param
   * @return
   * @see
   */
  final synchronized void destroy() {

    try {
      if (poa != null && thisRef != null) {
        poa.deactivate_object(poa.reference_to_id(thisRef));
        thisRef = null;
      } else {
        // BUGFIX(Ram J) It is possible that the
        // RecoveryCoordinator object was activated via the activation
        // daemon. In that case, there is no guarantee
        // that poa and thisRef are set to a meaningful value.
        // So, try to deactivate the RecoveryCoordinator object anyway.

        POA rcPoa = null;
        if (poa == null) {
          rcPoa = Configuration.getPOA("RecoveryCoordinator" /*#Frozen*/);
        } else {
          rcPoa = poa;
        }

        if (thisRef == null) {
          rcPoa.deactivate_object(rcPoa.servant_to_id(this));
        } else {
          rcPoa.deactivate_object(rcPoa.reference_to_id(thisRef));
          thisRef = null;
        }
      }
    } catch (Exception exc) {
      _logger.log(Level.WARNING, "jts.object_destroy_error", "RecoveryCoordinator");
    }

    // finalize();
    globalTID = null;
    internalSeq = 0;
  }
  /**
   * Returns the CORBA Object which represents this object.
   *
   * @param
   * @return The CORBA object.
   * @see
   */
  final synchronized RecoveryCoordinator object() {

    if (thisRef == null) {
      if (poa == null) {
        poa = Configuration.getPOA("RecoveryCoordinator" /*#Frozen*/);
        recoverable = Configuration.isRecoverable();
      }

      try {

        if (recoverable && globalTID != null) {
          // Create the object id from the global transaction
          // identifier and the internal sequence number.

          byte[] tidBytes = globalTID.toBytes();
          byte[] id = new byte[tidBytes.length + 4];
          System.arraycopy(tidBytes, 0, id, 4, tidBytes.length);
          id[0] = (byte) internalSeq;
          id[1] = (byte) (internalSeq >> 8);
          id[2] = (byte) (internalSeq >> 16);
          id[3] = (byte) (internalSeq >> 24);

          // Activate the object and create the reference.

          poa.activate_object_with_id(id, this);

          org.omg.CORBA.Object obj =
              poa.create_reference_with_id(id, RecoveryCoordinatorHelper.id());
          thisRef = RecoveryCoordinatorHelper.narrow(obj);
          // thisRef = (RecoveryCoordinator) this;
        } else {
          poa.activate_object(this);
          org.omg.CORBA.Object obj = poa.servant_to_reference(this);
          thisRef = RecoveryCoordinatorHelper.narrow(obj);
          // thisRef = (RecoveryCoordinator)this;
        }
      } catch (Exception exc) {
        _logger.log(Level.SEVERE, "jts.create_recoverycoordinator_error");
        String msg =
            LogFormatter.getLocalizedMessage(_logger, "jts.create_recoverycoordinator_error");
        throw new org.omg.CORBA.INTERNAL(msg);
      }
    }

    return thisRef;
  }
  // same as replay_completion(res) : added for delegated recovery support
  public Status replay_completion(Resource res, String logPath) throws NotPrepared {

    if (_logger.isLoggable(Level.FINE)) {
      _logger.logp(
          Level.FINE,
          "RecoveryCoordinatorImpl",
          "replay_completion()",
          "replay_completion on Resource:" + res);
    }

    Status result = Status.StatusRolledBack;

    CoordinatorImpl coord = DelegatedRecoveryManager.getCoordinator(globalTID, logPath);
    if (coord != null) {
      try {
        result = coord.get_status();
      } catch (SystemException exc) {
      }
    }

    switch (result.value()) {

        /*
         * If the transaction is still active, raise the NotPrepared
         * exception. The Coordinator must be marked rollback-only at
         * this point because we cannot allow the transaction to
         * complete if a participant has failed.
         */

      case Status._StatusActive:
      case Status._StatusMarkedRollback:
        try {
          coord.rollback_only();
        } catch (Throwable exc) {
        }

        throw new NotPrepared();

        /*
         * If the transaction is prepared, the caller must wait for the
         * Coordinator to tell it what to do, so return an unknown status, and
         * do nothing.  Note that if this Coordinator is sitting waiting for
         * its superior, this could take a int time.
         */

      case Status._StatusPrepared:
        result = Status.StatusUnknown;
        break;

        /*
         * If the transaction has been committed, the caller will receive
         * a commit.
         *
         * GDH If the transaction is commiting then we pass this on
         * to the caller. This state (added in OTS 1.1 means that
         * TopCoordinator.recover must now accept the COMMITTING state.
         */

      case Status._StatusCommitting:
        // MODIFICATION (Ram Jeyaraman) commented out the code below,
        // since a StatusCommitting will be upgraded to Committed in
        // the subordinate.
        /*
        // (Ram Jeyaraman) let the subordinate wait, and allow the root
        // finish driving the commit.
        result = Status.StatusUnknown;
        */
        break;

      case Status._StatusCommitted:
        break;

      case Status._StatusRolledBack:

        // If the transaction has been rolled back, and there is
        // no Coordinator for the transaction, we must invoke rollback
        // directly, as it will not be done otherwise.  However for
        // proxies, this rollback cannot be done from this thread as
        // it would cause deadlock in the server requesting resync.

        if (coord == null) {

          if (!Configuration.getProxyChecker().isProxy(res)) {
            rollbackOrphan(res);
          } else {

            // We must pass a duplicate of the proxy to the
            // rollback thread because this proxy will be destroyed
            // when the replay_completion request returns
            // to the remote server.

            try {
              OrphanRollbackThread rollbackThread =
                  new OrphanRollbackThread(this, (Resource) res._duplicate());
              rollbackThread.start();
            } catch (SystemException exc) {
            }
          }
        }

        break;

        /*
         * In any other situation, assume that the transaction has been rolled
         * back. As there is a Coordinator, it will direct the Resource to roll
         * back.
         */

      default:
        result = Status.StatusRolledBack;
    }

    return result;
  }