예제 #1
0
파일: RPC.java 프로젝트: patricktoohey/h2o
 // Got a response UDP packet, or completed a large TCP answer-receive.
 // Install it as The Answer packet and wake up anybody waiting on an answer.
 protected void response(AutoBuffer ab) {
   assert _tasknum == ab.getTask();
   if (_done) {
     ab.close();
     return;
   } // Ignore duplicate response packet
   int flag = ab.getFlag(); // Must read flag also, to advance ab
   if (flag == SERVER_TCP_SEND) {
     ab.close();
     return;
   } // Ignore UDP packet for a TCP reply
   assert flag == SERVER_UDP_SEND;
   synchronized (this) { // Install the answer under lock
     if (_done) {
       ab.close();
       return;
     } // Ignore duplicate response packet
     _dt.read(ab); // Read the answer (under lock?)
     ab.close(); // Also finish the read (under lock?)
     _dt.onAck(); // One time only execute (before sending ACKACK)
     _done = true;
     UDPTimeOutThread.PENDING.remove(this);
     TASKS.remove(_tasknum); // Flag as task-completed, even if the result is null
     notifyAll(); // And notify in any case
   }
 }
예제 #2
0
파일: RPC.java 프로젝트: patricktoohey/h2o
 // Attempt to cancel job
 public final boolean cancel(boolean mayInterruptIfRunning) {
   boolean did = false;
   synchronized (this) { // Install the answer under lock
     if (!isCancelled()) {
       did = true; // Did cancel (was not canceled already)
       _target = null; // Flag as canceled
       UDPTimeOutThread.PENDING.remove(this);
       TASKS.remove(_tasknum);
     }
     notifyAll(); // notify in any case
   }
   return did;
 }
예제 #3
0
파일: RPC.java 프로젝트: patricktoohey/h2o
  // Make an initial RPC, or re-send a packet.  Always called on 1st send; also
  // called on a timeout.
  public synchronized RPC<V> call() {
    // Keep a global record, for awhile
    TASKS.put(_tasknum, this);
    // We could be racing timeouts-vs-replies.  Blow off timeout if we have an answer.
    if (isDone()) {
      TASKS.remove(_tasknum);
      return this;
    }
    // Default strategy: (re)fire the packet and (re)start the timeout.  We
    // "count" exactly 1 failure: just whether or not we shipped via TCP ever
    // once.  After that we fearlessly (re)send UDP-sized packets until the
    // server replies.

    // Pack classloader/class & the instance data into the outgoing
    // AutoBuffer.  If it fits in a single UDP packet, ship it.  If not,
    // finish off the current AutoBuffer (which is now going TCP style), and
    // make a new UDP-sized packet.  On a re-send of a TCP-sized hunk, just
    // send the basic UDP control packet.
    if (!_sentTcp) {
      // Ship the UDP packet with clazz name to execute
      // totally replace me with Michal's enums!!!
      UDP.udp fjq = _dt.isHighPriority() ? UDP.udp.exechi : UDP.udp.execlo;
      AutoBuffer ab = new AutoBuffer(_target).putTask(fjq, _tasknum);
      ab.put1(CLIENT_UDP_SEND).put(_dt).close();
      if (ab.hasTCP()) _sentTcp = true;
    }

    // Double retry until we exceed existing age.  This is the time to delay
    // until we try again.  Note that we come here immediately on creation,
    // so the first doubling happens before anybody does any waiting.  Also
    // note the generous 5sec cap: ping at least every 5 sec.
    _retry += (_retry < 5000) ? _retry : 5000;
    // Put self on the "TBD" list of tasks awaiting Timeout.
    // So: dont really 'forget' but remember me in a little bit.
    assert !UDPTimeOutThread.PENDING.contains(this);
    UDPTimeOutThread.PENDING.add(this);
    return this;
  }