예제 #1
0
 public static Unicast2Header createXmitReqHeader(long low, long high) {
   if (low > high)
     throw new IllegalArgumentException("low (" + low + " needs to be <= high (" + high + ")");
   Unicast2Header retval = new Unicast2Header(XMIT_REQ, low);
   retval.high_seqno = high;
   return retval;
 }
예제 #2
0
  /**
   * We need to resend our first message with our conn_id
   *
   * @param sender
   * @param seqno Resend the non null messages in the range [lowest .. seqno]
   */
  protected void handleResendingOfFirstMessage(Address sender, long seqno) {
    if (log.isTraceEnabled())
      log.trace(local_addr + " <-- SEND_FIRST_SEQNO(" + sender + "," + seqno + ")");
    SenderEntry entry = send_table.get(sender);
    Table<Message> win = entry != null ? entry.sent_msgs : null;
    if (win == null) {
      if (log.isErrorEnabled())
        log.error(local_addr + ": sender window for " + sender + " not found");
      return;
    }

    boolean first_sent = false;
    for (long i = win.getLow() + 1; i <= seqno; i++) {
      Message rsp = win.get(i);
      if (rsp == null) continue;
      if (first_sent) {
        down_prot.down(new Event(Event.MSG, rsp));
      } else {
        first_sent = true;
        // We need to copy the UnicastHeader and put it back into the message because Message.copy()
        // doesn't copy
        // the headers and therefore we'd modify the original message in the sender retransmission
        // window
        // (https://jira.jboss.org/jira/browse/JGRP-965)
        Message copy = rsp.copy();
        Unicast2Header hdr = (Unicast2Header) copy.getHeader(this.id);
        Unicast2Header newhdr = hdr.copy();
        newhdr.first = true;
        copy.putHeader(this.id, newhdr);
        down_prot.down(new Event(Event.MSG, copy));
      }
    }
  }
예제 #3
0
 public static Unicast2Header createStableHeader(short conn_id, long low, long high) {
   if (low > high)
     throw new IllegalArgumentException("low (" + low + ") needs to be <= high (" + high + ")");
   Unicast2Header retval = new Unicast2Header(STABLE, low);
   retval.high_seqno = high;
   retval.conn_id = conn_id;
   return retval;
 }
예제 #4
0
 public void retransmit(long first_seqno, long last_seqno, Address sender) {
   if (last_seqno < first_seqno) return;
   Unicast2Header hdr = Unicast2Header.createXmitReqHeader(first_seqno, last_seqno);
   Message xmit_req = new Message(sender, null, null);
   xmit_req.putHeader(this.id, hdr);
   down_prot.down(new Event(Event.MSG, xmit_req));
 }
예제 #5
0
  protected void sendStableMessage(Address dest, short conn_id, long low, long high) {
    Message stable_msg = new Message(dest, null, null);
    Unicast2Header hdr = Unicast2Header.createStableHeader(conn_id, low, high);
    stable_msg.putHeader(this.id, hdr);
    stable_msg.setFlag(Message.OOB);
    if (log.isTraceEnabled()) {
      StringBuilder sb = new StringBuilder();
      sb.append(local_addr)
          .append(" --> STABLE(")
          .append(dest)
          .append(": ")
          .append(low)
          .append("-")
          .append(high)
          .append(", conn_id=")
          .append(conn_id)
          .append(")");
      log.trace(sb.toString());
    }
    down_prot.down(new Event(Event.MSG, stable_msg));

    ReceiverEntry entry = recv_table.get(dest);
    NakReceiverWindow win = entry != null ? entry.received_msgs : null;
    if (win != null) win.stable(win.getHighestDelivered());
  }
예제 #6
0
  /**
   * We need to resend our first message with our conn_id
   *
   * @param sender
   * @param seqno Resend messages in the range [lowest .. seqno]
   */
  private void handleResendingOfFirstMessage(Address sender, long seqno) {
    if (log.isTraceEnabled())
      log.trace(local_addr + " <-- SEND_FIRST_SEQNO(" + sender + "," + seqno + ")");
    SenderEntry entry = send_table.get(sender);
    AckSenderWindow win = entry != null ? entry.sent_msgs : null;
    if (win == null) {
      if (log.isErrorEnabled())
        log.error(local_addr + ": sender window for " + sender + " not found");
      return;
    }
    long lowest = win.getLowest();
    Message rsp = win.get(lowest);
    if (rsp == null) return;

    // We need to copy the UnicastHeader and put it back into the message because Message.copy()
    // doesn't copy
    // the headers and therefore we'd modify the original message in the sender retransmission
    // window
    // (https://jira.jboss.org/jira/browse/JGRP-965)
    Message copy = rsp.copy();
    Unicast2Header hdr = (Unicast2Header) copy.getHeader(this.id);
    Unicast2Header newhdr = hdr.copy();
    newhdr.first = true;
    copy.putHeader(this.id, newhdr);

    if (log.isTraceEnabled()) {
      StringBuilder sb = new StringBuilder();
      sb.append(local_addr)
          .append(" --> DATA(")
          .append(copy.getDest())
          .append(": #")
          .append(newhdr.seqno)
          .append(", conn_id=")
          .append(newhdr.conn_id);
      if (newhdr.first) sb.append(", first");
      sb.append(')');
      log.trace(sb);
    }
    down_prot.down(new Event(Event.MSG, copy));

    if (++lowest > seqno) return;
    for (long i = lowest; i <= seqno; i++) {
      rsp = win.get(i);
      if (rsp != null) down_prot.down(new Event(Event.MSG, rsp));
    }
  }
예제 #7
0
 private void sendRequestForFirstSeqno(Address dest, long seqno_received) {
   Message msg = new Message(dest);
   msg.setFlag(Message.OOB);
   Unicast2Header hdr = Unicast2Header.createSendFirstSeqnoHeader(seqno_received);
   msg.putHeader(this.id, hdr);
   if (log.isTraceEnabled())
     log.trace(local_addr + " --> SEND_FIRST_SEQNO(" + dest + "," + seqno_received + ")");
   down_prot.down(new Event(Event.MSG, msg));
 }
예제 #8
0
 public void retransmit(SeqnoList missing, Address sender) {
   Unicast2Header hdr = Unicast2Header.createXmitReqHeader();
   Message retransmit_msg = new Message(sender, null, missing);
   retransmit_msg.setFlag(Message.OOB);
   if (log.isTraceEnabled())
     log.trace(local_addr + ": sending XMIT_REQ (" + missing + ") to " + sender);
   retransmit_msg.putHeader(this.id, hdr);
   down_prot.down(new Event(Event.MSG, retransmit_msg));
   xmit_reqs_sent.addAndGet(missing.size());
 }
예제 #9
0
 protected void sendStableMessage(Address dest, short conn_id, long hd, long hr) {
   Message stable_msg = new Message(dest, null, null);
   Unicast2Header hdr = Unicast2Header.createStableHeader(conn_id, hd, hr);
   stable_msg.putHeader(this.id, hdr);
   stable_msg.setFlag(Message.OOB);
   if (log.isTraceEnabled()) {
     StringBuilder sb = new StringBuilder();
     sb.append(local_addr)
         .append(" --> STABLE(")
         .append(dest)
         .append(": ")
         .append(hd)
         .append("-")
         .append(hr)
         .append(", conn_id=")
         .append(conn_id)
         .append(")");
     log.trace(sb.toString());
   }
   down_prot.down(new Event(Event.MSG, stable_msg));
 }
예제 #10
0
  public Object down(Event evt) {
    switch (evt.getType()) {
      case Event.MSG: // Add UnicastHeader, add to AckSenderWindow and pass down
        Message msg = (Message) evt.getArg();
        Address dst = msg.getDest();

        /* only handle unicast messages */
        if (dst == null || msg.isFlagSet(Message.NO_RELIABILITY)) break;

        if (!started) {
          if (log.isTraceEnabled())
            log.trace("discarded message as start() has not yet been called, message: " + msg);
          return null;
        }

        SenderEntry entry = send_table.get(dst);
        if (entry == null) {
          entry = new SenderEntry(getNewConnectionId());
          SenderEntry existing = send_table.putIfAbsent(dst, entry);
          if (existing != null) entry = existing;
          else {
            if (log.isTraceEnabled())
              log.trace(
                  local_addr
                      + ": created connection to "
                      + dst
                      + " (conn_id="
                      + entry.send_conn_id
                      + ")");
            if (cache != null && !members.contains(dst)) cache.add(dst);
          }
        }

        long seqno = -2;
        short send_conn_id = -1;
        Unicast2Header hdr;

        entry.lock(); // threads will only sync if they access the same entry
        try {
          seqno = entry.sent_msgs_seqno;
          send_conn_id = entry.send_conn_id;
          hdr = Unicast2Header.createDataHeader(seqno, send_conn_id, seqno == DEFAULT_FIRST_SEQNO);
          msg.putHeader(this.id, hdr);
          entry.sent_msgs.addToMessages(
              seqno, msg); // add *including* UnicastHeader, adds to retransmitter
          entry.sent_msgs_seqno++;
          entry.update();
        } finally {
          entry.unlock();
        }

        if (log.isTraceEnabled()) {
          StringBuilder sb = new StringBuilder();
          sb.append(local_addr)
              .append(" --> DATA(")
              .append(dst)
              .append(": #")
              .append(seqno)
              .append(", conn_id=")
              .append(send_conn_id);
          if (hdr.first) sb.append(", first");
          sb.append(')');
          log.trace(sb);
        }

        try {
          down_prot.down(evt);
          num_msgs_sent++;
          num_bytes_sent += msg.getLength();
        } catch (Throwable t) {
          log.warn("failed sending the message", t);
        }
        return null; // we already passed the msg down

      case Event.VIEW_CHANGE: // remove connections to peers that are not members anymore !
        View view = (View) evt.getArg();
        List<Address> new_members = view.getMembers();
        Set<Address> non_members = new HashSet<Address>(send_table.keySet());
        non_members.addAll(recv_table.keySet());

        synchronized (members) {
          members.clear();
          if (new_members != null) members.addAll(new_members);
          non_members.removeAll(members);
          if (cache != null) {
            cache.removeAll(members);
          }
        }

        if (!non_members.isEmpty()) {
          if (log.isTraceEnabled()) log.trace("removing non members " + non_members);
          for (Address non_mbr : non_members) removeConnection(non_mbr);
        }
        break;

      case Event.SET_LOCAL_ADDRESS:
        local_addr = (Address) evt.getArg();
        break;
    }

    return down_prot.down(evt); // Pass on to the layer below us
  }
예제 #11
0
  public Object down(Event evt) {
    switch (evt.getType()) {
      case Event.MSG: // Add UnicastHeader, add to AckSenderWindow and pass down
        Message msg = (Message) evt.getArg();
        Address dst = msg.getDest();

        /* only handle unicast messages */
        if (dst == null || msg.isFlagSet(Message.NO_RELIABILITY)) break;

        if (!running) {
          if (log.isTraceEnabled())
            log.trace("discarded message as start() has not yet been called, message: " + msg);
          return null;
        }

        SenderEntry entry = send_table.get(dst);
        if (entry == null) {
          entry = new SenderEntry(getNewConnectionId());
          SenderEntry existing = send_table.putIfAbsent(dst, entry);
          if (existing != null) entry = existing;
          else {
            if (log.isTraceEnabled())
              log.trace(
                  local_addr
                      + ": created connection to "
                      + dst
                      + " (conn_id="
                      + entry.send_conn_id
                      + ")");
            if (cache != null && !members.contains(dst)) cache.add(dst);
          }
        }

        short send_conn_id = entry.send_conn_id;
        long seqno = entry.sent_msgs_seqno.getAndIncrement();
        long sleep = 10;
        while (running) {
          try {
            msg.putHeader(
                this.id,
                Unicast2Header.createDataHeader(seqno, send_conn_id, seqno == DEFAULT_FIRST_SEQNO));
            entry.sent_msgs.add(seqno, msg); // add *including* UnicastHeader, adds to retransmitter
            if (conn_expiry_timeout > 0) entry.update();
            break;
          } catch (Throwable t) {
            if (!running) break;
            if (log.isWarnEnabled()) log.warn("failed sending message", t);
            Util.sleep(sleep);
            sleep = Math.min(5000, sleep * 2);
          }
        }

        if (log.isTraceEnabled()) {
          StringBuilder sb = new StringBuilder();
          sb.append(local_addr)
              .append(" --> DATA(")
              .append(dst)
              .append(": #")
              .append(seqno)
              .append(", conn_id=")
              .append(send_conn_id);
          if (seqno == DEFAULT_FIRST_SEQNO) sb.append(", first");
          sb.append(')');
          log.trace(sb);
        }

        try {
          down_prot.down(evt);
          num_msgs_sent++;
        } catch (Throwable t) {
          log.warn("failed sending the message", t);
        }
        return null; // we already passed the msg down

      case Event.VIEW_CHANGE: // remove connections to peers that are not members anymore !
        View view = (View) evt.getArg();
        List<Address> new_members = view.getMembers();
        Set<Address> non_members = new HashSet<Address>(send_table.keySet());
        non_members.addAll(recv_table.keySet());

        members = new_members;
        non_members.removeAll(new_members);
        if (cache != null) cache.removeAll(new_members);

        if (!non_members.isEmpty()) {
          if (log.isTraceEnabled()) log.trace("removing non members " + non_members);
          for (Address non_mbr : non_members) removeConnection(non_mbr);
        }
        break;

      case Event.SET_LOCAL_ADDRESS:
        local_addr = (Address) evt.getArg();
        break;
    }

    return down_prot.down(evt); // Pass on to the layer below us
  }