summaryrefslogblamecommitdiffstats
path: root/gearman/controllerWorker/ControllerWorker/Shutdown.java
blob: 2558d64b457486cf11b7b53bad95269b82a121be (plain) (tree)
1
2
3
4
5
6
7
8




                                               
                      
                         
                                 






















                                                        
                              
                                    

                                                      

                                                          
                                                              
                                                    
                                                 
                                                
                                                        






                                                                   

                                                                                
                                                                   

                                                                       
                                                                           
                                                                 
                                                              
                                                             





                                                                                 
                                                






                                                                          
                                                 
                                                                                            





















                                                                                
                                                        







                                                                           



                                                                          
 

                                             
 
                                      
 














                                                                                                     
                                                                                            

                                                                                                     
 











                                                                                                                           
                                                                






                                                                                                                                             




                                                                                          
 
                                      
 
                               
                                            
 
                                      
 
                               













                                                                                                     
                                                                                            







                                                                                                             
 










                                                                                                              
                                                                










                                                                                                                                                     

                                                                                         


                                                 
 
                                      
 
                               
                                                 
 
                                      
 
                               








                                                                                                 


                                                                                                     
                                                                                            















                                                                                                                                                 



















                                                                               



                                                                                            
                                                                    
                                                                                      

                                                                      









                                                                                                             
                                                                                                    















                                                                                                                                                             
                                                                        
                                                                                  








                                                                                                                                                                    





                                                                                              



                                                                                                         


                                                                                  
 
                                      
 
                               
                                           



                                      
                                                                        
 
                                                    
                                                                                  
                                                                             
 

                                                                                         





                                                                                                     
                                                                                            






                                                                                                               
                                                                                                



                                                                                                                  
                                                                                                
                                                                 

                                                                                            






                                                                                                                                                   
                                                                                        
                                                         






                                                 
                                                                            



                                      
                                                                                    
 

                                      
                                
                                                                                          
 
                                      
 
                         
                                                 
                                                   
                                                        


























                                                                                       
 
                                                          






                                                                                      
                                                       
                                           
 
                                                       
         
 



                                                                  

                                                                               

                                          
                                                            
                                                
 
                                                            
         
 







                                                                                       
                                                                



                                                        
 
                                                         


                                                                  

                                                                                     

                                          

                                                      
 
                                                      

         



                                                                     

         



                                                                  








                                               



                                                             
 
package ControllerWorker;

import java.io.IOException;
import java.lang.Thread;
import java.util.concurrent.ExecutionException;
import java.util.Date;
import java.util.HashMap;
import java.util.StringTokenizer;
import java.util.Vector;

import org.gearman.client.GearmanClient;
import org.gearman.client.GearmanClientImpl;
import org.gearman.client.GearmanJob;
import org.gearman.client.GearmanJobImpl;
import org.gearman.client.GearmanJobResult;
import org.gearman.client.GearmanJobStatus;
import org.gearman.common.GearmanJobServerConnection;
import org.gearman.common.GearmanNIOJobServerConnection;
import org.gearman.util.ByteUtils;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

public class Shutdown extends Thread {
	private long beginTime;
	private long timeTaken;
	private long timeLeft;
	private Boolean finished;
	private Boolean error;
	private final int updateRate;
	private final long updatePeriod;
	private long waitTime;
	private String[] statusText;

	private HashMap<Integer, GearmanJob> pingJobs;
	private HashMap<Integer, GearmanJob> whoJobs;
	private HashMap<Integer, GearmanJob> shutdownJobs;
	private HashMap<Integer, GearmanJob> pingShutdownJobs;
	private HashMap<Integer, GearmanJob> psJobs;
	private HashMap<Integer, Integer> status;
	private HashMap<Integer, String> errors;
	private HashMap<Integer, Long> pingShutdownTime;

	private Vector<HashMap<String, String>> clients;

	private final GearmanJobServerConnection gearmanConnection;
	private GearmanClient gearmanClient;

	public Shutdown(String serverAddress, int port,
			Vector<HashMap<String, String>> clients, int updateRate,
			long waitTime) {
		this.pingJobs = new HashMap<Integer, GearmanJob>();
		this.whoJobs = new HashMap<Integer, GearmanJob>();
		this.shutdownJobs = new HashMap<Integer, GearmanJob>();
		this.pingShutdownJobs = new HashMap<Integer, GearmanJob>();
		this.psJobs = new HashMap<Integer, GearmanJob>();
		this.status = new HashMap<Integer, Integer>();
		this.errors = new HashMap<Integer, String>();
		this.updateRate = updateRate; // updates per second
		this.updatePeriod = 1000000000L / this.updateRate; // nanoseconds
		this.gearmanConnection = new GearmanNIOJobServerConnection(
				serverAddress, port);
		this.gearmanClient = new GearmanClientImpl();
		gearmanClient.addJobServer(this.gearmanConnection);
		this.waitTime = waitTime * 1000;
		this.clients = clients;
		for (HashMap<String, String> client : clients) {
			int clientID = Integer.parseInt(client.get("id"));
			status.put(clientID, 0); // no work
		}
		this.finished = false;
		this.error = false;
		this.statusText = new String[14];
		this.statusText[0] = "The shutdown process of the client has been started.";
	}

	public void run() {
		workerLoop();
	}

	private void workerLoop() {
		Boolean run = true;
		while (run) {
			try {
				beginTime = System.nanoTime();
				run = update();
				timeTaken = System.nanoTime() - beginTime;
				timeLeft = (updatePeriod - timeTaken) / 1000000;
				if (timeLeft < 10)
					timeLeft = 10;
				Thread.sleep(timeLeft);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		this.finished = true;
		System.out.println("Shutdown finished");
	}

	private Boolean update() throws IllegalStateException, IOException,
			InterruptedException, ExecutionException {
		Boolean allFinished = false;

		for (HashMap<String, String> client : clients) {
			String ipAddress = client.get("ip");
			int clientID = Integer.parseInt(client.get("id"));
			int clientStatus = status.get(clientID);

			switch (clientStatus) {

			case 0:
				ping(client);

				break;

			case 1:
				GearmanJob pingJob = pingJobs.get(clientID);

				if (pingJob != null) {
					GearmanJobStatus jobStatus = gearmanClient
							.getJobStatus(pingJob);

					if (!jobStatus.isKnown() && pingJob.isDone()) {
						GearmanJobResult pingJobRes = pingJob.get();
						String result = ByteUtils.fromUTF8Bytes(pingJobRes
								.getResults());

						if (result != "") {
							JSONObject resultObj = (JSONObject) JSONValue
									.parse(result);
							if (!resultObj.containsKey("err")) {
								String alive = resultObj.get("alive")
										.toString();

								if (alive.equals("true")) {
									System.out.println(ipAddress + " alive");
									status.put(clientID, 2); // alive, check
									// Users
									pingJobs.remove(clientID);
								} else {
									System.out
											.println(ipAddress + " not alive");
									// not alive, go in successState
									status.put(clientID, 13);
									pingJobs.remove(clientID);
								}
							} else {
								System.out.println(ipAddress
										+ " Cannot send the ping message.");
								this.errors
										.put(clientID,
												"Sending the ping message has been failed.");
								// sending the ping message has been failed
								status.put(clientID, 12);
								pingJobs.remove(clientID);
							}
						}
					}
				}

				break;

			case 2:
				who(client);

				break;

			case 3:
				GearmanJob whoJob = whoJobs.get(clientID);

				if (whoJob != null) {
					GearmanJobStatus jobStatus = gearmanClient
							.getJobStatus(whoJob);

					if (!jobStatus.isKnown() && whoJob.isDone()) {
						GearmanJobResult whoJobRes = whoJob.get();
						String result = ByteUtils.fromUTF8Bytes(whoJobRes
								.getResults());

						if (result != "") {
							JSONObject resultObj = (JSONObject) JSONValue
									.parse(result);
							if (!resultObj.containsKey("err")) {
								String rawoutput = resultObj.get("rawoutput")
										.toString();
								StringTokenizer str = new StringTokenizer(
										rawoutput, " ");
								String user = "";
								if (str.hasMoreTokens()) {
									user = str.nextToken();
								}

								if (user.isEmpty()) {
									System.out.println(ipAddress
											+ " right User");
									status.put(clientID, 4); // right user
									whoJobs.remove(clientID);
								} else {
									System.out.println(ipAddress
											+ " wrong User");
									status.put(clientID, 9); // wrong user
									whoJobs.remove(clientID);
								}
							} else {
								System.out
										.println(ipAddress
												+ " Cannot check if a user is logged in.");
								this.errors
										.put(clientID,
												"The check if a user is logged in has been failed.");
								/*
								 * cannot check if a user is logged in, go in
								 * errorState
								 */
								status.put(clientID, 12);
								whoJobs.remove(clientID);
							}
						}
					}
				}

				break;

			case 4:
				shutdown(client);

				break;

			case 5:
				GearmanJob shutdownJob = shutdownJobs.get(clientID);
				if (shutdownJob != null) {
					GearmanJobStatus jobStatus = gearmanClient
							.getJobStatus(shutdownJob);

					if (!jobStatus.isKnown() && shutdownJob.isDone()) {
						GearmanJobResult wolJobRes = shutdownJob.get();
						String result = ByteUtils.fromUTF8Bytes(wolJobRes
								.getResults());
						if (result != "") {
							JSONObject resultObj = (JSONObject) JSONValue
									.parse(result);
							if (!resultObj.containsKey("err")) {
								System.out.println(ipAddress
										+ " Shutdown command send");
								status.put(clientID, 6); // shutdown command
								// send
								shutdownJobs.remove(clientID);
							} else {
								System.out.println(ipAddress
										+ " Cannot send shutdown command");
								this.errors
										.put(clientID,
												"Sending the shutdown command has been failed.");
								// cannot send shutdown command, go in
								// errorState
								status.put(clientID, 12);
								shutdownJobs.remove(clientID);
							}
						}
					}
				}

				break;

			case 6:
				Date date = new Date();
				Long timestamp = date.getTime();
				pingShutdownTime.put(clientID, timestamp);
				status.put(clientID, 7); // ping after shutdown

				break;

			case 7:
				pingShutdown(client);

				break;

			case 8:
				GearmanJob pingJobShutdown = pingShutdownJobs.get(clientID);
				if (pingJobShutdown != null) {
					Date currentDate = new Date();
					Long currentTimestamp = currentDate.getTime();
					// wait 2 min until shutdown
					Long expectedTimestamp = this.pingShutdownTime
							.get(clientID)
							+ waitTime;
					if (expectedTimestamp >= currentTimestamp) {
						GearmanJobStatus jobStatus = gearmanClient
								.getJobStatus(pingJobShutdown);
						if (!jobStatus.isKnown() && pingJobShutdown.isDone()) {
							GearmanJobResult pingJobRes = pingJobShutdown.get();
							String result = ByteUtils.fromUTF8Bytes(pingJobRes
									.getResults());
							if (result != "") {
								JSONObject resultObj = (JSONObject) JSONValue
										.parse(result);
								if (!resultObj.containsKey("err")) {
									String alive = resultObj.get("alive")
											.toString();
									if (alive.equals("false")) {
										System.out
												.println(ipAddress
														+ " is alive after shutdown. Ping again...");
										// alive, ping again
										status.put(clientID, 7);
										pingShutdownJobs.remove(clientID);
									} else {
										System.out
												.println("not alive after shutdown"
														+ ipAddress);
										// go in successState
										status.put(clientID, 13);
									}
								} else {
									System.out
											.println(ipAddress
													+ " Cannot send the ping after shutdown message.");
									this.errors
											.put(clientID,
													"Sending the ping after shutdown message has been failed.");
									// sending the ping after shutdown message
									// has been failed
									status.put(clientID, 12);
									pingJobs.remove(clientID);
								}
							}
						}
					} else {
						System.out.println(ipAddress
								+ " is alive after shutdown");
						this.errors.put(clientID,
								"Client is still alive after shutdown.");
						// still alive, go in errorState
						status.put(clientID, 12);
						pingShutdownJobs.remove(clientID);
					}
				}

				break;

			case 9:
				ps(client);

				break;

			case 10:
				GearmanJob psJob = psJobs.get(clientID);

				if (psJob != null) {
					GearmanJobStatus jobStatus = gearmanClient
							.getJobStatus(psJob);

					if (!jobStatus.isKnown() && psJob.isDone()) {
						GearmanJobResult whoJobRes = psJob.get();
						String result = ByteUtils.fromUTF8Bytes(whoJobRes
								.getResults());

						if (result != "") {
							JSONObject resultObj = (JSONObject) JSONValue
									.parse(result);
							if (!resultObj.containsKey("err")) {
								String rawoutput = resultObj.get("rawoutput")
										.toString();
								System.out.println(rawoutput);
								if (rawoutput.equals("is working")) {
									System.out.println(ipAddress
											+ " is working");
									status.put(clientID, 11); // is working
									psJobs.remove(clientID);
								} else {
									System.out.println(ipAddress
											+ " is not working");
									status.put(clientID, 4); // is not working
									psJobs.remove(clientID);
								}
							} else {
								System.out.println(ipAddress
										+ " Cannot check if user is working.");
								this.errors
										.put(clientID,
												"The check if a user is working has been failed.");
								// cannot check if user is working, go in
								// errorState
								status.put(clientID, 12);
								psJobs.remove(clientID);
							}
						}
					}
				}

				break;

			case 11:
				System.out.println("User is working Logik");

				break;

			case 12:
				System.out.println("Shutdown failed"); // errorState

				break;

			case 13:
				System.out.println("Shutdown successful"); // successState

				break;

			}
			if (clientStatus == 12) {
				allFinished = true;
			} else if (clientStatus == 13) {
				allFinished = true;
				this.error = true;
			} else {
				allFinished = false;
			}
		}

		if (allFinished) {
			return false;
		} else {
			return true;
		}
	}

	private void ping(HashMap<String, String> client) {
		String ipAddress = client.get("ip");
		int clientID = Integer.parseInt(client.get("id"));

		GearmanJob job = GearmanJobImpl.createJob("ping", ipAddress.getBytes(),
				"ping" + clientID);
		gearmanClient.submit(job);

		status.put(clientID, 1); // ping started
		pingJobs.put(clientID, job);

		System.out.println("ping " + ipAddress);
	}

	private void who(HashMap<String, String> client) {
		String ipAddress = client.get("ip");
		int clientID = Integer.parseInt(client.get("id"));

		GearmanJob job = GearmanJobImpl.createJob("who", ipAddress.getBytes(),
				"who" + clientID);
		gearmanClient.submit(job);

		status.put(clientID, 3); // who started
		whoJobs.put(clientID, job);

		System.out.println("who " + ipAddress);
	}

	private void shutdown(HashMap<String, String> client) {
		String ipAddress = client.get("ip");
		int clientID = Integer.parseInt(client.get("id"));

		GearmanJob job = GearmanJobImpl.createJob("shutdown", ipAddress
				.getBytes(), "shutdown" + clientID);
		gearmanClient.submit(job);

		status.put(clientID, 5); // shutdown started
		shutdownJobs.put(clientID, job);

		System.out.println("shutdown " + ipAddress);
	}

	private void pingShutdown(HashMap<String, String> client) {
		String ipAddress = client.get("ip");
		int clientID = Integer.parseInt(client.get("id"));

		GearmanJob job = GearmanJobImpl.createJob("ping", ipAddress.getBytes(),
				"ping" + clientID);
		gearmanClient.submit(job);

		status.put(clientID, 8); // pingShutdown started
		pingShutdownJobs.put(clientID, job);

		System.out.println("ping " + ipAddress);
	}

	private void ps(HashMap<String, String> client) {
		String ipAddress = client.get("ip");
		int clientID = Integer.parseInt(client.get("id"));

		GearmanJob job = GearmanJobImpl.createJob("ps", ipAddress.getBytes(),
				"ps" + clientID);
		gearmanClient.submit(job);

		status.put(clientID, 9); // ps started
		psJobs.put(clientID, job);

		System.out.println("ps " + ipAddress);
	}

	public String getStatusText(HashMap<String, String> client) {
		int clientID = Integer.parseInt(client.get("id"));
		int clientStatus = this.status.get(clientID);
		return this.statusText[clientStatus];
	}

	public String getError(HashMap<String, String> client) {
		int clientID = Integer.parseInt(client.get("id"));
		String clientError = this.errors.get(clientID);
		return clientError;
	}

	public Boolean isFinished() {
		return finished;
	}

	public Boolean isFinishedWithErrors() {
		return finished && error;
	}

	public Vector<HashMap<String, String>> getClients() {
		return clients;
	}
}