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;
     }
     /**