Author: cwiklik
Date: Thu Jan  5 16:38:14 2017
New Revision: 1777479

URL: http://svn.apache.org/viewvc?rev=1777479&view=rev
Log:
UIMA-5150 Added duplicate ducc daemon detector to prevent starting secondary 
ones

Added:
    
uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/node/DuplicateDuccDaemonProcessDetector.java
   (with props)
Modified:
    
uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/main/DuccService.java

Modified: 
uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/main/DuccService.java
URL: 
http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/main/DuccService.java?rev=1777479&r1=1777478&r2=1777479&view=diff
==============================================================================
--- 
uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/main/DuccService.java
 (original)
+++ 
uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/main/DuccService.java
 Thu Jan  5 16:38:14 2017
@@ -34,6 +34,7 @@ import org.apache.uima.ducc.common.NodeI
 import org.apache.uima.ducc.common.component.AbstractDuccComponent;
 import org.apache.uima.ducc.common.component.IJobProcessor;
 import 
org.apache.uima.ducc.common.exception.DuccComponentInitializationException;
+import org.apache.uima.ducc.common.node.DuplicateDuccDaemonProcessDetector;
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.Utils;
 import org.springframework.context.ApplicationContext;
@@ -270,6 +271,19 @@ public class DuccService extends Abstrac
        public static void main(String[] args) {
                DuccService duccService = null;
                try {
+                       // run duplicate daemon detector to make sure we dont 
start
+                       // multiple copies of Ducc daemons. It checks of this 
process
+                       // is a duplicate of OR, WS, PM, RM, SM, or Agent. The 
code
+                       // simply exits if another instance is running.
+                       DuplicateDuccDaemonProcessDetector daemonDetector =
+                                       new 
DuplicateDuccDaemonProcessDetector();
+                       String thisProcessDaemonType = 
System.getProperty(DUCC_DEPLOY_COMPONENTS);
+                       if ( 
daemonDetector.isThisProcessDuplicateDaemon(thisProcessDaemonType) ) {
+                               System.out.println("Ducc Daemon process 
"+thisProcessDaemonType+" is already running - duplicates are not allowed - 
exiting ...");
+                               System.exit(1);
+                       }
+
+                       
                        if ( Utils.findDuccHome() == null ) {
                 //findDuccHome places it into System.properties
                                System.out.println("Unable to Launch Ducc 
Service - DUCC_HOME not defined. Add it to your environment or provide it with 
-DDUCC_HOME=<path>");

Added: 
uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/node/DuplicateDuccDaemonProcessDetector.java
URL: 
http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/node/DuplicateDuccDaemonProcessDetector.java?rev=1777479&view=auto
==============================================================================
--- 
uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/node/DuplicateDuccDaemonProcessDetector.java
 (added)
+++ 
uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/node/DuplicateDuccDaemonProcessDetector.java
 Thu Jan  5 16:38:14 2017
@@ -0,0 +1,259 @@
+/*
+ * 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.common.node;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.uima.ducc.common.utils.Utils;
+
+public class DuplicateDuccDaemonProcessDetector {
+       private static String thisProcessPID = Utils.getPID();
+       private static String ducc_user = System.getProperty("user.name");
+       private static final String brokerProcessId = "-Dactivemq.base";
+       private static final String duccDaemonId = "-Dducc.deploy.components";
+       private static final String[] processCollectorCommandLine = 
+                       new String[] {"ps","-Ao","user:12,pid,ppid,uid,args", 
"--no-heading"};
+
+       
+       public enum DuccDaemonType {
+               
+               AGENT("agent"),OR("orchestrator"),
+               RM("rm"),SM("sm"),BROKER("broker"),
+               WS("ws"), PM("pm"),NotDuccDaemon("");
+               private final String daemonType;
+
+               private DuccDaemonType(String type) {
+                       daemonType = type;
+               }
+               
+               public String getName() {
+                       return daemonType;
+               }
+       }
+       public static void main(String[] args) {
+
+               DuplicateDuccDaemonProcessDetector processCollector =
+                               new DuplicateDuccDaemonProcessDetector();
+               String thisProcessDaemonType = 
System.getProperty(duccDaemonId.substring(2)); // skip -D
+               
processCollector.isThisProcessDuplicateDaemon(thisProcessDaemonType);  
+       }
+       /**
+        * Checks if this process is another instance of PM, OR, SM, RM, WS, or 
Agent.
+        * The JD, JP, and Services are excluded from the check although the 
bootstrapping
+        * code is the same as the real daemons. 
+        * 
+        * @param daemonName
+        * @return
+        */
+       public boolean isThisProcessDuplicateDaemon(String daemonName ) {
+               // Convert this daemon type ("or", "sm", etc) to enumeration 
type.
+               // Returns NotDuccDaemon if this process is not a true ducc 
daemon,
+               // WS, RM, PM, SM, OR, or Agent.
+               DuccDaemonType thisDuccDaemonType = 
getDaemonTypeForName(daemonName);
+               // If cant convert to enumeration type, this process is not a 
ducc daemon
+               if ( !thisDuccDaemonType.equals(DuccDaemonType.NotDuccDaemon)) {
+                       return isThisProcessDuplicateDaemon(thisDuccDaemonType);
+               }
+               return false;
+       }
+       /**
+        * Launches ps command and scrapes a list of processes currently 
running on a node
+        * to detect if this process is a duplicate of already running Ducc 
daemon.
+        * 
+        * @param thisDuccDaemonType - this process daemon type (OR, WS, PM, 
etc)
+        * 
+        * @return true if this process is a duplicate of a running ducc 
daemon, otherwise false.
+        */
+       public boolean isThisProcessDuplicateDaemon(DuccDaemonType 
thisDuccDaemonType) {
+               try {
+                       // launch 'ps' command and return a list of running 
processes on this node
+                       List<RunningProcess> allProcesses = 
+                                       getAllProcessesRunningOnNodeNow();
+                       
+                       for( RunningProcess process : allProcesses ) {
+                               // exclude this process from the check
+                               if ( thisProcessPID.equals(process.getPid()) ) {
+                                       continue; // skip this process
+                               }
+                               // only care about current user processes
+                               if (ducc_user.equals(process.getUserName()) ) {
+                                       // extract process type ("ws", 
"or",etc. Returns NotDuccDaemon otherwise.
+                                       // It checks the value of 
-Dducc.deploy.components property to determine
+                                       // if it is a daemon process.
+                                       DuccDaemonType runningDuccDaemonType = 
+                                                       
duccDaemonType(process.getCommandline());
+                                       // Only care about Ducc daemon processes
+                                       if 
(DuccDaemonType.NotDuccDaemon.equals(runningDuccDaemonType)) {
+                                               continue; // skip
+                                       } else if ( 
thisDuccDaemonType.equals(runningDuccDaemonType) ) {
+                                               /****** FOUND DUPLICATE DUCC 
DAEMON ******/
+                                               System.out.println("The Ducc 
daemon:"+runningDuccDaemonType.getName()+" is already runninig - duplicates are 
not allowed");
+                                               return true;
+                                       } else {
+                                       //      System.out.println("Process 
PID:"+process.getPid()+" Ducc Daemon:"+runningDuccDaemonType.getName());
+                                       }
+                               }
+                       }
+               } catch( Exception e) {
+                       e.printStackTrace();
+               }
+               return false;
+       }
+       
+       public List<RunningProcess> getAllProcessesRunningOnNodeNow() throws 
RuntimeException {
+               BufferedReader reader = null;
+               List<RunningProcess> nodeProcessList = new 
ArrayList<RunningProcess>();
+               try {
+                       InputStream inputStream = 
launchProcessCollector(processCollectorCommandLine);
+                   reader = new BufferedReader(new 
InputStreamReader(inputStream));
+                   String line;
+                   String regex = "\\s+";
+                   
+               // read the next line from ps output
+                   while ((line = reader.readLine()) != null) {
+                     String tokens[] = line.split(regex);
+                     if ( tokens.length > 0 ) {
+                        // copy the whole command line starting at index 4 
+                        String[] commandLine = Arrays.copyOfRange(tokens, 4, 
tokens.length);
+                         
+                        RunningProcess p = 
+                                     new RunningProcess().
+                                     withUserName(tokens[0]).
+                                     withPid(tokens[1]).
+                                     withParentPid(tokens[2]).
+                                     withUserId(tokens[3]).
+                                     withCommandline(commandLine);
+                        
+                           // add process to a list which is used to look up 
each process parent
+                        nodeProcessList.add(p);
+                     }
+                   }
+               } catch( Exception e) {
+                       e.printStackTrace();
+               } finally {
+                       try {
+                               reader.close();
+                       } catch( IOException ioe) {
+                       }
+               }
+               return nodeProcessList;
+       }
+       
+       private InputStream launchProcessCollector(String[] processCommandLine) 
throws Exception {
+               InputStream inputStream = null;
+       
+        ProcessBuilder pb = new ProcessBuilder(processCommandLine);
+           pb.redirectErrorStream(true);
+           Process proc = pb.start();
+           //  spawn ps command and scrape the output
+           inputStream = proc.getInputStream();
+        return inputStream;
+       }
+       private DuccDaemonType getDaemonTypeForName(String aName) {
+       for( DuccDaemonType dt : DuccDaemonType.values() ) {
+               if ( dt.getName().equals(aName)) {
+                       return dt;
+               }
+       }
+       return DuccDaemonType.NotDuccDaemon;
+       }
+         private DuccDaemonType duccDaemonType(String[] tokens) {
+                 DuccDaemonType daemonType = DuccDaemonType.NotDuccDaemon;
+                 
+                 for( String token : tokens ) {
+                     if ( token.startsWith(duccDaemonId)) {
+                       int pos = token.indexOf("=");
+                       if ( pos > -1 ) {
+                               String daemon = token.substring(pos+1);
+                               for( DuccDaemonType dt : 
DuccDaemonType.values() ) {
+                                       if ( dt.getName().equals(daemon)) {
+                                               return dt;
+                                       }
+                               }
+                       }
+                     } else if (token.startsWith(brokerProcessId)) {
+                         daemonType = DuccDaemonType.BROKER;
+                         break;
+                     }
+                   }
+                   return daemonType;
+                 }
+
+         private class RunningProcess {
+                 String pid;
+                 String userName;
+                 String userId;
+                 String parentPid;
+                 String[] commandline;
+                 
+                 
+               public String getPid() {
+                       return pid;
+               }
+
+               protected RunningProcess withPid(String pid) {
+                       this.pid = pid;
+                       return this;
+               }
+
+               public String getUserName() {
+                       return userName;
+               }
+
+               protected RunningProcess withUserName(String userName) {
+                       this.userName = userName;
+                       return this;
+               }
+
+               @SuppressWarnings("unused")
+               public String getUserId() {
+                       return userId;
+               }
+
+               protected RunningProcess withUserId(String userId) {
+                       this.userId = userId;
+                       return this;
+               }
+
+               @SuppressWarnings("unused")
+               public String getParentPid() {
+                       return parentPid;
+               }
+
+               protected RunningProcess withParentPid(String parentPid) {
+                       this.parentPid = parentPid;
+                       return this;
+               }
+
+               public String[] getCommandline() {
+                       return commandline;
+               }
+
+               protected RunningProcess withCommandline(String[] commandline) {
+                       this.commandline = commandline;
+                       return this;
+               }
+         }
+}

Propchange: 
uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/node/DuplicateDuccDaemonProcessDetector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain


Reply via email to