public boolean addServer(GearmanJobServerConnection conn)
      throws IllegalArgumentException, IllegalStateException {

    if (conn == null) {
      throw new IllegalArgumentException("Connection can not be null");
    }
    // this is a sub-optimal way to look for dups, but addJobServer
    // ops should be infrequent enough that this should be a big penalty
    for (GearmanJobServerSession sess : sessionMap.values()) {
      if (sess.getConnection().equals(conn)) {
        return true;
      }
    }

    GearmanJobServerSession session = new GearmanJobServerSession(conn);
    if (ioAvailable == null) {
      try {
        ioAvailable = Selector.open();
      } catch (IOException ioe) {
        LOG.warn("Failed to connect to job server " + conn + ".", ioe);
        return false;
      }
    }
    try {
      session.initSession(ioAvailable, this);
    } catch (IOException ioe) {
      LOG.warn("Failed to initialize session with job server " + conn + ".", ioe);
      return false;
    }
    SelectionKey key = session.getSelectionKey();
    if (key == null) {
      String msg =
          "Session "
              + session
              + " has a null "
              + "selection key. Server will not be added to worker.";
      LOG.warn(msg);
      throw new IllegalStateException(msg);
    }
    sessionMap.put(key, session);

    GearmanPacket p =
        new GearmanPacketImpl(
            GearmanPacketMagic.REQ, GearmanPacketType.SET_CLIENT_ID, ByteUtils.toUTF8Bytes(id));
    session.submitTask(new GearmanTask(p));

    for (FunctionDefinition def : functionMap.values()) {
      p = generateCanDoPacket(def);
      session.submitTask(new GearmanTask(p)); // NOPMD
    }

    p = new GearmanPacketImpl(GearmanPacketMagic.REQ, getGrabJobPacketType(), new byte[0]);
    GearmanTask gsr = new GearmanTask(new GrabJobEventHandler(session), p);
    taskMap.put(session, gsr);
    session.submitTask(gsr);

    LOG.debug("Added server " + conn + " to worker " + this);
    return true;
  }
  private GearmanPacket generateCanDoPacket(FunctionDefinition def) {
    GearmanPacketType pt = GearmanPacketType.CAN_DO;
    byte[] data = null;
    byte[] name = ByteUtils.toUTF8Bytes(def.getFactory().getFunctionName());
    long timeout = def.getTimeout();

    if (timeout > 0) {
      pt = GearmanPacketType.CAN_DO_TIMEOUT;
      byte[] to = ByteUtils.toUTF8Bytes(String.valueOf(timeout));
      data = new byte[name.length + to.length + 1];
      System.arraycopy(name, 0, data, 0, name.length);
      data[name.length] = ByteUtils.NULL;
      System.arraycopy(to, 0, data, name.length + 1, to.length);
    } else {
      data = name;
    }
    return new GearmanPacketImpl(GearmanPacketMagic.REQ, pt, data);
  }
 public void unregisterFunction(String functionName) {
   functionMap.remove(functionName);
   sendToAll(
       new GearmanPacketImpl(
           GearmanPacketMagic.REQ,
           GearmanPacketType.CANT_DO,
           ByteUtils.toUTF8Bytes(functionName)));
   LOG.debug("Worker " + this + " has unregistered function " + functionName);
 }
 public void setWorkerID(String id) throws IllegalArgumentException {
   if (id == null) {
     throw new IllegalArgumentException("Worker ID may not be null");
   }
   this.id = id;
   sendToAll(
       new GearmanPacketImpl(
           GearmanPacketMagic.REQ, GearmanPacketType.SET_CLIENT_ID, ByteUtils.toUTF8Bytes(id)));
 }
 public static void main(String[] args) {
   if (args.length == 0 || args.length > 3) {
     usage();
     return;
   }
   String host = Constants.GEARMAN_DEFAULT_TCP_HOST;
   int port = Constants.GEARMAN_DEFAULT_TCP_PORT;
   byte[] payload = ByteUtils.toUTF8Bytes(args[args.length - 1]);
   for (String arg : args) {
     if (arg.startsWith("-h")) {
       host = arg.substring(2);
     } else if (arg.startsWith("-p")) {
       port = Integer.parseInt(arg.substring(2));
     }
   }
   DigestClient dc = new DigestClient(host, port);
   byte[] md5 = dc.digest(payload);
   System.out.println(ByteUtils.toHex(md5)); // NOPMD
   dc.shutdown();
 }
  public void work() {
    if (!state.equals(State.IDLE)) {
      throw new IllegalStateException(
          "Can not call work while worker " + "is running or shutting down");
    }

    state = State.RUNNING;
    // a map keeping track of sessions with connection errors
    // (to avoid printing an error about them in every reconnect attempt)
    Map<GearmanJobServerSession, Boolean> havingConnectionError =
        new HashMap<GearmanJobServerSession, Boolean>();

    while (isRunning()) {

      // look for sessions which have been disconnected and attempt to reconnect.
      for (Iterator<GearmanJobServerSession> iter = sessionMap.values().iterator();
          iter.hasNext(); ) {
        GearmanJobServerSession sess = iter.next();
        if (!sess.isInitialized()) {
          try {

            // reconnect, unregister old selection key and register new one
            SelectionKey oldKey = sess.isInitialized() ? sess.getSelectionKey() : null;
            sess.initSession(ioAvailable, this);
            if (oldKey != null) {
              iter.remove();
            }
            sessionMap.put(sess.getSelectionKey(), sess);

            // register all functions with the newly reconnected server
            for (FunctionDefinition d : functionMap.values()) {
              GearmanTask gsr = new GearmanTask(null, generateCanDoPacket(d));
              sess.submitTask(gsr);
            }

            GearmanPacket p =
                new GearmanPacketImpl(
                    GearmanPacketMagic.REQ,
                    GearmanPacketType.SET_CLIENT_ID,
                    ByteUtils.toUTF8Bytes(id));
            sess.submitTask(new GearmanTask(p));

            GearmanTask sessTask =
                new GearmanTask(
                    new GrabJobEventHandler(sess),
                    new GearmanPacketImpl(
                        GearmanPacketMagic.REQ, getGrabJobPacketType(), new byte[0]));
            sess.submitTask(sessTask);
            sess.driveSessionIO();

            // log reconnection message
            if (havingConnectionError.get(sess)) {
              LOG.info("Re-established connection to " + sess.getConnection().toString());
            }
            havingConnectionError.put(sess, false);
          } catch (IOException e) {
            if (!havingConnectionError.get(sess)) {
              LOG.warn("Error connecting to " + sess + ", will keep trying..");
            }

            havingConnectionError.put(sess, true);

            try {
              Thread.sleep(50);
            } catch (InterruptedException e1) {
            }
          }
        } else {
          havingConnectionError.put(sess, false);
        }
      }

      for (GearmanJobServerSession sess : sessionMap.values()) {
        // if still disconnected, skip
        if (!sess.isInitialized()) {
          continue;
        }
        int interestOps = SelectionKey.OP_READ;
        if (sess.sessionHasDataToWrite()) {
          interestOps |= SelectionKey.OP_WRITE;
        }
        sess.getSelectionKey().interestOps(interestOps);
      }
      try {
        ioAvailable.select(1);
      } catch (IOException io) {
        LOG.warn("Receieved IOException while" + " selecting for IO", io);
      }

      for (SelectionKey key : ioAvailable.selectedKeys()) {
        GearmanJobServerSession sess = sessionMap.get(key);
        if (sess == null) {
          LOG.warn("Worker does not have " + "session for key " + key);
          continue;
        }
        if (!sess.isInitialized()) {
          continue;
        }
        try {
          GearmanTask sessTask = taskMap.get(sess);
          if (sessTask == null) {
            sessTask =
                new GearmanTask( // NOPMD
                    new GrabJobEventHandler(sess),
                    new GearmanPacketImpl(
                        GearmanPacketMagic.REQ, getGrabJobPacketType(), new byte[0]));
            taskMap.put(sess, sessTask);
            sess.submitTask(sessTask);
            LOG.debug(
                "Worker: "
                    + this
                    + " submitted a "
                    + sessTask.getRequestPacket().getPacketType()
                    + " to session: "
                    + sess);
          }
          sess.driveSessionIO();
          // For the time being we will execute the jobs synchronously
          // in the future, I expect to change this.
          if (!functionList.isEmpty()) {
            GearmanFunction fun = functionList.remove();
            submitFunction(fun);
            statistics();
          }

        } catch (IOException ioe) {
          LOG.warn("Received IOException while driving" + " IO on session " + sess, ioe);
          sess.closeSession();
          continue;
        }
      }
    }

    shutDownWorker(true);
  }
 private GearmanPacketMagic(String kind) {
   this.name = new byte[1 + kind.length()];
   this.name[0] = 0;
   byte[] bytes = ByteUtils.toUTF8Bytes(kind);
   System.arraycopy(bytes, 0, this.name, 1, kind.length());
 }