/**
  * 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.");
   }
 }