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 2014/11/15 01:05:23 UTC
[14/21] incubator-brooklyn git commit: final fixes from code review
of #314, hot_backup
final fixes from code review of #314, hot_backup
fixes state transitions (master -> hot_backup etc) and some better logging around catalog
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/24a3c341
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/24a3c341
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/24a3c341
Branch: refs/heads/master
Commit: 24a3c3417f0ad2c60d3acc2328b6a437d2dfdacf
Parents: 5060c4f
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Nov 13 23:35:15 2014 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Nov 13 23:38:55 2014 +0000
----------------------------------------------------------------------
.../management/ha/ManagementNodeState.java | 10 ++++
.../catalog/internal/CatalogClasspathDo.java | 2 +-
.../entity/rebind/RebindManagerImpl.java | 4 +-
.../ha/HighAvailabilityManagerImpl.java | 51 ++++++++++++--------
.../internal/AbstractManagementContext.java | 18 +++++--
5 files changed, 58 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/24a3c341/api/src/main/java/brooklyn/management/ha/ManagementNodeState.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/management/ha/ManagementNodeState.java b/api/src/main/java/brooklyn/management/ha/ManagementNodeState.java
index 4587b57..d7608bd 100644
--- a/api/src/main/java/brooklyn/management/ha/ManagementNodeState.java
+++ b/api/src/main/java/brooklyn/management/ha/ManagementNodeState.java
@@ -61,4 +61,14 @@ public enum ManagementNodeState {
// above should be exhaustive
return Maybe.absent("Requested "+HighAvailabilityMode.class+" mode "+startMode+" was not expected");
}
+
+ /** true for hot non-master modes, where we are proxying the data from the persistent store */
+ public static boolean isHotProxy(ManagementNodeState state) {
+ return state==HOT_BACKUP || state==HOT_STANDBY;
+ }
+
+ /** true for non-master modes which can be promoted to master */
+ public static boolean isStandby(ManagementNodeState state) {
+ return state==ManagementNodeState.STANDBY || state==ManagementNodeState.HOT_STANDBY;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/24a3c341/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
index f6569d7..6ec073f 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
@@ -149,7 +149,7 @@ public class CatalogClasspathDo {
baseCP = ((ManagementContextInternal)catalog.mgmt).getBaseClassPathForScanning();
scanner = new ReflectionScanner(baseCP, prefix, baseCL, catalog.getRootClassLoader());
} catch (Exception e) {
- log.info("Catalog scan is empty, and unable to use java.class.path (base classpath is "+baseCP+")");
+ log.info("Catalog scan is empty, and unable to use java.class.path (base classpath is "+baseCP+"): "+e);
Exceptions.propagateIfFatal(e);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/24a3c341/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 9dad632..ed59bcc 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -307,7 +307,7 @@ public class RebindManagerImpl implements RebindManager {
@SuppressWarnings("unchecked")
@Override
public void startReadOnly(final ManagementNodeState mode) {
- if (mode!=ManagementNodeState.HOT_STANDBY && mode!=ManagementNodeState.HOT_BACKUP) {
+ if (!ManagementNodeState.isHotProxy(mode)) {
throw new IllegalStateException("Read-only rebind thread only permitted for hot proxy modes; not "+mode);
}
@@ -1065,6 +1065,7 @@ public class RebindManagerImpl implements RebindManager {
while (ptr != null) {
CatalogItem<?, ?> catalogItem = catalog.getCatalogItem(ptr.getType(), BrooklynCatalog.DEFAULT_VERSION);
if (catalogItem != null) {
+ LOG.debug("Inferred catalog item ID "+catalogItem.getId()+" for "+entityManifest+" from ancestor "+ptr);
return catalogItem.getId();
}
if (ptr.getParent() != null) {
@@ -1086,6 +1087,7 @@ public class RebindManagerImpl implements RebindManager {
BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(managementContext, item);
boolean canLoadClass = loader.tryLoadClass(entityManifest.getType()).isPresent();
if (canLoadClass) {
+ LOG.warn("Missing catalog item for "+entityManifest.getId()+", inferring as "+item.getId()+" because that is able to load the item");
return item.getId();
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/24a3c341/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 08c1d06..e44f30e 100644
--- a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
+++ b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
@@ -295,6 +295,8 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
}
}
+ ManagementNodeState oldState = getInternalNodeState();
+
// now do election
switch (startMode) {
case AUTO:
@@ -336,22 +338,28 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
}
break;
case HOT_BACKUP:
+ setInternalNodeState(ManagementNodeState.HOT_BACKUP);
+ // then continue into next block
case STANDBY:
case HOT_STANDBY:
- if (getInternalNodeState()==ManagementNodeState.STANDBY || getInternalNodeState()==ManagementNodeState.HOT_STANDBY) {
- if (!preventElectionOnExplicitStandbyMode)
+ if (startMode!=HighAvailabilityMode.HOT_BACKUP) {
+ if (ManagementNodeState.isHotProxy(getInternalNodeState()) && startMode==HighAvailabilityMode.HOT_STANDBY) {
+ // if was hot_backup, we can immediately go hot_standby
+ setInternalNodeState(ManagementNodeState.HOT_STANDBY);
+ } else {
+ // from any other state, set standby, then perhaps switch to hot_standby later on (or might become master in the next block)
+ setInternalNodeState(ManagementNodeState.STANDBY);
+ }
+ }
+ if (ManagementNodeState.isStandby(getInternalNodeState())) {
+ if (!preventElectionOnExplicitStandbyMode) {
publishAndCheck(true);
+ }
if (failOnExplicitStandbyModeIfNoMaster && existingMaster==null) {
LOG.error("Management node "+ownNodeId+" detected no master when "+startMode+" requested and existing master required; failing.");
throw new IllegalStateException("No existing master; cannot start as "+startMode);
}
}
- if (startMode==HighAvailabilityMode.HOT_BACKUP) {
- setInternalNodeState(ManagementNodeState.HOT_BACKUP);
- } else {
- setInternalNodeState(ManagementNodeState.STANDBY);
- // might jump to hot_standby next
- }
String message = "Management node "+ownNodeId+" running as HA "+getNodeState()+" (";
if (getNodeState().toString().equals(startMode.toString()))
message += "explicitly requested";
@@ -391,11 +399,13 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
}
}
if ((getInternalNodeState()==ManagementNodeState.STANDBY && startMode==HighAvailabilityMode.HOT_STANDBY) ||
- (startMode==HighAvailabilityMode.HOT_BACKUP)) {
+ (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 need to promote
- // inform the world that we are transitioning (not eligible for promotion while going in to 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 {
@@ -465,6 +475,7 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
}
protected void setInternalNodeState(ManagementNodeState newState) {
+ ManagementNodeState oldState = getInternalNodeState();
synchronized (nodeStateHistory) {
if (this.nodeState != newState) {
nodeStateHistory.add(0, MutableMap.<String,Object>of("state", newState, "timestamp", currentTimeMillis()));
@@ -472,9 +483,15 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
nodeStateHistory.remove(nodeStateHistory.size()-1);
}
}
-
this.nodeState = newState;
}
+
+ if (ManagementNodeState.isHotProxy(oldState) && !ManagementNodeState.isHotProxy(newState)) {
+ // could perhaps promote standby items on some transitions; but for now we stop the old read-only and re-load them
+ // TODO ideally there'd be an incremental rebind as well as an incremental persist
+ managementContext.getRebindManager().stopReadOnly();
+ clearManagedItems(ManagementTransitionMode.REBINDING_DESTROYED);
+ }
}
@SuppressWarnings("deprecation")
@@ -719,8 +736,9 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
if (!initializing) {
String message = "Management node "+ownNodeId+" detected ";
if (weAreNewMaster) message += "we should be master, changing from ";
+ else if (currMasterNodeRecord==null && newMasterNodeId==null) message += "master change attempted but no candidates ";
else message += "master change, from ";
- message +=currMasterNodeId + " (" + (currMasterNodeRecord==null ? "?" : timestampString(currMasterNodeRecord.getRemoteTimestamp())) + ")"
+ message +=currMasterNodeId + "(" + (currMasterNodeRecord==null ? "<none>" : timestampString(currMasterNodeRecord.getRemoteTimestamp())) + ")"
+ " to "
+ (newMasterNodeId == null ? "<none>" :
(weAreNewMaster ? "us " : "")
@@ -754,16 +772,9 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
LOG.warn("Problem in promption-listener (continuing)", e);
}
}
- boolean wasHot = (getInternalNodeState()==ManagementNodeState.HOT_STANDBY || getInternalNodeState()==ManagementNodeState.HOT_BACKUP);
setInternalNodeState(ManagementNodeState.MASTER);
publishPromotionToMaster();
try {
- if (wasHot) {
- // could just promote the standby items; but for now we stop the old read-only and re-load them, to make sure nothing has been missed
- // TODO ideally there'd be an incremental rebind as well as an incremental persist
- managementContext.getRebindManager().stopReadOnly();
- clearManagedItems(ManagementTransitionMode.REBINDING_DESTROYED);
- }
managementContext.getRebindManager().rebind(managementContext.getCatalog().getRootClassLoader(), null, getInternalNodeState());
} catch (Exception e) {
LOG.error("Management node enountered problem during rebind when promoting self to master; demoting to FAILED and rethrowing: "+e);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/24a3c341/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 944dac4..e35b708 100644
--- a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
@@ -76,6 +76,7 @@ import brooklyn.util.guava.Maybe;
import brooklyn.util.task.BasicExecutionContext;
import brooklyn.util.task.Tasks;
+import com.google.api.client.repackaged.com.google.common.base.Objects;
import com.google.common.base.Function;
public abstract class AbstractManagementContext implements ManagementContextInternal {
@@ -382,14 +383,21 @@ public abstract class AbstractManagementContext implements ManagementContextInte
* is scanning the default classpath. Usually it infers the right thing, but some classloaders
* (e.g. surefire) do funny things which the underlying org.reflections.Reflectiosn library can't see in to.
* <p>
- * Only settable once, before catalog is loaded.
+ * This should normally be invoked early in the server startup. Setting it after the catalog is loaded will not
+ * take effect without an explicit internal call to do so. Once set, it can be changed prior to catalog loading
+ * but it cannot be <i>changed</i> once the catalog is loaded.
* <p>
- * ClasspathHelper.forJavaClassPath() is often a good argument to pass. */
+ * ClasspathHelper.forJavaClassPath() is often a good argument to pass, and is used internally in some places
+ * when no items are found on the catalog. */
@Override
public void setBaseClassPathForScanning(Iterable<URL> urls) {
- if (baseClassPathForScanning == urls) return;
- if (baseClassPathForScanning != null) throw new IllegalStateException("Cannot change base class path for scanning (in "+this+")");
- if (catalog != null) throw new IllegalStateException("Cannot set base class path for scanning after catalog has been loaded (in "+this+")");
+ if (Objects.equal(baseClassPathForScanning, urls)) return;
+ if (baseClassPathForScanning != null) {
+ if (catalog==null)
+ log.warn("Changing scan classpath to "+urls+" from "+baseClassPathForScanning);
+ else
+ throw new IllegalStateException("Cannot change base class path for scanning (in "+this+")");
+ }
this.baseClassPathForScanning = urls;
}
/**