/** * creates a server socket listening on port specified in the object constructor, and then * enters an infinite loop waiting for incoming socket connection requests representing a worker * process attempting to connect to this server, which it handles via the enclosing server's * <CODE>addNewWorkerConnection(s)</CODE> method. */ public void run() { try { ServerSocket ss = new ServerSocket(_port); System.out.println("Srv: Now Accepting Worker Connections"); while (true) { try { Socket s = ss.accept(); System.out.println("Srv: Incoming New Worker Connection to the Network"); System.out.println( "Srv: Thread may have to wait if an init_cmd has not yet arrived from the client"); addNewWorkerConnection(s); System.out.println("Srv: finished adding new worker connection to the _workers"); } catch (Exception e) { utils.Messenger.getInstance() .msg( "PDBTExecSingleCltWrkInitSrv.W2Thread.run(): " + "An error occured while adding new worker connection", 2); // e.printStackTrace(); } } } catch (IOException e) { // e.printStackTrace(); utils.Messenger.getInstance() .msg( "PDBTExecSingleCltWrkInitSrv.W2Thread.run(): " + "Failed to create Server Socket, Server exiting.", 0); System.exit(-1); } }
/** * simply calls the method <CODE>t.runObject(req)</CODE> wrapped in some debug messages, and * returns the result of the call. * * @param req TaskObjectsExecutionRequest * @param t PDBTEW2Listener * @return TaskObjectsExecutionResults * @throws IOException * @throws PDBatchTaskExecutorException */ private TaskObjectsExecutionResults submitWork(TaskObjectsExecutionRequest req, PDBTEW2Listener t) throws IOException, PDBatchTaskExecutorException { utils.Messenger.getInstance() .msg("PDBTExecSingleCltWrkInitSrv.submitWork(req,t): sending request", 1); TaskObjectsExecutionResults res = t.runObject(req); utils.Messenger.getInstance() .msg("PDBTExecSingleCltWrkInitSrv.submitWork(req,t): response received", 1); return res; }
/** * there is an issue with this method: if it is called often enough, the <CODE> * _s.sendUrgentData(0);</CODE> method that it invokes, will force the <CODE>_s</CODE> socket to * close on the other end, at least on Windows systems. This behavior is due to the fact that * OOB data handling is problematic since there are conflicting specifications in TCP. * Therefore, it is required that the method is not called with high frequency (see the <CODE> * PDBTExecSingleCltWrkInitSrv._CHECK_PERIOD_MSECS</CODE> flag in this file.) * * @return true iff the worker is available to accept work according to all evidence. */ private synchronized boolean getAvailability() { boolean res = _isAvail && _s != null && _s.isClosed() == false; if (res && _OK2SendOOB) { // work-around the OOB data issue // last test using OOB sending of data try { _OK2SendOOB = false; // indicates should not send OOB data until set to true _s.sendUrgentData(0); // unfortunately, if this method is called often enough, // it will cause the socket to close??? res = true; } catch (IOException e) { // e.printStackTrace(); utils.Messenger.getInstance() .msg("PDBTExecSingleCltWrkInitSrv.getAvailability(): Socket has been closed", 0); res = false; _isAvail = false; // declare availability to false as well // try graceful exit try { _s.shutdownOutput(); _s.close(); // Now we can close the Socket } catch (IOException e2) { // silently ignore } } } return res; }
/** * creates a server socket listening on the port specified in the parameter of the constructor, * and waits for a single incoming client connection which it handles by invoking the <CODE> * addNewClientConnection(s)</CODE> method of the enclosing server, and then the thread exits. */ public void run() { try { ServerSocket ss = new ServerSocket(_port); System.out.println("Srv: Now Accepting Single Client Connection"); // while (true) { try { Socket s = ss.accept(); System.out.println("Srv: Client Added to the Network"); addNewClientConnection(s); System.out.println("Srv: finished adding client connection"); } catch (Exception e) { // e.printStackTrace(); System.err.println("Client Connection failed, exiting..."); System.exit(-1); } // } } catch (IOException e) { // e.printStackTrace(); utils.Messenger.getInstance() .msg( "PDBTExecSingleCltWrkInitSrv.C2Thread.run(): " + "Failed to create Server Socket, Server exiting.", 0); System.exit(-1); } }
private void secondChance(RRObject obj) throws ClassNotFoundException, IOException { try { obj.runProtocol(_srv, _ois, _oos); } catch (PDBatchTaskExecutorException e2) { utils.Messenger.getInstance() .msg( "PDBTEC2ListenerThread.run(): sending NoWorkerAvailableResponse() to client...", 1); // e.printStackTrace(); _oos.writeObject(new NoWorkerAvailableResponse(((TaskObjectsExecutionRequest) obj)._tasks)); _oos.flush(); } catch (IOException e2) { utils.Messenger.getInstance() .msg("PDBTEC2ListenerThread.run(): sending FailedReply to client...", 1); // e.printStackTrace(); _oos.writeObject(new FailedReply()); _oos.flush(); } }
/** * no need to synchronize any block in this method, as it is already synchronized on _srv since * it's only called by the <CODE>_srv.addNewWorkerConnection(s)</CODE> method. * * @throws IOException */ private void init() throws IOException { // wait until the _initCmd is ready, and send it over the socket while (_initCmd == null) { try { utils.Messenger.getInstance() .msg( "PDBTExecSingleCltWrkInitSrv.PDBTEW2Listener.init(): " + "W2Thread waiting on server to obtain init_cmd from client...", 1); _srv.wait(); // the thread calling this method is already synchronized on _srv. } catch (InterruptedException e) { // e.printStackTrace(); Thread.currentThread().interrupt(); } } _oos.writeObject(_initCmd); _oos.flush(); utils.Messenger.getInstance() .msg("PDBTExecSingleCltWrkInitSrv.PDBTEW2Listener.init(): done.", 1); }
private void processException(Exception e) { // e.printStackTrace(); try { _ois.close(); _oos.close(); _s.close(); } catch (Exception e2) { // e2.printStackTrace(); } finally { synchronized (_srv) { getWorkers().remove(_s); utils.Messenger.getInstance() .msg("PDBTExecSingleCltWrkInitSrv: Worker Network Connection Closed", 0); } _ois = null; _oos = null; _s = null; } }
/** * reads from the input stream the initialization command sent to it, sends back to the client * an <CODE>OKReply</CODE> "ACK" msg, and then enters an infinite loop waiting to read from the * input stream an <CODE>RRObject</CODE> obj that should really be of type <CODE> * TaskObjectsExecutionRequest</CODE>, on which it executes its method <CODE> * obj.runProtocol(_srv,_ois, _oos)</CODE>. */ public void run() { // first, read from socket the worker-initialization object that will // be broadcast for execution to every worker connecting to this server. utils.Messenger mger = utils.Messenger.getInstance(); try { mger.msg("PDBTEC2ListenerThread: waiting to read the init_cmd from client", 1); RRObject initCmd = (RRObject) _ois.readObject(); mger.msg("PDBTEC2ListenerThread: done reading the init_cmd from client", 1); setInitCmd(initCmd); mger.msg("PDBTEC2ListenerThread: done setting the init_cmd", 2); // send back to the clt an "ACK" message _oos.writeObject(new OKReply()); _oos.flush(); mger.msg("PDBTEC2ListenerThread: done sending OKReply through the socket", MIN_PRIORITY); } catch (Exception e) { // client closed connection // e.printStackTrace(); try { _ois.close(); _oos.close(); _s.close(); } catch (Exception e2) { // e2.printStackTrace(); } mger.msg("PDBTEC2ListenerThread: Client Network Connection Closed", 0); System.exit(-1); } while (true) { try { mger.msg("PDBTEC2ListenerThread.run(): waiting to read an RRObject...", 2); // 1. read from socket input RRObject obj = (RRObject) _ois.readObject(); // obj is an TaskObjectsExecutionRequest mger.msg("PDBTEC2ListenerThread.run(): RRObject read", 2); // 2. take appropriate action try { obj.runProtocol(_srv, _ois, _oos); } catch (PDBatchTaskExecutorException e) { mger.msg( "PDBTEC2ListenerThread.run(): calling obj.runProtocol() " + "issued PDBatchTaskExecutorException, will try one more time.", 1); secondChance(obj); } catch ( IOException e) { // worker somehow failed, give srv one more shot, then notify client mger.msg( "PDBTEC2ListenerThread.run(): calling obj.runProtocol() " + "issued IOException, will try one more time.", 1); secondChance(obj); } } catch (Exception e) { // client closed connection // e.printStackTrace(); try { _ois.close(); _oos.close(); _s.close(); } catch (Exception e2) { // e2.printStackTrace(); } mger.msg( "PDBTExecSingleCltWrkInitSrv: Client Network Connection Closed " + "(exception '" + e + "' caught)", 0); System.exit(-1); } } }
TaskObjectsExecutionResults submitWork(Vector originating_clients, TaskObject[] tasks) throws IOException, ClassNotFoundException, PDBatchTaskExecutorException { Set workers2rm = new HashSet(); // Set<PDBTEW2Listener> PDBTEW2Listener t = null; utils.Messenger.getInstance() .msg( "PDBTExecSingleCltWrkInitSrv.submitWork(clts,tasks): " + "finding an available worker connection among " + getNumWorkers() + " known workers", 1); // 1. find a worker (via Round-Robin) synchronized (this) { boolean cont = true; while (cont) { workers2rm.clear(); Iterator sit = getWorkers().keySet().iterator(); while (sit.hasNext()) { Socket s = (Socket) sit.next(); t = (PDBTEW2Listener) getWorkers().get(s); boolean is_avail = t.getAvailability() && !getWorking().contains(t); // the _working set is needed so that submitWork() is guaranteed not // to choose twice the same worker before the worker is done with the // first request. if (is_avail) { cont = false; // break out of the top-level while-loop too getWorking().add(t); break; } else { if (t.isConnectionLost()) workers2rm.add(t); t = null; // reset to null } } // remove any "lost connections" worker listeners Iterator it = workers2rm.iterator(); while (it.hasNext()) getWorkers().remove(it.next()); if (t == null) { // before trying again to find an available worker, wait a while try { wait(_CHECK_PERIOD_MSECS); // wait out the workers for some time } catch (InterruptedException e) { // e.printStackTrace(); Thread.currentThread().interrupt(); // recommended } } } } // synchronized (this) if (t == null) { // failed to find an available thread utils.Messenger.getInstance() .msg("PDBTExecSingleCltWrkInitSrv.submitWork(clt,tasks): no available threads...", 1); throw new PDBatchTaskExecutorException("no available worker or known srv to undertake work"); } utils.Messenger.getInstance() .msg("PDBTExecSingleCltWrkInitSrv.submitWork(clt,tasks): found an available worker", 1); // 2. submit tasks and get back results TaskObjectsExecutionRequest req = new TaskObjectsExecutionRequest(originating_clients, tasks); utils.Messenger.getInstance() .msg( "PDBTExecSingleCltWrkInitSrv.submitWork(clt,tasks): created the TaskObjectsExecutionRequest to send", 1); RRObject res = submitWork(req, t); utils.Messenger.getInstance() .msg( "PDBTExecSingleCltWrkInitSrv.submitWork(tasks): finished running submitWork(req,ois,oos)", 1); synchronized (this) { getWorking().remove(t); // declare worker's availability again notifyAll(); // declare I'm done. With only a single client connected, not of much use. } if (res instanceof TaskObjectsExecutionResults) return (TaskObjectsExecutionResults) res; else { throw new PDBatchTaskExecutorException( "PDBTExecSingleCltWrkInitSrv.submitWork(tasks): worker failed to process tasks."); } }