You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by de...@apache.org on 2018/03/08 20:43:05 UTC

svn commit: r1826275 [4/6] - in /uima/uima-ducc/branches/reliable-ducc: src/main/admin/ src/main/config/ src/main/resources/ uima-ducc-agent/src/main/java/org/apache/uima/ducc/agent/deploy/ uima-ducc-agent/src/main/java/org/apache/uima/ducc/agent/event...

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/NodePool.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/NodePool.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/NodePool.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/NodePool.java Thu Mar  8 20:43:04 2018
@@ -30,11 +30,11 @@ import java.util.Map;
 
 import org.apache.uima.ducc.common.Node;
 import org.apache.uima.ducc.common.NodeIdentity;
-import org.apache.uima.ducc.common.persistence.rm.IRmPersistence;
 import org.apache.uima.ducc.common.persistence.rm.IRmPersistence.RmNodes;
-import org.apache.uima.ducc.common.persistence.rm.RmPersistenceFactory;
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.SystemPropertyResolver;
+import org.apache.uima.ducc.rm.persistence.access.IPersistenceAccess;
+import org.apache.uima.ducc.rm.persistence.access.PersistenceAccess;
 import org.apache.uima.ducc.transport.event.common.IDuccTypes.DuccType;
 
 
@@ -101,7 +101,7 @@ class NodePool
     HashMap<Integer, Map<Node, Machine>> virtualMachinesByOrder = new HashMap<Integer, Map<Node, Machine>>();  // UIMA-4142
     GlobalOrder maxorder = null;
 
-    IRmPersistence persistence = null;
+    private IPersistenceAccess persistenceAccess = PersistenceAccess.getInstance();
     boolean canReserve = false;       // if we contain a class with policy Reserve, then stuff in this pool is reservable
 
     int reserve_overage;              // Allowable excess size in GB for unmanaged reservations
@@ -127,8 +127,6 @@ class NodePool
             maxorder = parent.getGlobalOrder();
         }
 
-        persistence = RmPersistenceFactory.getInstance(this.getClass().getName(), "RM");
-
         reserve_overage = SystemPropertyResolver.getIntProperty("ducc.rm.reserve_overage", 0);  // Can't be static as may be reconfigured
     }
 
@@ -1014,7 +1012,7 @@ class NodePool
     {
         String methodName = "signalDb";
         try {
-            persistence.setNodeProperty(m.getNode().getNodeIdentity().getName(), key, value);
+            persistenceAccess.setNodeProperty(m.getNode().getNodeIdentity().getName(), key, value);
         } catch (Exception e) {
             logger.warn(methodName, null, "Cannot update DB property", key, "for machine", m);
         }
@@ -1147,7 +1145,7 @@ class NodePool
         props.put(RmNodes.Responsive, true);
         props.put(RmNodes.Online, true);
         try {
-            persistence.createMachine(machine.getId(), props);
+            persistenceAccess.createMachine(machine.getId(), props);
         } catch (Exception e) {
             logger.warn(methodName, null, "Cannot write machine to DB:", machine.getId(), e);
         }

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/Scheduler.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/Scheduler.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/Scheduler.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/Scheduler.java Thu Mar  8 20:43:04 2018
@@ -37,8 +37,6 @@ import org.apache.uima.ducc.common.admin
 import org.apache.uima.ducc.common.admin.event.RmQueriedMachine;
 import org.apache.uima.ducc.common.admin.event.RmQueriedNodepool;
 import org.apache.uima.ducc.common.component.AbstractDuccComponent;
-import org.apache.uima.ducc.common.persistence.rm.IRmPersistence;
-import org.apache.uima.ducc.common.persistence.rm.RmPersistenceFactory;
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.DuccProperties;
 import org.apache.uima.ducc.common.utils.DuccPropertiesResolver;
@@ -46,6 +44,8 @@ import org.apache.uima.ducc.common.utils
 import org.apache.uima.ducc.common.utils.Version;
 import org.apache.uima.ducc.common.utils.id.DuccId;
 import org.apache.uima.ducc.common.utils.id.DuccIdFactory;
+import org.apache.uima.ducc.rm.persistence.access.IPersistenceAccess;
+import org.apache.uima.ducc.rm.persistence.access.PersistenceAccess;
 
 
 /**
@@ -131,7 +131,7 @@ public class Scheduler
     boolean stability = false;
 
     private static DuccIdFactory idFactory;
-    IRmPersistence persistence = null;
+    private IPersistenceAccess persistenceAccess = PersistenceAccess.getInstance();
 
     // static boolean expandByDoubling = true;
     // static int initializationCap = 2;      // Max allocation until we know initialization works in
@@ -264,8 +264,7 @@ public class Scheduler
         logger.info(methodName, null, "                       RM Version              : ", ""+ rmversion_major   + "." 
                                                                                              + rmversion_minor   + "." 
                                                                                              + rmversion_ptf);
-        persistence = RmPersistenceFactory.getInstance(this.getClass().getName(), "RM");
-        persistence.clear();
+        persistenceAccess.clear();
         initialized = true;
     }
 
@@ -803,7 +802,7 @@ public class Scheduler
 
     public void stop()
     {
-        persistence.close();
+        persistenceAccess.close();
     }
 
     protected void handleIllNodes()
@@ -1059,7 +1058,7 @@ public class Scheduler
                 prclass.addJob(j);
                 j.setResourceClass(prclass);
                 try {
-					persistence.addJob(j);
+					persistenceAccess.addJob(j);
 				} catch (Exception e) {
 					logger.warn(methodName, j.getId(), "Cannot persist new job in database:", e);					
 				}
@@ -1074,7 +1073,7 @@ public class Scheduler
 
             for ( IRmJob j : allJobs.values() ) {       // UIMA-4577 persist 'demand'
                 try {
-					persistence.updateDemand(j);
+					persistenceAccess.updateDemand(j);
 				} catch (Exception e) {
 					logger.warn(methodName, j.getId(), "Cannot update demand in database:", e);
 				}
@@ -1561,7 +1560,7 @@ public class Scheduler
         logger.info(methodName, job.getId(), "Job completes.");
 
         try {
-			persistence.deleteJob(job);     // UIMA-4577
+			persistenceAccess.deleteJob(job);     // UIMA-4577
 		} catch (Exception e) {
 			logger.warn(methodName, job.getId(), "Cannot delete job from database:", e);
 		}
@@ -1731,7 +1730,7 @@ public class Scheduler
         logger.info(methodName, j.getId(), "Recovered shares:", sharenames.toString());
 
         try {
-			persistence.addJob(j);
+			persistenceAccess.addJob(j);
 		} catch (Exception e) {
 			logger.warn(methodName, j.getId(), "Cannot persist recovered job in database:", j);
 		}

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/Share.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/Share.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/Share.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-rm/src/main/java/org/apache/uima/ducc/rm/scheduler/Share.java Thu Mar  8 20:43:04 2018
@@ -24,10 +24,10 @@ import java.util.Map;
 import org.apache.uima.ducc.common.Node;
 import org.apache.uima.ducc.common.NodeIdentity;
 import org.apache.uima.ducc.common.persistence.rm.IDbShare;
-import org.apache.uima.ducc.common.persistence.rm.IRmPersistence;
-import org.apache.uima.ducc.common.persistence.rm.RmPersistenceFactory;
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.id.DuccId;
+import org.apache.uima.ducc.rm.persistence.access.IPersistenceAccess;
+import org.apache.uima.ducc.rm.persistence.access.PersistenceAccess;
 import org.apache.uima.ducc.transport.event.common.IProcessState.ProcessState;
 import org.apache.uima.ducc.transport.event.common.ITimeWindow;
 import org.apache.uima.ducc.transport.event.common.TimeWindow;
@@ -63,7 +63,7 @@ public class Share
     private long investment = 0;          // Current time for all ACTIVE work items in the process
 
     // note this returns a global static instance, no need to staticisze it here
-    private IRmPersistence persistence = null;
+    private IPersistenceAccess persistenceAccess = PersistenceAccess.getInstance();
 
      @SuppressWarnings("unused")
  	private long resident_memory = 0;
@@ -96,7 +96,6 @@ public class Share
         this.job = job;
         this.bljobid = null;        // UIMA-4142
         this.share_order = share_order;
-        this.persistence = RmPersistenceFactory.getInstance(this.getClass().getName(), "RM");
     }
 
     /**
@@ -111,7 +110,6 @@ public class Share
         this.job = null;
         this.bljobid = jobid;       // UIMA-4142
         this.share_order = share_order;
-        this.persistence = RmPersistenceFactory.getInstance(this.getClass().getName(), "RM");
     }
 
     /**
@@ -124,7 +122,6 @@ public class Share
         this.job = job;
         this.bljobid = null;        // UIMA-4142
         this.share_order = share_order;
-        this.persistence = RmPersistenceFactory.getInstance(this.getClass().getName(), "RM");
     }
 
 //     /**
@@ -290,7 +287,7 @@ public class Share
                 npid = Long.parseLong(pid);
             }
 
-			persistence.updateShare(getNode().getNodeIdentity().getName(), id, jobid, investment, state.toString(), getInitializationTime(), npid);
+			persistenceAccess.updateShare(getNode().getNodeIdentity().getName(), id, jobid, investment, state.toString(), getInitializationTime(), npid);
 		} catch (Exception e) {
             logger.warn(methodName, job.getId(), "Cannot update share statistics in database for share", id, e);
 		}
@@ -364,7 +361,7 @@ public class Share
     	String methodName = "setFixed";
         fixed = true;
         try {
-			persistence.setFixed(getNode().getNodeIdentity().getName(), id, job.getId(), true);
+			persistenceAccess.setFixed(getNode().getNodeIdentity().getName(), id, job.getId(), true);
 		} catch (Exception e) {
             logger.warn(methodName, job.getId(), "Cannot update 'fixed' in database for share", id, e);
 		}
@@ -380,7 +377,7 @@ public class Share
     	String methodName = "evicted";
         evicted = true;
         try {
-			persistence.setEvicted(getNode().getNodeIdentity().getName(), id, job.getId(), true);
+        	persistenceAccess.setEvicted(getNode().getNodeIdentity().getName(), id, job.getId(), true);
 		} catch (Exception e) {
             logger.warn(methodName, job.getId(), "Cannot update 'evicted' in database for share", id, e);
 		}
@@ -396,7 +393,7 @@ public class Share
     	String methodName = "purge";
         purged = true;
         try {
-			persistence.setPurged(getNode().getNodeIdentity().getName(), id, job.getId(), true);
+        	persistenceAccess.setPurged(getNode().getNodeIdentity().getName(), id, job.getId(), true);
 		} catch (Exception e) {
             logger.warn(methodName, job.getId(), "Cannot update 'purge bit' in database for share", id, e);
 		}

Added: uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/DuccHead.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/DuccHead.java?rev=1826275&view=auto
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/DuccHead.java (added)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/DuccHead.java Thu Mar  8 20:43:04 2018
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+*/
+package org.apache.uima.ducc.sm;
+
+import org.apache.uima.ducc.common.head.ADuccHead;
+import org.apache.uima.ducc.common.head.IDuccHead;
+import org.apache.uima.ducc.common.utils.DuccLogger;
+
+public class DuccHead extends ADuccHead {
+
+	private static DuccLogger logger = DuccLogger.getLogger(DuccHead.class);
+	
+	private static IDuccHead instance = new DuccHead(logger);
+	
+	public static IDuccHead getInstance() {
+		return instance;
+	}
+	
+	private DuccHead(DuccLogger logger) {
+		super(logger);
+	}
+}

Propchange: uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/DuccHead.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceHandler.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceHandler.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceHandler.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceHandler.java Thu Mar  8 20:43:04 2018
@@ -29,6 +29,7 @@ import org.apache.uima.ducc.cli.DuccServ
 import org.apache.uima.ducc.cli.IUiOptions.UiOption;
 import org.apache.uima.ducc.common.NodeIdentity;
 import org.apache.uima.ducc.common.persistence.services.IStateServices;
+import org.apache.uima.ducc.common.persistence.services.IStateServices.AccessMode;
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.DuccProperties;
 import org.apache.uima.ducc.common.utils.id.DuccId;
@@ -47,6 +48,8 @@ import org.apache.uima.ducc.transport.ev
 import org.apache.uima.ducc.transport.event.common.DuccWorkJob;
 import org.apache.uima.ducc.transport.event.common.IDuccProcessMap;
 import org.apache.uima.ducc.transport.event.common.IDuccWork;
+import org.apache.uima.ducc.transport.event.common.IDuccWorkMap;
+import org.apache.uima.ducc.transport.event.common.IDuccWorkService;
 import org.apache.uima.ducc.transport.event.sm.IService.ServiceState;
 import org.apache.uima.ducc.transport.event.sm.IServiceDescription;
 import org.apache.uima.ducc.transport.event.sm.ServiceDependency;
@@ -63,7 +66,8 @@ public class ServiceHandler
 	 *
 	 */
 	private DuccLogger logger = DuccLogger.getLogger(ServiceHandler.class.getName(), COMPONENT_NAME);
-    private IServiceManager serviceManager;
+    private DuccId jobid = null;
+	private IServiceManager serviceManager;
 
     private ServiceStateHandler serviceStateHandler = new ServiceStateHandler();
 	private ServiceMap serviceMap = new ServiceMap();       // note this is the sync object for publish
@@ -98,6 +102,85 @@ public class ServiceHandler
         }
     }
 
+    /*
+     * initialize data structures (in preparation for resume)
+     */
+    public void init() {
+    	String methodName = "init";
+    	logger.debug(methodName, jobid, "");
+    	serviceStateHandler = new ServiceStateHandler();
+    	serviceMap.clear();  
+    }
+    
+    /*
+     * resume: this head node has become master
+     */
+    public void resume(IDuccWorkMap dwm) {
+    	String methodName = "resume";
+    	logger.debug(methodName, jobid, "");
+    	// clear state
+        newJobs.clear();
+        newServices.clear();
+        deletedJobs.clear();
+        deletedServices.clear();
+        modifiedJobs.clear();
+        modifiedServices.clear();
+        pendingRequests.clear();
+        // Add implementors from OR publication to SM state
+        Set<DuccId> serviceKeys = dwm.getServiceKeySet();
+        if(serviceKeys != null) {
+        	for(DuccId duccId : serviceKeys) {
+            	IDuccWork dw = dwm.findDuccWork(duccId);
+            	if(dw != null) {
+            		IDuccWorkService service = (IDuccWorkService) dw;
+            		long swId = duccId.getFriendly();
+            		String endpoint = service.getServiceEndpoint();
+            		if(endpoint != null) {
+            			ServiceSet ss = serviceStateHandler.getServiceByUrl(endpoint);
+            			if(ss != null) {
+            				ServiceInstance si = new ServiceInstance(ss);
+            				ss.implementors.put(swId, si);
+            				addInstance(ss, si);
+            				logger.info(methodName, ss.getId(), swId, ss.endpoint);
+            			}
+            			else {
+            				logger.warn(methodName, duccId, "ss == null");
+            			}
+            		}
+            		else {
+            			logger.warn(methodName, duccId, "endpoint == null");
+            		}
+            	}
+            	else {
+            		logger.warn(methodName, duccId, "dw == null");
+            	}
+            }
+        }
+        else {
+        	logger.debug(methodName, jobid, "serviceKeys == null");
+        }
+    }
+    
+    /*
+     * quiesce: this head node has become backup
+     */
+    public void quiesce() {
+    	String methodName = "quiesce";
+    	List<ServiceSet> list = serviceStateHandler.getServices();
+    	logger.debug(methodName, jobid, list.size());
+    	// stop all pingers
+        for(ServiceSet ss : list) {
+        	DuccId duccId = ss.getId();
+        	ss.setState(ServiceState.Dispossessed);
+        	logger.info(methodName, duccId, ss.getState(), ss.getImplementors().length, ss.getKey());
+        	ss.stopPingThread();
+        }
+    }
+    
+    public void setAccessMode(AccessMode accessMode) {
+    	stateHandler.setAccessMode(accessMode);
+    }
+    
     void setStateHandler(IStateServices handler)
     {
         this.stateHandler = handler;
@@ -166,21 +249,27 @@ public class ServiceHandler
         synchronized(stateUpdateLock) {
                 deletedJobsMap.putAll(deletedJobs);
                 deletedJobs.clear();
+                logger.info(methodName, jobid, "deletedJobsMap", deletedJobsMap.size());
 
                 modifiedJobsMap.putAll(modifiedJobs);
                 modifiedJobs.clear();
-
+                logger.info(methodName, jobid, "modifiedJobsMap", modifiedJobsMap.size());
+                
                 deletedServicesMap.putAll(deletedServices);
                 deletedServices.clear();
-
+                logger.info(methodName, jobid, "deletedServicessMap", deletedServicesMap.size());
+                
                 modifiedServicesMap.putAll(modifiedServices);
                 modifiedServices.clear();
+                logger.info(methodName, jobid, "modifiedServicesMap", modifiedServicesMap.size());
 
                 newServicesMap.putAll(newServices);
                 newServices.clear();
-
+                logger.info(methodName, jobid, "newServicesMap", newServicesMap.size());
+                
                 newJobsMap.putAll(newJobs);
                 newJobs.clear();
+                logger.info(methodName, jobid, "newJobsMap", newJobsMap.size());
         }
 
         // We could potentially have several updates where a service or arrives, is modified, and then deleted, while

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceManagerComponent.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceManagerComponent.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceManagerComponent.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceManagerComponent.java Thu Mar  8 20:43:04 2018
@@ -35,8 +35,11 @@ import org.apache.uima.ducc.common.boot.
 import org.apache.uima.ducc.common.boot.DuccDaemonRuntimeProperties.DaemonName;
 import org.apache.uima.ducc.common.component.AbstractDuccComponent;
 import org.apache.uima.ducc.common.crypto.Crypto;
+import org.apache.uima.ducc.common.head.IDuccHead;
+import org.apache.uima.ducc.common.head.IDuccHead.DuccHeadTransition;
 import org.apache.uima.ducc.common.main.DuccService;
 import org.apache.uima.ducc.common.persistence.services.IStateServices;
+import org.apache.uima.ducc.common.persistence.services.IStateServices.AccessMode;
 import org.apache.uima.ducc.common.persistence.services.IStateServices.SvcMetaProps;
 import org.apache.uima.ducc.common.persistence.services.StateServicesDirectory;
 import org.apache.uima.ducc.common.persistence.services.StateServicesFactory;
@@ -44,17 +47,18 @@ import org.apache.uima.ducc.common.persi
 import org.apache.uima.ducc.common.utils.DuccCollectionUtils;
 import org.apache.uima.ducc.common.utils.DuccCollectionUtils.DuccMapDifference;
 import org.apache.uima.ducc.common.utils.DuccCollectionUtils.DuccMapValueDifference;
-import org.apache.uima.ducc.common.utils.IDuccLoggerComponents.Daemon;
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.DuccProperties;
+import org.apache.uima.ducc.common.utils.IDuccLoggerComponents.Daemon;
 import org.apache.uima.ducc.common.utils.MissingPropertyException;
 import org.apache.uima.ducc.common.utils.SystemPropertyResolver;
 import org.apache.uima.ducc.common.utils.Version;
 import org.apache.uima.ducc.common.utils.id.DuccId;
-import org.apache.uima.ducc.common.utils.id.DuccIdFactory;
+import org.apache.uima.ducc.common.utils.id.IDuccIdFactory;
 import org.apache.uima.ducc.transport.dispatcher.DuccEventDispatcher;
 import org.apache.uima.ducc.transport.event.AServiceRequest;
 import org.apache.uima.ducc.transport.event.DaemonDuccEvent;
+import org.apache.uima.ducc.transport.event.DuccEvent.EventType;
 import org.apache.uima.ducc.transport.event.ServiceDisableEvent;
 import org.apache.uima.ducc.transport.event.ServiceEnableEvent;
 import org.apache.uima.ducc.transport.event.ServiceIgnoreEvent;
@@ -68,7 +72,6 @@ import org.apache.uima.ducc.transport.ev
 import org.apache.uima.ducc.transport.event.ServiceUnregisterEvent;
 import org.apache.uima.ducc.transport.event.SmHeartbeatDuccEvent;
 import org.apache.uima.ducc.transport.event.SmStateDuccEvent;
-import org.apache.uima.ducc.transport.event.DuccEvent.EventType;
 import org.apache.uima.ducc.transport.event.common.DuccWorkJob;
 import org.apache.uima.ducc.transport.event.common.DuccWorkMap;
 import org.apache.uima.ducc.transport.event.common.IDuccTypes.DuccType;
@@ -97,7 +100,7 @@ public class ServiceManagerComponent
 	private static DuccLogger logger = DuccLogger.getLogger(ServiceManagerComponent.class.getName(), COMPONENT_NAME);
 	private static DuccId jobid = null;
 
-	private DuccWorkMap localMap = null;
+	private IDuccWorkMap localMap = null;
 
     private DuccEventDispatcher eventDispatcher;
     private String stateEndpoint;
@@ -117,12 +120,7 @@ public class ServiceManagerComponent
     static int failure_max = 5;              // total in window
     static int failure_window = 30;          // window size in minutes
 
-    private String state_dir = null;
-    private String state_file = null;
-
-    private DuccProperties sm_props = null;
-    private String service_seqno = IStateServices.sequenceKey;
-    private DuccIdFactory idFactory = new DuccIdFactory();
+    private IDuccIdFactory idFactory = null;
 
     private boolean signature_required = true;
     private boolean initialized = false;
@@ -131,6 +129,8 @@ public class ServiceManagerComponent
 
     private Map<String, String> administrators = new HashMap<String, String>();
 
+    private IDuccHead dh = null;
+    
     // Local SM version
     //    1.1.0 - reworked SM
     //    1.1.3 - added shutdown hook, pinger last-use, pinger disable autostart
@@ -151,6 +151,37 @@ public class ServiceManagerComponent
 		return logger;
 	}
 
+    /*
+     * resume: this head node has become master
+     */
+	private void resume(IDuccWorkMap dwm) {
+		String methodName = "resume";
+		try {
+			logger.info(methodName, jobid, "");
+			handler.init();
+			init();
+			this.localMap = dwm;
+			handler.resume(this.localMap);
+		}
+		catch(Exception e) {
+			logger.error(methodName, jobid, e);
+		}
+	}
+	
+    /*
+     * quiesce: this head node has become backup
+     */
+	private void quiesce() {
+		String methodName = "quiesce";
+		try {
+			logger.info(methodName, jobid, "");
+			handler.quiesce();
+		}
+		catch(Exception e) {
+			logger.error(methodName, jobid, e);
+		}
+	}
+	
     /**
      * Initialization tasks:
      * - read all the service descriptors
@@ -196,65 +227,7 @@ public class ServiceManagerComponent
 
         }
 
-        // try {
-		// 	File histdir = new File(serviceHistoryLocation());
-		// 	if ( ! histdir.exists() ) {
-		// 		histdir.mkdirs();
-		// 	}
-
-        //     Map<Long, Properties> sprops = h.getPropertiesForType(DbVertex.Service);
-        //     Map<Long, Properties> mprops = h.getPropertiesForType(DbVertex.ServiceMeta);
-
-        //     for ( Long k : sprops.keySet() ) {
-        //         DuccProperties svcprops  = (DuccProperties) sprops.get(k);
-        //         DuccProperties metaprops = (DuccProperties) mprops.get(k);
-
-        //         String uuid = metaprops.getProperty("uuid");
-
-        //         DuccId id = new DuccId(k);
-        //         id.setUUID(UUID.fromString(uuid));
-        //         logger.debug(methodName, id, "Unique:", id.getUnique());
-
-        //         try {
-        //             handler.register(id, svcprops, metaprops, true);
-        //         } catch (IllegalStateException e ) {                 // happens on duplicate service
-        //             logger.error(methodName, id, e);  // message has all I need.
-        //         }
-        //     }
-
-		// } catch (Throwable e) {
-        //     // If we get here we aren't startable.
-		// 	logger.error(methodName, null, "Cannot initialize service manger: ", e);
-		// 	System.exit(1);
-		// } finally {
-        //     h.close();
-        // }
-
-        state_dir = System.getProperty("DUCC_HOME") + "/state";
-        state_file = state_dir + "/sm.properties";
-
-        sm_props = new DuccProperties();
-        File sf = new File(state_file);
-        int seq = 0;
-        FileInputStream fos;
-        if ( sf.exists() ) {
-            fos = new FileInputStream(state_file);
-            try {
-                sm_props.load(fos);
-                String s = sm_props.getProperty(service_seqno);
-                seq = Integer.parseInt(s) + 1;
-            } finally {
-                fos.close();
-            }
-        }
-
-        long dbSeqNo = ServiceManagerHelper.getLargestServiceSeqNo();
-        if(dbSeqNo > seq) {
-        	logger.warn(methodName, jobid, "file:"+seq+" "+"db:"+dbSeqNo);
-        	seq = (int) dbSeqNo;
-        }
-
-        idFactory = new DuccIdFactory(seq);
+        idFactory = ServiceManagerHelper.getDuccIdFactory();
 
         synchronized(this) {
             initialized = true;
@@ -754,32 +727,75 @@ public class ServiceManagerComponent
 
         }
     }
-
+    
+    private IDuccHead getDuccHead() {
+    	if(dh == null) {
+    		dh = DuccHead.getInstance();
+    		if(dh.is_ducc_head_backup()) {
+    			stateChange(EventType.INIT_AS_BACKUP);
+    		}
+    		else {
+    			stateChange(EventType.INIT_AS_MASTER);
+    		}
+    	}
+    	return dh;
+    }
+    
     public synchronized void orchestratorStateArrives(IDuccWorkMap map)
     {
     	String methodName = "orchestratorStateArrives";
-        if ( ! initialized ) {
-            logger.info(methodName, null, "SM not initialized, ignoring Orchestrator state update.");
-            return;
-        }
-        else {
-        	logger.debug(methodName, null, "SM initialized.");
-        }
-
-        if ( ! map.isJobDriverMinimalAllocateRequirementMet() ) {
-            logger.info(methodName, null, "Orchestrator JD node not assigned, ignoring Orchestrator state update.");
-            // send a heartbeat to anyone who cares (
-            publish();
-            return;
-        }
-        else {
-        	logger.debug(methodName, null, "JD requirements met.");
-        }
+    	try {
+        	DuccHeadTransition transition = getDuccHead().transition();
+    		switch(transition) {
+    		case master_to_master:
+    			logger.debug(methodName, jobid, "ducc head == master");
+    			break;
+    		case master_to_backup:
+    			logger.warn(methodName, jobid, "ducc head -> backup");
+    			stateChange(EventType.SWITCH_TO_BACKUP);
+    			handler.setAccessMode(AccessMode.RO);
+    			quiesce();
+    			break;
+    		case backup_to_master:
+    			logger.warn(methodName, jobid, "ducc head -> master");
+    			stateChange(EventType.SWITCH_TO_MASTER);
+    			handler.setAccessMode(AccessMode.RW);
+    			resume(map);
+    			break;
+    		case backup_to_backup:
+    			logger.debug(methodName, jobid, "ducc head == backup");
+    			break;
+    		default:
+    			logger.debug(methodName, jobid, "ducc head == unspecified");
+    			break;
+    		}
+    		
+            if ( ! initialized ) {
+                logger.info(methodName, null, "SM not initialized, ignoring Orchestrator state update.");
+                return;
+            }
+            else {
+            	logger.debug(methodName, null, "SM initialized.");
+            }
+            
+            if ( ! map.isJobDriverMinimalAllocateRequirementMet() ) {
+                logger.info(methodName, null, "Orchestrator JD node not assigned, ignoring Orchestrator state update.");
+                // send a heartbeat to anyone who cares
+                publish();
+                return;
+            }
+            else {
+            	logger.debug(methodName, null, "JD requirements met.");
+            }
 
-        orchestrator_alive = true;
-        epochCounter++;
-        incomingMap = map;
-        notify();
+            orchestrator_alive = true;
+            epochCounter++;
+            incomingMap = map;
+            notify();
+    	}
+    	catch(Exception e) {
+    		logger.error(methodName, jobid, e);
+    	}
     }
 
     // @deprecated
@@ -800,6 +816,21 @@ public class ServiceManagerComponent
         return crypto.isValid(auth_block);
 	  }
 
+	private boolean validate_ducc_head(String action, AServiceRequest req) {
+		String methodName = "validate_ducc_head";
+		boolean retVal = true;
+		if(dh.is_ducc_head_virtual_master()) {
+			// all is well
+		}
+		else {
+			String reason = "not master node";
+			logger.warn(methodName, null, action + " rejected. " + reason);
+			req.setReply(makeResponse(false, reason, action, -1));
+			retVal = false;
+		}
+		return retVal;
+	}
+	  
     private boolean validate_user(String action, AServiceRequest req)
     {
     	String methodName = "validate_user";
@@ -854,6 +885,7 @@ public class ServiceManagerComponent
         long regdate = System.currentTimeMillis();
         String regdate_readable = (new Date(regdate)).toString();
 
+        if ( ! validate_ducc_head("Register", ev) ) return;
         if ( ! validate_user("Register", ev) ) return;   // necessary messages emitted in here
         if ( ! orchestratorAlive("Register", ev) ) return;
 
@@ -902,7 +934,8 @@ public class ServiceManagerComponent
 
     public synchronized void unregister(ServiceUnregisterEvent ev)
     {
-        if ( ! validate_user("Unregister", ev) ) return;   // necessary messages emitted in here
+    	if ( ! validate_ducc_head("Unregister", ev) ) return;
+    	if ( ! validate_user("Unregister", ev) ) return;   // necessary messages emitted in here
         if ( ! orchestratorAlive("Unregister", ev) ) return;
 
         ServiceReplyEvent reply = handler.unregister(ev);
@@ -913,6 +946,7 @@ public class ServiceManagerComponent
     {
         String methodName = "start";
 
+        if ( ! validate_ducc_head("Start", ev) ) return;
         if ( ! validate_user("Start", ev) ) return;   // necessary messages emitted in here
         if ( ! orchestratorAlive("Start", ev) ) return;
 
@@ -926,6 +960,7 @@ public class ServiceManagerComponent
     {
         String methodName = "stop";
 
+        if ( ! validate_ducc_head("Stop", ev) ) return;
         if ( ! validate_user("Stop", ev) ) return;   // necessary messages emitted in here
         if ( ! orchestratorAlive("Stop", ev) ) return;
 
@@ -939,6 +974,7 @@ public class ServiceManagerComponent
     {
         String methodName = "enable";
 
+        if ( ! validate_ducc_head("Enable", ev) ) return;
         if ( ! validate_user("Enable", ev) ) return;   // necessary messages emitted in here
         if ( ! orchestratorAlive("Enable", ev) ) return;
 
@@ -952,6 +988,7 @@ public class ServiceManagerComponent
     {
         String methodName = "disable";
 
+        if ( ! validate_ducc_head("Disable", ev) ) return;
         if ( ! validate_user("Disable", ev) ) return;   // necessary messages emitted in here
         if ( ! orchestratorAlive("Disable", ev) ) return;
 
@@ -964,7 +1001,8 @@ public class ServiceManagerComponent
     public synchronized void observe(ServiceObserveEvent ev)
     {
         String methodName = "observe";
-
+        
+        if ( ! validate_ducc_head("Observe", ev) ) return;
         if ( ! validate_user("Observe", ev) ) return;   // necessary messages emitted in here
         if ( ! orchestratorAlive("Observe", ev) ) return;
 
@@ -978,6 +1016,7 @@ public class ServiceManagerComponent
     {
         String methodName = "ignore";
 
+        if ( ! validate_ducc_head("Ignore", ev) ) return;
         if ( ! validate_user("Ignore", ev) ) return;   // necessary messages emitted in here
         if ( ! orchestratorAlive("Ignore", ev) ) return;
 
@@ -991,6 +1030,7 @@ public class ServiceManagerComponent
     {
         String methodName = "query";
 
+        if ( ! validate_ducc_head("Query", ev) ) return;
         if ( ! validate_user("Query", ev) ) return;   // necessary messages emitted in here
         if ( ! orchestratorAlive("Query", ev) ) return;
 
@@ -1004,6 +1044,7 @@ public class ServiceManagerComponent
     {
         String methodName = "modify";
 
+        if ( ! validate_ducc_head("Modify", ev) ) return;
         if ( ! validate_user("Modify", ev) ) return;   // necessary messages emitted in here
         if ( ! orchestratorAlive("Modify", ev) ) return;
 
@@ -1013,22 +1054,6 @@ public class ServiceManagerComponent
         //ev.setReply(ServiceCode.OK, "Service not implemented.", "no-endpoint", null);
     }
 
-    Object idSync = new Object();
-    public DuccId newId()
-        throws Exception
-    {
-    	DuccId id = null;
-        synchronized(idSync) {
-            id = idFactory.next();
-            sm_props.setProperty(service_seqno, id.toString());
-            FileOutputStream fos = new FileOutputStream(state_file);
-            sm_props.store(fos, "Service Manager Properties");
-            fos.close();
-        }
-        return id;
-    }
-
-
     static void deleteProperties(String id, String meta_filename, Properties meta_props, String props_filename, Properties job_props)
     {
         // NOTE: During init we may now know the ID as a DuccId so it has to be passed in as a string
@@ -1067,4 +1092,9 @@ public class ServiceManagerComponent
          props_filename = null;
     }
 
+	@Override
+	public DuccId newId() throws Exception {
+		return idFactory.next();
+	}
+
 }

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceManagerHelper.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceManagerHelper.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceManagerHelper.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceManagerHelper.java Thu Mar  8 20:43:04 2018
@@ -15,39 +15,94 @@
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
-*/
+ */
 package org.apache.uima.ducc.sm;
 
+import java.io.File;
+import java.io.FileInputStream;
 import java.util.NavigableSet;
+import java.util.Properties;
 
 import org.apache.uima.ducc.common.persistence.services.IStateServices;
 import org.apache.uima.ducc.common.persistence.services.StateServicesDirectory;
 import org.apache.uima.ducc.common.persistence.services.StateServicesFactory;
 import org.apache.uima.ducc.common.utils.DuccLogger;
+import org.apache.uima.ducc.common.utils.DuccProperties;
 import org.apache.uima.ducc.common.utils.id.DuccId;
+import org.apache.uima.ducc.common.utils.id.DuccIdFactory;
+import org.apache.uima.ducc.common.utils.id.IDuccIdFactory;
 
 public class ServiceManagerHelper {
 
-	private static DuccLogger logger = DuccLogger.getLogger(ServiceManagerHelper.class.getName(), SmConstants.COMPONENT_NAME);	
-    private static DuccId jobid = null;
+	private static DuccLogger logger = DuccLogger.getLogger(ServiceManagerHelper.class.getName(), SmConstants.COMPONENT_NAME);
+	private static DuccId jobid = null;
+
+	private static String service_seqno = IStateServices.sequenceKey;
 	
-    /**
-     * fetch largest service sequence number from database
-     */
-    public static long getLargestServiceSeqNo() {
-    	String location = "getLargestServiceSeqNo";
-    	long seqno = -1;
-    	try {
-    		IStateServices iss = StateServicesFactory.getInstance(ServiceManagerHelper.class.getName(), SmConstants.COMPONENT_NAME);
-    		StateServicesDirectory ssd = iss.getStateServicesDirectory();
-    		NavigableSet<Long> keys = ssd.getDescendingKeySet();
-    		if(!keys.isEmpty()) {
-    			seqno = keys.first();
-    		}
-    	}
-    	catch(Exception e) {
-    		logger.error(location, jobid, e);
-    	}
-    	return seqno;
-    }
+	/**
+	 * construct DuccIdFactory for services registry
+	 */
+	public static IDuccIdFactory getDuccIdFactory() {
+		String location = "getDuccIdFactory";
+		long fileSeqNo = getFileSeqNo()+1;
+		long dbSeqNo = getDbSeqNo()+1;
+		long seqNo = 0;
+		if(fileSeqNo > seqNo) {
+			seqNo = fileSeqNo;
+		}
+		if(dbSeqNo > seqNo) {
+			seqNo = dbSeqNo;
+		}
+		logger.info(location, jobid, "seqNo:", seqNo,  "dbSeqNo:", dbSeqNo, "fileSeqNo:", fileSeqNo);
+		IDuccIdFactory duccIdFactory = new DuccIdFactory(seqNo);
+		return duccIdFactory;
+	}
+
+	private static long getFileSeqNo() {
+		String location = "getFileSeqNo";
+		long seqNo = -1;
+		try {
+			String state_dir = System.getProperty("DUCC_HOME") + "/state";
+			String state_file = state_dir + "/sm.properties";
+
+			Properties sm_props = new DuccProperties();
+			File sf = new File(state_file);
+			FileInputStream fos;
+			if (sf.exists()) {
+				fos = new FileInputStream(state_file);
+				try {
+					sm_props.load(fos);
+					String s = sm_props.getProperty(service_seqno);
+					seqNo = Integer.parseInt(s) + 1;
+				} finally {
+					fos.close();
+				}
+			}
+		}
+		catch(Exception e) {
+			logger.error(location, jobid, e);
+		}
+		return seqNo;
+	}
+
+	/**
+	 * fetch largest service sequence number from database
+	 */
+	public static long getDbSeqNo() {
+		String location = "getDbSeqNo";
+		long seqno = -1;
+		try {
+			IStateServices iss = StateServicesFactory.getInstance(
+					ServiceManagerHelper.class.getName(),
+					SmConstants.COMPONENT_NAME);
+			StateServicesDirectory ssd = iss.getStateServicesDirectory();
+			NavigableSet<Long> keys = ssd.getDescendingKeySet();
+			if (!keys.isEmpty()) {
+				seqno = keys.first();
+			}
+		} catch (Exception e) {
+			logger.error(location, jobid, e);
+		}
+		return seqno;
+	}
 }

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceSet.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceSet.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceSet.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-sm/src/main/java/org/apache/uima/ducc/sm/ServiceSet.java Thu Mar  8 20:43:04 2018
@@ -1569,6 +1569,13 @@ public class ServiceSet
         return service_state;
     }
 
+    synchronized void setState(ServiceState ss)
+    {
+    	String methodName = "setState";
+    	logger.debug(methodName, id, service_state, "==>", ss);
+        service_state = ss;
+    }
+    
     synchronized void setState(ServiceState req_new_state, ServiceState req_cumulative, ServiceInstance si)
     {
         String methodName = "setState";
@@ -1581,6 +1588,11 @@ public class ServiceSet
         }
 
         ServiceState prev = this.service_state;
+        switch(prev) {
+        case Dispossessed:
+        	logger.debug(methodName, id, prev);
+        	return;
+        }
         ServiceState new_state = req_new_state;
         ServiceState cumulative = req_cumulative;
         
@@ -1677,6 +1689,8 @@ public class ServiceSet
                 // If I'm brand new and something is initting then I can be too.  If something is
                 // actually running then I can start a pinger which will set my state.
 
+            	case Dispossessed:
+            		return;
                 case Available:
                     switch ( cumulative ) {
                         case Starting:

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/configuration/jd/JobDriverStateExchanger.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/configuration/jd/JobDriverStateExchanger.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/configuration/jd/JobDriverStateExchanger.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/configuration/jd/JobDriverStateExchanger.java Thu Mar  8 20:43:04 2018
@@ -22,6 +22,7 @@ import java.util.Map.Entry;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.uima.ducc.common.NodeIdentity;
+import org.apache.uima.ducc.common.head.DuccHeadHelper;
 import org.apache.uima.ducc.common.jd.files.workitem.IWorkItemStateKeeper;
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.DuccLoggerComponents;
@@ -129,6 +130,10 @@ public class JobDriverStateExchanger ext
 		String targetUrl = null;
 		String server = getServer();
 		String host = DuccPropertiesResolver.get("ducc." + server + ".http.node");
+		
+		// employ virtual IP if configured
+		host = DuccHeadHelper.getVirtualHost(host);
+
 	    String port = DuccPropertiesResolver.get("ducc." + server + ".http.port");
         if ( host == null || port == null ) {
         	String message = "ducc." + server + ".http.node and/or .port not set in ducc.properties";
@@ -181,17 +186,22 @@ public class JobDriverStateExchanger ext
 	private void abortIfTold(JdReplyEvent jdReplyEvent) {
 		String location = "abortIfTold";
 		if(jdReplyEvent != null) {
-			String killDriverReason = jdReplyEvent.getKillDriverReason();
-			if(killDriverReason != null) {
-				int code = 255;
-				StringBuffer sb = new StringBuffer();
-				sb.append("System Exit");
-				sb.append(" ");
-				sb.append("code="+code);
-				sb.append(" ");
-				sb.append("reason="+killDriverReason);
-				logger.warn(location, jobid, sb.toString());
-				System.exit(code);
+			if(jdReplyEvent.isDuccHeadMaster()) {
+				String killDriverReason = jdReplyEvent.getKillDriverReason();
+				if(killDriverReason != null) {
+					int code = 255;
+					StringBuffer sb = new StringBuffer();
+					sb.append("System Exit");
+					sb.append(" ");
+					sb.append("code="+code);
+					sb.append(" ");
+					sb.append("reason="+killDriverReason);
+					logger.warn(location, jobid, sb.toString());
+					System.exit(code);
+				}
+			}
+			else {
+				logger.warn(location, jobid, "not master");
 			}
 		}
 	}

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/AbstractDuccEvent.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/AbstractDuccEvent.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/AbstractDuccEvent.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/AbstractDuccEvent.java Thu Mar  8 20:43:04 2018
@@ -18,6 +18,9 @@
 */
 package org.apache.uima.ducc.transport.event;
 
+import java.net.InetAddress;
+
+import org.apache.uima.ducc.common.head.IDuccHead.DuccHeadState;
 import org.apache.uima.ducc.transport.event.IDuccContext.DuccContext;
 
 public abstract class AbstractDuccEvent 
@@ -34,8 +37,12 @@ implements DuccEvent {
 	
 	private DuccContext context = DuccContext.Unspecified;
 	
+	private DuccHeadState duccHeadState = DuccHeadState.unspecified;
+	private String producerHost = "unknown";
+	
 	public AbstractDuccEvent(EventType eventType) {
 		this.eventType = eventType;
+		initProducerHost();
 	}
 	public EventType getEventType() {
 		return eventType;
@@ -74,5 +81,40 @@ implements DuccEvent {
 	public DuccContext getContext() {
 		return context;
 	}
-
+	
+	/*
+	 * DuccHeadState indicates Master or Backup
+	 */
+	public void setDuccHeadState(DuccHeadState value) {
+		if(value != null) {
+			duccHeadState = value;
+		}
+	}
+	
+	public DuccHeadState getDuccHeadState() {
+		DuccHeadState retVal = DuccHeadState.unspecified;
+		if(duccHeadState != null) {
+			retVal = duccHeadState;
+		}
+		return retVal;
+	}
+
+	private void initProducerHost() {
+		try {
+			String host = InetAddress.getLocalHost().getCanonicalHostName();
+			if(host != null) {
+				host = host.trim();
+				if(host.length() > 0) {
+					producerHost = host;
+				}
+			}
+		}
+		catch(Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	public String getProducerHost() {
+		return producerHost;
+	}
 }

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/DaemonDuccEvent.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/DaemonDuccEvent.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/DaemonDuccEvent.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/DaemonDuccEvent.java Thu Mar  8 20:43:04 2018
@@ -39,6 +39,16 @@ public class DaemonDuccEvent extends Abs
 		return dde;
 	}
 	
+	public static DaemonDuccEvent createSwitchToMaster(Daemon daemon, NodeIdentity nodeIdentity) {
+		DaemonDuccEvent dde = new DaemonDuccEvent(daemon, EventType.SWITCH_TO_MASTER, nodeIdentity);
+		return dde;
+	}
+	
+	public static DaemonDuccEvent createSwitchToBackup(Daemon daemon, NodeIdentity nodeIdentity) {
+		DaemonDuccEvent dde = new DaemonDuccEvent(daemon, EventType.SWITCH_TO_BACKUP, nodeIdentity);
+		return dde;
+	}
+	
 	public static DaemonDuccEvent create(Daemon daemon, EventType eventType, NodeIdentity nodeIdentity) {
 		DaemonDuccEvent dde = new DaemonDuccEvent(daemon, eventType, nodeIdentity);
 		return dde;

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/DuccEvent.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/DuccEvent.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/DuccEvent.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/DuccEvent.java Thu Mar  8 20:43:04 2018
@@ -25,6 +25,11 @@ public interface DuccEvent extends Seria
 			BOOT, 
 			SHUTDOWN, 
 			//
+			INIT_AS_MASTER, 
+			INIT_AS_BACKUP,
+			SWITCH_TO_MASTER, 
+			SWITCH_TO_BACKUP, 
+			//
         	SUBMIT_JOB, 
             CANCEL_JOB, 
             MODIFY_JOB, 

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/JdEvent.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/JdEvent.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/JdEvent.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/JdEvent.java Thu Mar  8 20:43:04 2018
@@ -28,6 +28,7 @@ public class JdEvent extends AbstractDuc
 	private IDuccProcessMap processMap = null;
 	
 	private String killDriverReason = null;
+	private boolean duccHeadMaster = true;
 	
 	public JdEvent() {
 		super(EventType.JD_STATE);
@@ -60,4 +61,12 @@ public class JdEvent extends AbstractDuc
 	public boolean isKillDriver() {
 		return (getKillDriverReason() != null);
 	}
+	
+	public boolean isDuccHeadMaster() {
+		return duccHeadMaster;
+	}
+	
+	public void setDuccHeadMaster(boolean value) {
+		duccHeadMaster = value;
+	}
 }

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/sm/IService.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/sm/IService.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/sm/IService.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/sm/IService.java Thu Mar  8 20:43:04 2018
@@ -105,6 +105,7 @@ public interface IService
         // In code we want to be able to use the nicer mixed-case names.
         // Always use encode and decode and you can't get this wrong.
         //
+		Dispossessed      { public String decode() { return "dispossessed"   ; } },  // Service is not controlled by this Service Manager
         Pending           { public String decode() { return "pending"        ; } },  // Work is waiting on at least one service to start but
                                                                                      // the service is not disabled or some such.  UIMA-4223
 
@@ -131,6 +132,7 @@ public interface IService
             if ( value.equals("available"     ) ) return Available;
             if ( value.equals("not-available" ) ) return NotAvailable;
             if ( value.equals("stopping"      ) ) return Stopping;
+            if ( value.equals("dispossessed"  ) ) return Dispossessed;
             if ( value.equals("undefined"     ) ) return Undefined;
             return Undefined;
         }
@@ -139,6 +141,7 @@ public interface IService
         public int ordinality()
         {
             switch ( this ) {
+            	case Dispossessed: return 10;
                 case Pending:      return 9;  // UIMA-4223 waiting for dependent service to become available
                 case Available:    return 8;
                 case Waiting:      return 7;

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java Thu Mar  8 20:43:04 2018
@@ -24,7 +24,6 @@ import java.util.HashSet;
 import java.util.List;
 
 import org.apache.uima.ducc.common.IDuccEnv;
-import org.apache.uima.ducc.common.config.CommonConfiguration;
 import org.apache.uima.ducc.common.internationalization.Messages;
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.DuccPropertiesResolver;
@@ -51,9 +50,9 @@ public class DuccBoot extends Thread {
 	public static long maxReservations = 4096;
 	public static long maxServices = 4096;
 	
-	public static void boot(CommonConfiguration commonConfiguration) {
+	public static void boot() {
 		DuccBoot duccBoot = new DuccBoot();
-		duccBoot.initialize(commonConfiguration);
+		duccBoot.initialize();
 		duccBoot.start();
 	}
 
@@ -359,7 +358,7 @@ public class DuccBoot extends Thread {
 	// 	logger.info(location, jobid, messages.fetch("Services restored: "+restored));
 	// }
 	
-	private void initialize(CommonConfiguration commonConfiguration) {
+	private void initialize() {
 		String location = "initialize";
 		long limit = getLimit();
 		if(limit > 0) {
@@ -374,6 +373,7 @@ public class DuccBoot extends Thread {
 		String location = "restore";
 		logger.info(location, jobid, messages.fetchLabel("History directory")+IDuccEnv.DUCC_HISTORY_DIR);
 		IHistoryPersistenceManager hpm = HistoryFactory.getInstance(this.getClass().getName());
+		DuccData.reset();
 		DuccData duccData = DuccData.getInstance();
 		experimentsFound = new HashSet<String>();  // Lets the restore methods avoid inspecting already-found experiments
 		restoreReservations(hpm, duccData);

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccData.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccData.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccData.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccData.java Thu Mar  8 20:43:04 2018
@@ -42,34 +42,40 @@ public class DuccData {
 	private static DuccLogger logger = DuccLogger.getLogger(DuccData.class);
 	private static DuccId jobid = null;
 	
-	private static IDuccWorkMap duccWorkMap = new DuccWorkMap();
-	private static IDuccWorkMap duccWorkLive = new DuccWorkMap();
+	private static DuccData instance = new DuccData();
+
+	public static void reset() {
+		String location = "reset";
+		logger.info(location, jobid, "");
+		instance = new DuccData();
+	}
 	
-	private static ConcurrentSkipListMap<JobInfo,JobInfo> sortedJobs = new ConcurrentSkipListMap<JobInfo,JobInfo>();
-	private static ConcurrentSkipListMap<DuccId,JobInfo> keyMapJobs = new ConcurrentSkipListMap<DuccId,JobInfo>();
+	public static DuccData getInstance() {
+		return instance;
+	}
 	
-	private static ConcurrentSkipListMap<ReservationInfo,ReservationInfo> sortedReservations = new ConcurrentSkipListMap<ReservationInfo,ReservationInfo>();
-	private static ConcurrentSkipListMap<DuccId,ReservationInfo> keyMapReservations = new ConcurrentSkipListMap<DuccId,ReservationInfo>();
+	private volatile String published = null;
 	
-	private static ConcurrentSkipListMap<JobInfo,JobInfo> sortedServices = new ConcurrentSkipListMap<JobInfo,JobInfo>();
-	private static ConcurrentSkipListMap<DuccId,JobInfo> keyMapServices = new ConcurrentSkipListMap<DuccId,JobInfo>();
+	private long slack = 100;
 	
-	private static ConcurrentSkipListMap<Info,Info> sortedCombinedReservations = new ConcurrentSkipListMap<Info,Info>();
-	private static ConcurrentSkipListMap<DuccId,Info> keyMapCombinedReservations = new ConcurrentSkipListMap<DuccId,Info>();
+	private IHistoryPersistenceManager hpm = HistoryFactory.getInstance(this.getClass().getName());
 	
-	private static PagingObserver pagingObserver = PagingObserver.getInstance();
+	private IDuccWorkMap duccWorkMap = new DuccWorkMap();
+	private IDuccWorkMap duccWorkLive = new DuccWorkMap();
 	
-	private static DuccData duccData = new DuccData();
+	private ConcurrentSkipListMap<JobInfo,JobInfo> sortedJobs = new ConcurrentSkipListMap<JobInfo,JobInfo>();
+	private ConcurrentSkipListMap<DuccId,JobInfo> keyMapJobs = new ConcurrentSkipListMap<DuccId,JobInfo>();
 	
-	private static long slack = 100;
+	private ConcurrentSkipListMap<ReservationInfo,ReservationInfo> sortedReservations = new ConcurrentSkipListMap<ReservationInfo,ReservationInfo>();
+	private ConcurrentSkipListMap<DuccId,ReservationInfo> keyMapReservations = new ConcurrentSkipListMap<DuccId,ReservationInfo>();
 	
-	public static DuccData getInstance() {
-		return duccData;
-	}
+	private ConcurrentSkipListMap<JobInfo,JobInfo> sortedServices = new ConcurrentSkipListMap<JobInfo,JobInfo>();
+	private ConcurrentSkipListMap<DuccId,JobInfo> keyMapServices = new ConcurrentSkipListMap<DuccId,JobInfo>();
 	
-	private volatile String published = null;
+	private ConcurrentSkipListMap<Info,Info> sortedCombinedReservations = new ConcurrentSkipListMap<Info,Info>();
+	private ConcurrentSkipListMap<DuccId,Info> keyMapCombinedReservations = new ConcurrentSkipListMap<DuccId,Info>();
 	
-	private IHistoryPersistenceManager hpm = HistoryFactory.getInstance(this.getClass().getName());
+	private PagingObserver pagingObserver = PagingObserver.getInstance();
 	
 	public boolean isPublished() {
 		return published != null;

Added: uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccHead.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccHead.java?rev=1826275&view=auto
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccHead.java (added)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccHead.java Thu Mar  8 20:43:04 2018
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+*/
+package org.apache.uima.ducc.ws;
+
+import org.apache.uima.ducc.common.head.ADuccHead;
+import org.apache.uima.ducc.common.head.IDuccHead;
+import org.apache.uima.ducc.common.utils.DuccLogger;
+
+public class DuccHead extends ADuccHead {
+
+	private static DuccLogger logger = DuccLogger.getLogger(DuccHead.class);
+	
+	private static IDuccHead instance = new DuccHead(logger);
+	
+	public static IDuccHead getInstance() {
+		return instance;
+	}
+	
+	private DuccHead(DuccLogger logger) {
+		super(logger);
+	}
+}

Propchange: uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccHead.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/WebServerComponent.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/WebServerComponent.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/WebServerComponent.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/WebServerComponent.java Thu Mar  8 20:43:04 2018
@@ -31,6 +31,8 @@ import org.apache.uima.ducc.common.boot.
 import org.apache.uima.ducc.common.boot.DuccDaemonRuntimeProperties.DaemonName;
 import org.apache.uima.ducc.common.component.AbstractDuccComponent;
 import org.apache.uima.ducc.common.config.CommonConfiguration;
+import org.apache.uima.ducc.common.head.IDuccHead;
+import org.apache.uima.ducc.common.head.IDuccHead.DuccHeadTransition;
 import org.apache.uima.ducc.common.internationalization.Messages;
 import org.apache.uima.ducc.common.main.DuccService;
 import org.apache.uima.ducc.common.utils.DuccLogger;
@@ -46,6 +48,7 @@ import org.apache.uima.ducc.transport.ev
 import org.apache.uima.ducc.transport.event.RmStateDuccEvent;
 import org.apache.uima.ducc.transport.event.SmHeartbeatDuccEvent;
 import org.apache.uima.ducc.transport.event.SmStateDuccEvent;
+import org.apache.uima.ducc.transport.event.common.DuccWorkMap;
 import org.apache.uima.ducc.transport.event.common.IDuccWorkMap;
 import org.apache.uima.ducc.ws.registry.ServicesRegistry;
 import org.apache.uima.ducc.ws.self.message.WebServerStateDuccEvent;
@@ -77,6 +80,8 @@ implements IWebServer {
 	private DuccEventDispatcher eventDispatcher;
 	private String stateChangeEndpoint;
 
+	private IDuccHead dh = null;
+	
 	public WebServerComponent(CamelContext context, CommonConfiguration common) {
 		super("WebServer",context);
 		String methodName = "WebServerComponent";
@@ -167,11 +172,49 @@ implements IWebServer {
 		duccLogger.trace(methodName, jobid, duccMsg.fetch("exit"));
 	}
 	
+	private IDuccHead getDuccHead() {
+    	if(dh == null) {
+    		dh = DuccHead.getInstance();
+    		if(dh.is_ducc_head_backup()) {
+    			stateChange(EventType.INIT_AS_BACKUP);
+    		}
+    		else {
+    			stateChange(EventType.INIT_AS_MASTER);
+    		}
+    	}
+    	return dh;
+    }
 	
 	public void update(OrchestratorStateDuccEvent duccEvent) {
 		String methodName = "update";
 		duccLogger.trace(methodName, jobid, duccMsg.fetch("enter"));
 		duccLogger.debug(methodName, jobid, duccMsg.fetchLabel("received")+"OrchestratorStateDuccEvent");
+		
+		DuccHeadTransition transition = getDuccHead().transition();
+		switch(transition) {
+		case master_to_master:
+			duccLogger.debug(methodName, jobid, "ducc head == master");
+			break;
+		case master_to_backup:
+			DuccData.reset();
+			duccEvent.setWorkMap(new DuccWorkMap());	// ignore OR map
+			duccLogger.warn(methodName, jobid, "ducc head -> backup");
+			stateChange(EventType.SWITCH_TO_BACKUP);
+			break;
+		case backup_to_master:
+			duccLogger.warn(methodName, jobid, "ducc head -> master");
+			stateChange(EventType.SWITCH_TO_MASTER);
+			DuccBoot.boot();
+			break;
+		case backup_to_backup:
+			duccEvent.setWorkMap(new DuccWorkMap());	// ignore OR map
+			duccLogger.debug(methodName, jobid, "ducc head == backup");
+			break;
+		default:
+			duccLogger.debug(methodName, jobid, "ducc head == unspecified");
+			break;
+		}
+		
 		DuccDaemonsData.getInstance().put(duccEvent);
 		IDuccWorkMap wm = duccEvent.getWorkMap();
 		boolean change = false;

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/config/WebServerConfiguration.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/config/WebServerConfiguration.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/config/WebServerConfiguration.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/config/WebServerConfiguration.java Thu Mar  8 20:43:04 2018
@@ -154,7 +154,7 @@ public class WebServerConfiguration {
 			}
 			ws = new WebServerComponent(common.camelContext(), common);
 			ws.setStateChangeEndpoint(common.daemonsStateChangeEndpoint);
-			DuccBoot.boot(common);
+			DuccBoot.boot();
 			//	Instantiate delegate listener to receive incoming messages. 
 			WebServerEventListener delegateListener = this.webServerDelegateListener(ws);
 			//	Inject a dispatcher into the listener in case it needs to send

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java?rev=1826275&r1=1826274&r2=1826275&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java Thu Mar  8 20:43:04 2018
@@ -49,6 +49,8 @@ import org.apache.uima.ducc.common.SizeB
 import org.apache.uima.ducc.common.SizeBytes.Type;
 import org.apache.uima.ducc.common.boot.DuccDaemonRuntimeProperties;
 import org.apache.uima.ducc.common.boot.DuccDaemonRuntimeProperties.DaemonName;
+import org.apache.uima.ducc.common.head.DuccHeadHelper;
+import org.apache.uima.ducc.common.head.IDuccHead;
 import org.apache.uima.ducc.common.internationalization.Messages;
 import org.apache.uima.ducc.common.jd.files.IWorkItemState;
 import org.apache.uima.ducc.common.jd.files.IWorkItemState.State;
@@ -59,6 +61,7 @@ import org.apache.uima.ducc.common.jd.fi
 import org.apache.uima.ducc.common.system.SystemState;
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.DuccProperties;
+import org.apache.uima.ducc.common.utils.DuccPropertiesHelper;
 import org.apache.uima.ducc.common.utils.DuccPropertiesResolver;
 import org.apache.uima.ducc.common.utils.DuccSchedulerClasses;
 import org.apache.uima.ducc.common.utils.IDuccLoggerComponents;
@@ -85,6 +88,7 @@ import org.apache.uima.ducc.transport.ev
 import org.apache.uima.ducc.ws.DuccDaemonsData;
 import org.apache.uima.ducc.ws.DuccData;
 import org.apache.uima.ducc.ws.DuccDataHelper;
+import org.apache.uima.ducc.ws.DuccHead;
 import org.apache.uima.ducc.ws.DuccMachinesData;
 import org.apache.uima.ducc.ws.MachineInfo;
 import org.apache.uima.ducc.ws.authentication.DuccAsUser;
@@ -122,7 +126,9 @@ public class DuccHandler extends DuccAbs
 	private static DuccLogger duccLogger = DuccLogger.getLogger(DuccHandler.class);
 	private static Messages messages = Messages.getInstance();
 	private static DuccId jobid = null;
-
+	
+	private static IDuccHead dh = DuccHead.getInstance();
+	
 	// These keys may have large values and be displayed with Show/Hide buttons.
 	// ducc.js must be updated if more than 4 are needed (services may have 4)
 	private final String[] n = {"classpath", "service_ping_classpath", "process_executable_args", "process_jvm_args", "environment"};
@@ -175,6 +181,8 @@ public class DuccHandler extends DuccAbs
 
 	private String duccClusterName 					= duccContext+"/cluster-name";
 	private String duccClusterUtilization 			= duccContext+"/cluster-utilization";
+	private String duccClusterReliableLabel			= duccContext+"/cluster-reliable-label";
+	private String duccClusterReliableStatus		= duccContext+"/cluster-reliable-status";
 	private String duccTimeStamp   					= duccContext+"/timestamp";
 	private String duccAlerts   					= duccContext+"/alerts";
 	private String duccBannerMessage   				= duccContext+"/banner-message";
@@ -215,7 +223,7 @@ public class DuccHandler extends DuccAbs
 	public DuccHandler(DuccWebServer duccWebServer) {
 		super.init(duccWebServer);
 	}
-
+	
 	public String getUserIdFromRequest(HttpServletRequest request) {
 		String retVal = duccWebSessionManager.getUserId(request);
 		return retVal;
@@ -3330,6 +3338,64 @@ public class DuccHandler extends DuccAbs
 		duccLogger.trace(methodName, null, messages.fetch("exit"));
 	}
 
+	private void handleDuccServletClusterReliableStatus(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response)
+	throws IOException, ServletException
+	{
+		String methodName = "handleDuccServletClusterReliableStatus";
+		duccLogger.trace(methodName, null, messages.fetch("enter"));
+		StringBuffer sb = new StringBuffer();
+		if(DuccHeadHelper.isVirtualIpAddress()) {
+			String ipAddress = DuccPropertiesHelper.getDuccHeadVirtualIpAddress();
+			String ipDevice = DuccPropertiesHelper.getDuccHeadVirtualIpDevice();
+			if(ipAddress.length() > 0) {
+				if(ipDevice.length() > 0) {
+					String status = dh.get_ducc_head_mode();
+					String hover = ipDevice+" "+ipAddress;
+					if(dh.is_ducc_head_master()) {
+						String text = "<span title=\""+hover+"\">"+status+"</span>";
+						sb.append(text);
+					}
+					else {
+						String text = "<span>"+status+"</span>";
+						sb.append(text);
+					}
+				}
+			}
+		}
+		response.getWriter().println(sb);
+		duccLogger.trace(methodName, null, messages.fetch("exit"));
+	}
+	
+	private void handleDuccServletClusterReliableLabel(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response)
+	throws IOException, ServletException
+	{
+		String methodName = "handleDuccServletClusterReliableLabel";
+		duccLogger.trace(methodName, null, messages.fetch("enter"));
+		StringBuffer sb = new StringBuffer();
+		if(DuccHeadHelper.isVirtualIpAddress()) {
+			String ipAddress = DuccPropertiesHelper.getDuccHeadVirtualIpAddress();
+			String ipDevice = DuccPropertiesHelper.getDuccHeadVirtualIpDevice();
+			if(ipAddress.length() > 0) {
+				if(ipDevice.length() > 0) {
+					String label = "reliable:";
+					if(dh.is_ducc_head_backup()) {
+						String hover = "Click to visit master";
+						String text = "<span title=\""+hover+"\">"+label+"</span>";
+						String link = "http://"+ipAddress+":"+getDuccWebServer().getPort()+"/";
+			    		String href = "<a href=\""+link+"\" target=\"_ducc_master\"  >"+text+"</a>";
+			    		sb.append(href);
+					}
+					else {
+						String text = "<span>"+label+"</span>";
+						sb.append(text);
+					}
+				}
+			}
+		}
+		response.getWriter().println(sb);
+		duccLogger.trace(methodName, null, messages.fetch("exit"));
+	}
+	
 	private void handleDuccServletTimeStamp(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response)
 	throws IOException, ServletException
 	{
@@ -4388,6 +4454,12 @@ public class DuccHandler extends DuccAbs
 			else if(reqURI.startsWith(duccLogoutLink)) {
 				handleDuccServletLogoutLink(target, baseRequest, request, response);
 			}
+			else if(reqURI.startsWith(duccClusterReliableStatus)) {
+				handleDuccServletClusterReliableStatus(target, baseRequest, request, response);
+			}
+			else if(reqURI.startsWith(duccClusterReliableLabel)) {
+				handleDuccServletClusterReliableLabel(target, baseRequest, request, response);
+			}
 			else if(reqURI.startsWith(duccJobIdData)) {
 				handleDuccServletJobIdData(target, baseRequest, request, response);
 				DuccWebUtil.noCache(response);