Пример #1
0
  public static void testComputeSize() {
    Table<Integer> table = new Table<Integer>(3, 10, 0);
    for (int num : Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) table.add(num, num);
    System.out.println("table = " + table);
    assert table.computeSize() == 10;
    table.removeMany(false, 3);
    System.out.println("table = " + table);
    assert table.computeSize() == 7;

    table.removeMany(true, 4);
    System.out.println("table = " + table);
    assert table.computeSize() == table.size();
    assert table.computeSize() == 3;
  }
Пример #2
0
  public void testGetHighestDeliverable() {
    Table<Integer> table = new Table<Integer>(3, 10, 0);
    System.out.println("table = " + table);
    long highest_deliverable = table.getHighestDeliverable(), hd = table.getHighestDelivered();
    System.out.println("highest delivered=" + hd + ", highest deliverable=" + highest_deliverable);
    assert hd == 0;
    assert highest_deliverable == 0;

    for (int num : Arrays.asList(1, 2, 3, 4, 5, 6, 8)) table.add(num, num);
    System.out.println("table = " + table);
    highest_deliverable = table.getHighestDeliverable();
    hd = table.getHighestDelivered();
    System.out.println("highest delivered=" + hd + ", highest deliverable=" + highest_deliverable);
    assert hd == 0;
    assert highest_deliverable == 6;

    table.removeMany(true, 4);
    System.out.println("table = " + table);
    highest_deliverable = table.getHighestDeliverable();
    hd = table.getHighestDelivered();
    System.out.println("highest delivered=" + hd + ", highest deliverable=" + highest_deliverable);
    assert hd == 4;
    assert highest_deliverable == 6;

    table.removeMany(true, 100);
    System.out.println("table = " + table);
    highest_deliverable = table.getHighestDeliverable();
    hd = table.getHighestDelivered();
    System.out.println("highest delivered=" + hd + ", highest deliverable=" + highest_deliverable);
    assert hd == 6;
    assert highest_deliverable == 6;

    table.add(7, 7);
    System.out.println("table = " + table);
    highest_deliverable = table.getHighestDeliverable();
    hd = table.getHighestDelivered();
    System.out.println("highest delivered=" + hd + ", highest deliverable=" + highest_deliverable);
    assert hd == 6;
    assert highest_deliverable == 8;

    table.removeMany(true, 100);
    System.out.println("table = " + table);
    highest_deliverable = table.getHighestDeliverable();
    hd = table.getHighestDelivered();
    System.out.println("highest delivered=" + hd + ", highest deliverable=" + highest_deliverable);
    assert hd == 8;
    assert highest_deliverable == 8;
  }
Пример #3
0
  public void testResizeWithPurge2() {
    Table<Integer> table = new Table<Integer>(3, 10, 0);
    for (int i = 1; i <= 50; i++) addAndGet(table, i);
    System.out.println("table = " + table);
    assert table.size() == 50;
    assertCapacity(table.capacity(), table.getNumRows(), 10);
    assertIndices(table, 0, 0, 50);
    table.removeMany(false, 43);
    System.out.println("table = " + table);
    assertIndices(table, 0, 43, 50);
    table.purge(43);
    System.out.println("table = " + table);
    assertIndices(table, 43, 43, 50);
    addAndGet(table, 52);
    assert table.get(43) == null;

    for (long i = 44; i <= 50; i++) {
      Integer num = table.get(i);
      assert num != null && num == i;
    }

    assert table.get(50) != null;
    assert table.get(51) == null;
    Integer num = table.get(52);
    assert num != null && num == 52;
    assert table.get(53) == null;
  }
Пример #4
0
 public void testPurge3() {
   Table<Integer> table = new Table<Integer>(3, 10, 0);
   for (int i = 1; i <= 100; i++) table.add(i, i);
   System.out.println("table = " + table);
   table.removeMany(true, 53);
   for (int i = 54; i <= 100; i++) assert table.get(i) == i;
 }
Пример #5
0
 public static void testMove() {
   Table<Integer> table = new Table<Integer>(3, 10, 0);
   for (int i = 1; i < 50; i++) addAndGet(table, i);
   table.removeMany(true, 49);
   assert table.isEmpty();
   addAndGet(table, 50);
   assert table.size() == 1;
   assertCapacity(table.capacity(), table.getNumRows(), 10);
 }
Пример #6
0
 public static void testMove3() {
   Table<Integer> table = new Table<Integer>(3, 10, 0);
   for (int i = 1; i < 30; i++) table.add(i, i);
   table.removeMany(true, 23);
   System.out.println("table = " + table);
   table.add(30, 30); // triggers a resize() --> move()
   for (int i = 1; i <= 23; i++) assert table._get(i) == null;
   for (int i = 24; i < 30; i++) assert table._get(i) != null;
 }
Пример #7
0
  public void testRemoveMany2() {
    Table<Integer> buf = new Table<Integer>(3, 10, 0);
    for (int i : Arrays.asList(1, 2, 3, 4, 5, 6, 7, 9, 10)) buf.add(i, i);
    List<Integer> list = buf.removeMany(false, 3);
    System.out.println("list = " + list);
    assert list != null && list.size() == 3;

    list = buf.removeMany(false, 0);
    System.out.println("list = " + list);
    assert list != null && list.size() == 4;

    list = buf.removeMany(false, 10);
    assert list == null;

    buf.add(8, 8);
    list = buf.removeMany(false, 0);
    System.out.println("list = " + list);
    assert list != null && list.size() == 3;
  }
Пример #8
0
 public static void testRemoveMany() {
   Table<Integer> table = new Table<Integer>(3, 10, 0);
   for (int seqno : Arrays.asList(1, 2, 3, 4, 5, 7, 8, 9, 10)) table.add(seqno, seqno);
   System.out.println("table = " + table);
   assertIndices(table, 0, 0, 10);
   List<Integer> list = table.removeMany(true, 4);
   System.out.println("list=" + list + ", table=" + table);
   assert table.size() == 5 && table.getNumMissing() == 1;
   assert list != null && list.size() == 4;
   for (int num : Arrays.asList(1, 2, 3, 4)) assert list.contains(num);
   assertIndices(table, 4, 4, 10);
 }
Пример #9
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);
 }
Пример #10
0
  public void testAddWithWrapAroundAndRemoveMany() {
    Table<Integer> buf = new Table<Integer>(3, 10, 5);
    for (int i = 6; i <= 15; i++) assert buf.add(i, i) : "addition of seqno " + i + " failed";
    System.out.println("buf = " + buf);
    List<Integer> removed = buf.removeMany(true, 3);
    System.out.println("removed " + removed);
    System.out.println("buf = " + buf);
    for (int i : removed) assert buf._get(i) == null;
    assertIndices(buf, 8, 8, 15);

    for (int i = 16; i <= 18; i++) assert buf.add(i, i);
    System.out.println("buf = " + buf);

    removed = buf.removeMany(true, 0);
    System.out.println("buf = " + buf);
    System.out.println("removed = " + removed);
    assert removed.size() == 10;
    for (int i : removed) assert buf._get(i) == null;

    assert buf.isEmpty();
    assert buf.getNumMissing() == 0;
    assertIndices(buf, 18, 18, 18);
  }
Пример #11
0
 public static void testRemoveManyWithWrapping2() {
   Table<Integer> table = new Table<Integer>(3, 10, 0);
   for (int seqno : Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20))
     table.add(seqno, seqno);
   System.out.println("table = " + table);
   assertIndices(table, 0, 0, 20);
   assert table.size() == 18 && table.getNumMissing() == 2;
   List<Integer> list = table.removeMany(false, 0);
   assert list.size() == 12;
   assertIndices(table, 0, 12, 20);
   assert table.size() == 6 && table.getNumMissing() == 2;
   table.purge(12);
   assertIndices(table, 12, 12, 20);
   assert table.size() == 6 && table.getNumMissing() == 2;
 }
Пример #12
0
  /**
   * Creates a table and fills it to capacity. Then starts a number of adder threads, each trying to
   * add a seqno, blocking until there is more space. Each adder will block until the remover
   * removes elements, so the adder threads get unblocked and can then add their elements to the
   * buffer.
   */
  public void testConcurrentAddAndRemove() throws Exception {
    final int NUM = 5;
    final Table<Integer> buf = new Table<Integer>(3, 10, 0);
    for (int i = 1; i <= 10; i++) buf.add(i, i); // fill the buffer, add() will block now

    CountDownLatch latch = new CountDownLatch(1);
    Adder[] adders = new Adder[NUM];
    for (int i = 0; i < adders.length; i++) {
      adders[i] = new Adder(latch, i + 11, buf);
      adders[i].start();
    }

    System.out.println("releasing threads");
    latch.countDown();
    System.out.print("waiting for threads to be done: ");

    Thread remover =
        new Thread("Remover") {
          public void run() {
            Util.sleep(2000);
            List<Integer> list = buf.removeMany(true, 5);
            System.out.println("\nremover: removed = " + list);
          }
        };
    remover.start();

    for (Adder adder : adders) {
      try {
        adder.join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    remover.join();

    System.out.println("OK");
    System.out.println("buf = " + buf);
    assert buf.size() == 10;
    assertIndices(buf, 5, 5, 15);

    List<Integer> list = buf.removeMany(true, 0);
    System.out.println("removed = " + list);
    assert list.size() == 10;
    for (int i = 6; i <= 15; i++) assert list.contains(i);
    assertIndices(buf, 15, 15, 15);
  }
Пример #13
0
 public void testCompact() {
   Table<Integer> table = new Table<Integer>(3, 10, 0);
   for (int i = 1; i <= 80; i++) addAndGet(table, i);
   assert table.size() == 80;
   assertIndices(table, 0, 0, 80);
   List<Integer> list = table.removeMany(false, 60);
   assert list.size() == 60;
   assert list.get(0) == 1 && list.get(list.size() - 1) == 60;
   assertIndices(table, 0, 60, 80);
   table.purge(60);
   assertIndices(table, 60, 60, 80);
   assert table.size() == 20;
   table.compact();
   assertIndices(table, 60, 60, 80);
   assert table.size() == 20;
   assertCapacity(table.capacity(), table.getNumRows(), 10);
 }
Пример #14
0
 public static void testRemoveManyWithFilterAcceptNone() {
   Table<Integer> table = new Table<Integer>(3, 10, 0);
   for (int i = 1; i <= 10; i++) table.add(i, i);
   List<Integer> list =
       table.removeMany(
           null,
           true,
           0,
           new Filter<Integer>() {
             public boolean accept(Integer element) {
               return false;
             }
           });
   System.out.println("list = " + list);
   System.out.println("table = " + table);
   assert list == null;
   assert table.isEmpty();
 }
Пример #15
0
  /**
   * Try to remove as many messages as possible from the table as pass them up. Prevents concurrent
   * passing up of messages by different threads (http://jira.jboss.com/jira/browse/JGRP-198); 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 in the order in which they were sent
   */
  protected int removeAndDeliver(
      final AtomicBoolean processing, Table<Message> win, Address sender) {
    int retval = 0;
    boolean released_processing = false;
    try {
      while (true) {
        List<Message> list = win.removeMany(processing, true, max_msg_batch_size);
        if (list == null) {
          released_processing = true;
          return retval;
        }

        MessageBatch batch = new MessageBatch(local_addr, sender, null, false, list);
        for (Message msg_to_deliver : batch) {
          // discard OOB msg: it has already been delivered
          // (http://jira.jboss.com/jira/browse/JGRP-377)
          if (msg_to_deliver.isFlagSet(Message.Flag.OOB)) batch.remove(msg_to_deliver);
        }

        try {
          if (log.isTraceEnabled()) {
            Message first = batch.first(), last = batch.last();
            StringBuilder sb = new StringBuilder(local_addr + ": delivering");
            if (first != null && last != null) {
              UnicastHeader hdr1 = (UnicastHeader) first.getHeader(id),
                  hdr2 = (UnicastHeader) last.getHeader(id);
              sb.append(" #").append(hdr1.seqno).append(" - #").append(hdr2.seqno);
            }
            sb.append(" (" + batch.size()).append(" messages)");
            log.trace(sb);
          }
          up_prot.up(batch);
        } catch (Throwable t) {
          log.error("failed to deliver batch " + batch, 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);
    }
  }
Пример #16
0
 public static void testRemoveManyWithFilter() {
   Table<Integer> table = new Table<Integer>(3, 10, 0);
   for (int i = 1; i <= 10; i++) table.add(i, i);
   List<Integer> list =
       table.removeMany(
           null,
           true,
           0,
           new Filter<Integer>() {
             public boolean accept(Integer element) {
               return element % 2 == 0;
             }
           });
   System.out.println("list = " + list);
   System.out.println("table = " + table);
   assert list.size() == 5;
   assert table.isEmpty();
   for (Integer num : Arrays.asList(2, 4, 6, 8, 10)) assert list.contains(num);
 }
Пример #17
0
  public void testPurge5() {
    Table<Integer> table = new Table<Integer>(3, 10, 0);
    for (int i = 1; i <= 100; i++) table.add(i, i);
    System.out.println("table = " + table);
    table.removeMany(false, 0);

    table.purge(10);
    for (int i = 1; i <= 10; i++) assert table._get(i) == null;
    for (int i = 11; i <= 100; i++) assert table.get(i) == i;

    table.purge(10);
    for (int i = 11; i <= 100; i++) assert table.get(i) == i;

    table.purge(50);
    for (int i = 1; i <= 50; i++) assert table._get(i) == null;
    for (int i = 51; i <= 100; i++) assert table.get(i) == i;

    table.purge(100);
    for (int i = 51; i <= 100; i++) assert table._get(i) == null;
  }
Пример #18
0
 public void testAddListWithConstValue() {
   Table<Integer> buf = new Table<Integer>(3, 10, 0);
   List<Tuple<Long, Integer>> msgs = createList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
   final Integer DUMMY = 0;
   boolean rc = buf.add(msgs, false, DUMMY);
   System.out.println("buf = " + buf);
   assert rc;
   assert buf.size() == 10;
   List<Integer> list =
       buf.removeMany(
           null,
           true,
           0,
           new Filter<Integer>() {
             public boolean accept(Integer element) {
               return element.hashCode() == DUMMY.hashCode();
             }
           });
   System.out.println("list = " + list);
   assert list.size() == 10;
   for (int num : list) assert num == DUMMY;
 }
Пример #19
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);
    }
  }