@Override
 public void stopReadOnly() {
   readOnlyRunning = false;
   if (readOnlyTask != null) {
     LOG.debug(
         "Stopping read-only rebinding ("
             + this
             + "), mgmt "
             + managementContext.getManagementNodeId());
     readOnlyTask.cancel(true);
     readOnlyTask.blockUntilEnded();
     boolean reallyEnded = Tasks.blockUntilInternalTasksEnded(readOnlyTask, Duration.TEN_SECONDS);
     if (!reallyEnded) {
       LOG.warn(
           "Rebind (read-only) tasks took too long to die after interrupt (ignoring): "
               + readOnlyTask);
     }
     readOnlyTask = null;
     LOG.debug(
         "Stopped read-only rebinding ("
             + this
             + "), mgmt "
             + managementContext.getManagementNodeId());
   }
 }
 public BrooklynCampPlatform setConfigKeyAtManagmentContext() {
   ((ManagementContextInternal) bmc)
       .getBrooklynProperties()
       .put(BrooklynCampConstants.CAMP_PLATFORM, this);
   ((ManagementContextInternal) bmc)
       .getBrooklynProperties()
       .put(CampYamlParser.YAML_PARSER_KEY, new YamlParserImpl(this));
   return this;
 }
 @Override
 public void stopPersistence() {
   LOG.debug(
       "Stopping persistence (" + this + "), mgmt " + managementContext.getManagementNodeId());
   persistenceRunning = false;
   if (persistenceRealChangeListener != null) persistenceRealChangeListener.stop();
   if (persistenceStoreAccess != null) persistenceStoreAccess.disableWriteAccess(true);
   LOG.debug("Stopped rebind (persistence), mgmt " + managementContext.getManagementNodeId());
 }
 protected ManagementNodeState getRebindMode() {
   if (managementContext == null)
     throw new IllegalStateException("Invalid " + this + ": no management context");
   if (!(managementContext.getHighAvailabilityManager() instanceof HighAvailabilityManagerImpl))
     throw new IllegalStateException(
         "Invalid "
             + this
             + ": unknown HA manager type "
             + managementContext.getHighAvailabilityManager());
   ManagementNodeState target =
       ((HighAvailabilityManagerImpl) managementContext.getHighAvailabilityManager())
           .getTransitionTargetNodeState();
   return target;
 }
  @Override
  public void setPersister(
      BrooklynMementoPersister val, PersistenceExceptionHandler exceptionHandler) {
    if (persistenceStoreAccess != null && persistenceStoreAccess != val) {
      throw new IllegalStateException(
          "Dynamically changing persister is not supported: old="
              + persistenceStoreAccess
              + "; new="
              + val);
    }
    if (persistenceRealChangeListener != null) {
      // TODO should probably throw here, but previously we have not -- so let's log for now to be
      // sure it's not happening
      LOG.warn(
          "Persister reset after listeners have been set",
          new Throwable("Source of persister reset"));
    }

    this.persistenceStoreAccess = checkNotNull(val, "persister");

    this.persistenceRealChangeListener =
        new PeriodicDeltaChangeListener(
            managementContext.getServerExecutionContext(),
            persistenceStoreAccess,
            exceptionHandler,
            persistMetrics,
            periodicPersistPeriod);
    this.persistencePublicChangeListener = new SafeChangeListener(persistenceRealChangeListener);

    if (persistenceRunning) {
      persistenceRealChangeListener.start();
    }
  }
  @Override
  public List<Application> rebind(
      ClassLoader classLoaderO,
      RebindExceptionHandler exceptionHandlerO,
      ManagementNodeState modeO) {
    final ClassLoader classLoader =
        classLoaderO != null ? classLoaderO : managementContext.getCatalogClassLoader();
    final RebindExceptionHandler exceptionHandler =
        exceptionHandlerO != null
            ? exceptionHandlerO
            : RebindExceptionHandlerImpl.builder()
                .danglingRefFailureMode(danglingRefFailureMode)
                .danglingRefQuorumRequiredHealthy(danglingRefsQuorumRequiredHealthy)
                .rebindFailureMode(rebindFailureMode)
                .addConfigFailureMode(addConfigFailureMode)
                .addPolicyFailureMode(addPolicyFailureMode)
                .loadPolicyFailureMode(loadPolicyFailureMode)
                .build();
    final ManagementNodeState mode = modeO != null ? modeO : getRebindMode();

    if (mode != ManagementNodeState.MASTER
        && mode != ManagementNodeState.HOT_STANDBY
        && mode != ManagementNodeState.HOT_BACKUP)
      throw new IllegalStateException(
          "Must be either master or hot standby/backup to rebind (mode " + mode + ")");

    ExecutionContext ec = BasicExecutionContext.getCurrentExecutionContext();
    if (ec == null) {
      ec = managementContext.getServerExecutionContext();
      Task<List<Application>> task =
          ec.submit(
              new Callable<List<Application>>() {
                @Override
                public List<Application> call() throws Exception {
                  return rebindImpl(classLoader, exceptionHandler, mode);
                }
              });
      try {
        return task.get();
      } catch (Exception e) {
        throw Exceptions.propagate(e);
      }
    } else {
      return rebindImpl(classLoader, exceptionHandler, mode);
    }
  }
 public void rebindPartialActive(CompoundTransformer transformer, String... objectsToRebindIds) {
   List<BrooklynObject> objectsToRebind = MutableList.of();
   for (String objectId : objectsToRebindIds) {
     BrooklynObject obj = managementContext.lookup(objectId);
     objectsToRebind.add(obj);
   }
   rebindPartialActive(transformer, objectsToRebind.iterator());
 }
 @Override
 public void startPersistence() {
   if (readOnlyRunning) {
     throw new IllegalStateException(
         "Cannot start read-only when already running with persistence");
   }
   LOG.debug(
       "Starting persistence (" + this + "), mgmt " + managementContext.getManagementNodeId());
   if (!persistenceRunning) {
     if (managementContext
         .getBrooklynProperties()
         .getConfig(BrooklynServerConfig.PERSISTENCE_BACKUPS_REQUIRED_ON_PROMOTION)) {
       BrooklynPersistenceUtils.createBackup(
           managementContext, CreateBackupMode.PROMOTION, MementoCopyMode.REMOTE);
     }
   }
   persistenceRunning = true;
   readOnlyRebindCount.set(Integer.MIN_VALUE);
   persistenceStoreAccess.enableWriteAccess();
   if (persistenceRealChangeListener != null) persistenceRealChangeListener.start();
 }
  public RebindManagerImpl(ManagementContextInternal managementContext) {
    this.managementContext = managementContext;
    this.persistencePublicChangeListener = ChangeListener.NOOP;

    this.persistPoliciesEnabled =
        BrooklynFeatureEnablement.isEnabled(
            BrooklynFeatureEnablement.FEATURE_POLICY_PERSISTENCE_PROPERTY);
    this.persistEnrichersEnabled =
        BrooklynFeatureEnablement.isEnabled(
            BrooklynFeatureEnablement.FEATURE_ENRICHER_PERSISTENCE_PROPERTY);
    this.persistFeedsEnabled =
        BrooklynFeatureEnablement.isEnabled(
            BrooklynFeatureEnablement.FEATURE_FEED_PERSISTENCE_PROPERTY);
    this.persistCatalogItemsEnabled =
        BrooklynFeatureEnablement.isEnabled(
            BrooklynFeatureEnablement.FEATURE_CATALOG_PERSISTENCE_PROPERTY);

    danglingRefFailureMode =
        managementContext.getConfig().getConfig(DANGLING_REFERENCE_FAILURE_MODE);
    rebindFailureMode = managementContext.getConfig().getConfig(REBIND_FAILURE_MODE);
    addConfigFailureMode = managementContext.getConfig().getConfig(ADD_CONFIG_FAILURE_MODE);
    addPolicyFailureMode = managementContext.getConfig().getConfig(ADD_POLICY_FAILURE_MODE);
    loadPolicyFailureMode = managementContext.getConfig().getConfig(LOAD_POLICY_FAILURE_MODE);

    danglingRefsQuorumRequiredHealthy =
        managementContext.getConfig().getConfig(DANGLING_REFERENCES_MIN_REQUIRED_HEALTHY);

    LOG.debug(
        "{} initialized, settings: policies={}, enrichers={}, feeds={}, catalog={}",
        new Object[] {
          this,
          persistPoliciesEnabled,
          persistEnrichersEnabled,
          persistFeedsEnabled,
          persistCatalogItemsEnabled
        });
  }
  public void rebindPartialActive(
      CompoundTransformer transformer, Iterator<BrooklynObject> objectsToRebind) {
    final ClassLoader classLoader = managementContext.getCatalogClassLoader();
    // TODO we might want different exception handling for partials;
    // failure at various points should leave proxies in a sensible state,
    // either pointing at old or at new, though this is relatively untested,
    // and some things e.g. policies might not be properly started
    final RebindExceptionHandler exceptionHandler =
        RebindExceptionHandlerImpl.builder()
            .danglingRefFailureMode(danglingRefFailureMode)
            .danglingRefQuorumRequiredHealthy(danglingRefsQuorumRequiredHealthy)
            .rebindFailureMode(rebindFailureMode)
            .addConfigFailureMode(addConfigFailureMode)
            .addPolicyFailureMode(addPolicyFailureMode)
            .loadPolicyFailureMode(loadPolicyFailureMode)
            .build();
    final ManagementNodeState mode = getRebindMode();

    ActivePartialRebindIteration iteration =
        new ActivePartialRebindIteration(
            this,
            mode,
            classLoader,
            exceptionHandler,
            rebindActive,
            readOnlyRebindCount,
            rebindMetrics,
            persistenceStoreAccess);

    iteration.setObjectIterator(
        Iterators.transform(
            objectsToRebind,
            new Function<BrooklynObject, BrooklynObject>() {
              @Override
              public BrooklynObject apply(BrooklynObject obj) {
                // entities must be deproxied
                if (obj instanceof Entity) obj = Entities.deproxy((Entity) obj);
                return obj;
              }
            }));
    if (transformer != null) iteration.applyTransformer(transformer);
    iteration.run();
  }
  public static Collection<Application> rebindAll(RebindOptions options) throws Exception {
    File mementoDir = options.mementoDir;
    File mementoDirBackup = options.mementoDirBackup;
    ClassLoader classLoader = checkNotNull(options.classLoader, "classLoader");
    ManagementContextInternal origManagementContext =
        (ManagementContextInternal) options.origManagementContext;
    ManagementContextInternal newManagementContext =
        (ManagementContextInternal) options.newManagementContext;
    PersistenceObjectStore objectStore = options.objectStore;
    HighAvailabilityMode haMode =
        (options.haMode == null ? HighAvailabilityMode.DISABLED : options.haMode);
    RebindExceptionHandler exceptionHandler = options.exceptionHandler;
    boolean hasPersister =
        newManagementContext != null
            && newManagementContext.getRebindManager().getPersister() != null;
    boolean checkSerializable = options.checkSerializable;
    boolean terminateOrigManagementContext = options.terminateOrigManagementContext;
    Function<BrooklynMementoPersister, Void> stateTransformer = options.stateTransformer;

    LOG.info("Rebinding app, using mementoDir " + mementoDir + "; object store " + objectStore);

    if (newManagementContext == null) {
      // TODO Could use empty properties, to save reading brooklyn.properties file.
      // Would that affect any tests?
      newManagementContext =
          new LocalManagementContextForTests(BrooklynProperties.Factory.newDefault());
    }
    if (!hasPersister) {
      if (objectStore == null) {
        objectStore =
            new FileBasedObjectStore(
                checkNotNull(mementoDir, "mementoDir and objectStore must not both be null"));
      }
      objectStore.injectManagementContext(newManagementContext);
      objectStore.prepareForSharedUse(PersistMode.AUTO, haMode);

      BrooklynMementoPersisterToObjectStore newPersister =
          new BrooklynMementoPersisterToObjectStore(
              objectStore, newManagementContext.getBrooklynProperties(), classLoader);
      newManagementContext
          .getRebindManager()
          .setPersister(newPersister, PersistenceExceptionHandlerImpl.builder().build());
    } else {
      if (objectStore != null)
        throw new IllegalStateException(
            "Must not supply ManagementContext with persister and an object store");
    }

    if (checkSerializable) {
      checkNotNull(
          origManagementContext, "must supply origManagementContext with checkSerializable");
      RebindTestUtils.checkCurrentMementoSerializable(origManagementContext);
    }

    if (terminateOrigManagementContext) {
      checkNotNull(
          origManagementContext,
          "must supply origManagementContext with terminateOrigManagementContext");
      origManagementContext.terminate();
    }

    if (mementoDirBackup != null) {
      FileUtil.copyDir(mementoDir, mementoDirBackup);
      FileUtil.setFilePermissionsTo700(mementoDirBackup);
    }

    if (stateTransformer != null) {
      BrooklynMementoPersister persister = newManagementContext.getRebindManager().getPersister();
      stateTransformer.apply(persister);
    }

    List<Application> newApps =
        newManagementContext
            .getRebindManager()
            .rebind(
                classLoader,
                exceptionHandler,
                (haMode == HighAvailabilityMode.DISABLED)
                    ? ManagementNodeState.MASTER
                    : ManagementNodeState.of(haMode).get());
    newManagementContext.getRebindManager().startPersistence();
    return newApps;
  }
 @Override
 public String toString() {
   return super.toString() + "[mgmt=" + managementContext.getManagementNodeId() + "]";
 }
  @SuppressWarnings("unchecked")
  @Override
  public void startReadOnly(final ManagementNodeState mode) {
    if (!ManagementNodeState.isHotProxy(mode)) {
      throw new IllegalStateException(
          "Read-only rebind thread only permitted for hot proxy modes; not " + mode);
    }

    if (persistenceRunning) {
      throw new IllegalStateException(
          "Cannot start read-only when already running with persistence");
    }
    if (readOnlyRunning || readOnlyTask != null) {
      LOG.warn(
          "Cannot request read-only mode for "
              + this
              + " when already running - "
              + readOnlyTask
              + "; ignoring");
      return;
    }
    LOG.debug(
        "Starting read-only rebinding ("
            + this
            + "), mgmt "
            + managementContext.getManagementNodeId());

    if (persistenceRealChangeListener != null) persistenceRealChangeListener.stop();
    if (persistenceStoreAccess != null) persistenceStoreAccess.disableWriteAccess(true);

    readOnlyRunning = true;
    readOnlyRebindCount.set(0);

    try {
      rebind(null, null, mode);
    } catch (Exception e) {
      throw Exceptions.propagate(e);
    }

    Callable<Task<?>> taskFactory =
        new Callable<Task<?>>() {
          @Override
          public Task<Void> call() {
            return Tasks.<Void>builder()
                .dynamic(false)
                .displayName("rebind (periodic run")
                .body(
                    new Callable<Void>() {
                      public Void call() {
                        try {
                          rebind(null, null, mode);
                          return null;
                        } catch (RuntimeInterruptedException e) {
                          LOG.debug("Interrupted rebinding (re-interrupting): " + e);
                          if (LOG.isTraceEnabled())
                            LOG.trace("Interrupted rebinding (re-interrupting), details: " + e, e);
                          Thread.currentThread().interrupt();
                          return null;
                        } catch (Exception e) {
                          // Don't rethrow: the behaviour of executionManager is different from a
                          // scheduledExecutorService,
                          // if we throw an exception, then our task will never get executed again
                          if (!readOnlyRunning) {
                            LOG.debug(
                                "Problem rebinding (read-only running has probably just been turned off): "
                                    + e);
                            if (LOG.isTraceEnabled()) {
                              LOG.trace(
                                  "Problem rebinding (read-only running has probably just been turned off), details: "
                                      + e,
                                  e);
                            }
                          } else {
                            LOG.error("Problem rebinding: " + Exceptions.collapseText(e), e);
                          }
                          return null;
                        } catch (Throwable t) {
                          LOG.warn("Problem rebinding (rethrowing)", t);
                          throw Exceptions.propagate(t);
                        }
                      }
                    })
                .build();
          }
        };
    readOnlyTask =
        (ScheduledTask)
            managementContext
                .getServerExecutionContext()
                .submit(
                    new ScheduledTask(
                            MutableMap.of("displayName", "Periodic read-only rebind"), taskFactory)
                        .period(periodicPersistPeriod));
  }