// This method generally should only be called by HubProvideFactory.removeHubRequestMonitor()
  public void destroy() {
    if (systemData != null) systemData.system.destroy();

    synchronized (this) {
      if (createSystemFuture != null) createSystemFuture.cancel(true);
      if (queryOperation != null) queryOperation.cancel();
      queryOperation = null;

      if (gracePeriodFuture != null) gracePeriodFuture.cancel(true);
      gracePeriodFuture = null;

      if (gracePeriodExpiredFuture != null) gracePeriodExpiredFuture.cancel(true);
      gracePeriodExpiredFuture = null;

      if (activateInterestOperation != null) activateInterestOperation.cancel();
      activateInterestOperation = null;
      if (provider != null) provider.destroy();
      provider = null;
      if (hubConfig != null) hubProvideFactory.removeHubConfig(hubConfig);
      hubConfig = null;

      if (hubRequestRequestor != null) hubRequestRequestor.destroy();
      hubRequestRequestor = null;
    }
  }
  public void handleGracePeriodExpired() {
    synchronized (this) {
      gracePeriodExpiredFuture = null;
      //            if (requestProvided.get())
      //                return;
      //            gracePeriodExpired.set(true);

      if (provider != null) {
        provider.destroy();
        provider = null;
      }
    }
    hubProvideFactory.removeHubConfig(hubConfig);
  }
 public void cancelActivate() {
   boolean cleanup = false;
   synchronized (this) {
     if (provider == null) {
       // If the hubProvider has not been started its because the grace period has not been
       // obtained from the requestor.
       // The requestor not seeing a get call for the grace period is it's sign that something
       // failed (i.e. create system)
       // this flags the requestor to cancel interest and re-issue interest for retries.
       // thus clean everything up to this point
       if (createSystemFuture != null) createSystemFuture.cancel(true);
       if (gracePeriodFuture != null) gracePeriodFuture.cancel(true);
       cleanup = true;
     }
   }
   if (cleanup)
     hubProvideFactory.removeHubRequestMonitor(
         providerId); // in a state that only a new interest can get it back up.
   // else if the requestor wanted to drop interest at this point, they could simply keep grace
   // period provide up to keep the hub provider active
   // losing and gaining the grace period interface will be the trigger for gracePeriod timeout and
   // cleanup from here out.
 }
 private void setHubConfig() {
   boolean created = false;
   synchronized (this) {
     if (hubConfig == null) {
       // @formatter:off
       hubConfig =
           new DOFConnection.Config.Builder(
                   DOFConnection.Type.HUB, new DOFGroupAddress(systemData.groupId))
               .setName(
                   systemData.groupId.getDataString()
                       + "."
                       + systemData.domainId.getDataString()
                       + "-HubConnection")
               .setCredentials(systemData.credentials)
               .setTunnelDomains(HubManagerModule.HubsTunnelDomains)
               .setMaxReceiveSilence(HubManagerModule.HubsMaxReceiveSilence)
               .setMaxSendSilence(HubManagerModule.HubsMaxSendSilence)
               .build();
       // @formatter:on
       created = true;
     }
   }
   if (created) hubProvideFactory.addHubConfig(this);
 }
  void handleInterfaceAdded(DOFObjectID objectId, DOFInterfaceID interfaceId) {
    DOFObject requestor;
    int requestorGracePeriodMinutes = -1;
    // this is the flag that other domainManagers started this sequence, MAX_VALUE == started by
    // activate, not broadcast get
    boolean broadcastGetActivated =
        (hubProvideFactory.coreDomainGracePeriodMinutes.get() != Integer.MAX_VALUE);

    try {
      requestor =
          systemData.system.waitProvider(objectId, interfaceId, hubProvideFactory.commTimeout);
      requestorGracePeriodMinutes =
          HubRequestInterface.getGracePeriod(requestor, hubProvideFactory.commTimeout);

      synchronized (this) {
        if (gracePeriodExpiredFuture != null) {
          gracePeriodExpiredFuture.cancel(true);
          gracePeriodExpiredFuture = null;
          return;
        }
        hubRequestRequestor = requestor;
      }
    } catch (Exception e) {
      /*
       * Interesting point in time here ... the coredomain broadcast's get may have initiated the startup sequence instead of
       * a requestor's activate.  The coredomain's get handler will be capturing the smallest value seen from the broadcast
       * and we are going to go with the lowest that has been seen at this time. (comm timeout on get from the requestor).
       * If the requestor's provide and getGracePeriod do not fail, then the state of the other cr/domain managers no longer matters
       * to this manager as we have a know live requestor.
       */

      // this is the flag that other domainManagers started this sequence, MAX_VALUE == started by
      // activate, not broadcast get
      if (!broadcastGetActivated) {
        // this is a fatal timeout, clean up the monitor;
        log.warn(
            "Failed to obtain hubRequestRequestor for getting grace period on {}: " + e,
            providerId);
        hubProvideFactory.removeHubRequestMonitor(providerId);
        return;
      }
    }
    synchronized (this) {
      provider =
          new HubProvider(hubProvideFactory.coreSystem, providerId, requestorGracePeriodMinutes);
      provider.init();
      provider.requestProvideStarted();
    }
    setHubConfig();
    if (broadcastGetActivated && requestorGracePeriodMinutes == -1) {
      GracePeriodExpiredTask gracePeriodExpiredTask = new GracePeriodExpiredTask(this);
      synchronized (this) {
        if (gracePeriodFuture != null) {
          gracePeriodFuture.cancel(true);
          gracePeriodFuture = null;
        }
        int remaining = hubProvideFactory.coreDomainGracePeriodMinutes.get();
        gracePeriodExpiredFuture =
            hubProvideFactory.timerExecutor.schedule(
                gracePeriodExpiredTask, remaining, TimeUnit.MINUTES);
        provider.requestProvideStopped(remaining);
      }
    }
  }
  void getSystemAndStartQuery() {
    try {
      Authentication groupId = DOFObjectID.Authentication.create(providerId.getBase());
      DOFObjectID.Attribute attr = providerId.getAttribute(DOFObjectID.Attribute.GROUP);
      Domain domainId = DOFObjectID.Domain.create(attr.getValueObjectID());
      DOFCredentials domainCredentials =
          DOFCredentials.create(hubProvideFactory.coreCredentials, domainId);
      //
      // @formatter:off
      DOFSystem.Config domainSystemConfig =
          new DOFSystem.Config.Builder()
              .setName(groupId.getDataString() + "." + domainId.getDataString() + "-DOFSystem")
              .setCredentials(domainCredentials)
              .setPermissionsExtendAllowed(true)
              .setTunnelDomains(true)
              .build();
      // @formatter:on

      DOFDomain.Config domainConfig = new DOFDomain.Config.Builder(domainCredentials).build();
      DOFDomain serviceDomain = hubProvideFactory.dof.createDomain(domainConfig);
      serviceDomain.addStateListener(this);
      long t0 = System.currentTimeMillis();
      long to = hubProvideFactory.commTimeout;
      synchronized (domainFound) {
        while (!domainFound.get()) {
          try {
            domainFound.wait(to);
            if (domainFound.get()) break;
            long delta = System.currentTimeMillis() - t0;
            if (delta >= hubProvideFactory.commTimeout)
              throw new TimeoutException(
                  "timed out: " + to + " waiting for Domain listener to report completed");
            to =
                hubProvideFactory.commTimeout
                    - delta; // spurious wakeup, or wait(to) slightly off System.currentTimeMillis
          } finally {
            serviceDomain.removeStateListener(this);
          }
        }
      }
      DOFSystem system =
          hubProvideFactory.dof.createSystem(domainSystemConfig, hubProvideFactory.commTimeout);
      systemData = new CreateSystemTask.SystemData(groupId, domainId, domainCredentials, system);
    } catch (InterruptedException e) {
      hubProvideFactory.removeHubRequestMonitor(providerId);
      log.debug("Create system task interrupted.");
      return;
    } catch (Exception e) {
      hubProvideFactory.removeHubRequestMonitor(providerId);
      log.debug("Create system failed {} - " + e.getCause(), providerId);
      return;
    }

    synchronized (this) {
      if (activateInterestOperation == null || activateInterestOperation.isComplete())
        activateInterestOperation =
            systemData.system.beginInterest(
                systemData.groupId,
                HubRequestInterface.IID,
                DOFInterestLevel.ACTIVATE,
                DOF.TIMEOUT_NEVER,
                null,
                null);

      if (queryOperation == null || queryOperation.isComplete()) {
        DOFQuery query =
            new DOFQuery.Builder()
                .addFilter(providerId)
                .addRestriction(HubRequestInterface.IID)
                .build();
        queryOperation = systemData.system.beginQuery(query, DOF.TIMEOUT_NEVER, this, null);
      }
      createSystemFuture = null;
      log.debug(
          "HubManager dof: "
              + hubProvideFactory.dof.getState().getName()
              + " beginQuery for: "
              + providerId.toStandardString()
              + ":"
              + HubRequestInterface.IID);
    }
  }