Beispiel #1
0
 protected static <T> void assertIndices(Table<T> table, long low, long hd, long hr) {
   assert table.getLow() == low : "expected low=" + low + " but was " + table.getLow();
   assert table.getHighestDelivered() == hd
       : "expected hd=" + hd + " but was " + table.getHighestDelivered();
   assert table.getHighestReceived() == hr
       : "expected hr=" + hr + " but was " + table.getHighestReceived();
 }
Beispiel #2
0
  public static void testForEach() {
    class MyVisitor<T> implements Table.Visitor<T> {
      List<int[]> list = new ArrayList<int[]>(20);

      public boolean visit(long seqno, T element, int row, int column) {
        System.out.println("#" + seqno + ": " + element + ", row=" + row + ", column=" + column);
        list.add(new int[] {row, column});
        return true;
      }
    }
    MyVisitor<Integer> visitor = new MyVisitor<Integer>();

    Table<Integer> table = new Table<Integer>(3, 10, 0);
    for (int i = 1; i <= 20; i++) table.add(i, i);
    System.out.println("table = " + table);
    table.forEach(table.getLow() + 1, table.getHighestReceived() - 1, visitor);
    int count = 1;
    for (int[] pair : visitor.list) {
      int row = pair[0], column = pair[1];
      if (count < Util.getNextHigherPowerOfTwo(10)) {
        assert row == 0;
        assert column == count;
      } else {
        assert row == 1;
        assert column == count - Util.getNextHigherPowerOfTwo(10);
      }
      count++;
    }
  }
Beispiel #3
0
 public void removeReceiveConnection(Address mbr) {
   ReceiverEntry entry2 = recv_table.remove(mbr);
   if (entry2 != null) {
     Table<Message> win = entry2.received_msgs;
     if (win != null)
       sendStableMessage(
           mbr, entry2.recv_conn_id, win.getHighestDelivered(), win.getHighestReceived());
     entry2.reset();
   }
 }
Beispiel #4
0
 public void run() {
   for (SenderEntry val : send_table.values()) {
     Table<Message> buf = val != null ? val.sent_msgs : null;
     if (buf != null && !buf.isEmpty()) {
       long from = buf.getHighestDelivered() + 1, to = buf.getHighestReceived();
       List<Message> list = buf.get(from, to);
       if (list != null) {
         for (Message msg : list) retransmit(msg);
       }
     }
   }
 }
Beispiel #5
0
 public void testIndexWithRemoveMany() {
   Table<Integer> buf = new Table<Integer>(3, 10, 5);
   assert buf.getHighestDelivered() == 5;
   assert buf.getHighestReceived() == 5;
   buf.add(6, 6);
   buf.add(7, 7);
   long low = buf.getLow();
   buf.removeMany(true, 0);
   System.out.println("buf = " + buf);
   for (long i = low; i <= 7; i++)
     assert buf._get(i) == null : "message with seqno=" + i + " is not null";
   assertIndices(buf, 7, 7, 7);
 }
Beispiel #6
0
 public void testIndex() {
   Table<Integer> buf = new Table<Integer>(3, 10, 5);
   assert buf.getHighestDelivered() == 5;
   assert buf.getHighestReceived() == 5;
   buf.add(6, 6);
   buf.add(7, 7);
   buf.remove(false);
   buf.remove(false);
   long low = buf.getLow();
   assert low == 5;
   buf.purge(4);
   buf.purge(5);
   buf.purge(6);
   buf.purge(7);
   System.out.println("buf = " + buf);
   for (long i = low; i <= 7; i++)
     assert buf._get(i) == null : "message with seqno=" + i + " is not null";
 }
Beispiel #7
0
  /**
   * Purge all messages in window for local_addr, which are <= low. Check if the window's highest
   * received message is > high: if true, retransmit all messages from high - win.high to sender
   *
   * @param sender
   * @param hd Highest delivered seqno
   * @param hr Highest received seqno
   */
  protected void stable(Address sender, short conn_id, long hd, long hr) {
    SenderEntry entry = send_table.get(sender);
    Table<Message> win = entry != null ? entry.sent_msgs : null;
    if (win == null) return;

    if (log.isTraceEnabled())
      log.trace(
          new StringBuilder()
                  .append(local_addr)
                  .append(" <-- STABLE(")
                  .append(sender)
                  .append(": ")
                  .append(hd)
                  .append("-")
                  .append(hr)
                  .append(", conn_id=" + conn_id)
              + ")");

    if (entry.send_conn_id != conn_id) {
      log.warn(
          local_addr
              + ": my conn_id ("
              + entry.send_conn_id
              + ") != received conn_id ("
              + conn_id
              + "); discarding STABLE message !");
      return;
    }

    win.purge(hd, true);
    long win_hr = win.getHighestReceived();
    if (win_hr > hr) {
      for (long seqno = hr; seqno <= win_hr; seqno++) {
        Message msg =
            win.get(
                seqno); // destination is still the same (the member which sent the STABLE message)
        if (msg != null) down_prot.down(new Event(Event.MSG, msg));
      }
    }
  }
Beispiel #8
0
  /**
   * Check whether the hashmap contains an entry e for <code>sender</code> (create if not). If
   * e.received_msgs is null and <code>first</code> is true: create a new AckReceiverWindow(seqno)
   * and add message. Set e.received_msgs to the new window. Else just add the message.
   */
  protected void handleDataReceived(
      Address sender, long seqno, short conn_id, boolean first, Message msg, Event evt) {
    if (log.isTraceEnabled()) {
      StringBuilder sb = new StringBuilder();
      sb.append(local_addr).append(" <-- DATA(").append(sender).append(": #").append(seqno);
      if (conn_id != 0) sb.append(", conn_id=").append(conn_id);
      if (first) sb.append(", first");
      sb.append(')');
      log.trace(sb);
    }

    ReceiverEntry entry = getReceiverEntry(sender, seqno, first, conn_id);
    if (entry == null) return;
    if (conn_expiry_timeout > 0) entry.update();
    Table<Message> win = entry.received_msgs;
    boolean added = win.add(seqno, msg); // win is guaranteed to be non-null if we get here
    num_msgs_received++;

    if (added) {
      int len = msg.getLength();
      if (len > 0 && entry.incrementStable(len))
        sendStableMessage(
            sender, entry.recv_conn_id, win.getHighestDelivered(), win.getHighestReceived());
    }

    // An OOB message is passed up immediately. Later, when remove() is called, we discard it. This
    // affects ordering !
    // http://jira.jboss.com/jira/browse/JGRP-377
    if (msg.isFlagSet(Message.OOB) && added) {
      try {
        up_prot.up(evt);
      } catch (Throwable t) {
        log.error("couldn't deliver OOB message " + msg, t);
      }
    }

    final AtomicBoolean processing = win.getProcessing();
    if (!processing.compareAndSet(false, true)) {
      return;
    }

    // Try to remove as many messages as possible and pass them up.
    // Prevents concurrent passing up of messages by different threads
    // (http://jira.jboss.com/jira/browse/JGRP-198);
    // this is all the more important once we have a concurrent stack
    // (http://jira.jboss.com/jira/browse/JGRP-181),
    // where lots of threads can come up to this point concurrently, but only 1 is allowed to pass
    // at a time
    // We *can* deliver messages from *different* senders concurrently, e.g. reception of P1, Q1,
    // P2, Q2 can result in
    // delivery of P1, Q1, Q2, P2: FIFO (implemented by UNICAST) says messages need to be delivered
    // only in the
    // order in which they were sent by their senders
    boolean released_processing = false;
    try {
      while (true) {
        List<Message> msgs =
            win.removeMany(processing, true, max_msg_batch_size); // remove my own messages
        if (msgs == null || msgs.isEmpty()) {
          released_processing = true;
          return;
        }

        for (Message m : msgs) {
          // discard OOB msg: it has already been delivered
          // (http://jira.jboss.com/jira/browse/JGRP-377)
          if (m.isFlagSet(Message.OOB)) continue;
          try {
            up_prot.up(new Event(Event.MSG, m));
          } catch (Throwable t) {
            log.error("couldn't deliver message " + m, t);
          }
        }
      }
    } finally {
      // processing is always set in win.remove(processing) above and never here ! This code is just
      // a
      // 2nd line of defense should there be an exception before win.remove(processing) sets
      // processing
      if (!released_processing) processing.set(false);
    }
  }