You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2015/05/29 12:36:05 UTC
[05/13] incubator-brooklyn git commit: more code review/cleanup for
catalog CLI
more code review/cleanup for catalog CLI
especially around the official/final/unofficial initialization interplay with HA modes,
so that after a node has been promoted to master, on subsequent promotions it doesn't re-apply the initializations
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/df21c711
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/df21c711
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/df21c711
Branch: refs/heads/master
Commit: df21c7116adb94986c4cb2c8e12ec6b86d580048
Parents: 9cc7293
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon May 25 11:24:55 2015 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon May 25 11:44:09 2015 +0100
----------------------------------------------------------------------
.../catalog/internal/CatalogInitialization.java | 127 ++++++++++++++-----
.../internal/CatalogItemDtoAbstract.java | 4 +-
.../rebind/PeriodicDeltaChangeListener.java | 38 +++---
.../entity/rebind/RebindContextImpl.java | 6 +-
.../brooklyn/entity/rebind/RebindIteration.java | 51 +++++---
.../entity/rebind/RebindManagerImpl.java | 2 +-
.../ha/HighAvailabilityManagerImpl.java | 57 +++++----
.../internal/AbstractManagementContext.java | 4 +-
usage/cli/src/main/java/brooklyn/cli/Main.java | 4 +
.../java/brooklyn/cli/lister/ClassFinder.java | 2 +-
.../brooklyn/launcher/BrooklynLauncher.java | 13 +-
.../rest/filter/HaHotCheckResourceFilter.java | 2 +-
.../rest/filter/HaMasterCheckFilter.java | 2 +-
.../util/javalang/AggregateClassLoader.java | 2 +-
14 files changed, 212 insertions(+), 102 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java b/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
index 6f0b80e..8f45a8c 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
@@ -29,6 +29,7 @@ import brooklyn.catalog.CatalogItem;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.management.ManagementContext;
import brooklyn.management.ManagementContextInjectable;
+import brooklyn.management.ha.ManagementNodeState;
import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
@@ -37,6 +38,7 @@ import brooklyn.util.exceptions.FatalRuntimeException;
import brooklyn.util.exceptions.RuntimeInterruptedException;
import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
+import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.os.Os;
import brooklyn.util.text.Strings;
@@ -78,7 +80,15 @@ public class CatalogInitialization implements ManagementContextInjectable {
private boolean disallowLocal = false;
private List<Function<CatalogInitialization, Void>> callbacks = MutableList.of();
- private boolean hasRunBestEffort = false, hasRunOfficial = false, isPopulating = false;
+ private boolean
+ /** has run an unofficial initialization (i.e. an early load, triggered by an early read of the catalog) */
+ hasRunUnofficialInitialization = false,
+ /** has run an official initialization, but it is not a permanent one (e.g. during a hot standby mode, or a run failed) */
+ hasRunTransientOfficialInitialization = false,
+ /** has run an official initialization which is permanent (node is master, and the new catalog is now set) */
+ hasRunFinalInitialization = false;
+ /** is running a populate method; used to prevent recursive loops */
+ private boolean isPopulating = false;
private ManagementContext managementContext;
private boolean isStartingUp = false;
@@ -97,6 +107,7 @@ public class CatalogInitialization implements ManagementContextInjectable {
this(null, false, null, false);
}
+ @Override
public void injectManagementContext(ManagementContext managementContext) {
Preconditions.checkNotNull(managementContext, "management context");
if (this.managementContext!=null && managementContext!=this.managementContext)
@@ -127,56 +138,108 @@ public class CatalogInitialization implements ManagementContextInjectable {
return reset;
}
- public boolean hasRunOfficial() { return hasRunOfficial; }
- public boolean hasRunIncludingBestEffort() { return hasRunOfficial || hasRunBestEffort; }
-
- /** makes or updates the mgmt catalog, based on the settings in this class */
- public void populateCatalog(boolean needsInitial, Collection<CatalogItem<?, ?>> optionalItemsForResettingCatalog) {
+ /** Returns true if the canonical initialization has completed,
+ * that is, an initialization which is done when a node is rebinded as master
+ * (or an initialization done by the startup routines when not running persistence);
+ * see also {@link #hasRunAnyInitialization()}. */
+ public boolean hasRunFinalInitialization() { return hasRunFinalInitialization; }
+ /** Returns true if an official initialization has run,
+ * even if it was a transient run, e.g. so that the launch sequence can tell whether rebind has triggered initialization */
+ public boolean hasRunOfficialInitialization() { return hasRunFinalInitialization || hasRunTransientOfficialInitialization; }
+ /** Returns true if the initializer has run at all,
+ * including transient initializations which might be needed before a canonical becoming-master rebind,
+ * for instance because the catalog is being accessed before loading rebind information
+ * (done by {@link #populateUnofficial(BasicBrooklynCatalog)}) */
+ public boolean hasRunAnyInitialization() { return hasRunFinalInitialization || hasRunTransientOfficialInitialization || hasRunUnofficialInitialization; }
+
+ /** makes or updates the mgmt catalog, based on the settings in this class
+ * @param nodeState the management node for which this is being read; if master, then we expect this run to be the last one,
+ * and so subsequent applications should ignore any initialization data (e.g. on a subsequent promotion to master,
+ * after a master -> standby -> master cycle)
+ * @param needsInitialItemsLoaded whether the catalog needs the initial items loaded
+ * @param needsInitialItemsLoaded whether the catalog needs the additiona items loaded
+ * @param optionalExcplicitItemsForResettingCatalog
+ * if supplied, the catalog is reset to contain only these items, before calling any other initialization
+ * for use primarily when rebinding
+ */
+ public void populateCatalog(ManagementNodeState nodeState, boolean needsInitialItemsLoaded, boolean needsAdditionsLoaded, Collection<CatalogItem<?, ?>> optionalExcplicitItemsForResettingCatalog) {
+ if (log.isDebugEnabled()) {
+ String message = "Populating catalog for "+nodeState+", needsInitial="+needsInitialItemsLoaded+", needsAdditional="+needsAdditionsLoaded+", explicitItems="+(optionalExcplicitItemsForResettingCatalog==null ? "null" : optionalExcplicitItemsForResettingCatalog.size())+"; from "+JavaClassNames.callerNiceClassAndMethod(1);
+ if (!ManagementNodeState.isHotProxy(nodeState)) {
+ log.debug(message);
+ } else {
+ // in hot modes, make this message trace so we don't get too much output then
+ log.trace(message);
+ }
+ }
synchronized (populatingCatalogMutex) {
try {
+ if (hasRunFinalInitialization() && (needsInitialItemsLoaded || needsAdditionsLoaded)) {
+ // if we have already run "final" then we should only ever be used to reset the catalog,
+ // not to initialize or add; e.g. we are being given a fixed list on a subsequent master rebind after the initial master rebind
+ log.warn("Catalog initialization called to populate initial, even though it has already run the final official initialization");
+ }
isPopulating = true;
BasicBrooklynCatalog catalog = (BasicBrooklynCatalog) managementContext.getCatalog();
if (!catalog.getCatalog().isLoaded()) {
catalog.load();
} else {
- if (needsInitial && (hasRunOfficial || hasRunBestEffort)) {
+ if (needsInitialItemsLoaded && hasRunAnyInitialization()) {
// an indication that something caused it to load early; not severe, but unusual
- log.warn("Catalog initialization has not properly run but management context has a catalog; re-populating, possibly overwriting items installed during earlier access (it may have been an early web request)");
+ if (hasRunTransientOfficialInitialization) {
+ log.debug("Catalog initialization now populating, but has noted a previous official run which was not final (probalby loaded while in a standby mode, or a previous run failed); overwriting any items installed earlier");
+ } else {
+ log.warn("Catalog initialization now populating, but has noted a previous unofficial run (it may have been an early web request); overwriting any items installed earlier");
+ }
catalog.reset(ImmutableList.<CatalogItem<?,?>>of());
}
}
- hasRunOfficial = true;
- populateCatalogImpl(catalog, needsInitial, optionalItemsForResettingCatalog);
+ populateCatalogImpl(catalog, needsInitialItemsLoaded, needsAdditionsLoaded, optionalExcplicitItemsForResettingCatalog);
+ if (nodeState == ManagementNodeState.MASTER) {
+ // TODO ideally this would remain false until it has *persisted* the changed catalog;
+ // if there is a subsequent startup failure the forced additions will not be persisted,
+ // but nor will they be loaded on a subsequent run.
+ // callers will have to restart a brooklyn, or reach into this class to change this field,
+ // or (recommended) manually adjust the catalog.
+ // TODO also, if a node comes up in standby, the addition might not take effector for a while
+ //
+ // however since these options are mainly for use on the very first brooklyn run, it's not such a big deal;
+ // once up and running the typical way to add items is via the REST API
+ hasRunFinalInitialization = true;
+ }
} finally {
- hasRunOfficial = true;
+ if (!hasRunFinalInitialization) {
+ hasRunTransientOfficialInitialization = true;
+ }
isPopulating = false;
}
}
}
- private void populateCatalogImpl(BasicBrooklynCatalog catalog, boolean needsInitial, Collection<CatalogItem<?, ?>> optionalItemsForResettingCatalog) {
+ private void populateCatalogImpl(BasicBrooklynCatalog catalog, boolean needsInitialItemsLoaded, boolean needsAdditionsLoaded, Collection<CatalogItem<?, ?>> optionalItemsForResettingCatalog) {
applyCatalogLoadMode();
if (optionalItemsForResettingCatalog!=null) {
catalog.reset(optionalItemsForResettingCatalog);
}
- if (needsInitial) {
+ if (needsInitialItemsLoaded) {
populateInitial(catalog);
}
-
- populateAdditions(catalog);
- populateViaCallbacks(catalog);
+ if (needsAdditionsLoaded) {
+ populateAdditions(catalog);
+ populateViaCallbacks(catalog);
+ }
}
private enum PopulateMode { YAML, XML, AUTODETECT }
protected void populateInitial(BasicBrooklynCatalog catalog) {
if (disallowLocal) {
- if (!hasRunOfficial()) {
- log.debug("CLI initial catalog not being read with disallow-local mode set.");
+ if (!hasRunFinalInitialization()) {
+ log.debug("CLI initial catalog not being read when local catalog load mode is disallowed.");
}
return;
}
@@ -201,13 +264,13 @@ public class CatalogInitialization implements ManagementContextInjectable {
catalogUrl = Os.mergePaths(BrooklynServerConfig.getMgmtBaseDir( managementContext.getConfig() ), "catalog.bom");
if (new File(catalogUrl).exists()) {
- populateInitialFromUri(catalog, "file:"+catalogUrl, PopulateMode.YAML);
+ populateInitialFromUri(catalog, new File(catalogUrl).toURI().toString(), PopulateMode.YAML);
return;
}
catalogUrl = Os.mergePaths(BrooklynServerConfig.getMgmtBaseDir( managementContext.getConfig() ), "catalog.xml");
if (new File(catalogUrl).exists()) {
- populateInitialFromUri(catalog, "file:"+catalogUrl, PopulateMode.XML);
+ populateInitialFromUri(catalog, new File(catalogUrl).toURI().toString(), PopulateMode.XML);
return;
}
@@ -287,7 +350,7 @@ public class CatalogInitialization implements ManagementContextInjectable {
if (Strings.isNonBlank(additionsUri)) {
if (disallowLocal) {
if (!hasRunAdditions) {
- log.warn("CLI additions supplied but not supported in disallow-local mode; ignoring.");
+ log.warn("CLI additions supplied but not supported when catalog load mode disallows local loads; ignoring.");
}
return;
}
@@ -340,21 +403,27 @@ public class CatalogInitialization implements ManagementContextInjectable {
}
}
- /** makes the catalog, warning if persistence is on and hasn't run yet
- * (as the catalog will be subsequently replaced) */
- public void populateBestEffort(BasicBrooklynCatalog catalog) {
+ /** Creates the catalog based on parameters set here, if not yet loaded,
+ * but ignoring persisted state and warning if persistence is on and we are starting up
+ * (because the official persistence is preferred and the catalog will be subsequently replaced);
+ * for use when the catalog is accessed before persistence is completed.
+ * <p>
+ * This method is primarily used during testing, which in many cases does not enforce the full startup order
+ * and which wants a local catalog in any case. It may also be invoked if a client requests the catalog
+ * while the server is starting up. */
+ public void populateUnofficial(BasicBrooklynCatalog catalog) {
synchronized (populatingCatalogMutex) {
- if (hasRunOfficial || hasRunBestEffort || isPopulating) return;
- // if a thread calls back in to this, ie calling to it from a getCatalog() call while populating,
- // it will own the mutex and observe isRunningBestEffort, returning quickly
+ // check isPopulating in case this method gets called from inside another populate call
+ if (hasRunAnyInitialization() || isPopulating) return;
+ log.debug("Populating catalog unofficially ("+catalog+")");
isPopulating = true;
try {
if (isStartingUp) {
log.warn("Catalog access requested when not yet initialized; populating best effort rather than through recommended pathway. Catalog data may be replaced subsequently.");
}
- populateCatalogImpl(catalog, true, null);
+ populateCatalogImpl(catalog, true, true, null);
} finally {
- hasRunBestEffort = true;
+ hasRunUnofficialInitialization = true;
isPopulating = false;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index c6ff97e..131c26e 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -184,7 +184,9 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
if (!Objects.equal(displayName, other.displayName)) return false;
if (!Objects.equal(iconUrl, other.iconUrl)) return false;
if (!Objects.equal(tags, other.tags)) return false;
- // 'type' not checked, because deprecated, we might want to allow removal in future
+ // 'type' not checked, because deprecated,
+ // and in future we might want to allow it to be removed/blanked in some impls without affecting equality
+ // (in most cases it is the same as symbolicName so doesn't matter)
return true;
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java b/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
index f3861bc..4203b4b 100644
--- a/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
+++ b/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
@@ -166,9 +166,8 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
private DeltaCollector deltaCollector = new DeltaCollector();
- private volatile boolean running = false;
-
- private volatile boolean stopping = false, stopCompleted = false;
+ private enum ListenerState { INIT, RUNNING, STOPPING, STOPPED }
+ private volatile ListenerState state = ListenerState.INIT;
private volatile ScheduledTask scheduledTask;
@@ -197,18 +196,17 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
@SuppressWarnings("unchecked")
public void start() {
synchronized (startStopMutex) {
- if (running || (scheduledTask!=null && !scheduledTask.isDone())) {
+ if (state==ListenerState.RUNNING || (scheduledTask!=null && !scheduledTask.isDone())) {
LOG.warn("Request to start "+this+" when already running - "+scheduledTask+"; ignoring");
return;
}
- stopCompleted = false;
- running = true;
+ state = ListenerState.RUNNING;
Callable<Task<?>> taskFactory = new Callable<Task<?>>() {
@Override public Task<Void> call() {
return Tasks.<Void>builder().dynamic(false).name("periodic-persister").body(new Callable<Void>() {
public Void call() {
- persistNowSafely(false);
+ persistNowSafely();
return null;
}}).build();
}
@@ -224,9 +222,8 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
}
void stop(Duration timeout, Duration graceTimeoutForSubsequentOperations) {
synchronized (startStopMutex) {
- running = false;
+ state = ListenerState.STOPPING;
try {
- stopping = true;
if (scheduledTask != null) {
CountdownTimer expiry = timeout.countdownTimer();
@@ -250,8 +247,7 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
deltaCollector = new DeltaCollector();
}
} finally {
- stopCompleted = true;
- stopping = false;
+ state = ListenerState.STOPPED;
}
}
}
@@ -259,7 +255,7 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
/** Waits for any in-progress writes to be completed then for or any unwritten data to be written. */
@VisibleForTesting
public void waitForPendingComplete(Duration timeout, boolean canTrigger) throws InterruptedException, TimeoutException {
- if (!isActive() && !stopping) return;
+ if (!isActive() && state != ListenerState.STOPPING) return;
CountdownTimer timer = timeout.isPositive() ? CountdownTimer.newInstanceStarted(timeout) : CountdownTimer.newInstancePaused(Duration.PRACTICALLY_FOREVER);
Integer targetWriteCount = null;
@@ -299,14 +295,16 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
* Even when not active, changes will still be tracked unless {@link #isStopped()}.
*/
private boolean isActive() {
- return running && persister != null && !isStopped();
+ return state == ListenerState.RUNNING && persister != null && !isStopped();
}
/**
- * Whether we have been stopped, in which case will not persist or store anything.
+ * Whether we have been stopped, ie are stopping are or fully stopped,
+ * in which case will not persist or store anything
+ * (except for a final internal persistence called while STOPPING.)
*/
private boolean isStopped() {
- return stopping || stopCompleted || executionContext.isShutdown();
+ return state == ListenerState.STOPPING || state == ListenerState.STOPPED || executionContext.isShutdown();
}
private void addReferencedObjects(DeltaCollector deltaCollector) {
@@ -336,7 +334,11 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
}
@VisibleForTesting
- public boolean persistNowSafely(boolean alreadyHasMutex) {
+ public boolean persistNowSafely() {
+ return persistNowSafely(false);
+ }
+
+ private boolean persistNowSafely(boolean alreadyHasMutex) {
Stopwatch timer = Stopwatch.createStarted();
try {
persistNowInternal(alreadyHasMutex);
@@ -364,12 +366,12 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
}
protected void persistNowInternal(boolean alreadyHasMutex) {
- if (!isActive() && !stopping) {
+ if (!isActive() && state != ListenerState.STOPPING) {
return;
}
try {
if (!alreadyHasMutex) persistingMutex.acquire();
- if (!isActive() && !stopping) return;
+ if (!isActive() && state != ListenerState.STOPPING) return;
// Atomically switch the delta, so subsequent modifications will be done in the
// next scheduled persist
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
index b7eba1a..b39fea4 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
@@ -100,6 +100,10 @@ public class RebindContextImpl implements RebindContext {
catalogItems.remove(item.getId());
}
+ public void clearCatalogItems() {
+ catalogItems.clear();
+ }
+
public Entity getEntity(String id) {
return entities.get(id);
}
@@ -180,5 +184,5 @@ public class RebindContextImpl implements RebindContext {
public LookupContext lookup() {
return lookupContext;
}
-
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index 2d1e47f..ad4915a 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -308,7 +308,7 @@ public abstract class RebindIteration {
if (rebindManager.persistCatalogItemsEnabled) {
logRebindingDebug("RebindManager instantiating catalog items: {}", mementoManifest.getCatalogItemIds());
for (CatalogItemMemento catalogItemMemento : mementoManifest.getCatalogItemMementos().values()) {
- if (LOG.isDebugEnabled()) LOG.debug("RebindManager instantiating catalog item {}", catalogItemMemento);
+ logRebindingDebug("RebindManager instantiating catalog item {}", catalogItemMemento);
try {
CatalogItem<?, ?> catalogItem = instantiator.newCatalogItem(catalogItemMemento);
rebindContext.registerCatalogItem(catalogItemMemento.getId(), catalogItem);
@@ -347,9 +347,9 @@ public abstract class RebindIteration {
CatalogInitialization catInit = ((ManagementContextInternal)managementContext).getCatalogInitialization();
catInit.applyCatalogLoadMode();
Collection<CatalogItem<?,?>> itemsForResettingCatalog = null;
- boolean needsInitialCatalog;
+ boolean needsInitialItemsLoaded, needsAdditionalItemsLoaded;
if (rebindManager.persistCatalogItemsEnabled) {
- if (!catInit.hasRunOfficial() && catInit.isInitialResetRequested()) {
+ if (!catInit.hasRunFinalInitialization() && catInit.isInitialResetRequested()) {
String message = "RebindManager resetting catalog on first run (catalog persistence enabled, but reset explicitly specified). ";
if (catalogItems.isEmpty()) {
message += "Catalog was empty anyway.";
@@ -361,6 +361,15 @@ public abstract class RebindIteration {
}
logRebindingDebug(message);
+ // we will have unnecessarily tried to load the catalog item manifests earlier in this iteration,
+ // and problems there could fail a rebind even when we are resetting;
+ // it might be cleaner to check earlier whether a reset is happening and not load those items at all,
+ // but that would be a significant new code path (to remove a directory in the persistent store, essentially),
+ // and as it stands we don't do much with those manifests (e.g. we won't register them or fail on missing types)
+ // so we think it's only really corrupted XML or CatalogItem schema changes which would cause such problems.
+ // in extremis someone might need to wipe their store but for most purposes i don't think there will be any issue
+ // with loading the catalog item manifests before wiping all those files.
+
itemsForResettingCatalog = MutableList.<CatalogItem<?,?>>of();
PersisterDeltaImpl delta = new PersisterDeltaImpl();
@@ -368,36 +377,42 @@ public abstract class RebindIteration {
getPersister().queueDelta(delta);
mementoRawData.clearCatalogItems();
- needsInitialCatalog = true;
+ rebindContext.clearCatalogItems();
+ needsInitialItemsLoaded = true;
+ needsAdditionalItemsLoaded = true;
} else {
if (!isEmpty) {
logRebindingDebug("RebindManager clearing local catalog and loading from persisted state");
itemsForResettingCatalog = rebindContext.getCatalogItems();
- needsInitialCatalog = false;
+ needsInitialItemsLoaded = false;
+ // only apply "add" if we haven't yet done so while in MASTER mode
+ needsAdditionalItemsLoaded = !catInit.hasRunFinalInitialization();
} else {
- if (catInit.hasRunOfficial()) {
- logRebindingDebug("RebindManager will re-add any new items (persisted state empty)");
- needsInitialCatalog = false;
+ if (catInit.hasRunFinalInitialization()) {
+ logRebindingDebug("RebindManager has already done the final official run, not doing anything (even though persisted state empty)");
+ needsInitialItemsLoaded = false;
+ needsAdditionalItemsLoaded = false;
} else {
- logRebindingDebug("RebindManager loading initial catalog locally because persisted state empty");
- needsInitialCatalog = true;
+ logRebindingDebug("RebindManager loading initial catalog locally because persisted state empty and the final official run has not yet been performed");
+ needsInitialItemsLoaded = true;
+ needsAdditionalItemsLoaded = true;
}
}
}
} else {
- if (catInit.hasRunOfficial()) {
+ if (catInit.hasRunFinalInitialization()) {
logRebindingDebug("RebindManager skipping catalog init because it has already run (catalog persistence disabled)");
- needsInitialCatalog = false;
+ needsInitialItemsLoaded = false;
+ needsAdditionalItemsLoaded = false;
} else {
- logRebindingDebug("RebindManager will initialize catalog locally because catalog persistence is disabled");
- needsInitialCatalog = true;
+ logRebindingDebug("RebindManager will initialize catalog locally because catalog persistence is disabled and the final official run has not yet been performed");
+ needsInitialItemsLoaded = true;
+ needsAdditionalItemsLoaded = true;
}
}
- // TODO in read-only mode, perhaps do this less frequently than entities etc ?
- // both in RW and in RO mode, the first run reads the initialization data;
- // maybe not desired for RO as it defers problems, although if it's standalone it is desired
- catInit.populateCatalog(needsInitialCatalog, itemsForResettingCatalog);
+ // TODO in read-only mode, perhaps do this less frequently than entities etc, maybe only if things change?
+ catInit.populateCatalog(mode, needsInitialItemsLoaded, needsAdditionalItemsLoaded, itemsForResettingCatalog);
}
protected void instantiateLocationsAndEntities() {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index ded0049..c94e8fa 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -441,7 +441,7 @@ public class RebindManagerImpl implements RebindManager {
}
persistenceStoreAccess.checkpoint(memento, exceptionHandler);
} else {
- if (!persistenceRealChangeListener.persistNowSafely(false)) {
+ if (!persistenceRealChangeListener.persistNowSafely()) {
throw new IllegalStateException("Forced persistence failed; see logs fore more detail");
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
index ab033fd..96e6bea 100644
--- a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
+++ b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
@@ -408,33 +408,40 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
throw new IllegalStateException("Unexpected high availability mode "+startMode+" requested for "+this);
}
- if ((startMode==HighAvailabilityMode.HOT_STANDBY || startMode==HighAvailabilityMode.HOT_BACKUP) && !ManagementNodeState.isHotProxy(oldState)) {
- // now transition to hot proxy
- nodeStateTransitionComplete = false;
- if (startMode==HighAvailabilityMode.HOT_STANDBY) {
- // if it should be hot standby, then we may need to promote
- // inform the world that we are transitioning (but not eligible for promotion while going in to hot standby)
- // (no harm in doing this twice)
- publishHealth();
- }
- try {
- activateHotProxy(ManagementNodeState.of(startMode).get()).get();
- // error above now throws
- nodeStateTransitionComplete = true;
- publishHealth();
-
- if (getNodeState()==ManagementNodeState.HOT_STANDBY || getNodeState()==ManagementNodeState.HOT_BACKUP) {
- LOG.info("Management node "+ownNodeId+" now running as HA "+getNodeState()+"; "
- + managementContext.getApplications().size()+" application"+Strings.s(managementContext.getApplications().size())+" loaded");
- } else {
- // shouldn't come here, we should have gotten an error above
- LOG.warn("Management node "+ownNodeId+" unable to promote to "+startMode+" (currently "+getNodeState()+"); "
- + "(see log for further details)");
+ if ((startMode==HighAvailabilityMode.HOT_STANDBY || startMode==HighAvailabilityMode.HOT_BACKUP)) {
+ if (!ManagementNodeState.isHotProxy(oldState)) {
+ // now transition to hot proxy
+ nodeStateTransitionComplete = false;
+ if (startMode==HighAvailabilityMode.HOT_STANDBY) {
+ // if it should be hot standby, then we may need to promote
+ // inform the world that we are transitioning (but not eligible for promotion while going in to hot standby)
+ // (no harm in doing this twice)
+ publishHealth();
}
- } catch (Exception e) {
- LOG.warn("Management node "+ownNodeId+" unable to promote to "+startMode+" (currently "+getNodeState()+"); rethrowing: "+Exceptions.collapseText(e));
+ try {
+ activateHotProxy(ManagementNodeState.of(startMode).get()).get();
+ // error above now throws
+ nodeStateTransitionComplete = true;
+ publishHealth();
+
+ if (getNodeState()==ManagementNodeState.HOT_STANDBY || getNodeState()==ManagementNodeState.HOT_BACKUP) {
+ LOG.info("Management node "+ownNodeId+" now running as HA "+getNodeState()+"; "
+ + managementContext.getApplications().size()+" application"+Strings.s(managementContext.getApplications().size())+" loaded");
+ } else {
+ // shouldn't come here, we should have gotten an error above
+ LOG.warn("Management node "+ownNodeId+" unable to promote to "+startMode+" (currently "+getNodeState()+"); "
+ + "(see log for further details)");
+ }
+ } catch (Exception e) {
+ LOG.warn("Management node "+ownNodeId+" unable to promote to "+startMode+" (currently "+getNodeState()+"); rethrowing: "+Exceptions.collapseText(e));
+ nodeStateTransitionComplete = true;
+ throw Exceptions.propagate(e);
+ }
+ } else {
+ // transitioning among hot proxy states - tell the rebind manager
+ managementContext.getRebindManager().stopReadOnly();
+ managementContext.getRebindManager().startReadOnly(ManagementNodeState.of(startMode).get());
nodeStateTransitionComplete = true;
- throw Exceptions.propagate(e);
}
} else {
nodeStateTransitionComplete = true;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
index b1fdc0c..81dd26b 100644
--- a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
@@ -363,11 +363,11 @@ public abstract class AbstractManagementContext implements ManagementContextInte
@Override
public BrooklynCatalog getCatalog() {
- if (!getCatalogInitialization().hasRunIncludingBestEffort()) {
+ if (!getCatalogInitialization().hasRunAnyInitialization()) {
// catalog init is needed; normally this will be done from start sequence,
// but if accessed early -- and in tests -- we will load it here
getCatalogInitialization().injectManagementContext(this);
- getCatalogInitialization().populateBestEffort(catalog);
+ getCatalogInitialization().populateUnofficial(catalog);
}
return catalog;
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/usage/cli/src/main/java/brooklyn/cli/Main.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/brooklyn/cli/Main.java b/usage/cli/src/main/java/brooklyn/cli/Main.java
index d98e0d8..6e48b3f 100644
--- a/usage/cli/src/main/java/brooklyn/cli/Main.java
+++ b/usage/cli/src/main/java/brooklyn/cli/Main.java
@@ -785,6 +785,10 @@ public class Main extends AbstractMain {
.add("startupFailsOnCatalogErrors", startupFailOnCatalogErrors)
.add("startupContinueOnWebErrors", startupContinueOnWebErrors)
.add("startupFailOnManagedAppsErrors", startupFailOnManagedAppsErrors)
+ .add("catalogInitial", catalogInitial)
+ .add("catalogAdd", catalogAdd)
+ .add("catalogReset", catalogReset)
+ .add("catalogForce", catalogForce)
.add("stopWhichAppsOnShutdown", stopWhichAppsOnShutdown)
.add("noShutdownOnExit", noShutdownOnExit)
.add("stopOnKeyPress", stopOnKeyPress)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/usage/cli/src/main/java/brooklyn/cli/lister/ClassFinder.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/brooklyn/cli/lister/ClassFinder.java b/usage/cli/src/main/java/brooklyn/cli/lister/ClassFinder.java
index a66fa7d..2fb913b 100644
--- a/usage/cli/src/main/java/brooklyn/cli/lister/ClassFinder.java
+++ b/usage/cli/src/main/java/brooklyn/cli/lister/ClassFinder.java
@@ -130,7 +130,7 @@ public class ClassFinder {
}
}
} else {
- result.add(new URL("file://"+tidiedFile));
+ result.add(tidiedFile.toURI().toURL());
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
index 6a201a2..e7d3948 100644
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
@@ -598,9 +598,16 @@ public class BrooklynLauncher {
try {
// run cat init now if it hasn't yet been run;
// will also run if there was an ignored error in catalog above, allowing it to fail startup here if requested
- if (catInit!=null && !catInit.hasRunOfficial()) {
- LOG.debug("Loading catalog as part of launcher (persistence did not run it)");
- catInit.populateCatalog(true, null);
+ if (catInit!=null && !catInit.hasRunOfficialInitialization()) {
+ if (persistMode==PersistMode.DISABLED) {
+ LOG.debug("Loading catalog as part of launch sequence (it was not loaded as part of any rebind sequence)");
+ catInit.populateCatalog(ManagementNodeState.MASTER, true, true, null);
+ } else {
+ // should have loaded during rebind
+ ManagementNodeState state = managementContext.getHighAvailabilityManager().getNodeState();
+ LOG.warn("Loading catalog for "+state+" as part of launch sequence (it was not loaded as part of the rebind sequence)");
+ catInit.populateCatalog(state, true, true, null);
+ }
}
} catch (Exception e) {
handleSubsystemStartupError(ignoreCatalogErrors, "initial catalog", e);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/usage/rest-server/src/main/java/brooklyn/rest/filter/HaHotCheckResourceFilter.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/filter/HaHotCheckResourceFilter.java b/usage/rest-server/src/main/java/brooklyn/rest/filter/HaHotCheckResourceFilter.java
index dc2e954..bae561a 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/filter/HaHotCheckResourceFilter.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/filter/HaHotCheckResourceFilter.java
@@ -112,7 +112,7 @@ public class HaHotCheckResourceFilter implements ResourceFilterFactory {
public ContainerRequest filter(ContainerRequest request) {
String problem = lookForProblem(request);
if (Strings.isNonBlank(problem)) {
- log.warn("Disallowing request as "+problem+": "+request+"/"+am+" (caller should set '"+HaMasterCheckFilter.SKIP_CHECK_HEADER+"' to force)");
+ log.warn("Disallowing web request as "+problem+": "+request+"/"+am+" (caller should set '"+HaMasterCheckFilter.SKIP_CHECK_HEADER+"' to force)");
throw new WebApplicationException(ApiError.builder()
.message("This request is only permitted against an active hot Brooklyn server")
.errorCode(Response.Status.FORBIDDEN).build().asJsonResponse());
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/usage/rest-server/src/main/java/brooklyn/rest/filter/HaMasterCheckFilter.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/filter/HaMasterCheckFilter.java b/usage/rest-server/src/main/java/brooklyn/rest/filter/HaMasterCheckFilter.java
index 9cca507..74e7cf1 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/filter/HaMasterCheckFilter.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/filter/HaMasterCheckFilter.java
@@ -94,7 +94,7 @@ public class HaMasterCheckFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String problem = lookForProblem(request);
if (problem!=null) {
- log.warn("Disallowing request as "+problem+": "+request.getParameterMap()+" (caller should set '"+SKIP_CHECK_HEADER+"' to force)");
+ log.warn("Disallowing web request as "+problem+": "+request.getParameterMap()+" (caller should set '"+SKIP_CHECK_HEADER+"' to force)");
WebResourceUtils.applyJsonResponse(servletContext, ApiError.builder()
.message("This request is only permitted against an active master Brooklyn server")
.errorCode(Response.Status.FORBIDDEN).build().asJsonResponse(), (HttpServletResponse)response);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df21c711/utils/common/src/main/java/brooklyn/util/javalang/AggregateClassLoader.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/javalang/AggregateClassLoader.java b/utils/common/src/main/java/brooklyn/util/javalang/AggregateClassLoader.java
index a3ca374..db0254b 100644
--- a/utils/common/src/main/java/brooklyn/util/javalang/AggregateClassLoader.java
+++ b/utils/common/src/main/java/brooklyn/util/javalang/AggregateClassLoader.java
@@ -115,7 +115,7 @@ public class AggregateClassLoader extends ClassLoader {
public Iterator<ClassLoader> iterator() {
synchronized (classLoaders) {
- // provides iterator of snapshot
+ // CopyOnWriteList iterator is immutable view of snapshot
return classLoaders.iterator();
}
}