helix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From zzh...@apache.org
Subject git commit: refactor helix-agent and add a simple test case
Date Fri, 14 Jun 2013 22:17:13 GMT
Updated Branches:
  refs/heads/master b5cff39e5 -> 02dcd649f


refactor helix-agent and add a simple test case


Project: http://git-wip-us.apache.org/repos/asf/incubator-helix/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-helix/commit/02dcd649
Tree: http://git-wip-us.apache.org/repos/asf/incubator-helix/tree/02dcd649
Diff: http://git-wip-us.apache.org/repos/asf/incubator-helix/diff/02dcd649

Branch: refs/heads/master
Commit: 02dcd649f014c3f39e2ecbac6f7d59a51e779851
Parents: b5cff39
Author: zzhang <zzhang5@uci.edu>
Authored: Fri Jun 14 15:17:04 2013 -0700
Committer: zzhang <zzhang5@uci.edu>
Committed: Fri Jun 14 15:17:04 2013 -0700

----------------------------------------------------------------------
 .../org/apache/helix/agent/AgentStateModel.java | 15 ++--
 .../org/apache/helix/agent/CommandConfig.java   | 19 ++++-
 .../helix/agent/ProcessMonitorThread.java       |  3 +-
 .../java/org/apache/helix/agent/SystemUtil.java |  2 +-
 .../integration-test/script/simpleHttpClient.py | 26 ++++++
 .../integration-test/script/simpleHttpServer.py | 36 ++++++++
 .../org/apache/helix/agent/TestHelixAgent.java  | 88 +++++++++++++-------
 7 files changed, 148 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/02dcd649/helix-agent/src/main/java/org/apache/helix/agent/AgentStateModel.java
----------------------------------------------------------------------
diff --git a/helix-agent/src/main/java/org/apache/helix/agent/AgentStateModel.java b/helix-agent/src/main/java/org/apache/helix/agent/AgentStateModel.java
index 30dd0a5..3e4626c 100644
--- a/helix-agent/src/main/java/org/apache/helix/agent/AgentStateModel.java
+++ b/helix-agent/src/main/java/org/apache/helix/agent/AgentStateModel.java
@@ -140,17 +140,16 @@ public class AgentStateModel extends StateModel
     }
     ExternalCommand externalCmd = ExternalCommand.executeWithTimeout(new File(workingDir),

         cmdValue, timeoutValue, args);
+        
+    int exitValue = externalCmd.exitValue();
     
     // debug
-    // System.out.println("command output:\n" + externalCmd.getStringOutput());
-    
-    int exitValue = externalCmd.exitValue();
-    _logger.info("Executed command: " + cmd + ", exitValue: " + exitValue);
+//    System.out.println("command: " + cmd + ", exitValue: " + exitValue
+//        + " output:\n" + externalCmd.getStringOutput());
     
-    // if exit-value != 0, transition fails
-    if (exitValue != 0) {
-      throw new Exception("fail to execute command: " + cmd + ", exitValue: " + exitValue

-          + ", error: " + externalCmd.getStringError());
+    if (_logger.isDebugEnabled()) {
+      _logger.debug("command: " + cmd + ", exitValue: " + exitValue
+        + " output:\n" + externalCmd.getStringOutput());
     }
     
     // monitor pid if pidFile exists

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/02dcd649/helix-agent/src/main/java/org/apache/helix/agent/CommandConfig.java
----------------------------------------------------------------------
diff --git a/helix-agent/src/main/java/org/apache/helix/agent/CommandConfig.java b/helix-agent/src/main/java/org/apache/helix/agent/CommandConfig.java
index a0e8700..4f700c0 100644
--- a/helix-agent/src/main/java/org/apache/helix/agent/CommandConfig.java
+++ b/helix-agent/src/main/java/org/apache/helix/agent/CommandConfig.java
@@ -32,6 +32,11 @@ public class CommandConfig {
 
   public CommandConfig(String fromState, String toState, String command,
       String workingDir, String timeout, String pidFile) {
+    if (command == null) {
+      throw new IllegalArgumentException("command is null");
+      
+    }
+    
     _fromState = fromState;
     _toState = toState;
     _command = command;
@@ -49,9 +54,17 @@ public class CommandConfig {
     Map<String, String> map = new TreeMap<String, String>();
     map.put(buildKey(_fromState, _toState, CommandAttribute.COMMAND), _command);
     if (!_command.equals(CommandAttribute.NOP.getName())) {
-      map.put(buildKey(_fromState, _toState, CommandAttribute.WORKING_DIR), _workingDir);
-      map.put(buildKey(_fromState, _toState, CommandAttribute.TIMEOUT), _timeout);
-      map.put(buildKey(_fromState, _toState, CommandAttribute.PID_FILE), _pidFile);
+      if (_workingDir != null) {
+        map.put(buildKey(_fromState, _toState, CommandAttribute.WORKING_DIR), _workingDir);
+      }
+      
+      if (_timeout != null) {
+        map.put(buildKey(_fromState, _toState, CommandAttribute.TIMEOUT), _timeout);
+      }
+      
+      if (_pidFile != null) {
+        map.put(buildKey(_fromState, _toState, CommandAttribute.PID_FILE), _pidFile);
+      }
     }  
     return map;
   }

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/02dcd649/helix-agent/src/main/java/org/apache/helix/agent/ProcessMonitorThread.java
----------------------------------------------------------------------
diff --git a/helix-agent/src/main/java/org/apache/helix/agent/ProcessMonitorThread.java b/helix-agent/src/main/java/org/apache/helix/agent/ProcessMonitorThread.java
index 1e3e177..6058b55 100644
--- a/helix-agent/src/main/java/org/apache/helix/agent/ProcessMonitorThread.java
+++ b/helix-agent/src/main/java/org/apache/helix/agent/ProcessMonitorThread.java
@@ -2,6 +2,7 @@ package org.apache.helix.agent;
 
 import java.io.File;
 import java.util.Random;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.helix.agent.SystemUtil.ProcessStateCode;
 import org.apache.log4j.Logger;
@@ -50,7 +51,7 @@ public class ProcessMonitorThread extends Thread {
           LOG.error("process: " + _pid + " is in zombie state");
           break;
         }
-        Thread.sleep(new Random().nextInt(MONITOR_PERIOD_BASE) + MONITOR_PERIOD_BASE);
+        TimeUnit.MILLISECONDS.sleep(new Random().nextInt(MONITOR_PERIOD_BASE) + MONITOR_PERIOD_BASE);
         processState = SystemUtil.getProcessState(_pid);
       }
     } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/02dcd649/helix-agent/src/main/java/org/apache/helix/agent/SystemUtil.java
----------------------------------------------------------------------
diff --git a/helix-agent/src/main/java/org/apache/helix/agent/SystemUtil.java b/helix-agent/src/main/java/org/apache/helix/agent/SystemUtil.java
index b53565e..81e6056 100644
--- a/helix-agent/src/main/java/org/apache/helix/agent/SystemUtil.java
+++ b/helix-agent/src/main/java/org/apache/helix/agent/SystemUtil.java
@@ -98,7 +98,7 @@ public class SystemUtil {
       String line = br.readLine();
       return line;
     } catch (IOException e) {
-      LOG.error("fail to read pid from pidFile: " + file, e);
+      LOG.warn("fail to read pid from pidFile: " + file + ". will not monitor");
     } finally {
       if (br != null) {
         try {

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/02dcd649/helix-agent/src/main/scripts/integration-test/script/simpleHttpClient.py
----------------------------------------------------------------------
diff --git a/helix-agent/src/main/scripts/integration-test/script/simpleHttpClient.py b/helix-agent/src/main/scripts/integration-test/script/simpleHttpClient.py
new file mode 100755
index 0000000..cfd16aa
--- /dev/null
+++ b/helix-agent/src/main/scripts/integration-test/script/simpleHttpClient.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+
+import httplib
+import sys
+
+#get http server ip
+http_server = "localhost:8080" 
+#create a connection
+conn = httplib.HTTPConnection(http_server)
+
+#request command to server
+if len(sys.argv) > 1:
+    conn.request("GET", "/" + sys.argv[1])
+else:
+    conn.request("GET", "/")
+
+#get response from server
+rsp = conn.getresponse()
+
+#print server response and data
+#print(rsp.status, rsp.reason)
+data_received = rsp.read()
+print(data_received)
+    
+conn.close()
+sys.exit(0)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/02dcd649/helix-agent/src/main/scripts/integration-test/script/simpleHttpServer.py
----------------------------------------------------------------------
diff --git a/helix-agent/src/main/scripts/integration-test/script/simpleHttpServer.py b/helix-agent/src/main/scripts/integration-test/script/simpleHttpServer.py
new file mode 100755
index 0000000..7f1322e
--- /dev/null
+++ b/helix-agent/src/main/scripts/integration-test/script/simpleHttpServer.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
+
+PORT_NUMBER = 8080
+
+#This class will handles any incoming request from
+#the browser 
+class myHandler(BaseHTTPRequestHandler):
+	
+	#Handler for the GET requests
+	def do_GET(self):
+		self.send_response(200)
+		self.send_header('Content-type','text/html')
+		self.end_headers()
+		# Send the html message
+		if self.path == "/exit":
+			print 'exit received, shutting down the web server'
+			server.socket.close()
+		else:
+			self.wfile.write("requestPath: " + self.path)
+			print("requestPath: " + self.path)
+		return
+
+try:
+	#Create a web server and define the handler to manage the
+	#incoming request
+	server = HTTPServer(('', PORT_NUMBER), myHandler)
+	print 'Started httpserver on port ' , PORT_NUMBER
+	
+	#Wait forever for incoming http requests
+	server.serve_forever()
+
+except KeyboardInterrupt:
+	print '^C received, shutting down the web server'
+	server.socket.close()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/02dcd649/helix-agent/src/test/java/org/apache/helix/agent/TestHelixAgent.java
----------------------------------------------------------------------
diff --git a/helix-agent/src/test/java/org/apache/helix/agent/TestHelixAgent.java b/helix-agent/src/test/java/org/apache/helix/agent/TestHelixAgent.java
index daad645..6097456 100644
--- a/helix-agent/src/test/java/org/apache/helix/agent/TestHelixAgent.java
+++ b/helix-agent/src/test/java/org/apache/helix/agent/TestHelixAgent.java
@@ -20,9 +20,12 @@ package org.apache.helix.agent;
  */
 
 import java.io.File;
+import java.io.IOException;
 import java.util.Date;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.helix.ConfigAccessor;
+import org.apache.helix.ExternalCommand;
 import org.apache.helix.ScriptTestHelper;
 import org.apache.helix.TestHelper;
 import org.apache.helix.ZkUnitTestBase;
@@ -36,12 +39,44 @@ import org.apache.helix.tools.ClusterSetup;
 import org.apache.helix.tools.ClusterStateVerifier;
 import org.apache.helix.tools.ClusterStateVerifier.BestPossAndExtViewZkVerifier;
 import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 public class TestHelixAgent extends ZkUnitTestBase {
+  final String workingDir = ScriptTestHelper.getPrefix() + ScriptTestHelper.INTEGRATION_SCRIPT_DIR;
+  ExternalCommand serverCmd = null;
+
+  @BeforeMethod
+  public void beforeMethod() throws Exception {
+    serverCmd = ExternalCommand.start(workingDir + "/simpleHttpServer.py");
+  }
+  
+  @AfterMethod
+  public void afterMethod() throws Exception {
+    if (serverCmd != null) {
+      // shutdown server
+      ExternalCommand.execute(new File(workingDir), "simpleHttpClient.py", "exit");
+//      System.out.println("simpleHttpServer output: \n" + serverCmd.getStringOutput());
+      
+      // check server has received all the requests
+      String serverOutput = serverCmd.getStringOutput();
+      int idx = serverOutput.indexOf("requestPath: /OFFLINE-SLAVE");
+      Assert.assertTrue(idx > 0, "server should receive OFFINE->SLAVE transition");
+      
+      idx = serverOutput.indexOf("requestPath: /SLAVE-MASTER", idx);
+      Assert.assertTrue(idx > 0, "server should receive SLAVE-MASTER transition");
+      
+      idx = serverOutput.indexOf("requestPath: /MASTER-SLAVE", idx);
+      Assert.assertTrue(idx > 0, "server should receive MASTER-SLAVE transition");
+
+      idx = serverOutput.indexOf("requestPath: /SLAVE-OFFLINE", idx);
+      Assert.assertTrue(idx > 0, "server should receive SLAVE-OFFLINE transition");
+
+    }
+  }
   
-  // disable this test
-  // @Test
+  @Test
   public void test() throws Exception {
     String className = TestHelper.getTestClassName();
     String methodName = TestHelper.getTestMethodName();
@@ -76,53 +111,51 @@ public class TestHelixAgent extends ZkUnitTestBase {
                                     .build();
     ConfigAccessor configAccessor = new ConfigAccessor(client);
     
-    // run foo_test.py during S->M
-    String workingDir = ScriptTestHelper.getPrefix() + ScriptTestHelper.INTEGRATION_SCRIPT_DIR;
-    String pidFile = ScriptTestHelper.getPrefix() + ScriptTestHelper.INTEGRATION_LOG_DIR
+ "/default/foo_{PARTITION_NAME}_pid.txt";
-    
-    // System.out.println("workingDir: " + workingDir);
+    // String pidFile = ScriptTestHelper.getPrefix() + ScriptTestHelper.INTEGRATION_LOG_DIR
+ "/default/foo_{PARTITION_NAME}_pid.txt";
     
     // the pid file path for the first partition
     // delete it if exists
-    String pidFileFirstPartition = ScriptTestHelper.getPrefix() + ScriptTestHelper.INTEGRATION_LOG_DIR
+ "/default/foo_TestDB0_0_pid.txt";
-    File file = new File(pidFileFirstPartition);
-    if (file.exists()) {
-      file.delete();
-    }
-    
+//    String pidFileFirstPartition = ScriptTestHelper.getPrefix() + ScriptTestHelper.INTEGRATION_LOG_DIR
+ "/default/foo_TestDB0_0_pid.txt";
+//    File file = new File(pidFileFirstPartition);
+//    if (file.exists()) {
+//      file.delete();
+//    }
     
+    // set commands for state-transitions
     CommandConfig.Builder builder = new CommandConfig.Builder();
     CommandConfig cmdConfig = builder.setTransition("SLAVE", "MASTER")
-                                     .setCommand("dds_driver.py -c foo_test -o start")
+                                     .setCommand("simpleHttpClient.py SLAVE-MASTER")
                                      .setCommandWorkingDir(workingDir)
                                      .setCommandTimeout("0")
-                                     .setPidFile(pidFile)
+    //                                 .setPidFile(pidFile)
                                      .build();
     configAccessor.set(scope, cmdConfig.toKeyValueMap());
     
-    // nop for O->S, M->S, and S->O
     builder = new CommandConfig.Builder();
     cmdConfig = builder.setTransition("OFFLINE", "SLAVE")
-                                     .setCommand(CommandAttribute.NOP.getName())
-                                     .build();
+                       .setCommand("simpleHttpClient.py OFFLINE-SLAVE")
+                       .setCommandWorkingDir(workingDir)
+                       .build();
     configAccessor.set(scope, cmdConfig.toKeyValueMap());
 
     builder = new CommandConfig.Builder();
     cmdConfig = builder.setTransition("MASTER", "SLAVE")
-                                     .setCommand(CommandAttribute.NOP.getName())
-                                     .build();
+                       .setCommand("simpleHttpClient.py MASTER-SLAVE")
+                       .setCommandWorkingDir(workingDir)
+                       .build();
     configAccessor.set(scope, cmdConfig.toKeyValueMap());
     
     builder = new CommandConfig.Builder();
     cmdConfig = builder.setTransition("SLAVE", "OFFLINE")
-                                     .setCommand(CommandAttribute.NOP.getName())
-                                     .build();
+                       .setCommand("simpleHttpClient.py SLAVE-OFFLINE")
+                       .setCommandWorkingDir(workingDir)
+                       .build();
     configAccessor.set(scope, cmdConfig.toKeyValueMap());
     
     builder = new CommandConfig.Builder();
     cmdConfig = builder.setTransition("OFFLINE", "DROPPED")
-                                     .setCommand(CommandAttribute.NOP.getName())
-                                     .build();
+                       .setCommand(CommandAttribute.NOP.getName())
+                       .build();
     configAccessor.set(scope, cmdConfig.toKeyValueMap());
 
 
@@ -158,8 +191,8 @@ public class TestHelixAgent extends ZkUnitTestBase {
     Assert.assertTrue(result);
 
     // read the pid file should get current process id
-    String readPid = SystemUtil.getPidFromFile(new File(pidFileFirstPartition));
-    Assert.assertNotNull(readPid, "readPid is the pid for foo_test.py. should NOT be null");
+//    String readPid = SystemUtil.getPidFromFile(new File(pidFileFirstPartition));
+//    Assert.assertNotNull(readPid, "readPid is the pid for foo_test.py. should NOT be null");
     
     // String name = ManagementFactory.getRuntimeMXBean().getName();
     // String currentPid = name.substring(0,name.indexOf("@"));
@@ -171,8 +204,7 @@ public class TestHelixAgent extends ZkUnitTestBase {
     result =
         ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR,
                                                                                  clusterName));
-    Assert.assertTrue(result);
-    
+    Assert.assertTrue(result);      
 
     System.out.println("END " + clusterName + " at "
         + new Date(System.currentTimeMillis()));


Mime
View raw message