/**
     * Create a new instance of WorkerThread
     *
     * @param node the FederationNode on which the WorkerMap will be executed
     * @param wm the instance of WorkerMap to be executed
     * @param tg the ThreadGroup to which this thread is attached
     */
    public WorkerThread(FederationNode node, WorkerMap wm, ThreadGroup tg) {
      super(tg, "WorkerThread for: " + node.toString());
      this.node = node;
      this.workerMap = wm;

      this.resultList = new ArrayList<Serializable>();
    }
    /** Overridden run method */
    @Override
    public void run() {
      taskData = getNextTaskData();

      while (taskData != null) {
        try {
          // first initiate a federation request
          ArrayList<Serializable> data = new ArrayList<Serializable>();
          data.add(taskData);

          FederationServiceMapReduceConsumer fsmrc =
              new FederationServiceMapReduceConsumer(workerMap, data);
          FederationRequest req = fsmrc.discover(node.getIpAddress());

          // then start a "heart-beat" thread
          startHeartBeatThread();

          // consume the service
          fsmrc.consume(req);

          // get back the processed data
          ArrayList<Serializable> results = fsmrc.getDataList();
          for (Serializable result : results) resultList.add(result);

          // stop the "heart-beat" thread
          stopHeartBeatThread();

          // and close the connections
          req.closeIt();
        } catch (FederationServiceDiscoveryFailed fe) {
          System.err.println(
              "Exception in Worker thread: " + fe.toString() + ", for node: " + node.toString());
          fe.printStackTrace();
          System.err.println("Will now try to use other free nodes...");

          synchronized (MapReduceControllerFederationImpl.this.freeNodeList) {
            // add to the end of the list
            MapReduceControllerFederationImpl.this.freeNodeList.add(node);

            System.out.println(MapReduceControllerFederationImpl.this.freeNodeList.size());

            // and change to a new node from beginning of the list
            // that is not the same as the current node, if none is
            // found keep trying the same node
            FederationNode newNode = null;
            for (FederationNode fn : MapReduceControllerFederationImpl.this.freeNodeList) {
              if (!fn.getIpAddress().equals(node.getIpAddress())) {
                newNode = fn;
                break;
              } // end if
            } // end for

            if (newNode == null) {
              node = MapReduceControllerFederationImpl.this.freeNodeList.get(0);
            } else {
              node = newNode;
            } // end if
          }

          System.err.println("Will be using: " + node);

          // there was some problem with processing
          // this data, so save it for other nodes
          pushBackTaskData(taskData);
        } catch (Exception ex) {
          System.err.println(
              "Exception in Worker thread: " + ex.toString() + ", for node: " + node.toString());
          ex.printStackTrace();

          // there was some problem with processing
          // this data, so save it for other nodes
          pushBackTaskData(taskData);

          try {
            // sleep for quite some time
            sleep(10000);
          } catch (InterruptedException ignored) {
          }
        } // end of try .. catch block

        taskData = getNextTaskData();
      } // end while

      // if we are done we add our selfs in the free node list
      // so as to make us available at a later stage, if some node
      // breaks down
      synchronized (MapReduceControllerFederationImpl.this.freeNodeList) {
        MapReduceControllerFederationImpl.this.freeNodeList.add(node);
      }
    }