Beispiel #1
0
  /**
   * Tests A|6, A|7, A|8 and B|7, B|8, B|9 -> we should have a subviews in MergeView consisting of
   * only 2 elements: A|5 and B|5
   */
  public void testMultipleViewsBySameMembers() throws Exception {
    View a1 =
        View.create(
            a.getAddress(),
            6,
            a.getAddress(),
            b.getAddress(),
            c.getAddress(),
            d.getAddress()); // {A,B,C,D}
    View a2 =
        View.create(a.getAddress(), 7, a.getAddress(), b.getAddress(), c.getAddress()); // {A,B,C}
    View a3 = View.create(a.getAddress(), 8, a.getAddress(), b.getAddress()); // {A,B}
    View a4 = View.create(a.getAddress(), 9, a.getAddress()); // {A}

    View b1 = View.create(b.getAddress(), 7, b.getAddress(), c.getAddress(), d.getAddress());
    View b2 = View.create(b.getAddress(), 8, b.getAddress(), c.getAddress());
    View b3 = View.create(b.getAddress(), 9, b.getAddress());

    Util.close(c, d); // not interested in those...

    // A and B cannot communicate:
    discard(true, a, b);

    // inject view A|6={A} into A and B|5={B} into B
    injectView(a4, a);
    injectView(b3, b);

    assert a.getView().equals(a4);
    assert b.getView().equals(b3);

    List<Event> merge_events = new ArrayList<>();
    for (View view : Arrays.asList(a3, a4, a2, a1)) {
      MERGE3.MergeHeader hdr = MERGE3.MergeHeader.createInfo(view.getViewId(), null, null);
      Message msg = new Message(null, a.getAddress(), null).putHeader(merge_id, hdr);
      merge_events.add(new Event(Event.MSG, msg));
    }
    for (View view : Arrays.asList(b2, b3, b1)) {
      MERGE3.MergeHeader hdr = MERGE3.MergeHeader.createInfo(view.getViewId(), null, null);
      Message msg = new Message(null, b.getAddress(), null).putHeader(merge_id, hdr);
      merge_events.add(new Event(Event.MSG, msg));
    }

    // A and B can communicate again
    discard(false, a, b);

    injectMergeEvents(merge_events, a, b);
    checkInconsistencies(a, b); // merge will happen between A and B
    Util.waitUntilAllChannelsHaveSameSize(10000, 500, a, b);
    System.out.println("A's view: " + a.getView() + "\nB's view: " + b.getView());
    assert a.getView().size() == 2;
    assert a.getView().containsMember(a.getAddress());
    assert a.getView().containsMember(b.getAddress());
    assert a.getView().equals(b.getView());
    for (View merge_view : Arrays.asList(getViewFromGMS(a), getViewFromGMS(b))) {
      System.out.println(merge_view);
      assert merge_view instanceof MergeView;
      List<View> subviews = ((MergeView) merge_view).getSubgroups();
      assert subviews.size() == 2;
    }
  }
Beispiel #2
0
  public static void testNewMembers() {
    final Address a = Util.createRandomAddress(),
        b = Util.createRandomAddress(),
        c = Util.createRandomAddress(),
        d = Util.createRandomAddress(),
        e = Util.createRandomAddress();
    List<Address> old = new ArrayList<>();
    List<Address> new_list = new ArrayList<>();

    old.add(a);
    old.add(b);
    old.add(c);
    new_list.add(b);
    new_list.add(a);
    new_list.add(c);
    new_list.add(d);
    new_list.add(e);

    System.out.println("old: " + old);
    System.out.println("new: " + new_list);

    List<Address> new_nodes = Util.newMembers(old, new_list);
    System.out.println("new_nodes = " + new_nodes);
    assert new_nodes.size() == 2 : "list should have d and e";
    assert new_nodes.contains(d);
    assert new_nodes.contains(e);
  }
Beispiel #3
0
 public List<Integer> providedUpServices() {
   List<Integer> ret = new ArrayList<Integer>(3);
   ret.add(Event.FIND_INITIAL_MBRS);
   ret.add(Event.FIND_ALL_VIEWS);
   ret.add(Event.GET_PHYSICAL_ADDRESS);
   return ret;
 }
Beispiel #4
0
  public static void testWriteView() throws Exception {
    List<Address> members = new ArrayList<>();
    View v;
    Address a1 = Util.createRandomAddress();
    Address a2 = Util.createRandomAddress();
    Address a4 = Util.createRandomAddress();
    ViewId vid = new ViewId(a1, 12345);
    members.add(a1);
    members.add(a2);
    members.add(a4);
    v = new View(vid, members);

    ByteArrayOutputStream outstream = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(outstream);
    Util.writeGenericStreamable(v, dos);
    Util.writeStreamable(v, dos);
    dos.close();
    byte[] buf = outstream.toByteArray();
    ByteArrayInputStream instream = new ByteArrayInputStream(buf);
    DataInputStream dis = new DataInputStream(instream);
    View v2 = (View) Util.readGenericStreamable(dis);
    Assert.assertEquals(v, v2);
    v2 = (View) Util.readStreamable(View.class, dis);
    Assert.assertEquals(v, v2);
  }
Beispiel #5
0
 public static void testAll() {
   List<String> l = new ArrayList<>();
   l.add("one");
   l.add("two");
   l.add("one");
   System.out.println("-- list is " + l);
   assert !(Util.all(l, "one"));
   l.remove("two");
   System.out.println("-- list is " + l);
   assert Util.all(l, "one");
 }
Beispiel #6
0
  /**
   * Creates a list of randomly generated partitions, each having a max size of max_partition_size
   */
  protected List<View> createPartitions(int max_partition_size, JChannel... channels) {
    long view_id = 1;
    for (JChannel ch : channels) view_id = Math.max(view_id, ch.getView().getViewId().getId());
    List<View> partitions = new ArrayList<>();
    List<Address> tmp = new ArrayList<>();
    for (JChannel ch : channels) tmp.add(ch.getAddress());

    while (!tmp.isEmpty()) {
      int num_to_remove = (int) Util.random(max_partition_size);
      List<Address> part = new ArrayList<>(max_partition_size);
      for (int x = 0; x < num_to_remove && !tmp.isEmpty(); x++) part.add(tmp.remove(0));
      partitions.add(new View(part.get(0), view_id + 1, part));
    }
    return partitions;
  }
Beispiel #7
0
  public void up(MessageBatch batch) {
    if (batch.dest() == null) { // not a unicast batch
      up_prot.up(batch);
      return;
    }

    int size = batch.size();
    Map<Short, List<Message>> msgs =
        new TreeMap<Short, List<Message>>(); // map of messages, keyed by conn-id
    for (Message msg : batch) {
      if (msg == null || msg.isFlagSet(Message.Flag.NO_RELIABILITY)) continue;
      UnicastHeader hdr = (UnicastHeader) msg.getHeader(id);
      if (hdr == null) continue;
      batch.remove(msg); // remove the message from the batch, so it won't be passed up the stack

      if (hdr.type != UnicastHeader.DATA) {
        try {
          handleUpEvent(msg.getSrc(), hdr);
        } catch (Throwable t) { // we cannot let an exception terminate the processing of this batch
          log.error(local_addr + ": failed handling event", t);
        }
        continue;
      }

      List<Message> list = msgs.get(hdr.conn_id);
      if (list == null) msgs.put(hdr.conn_id, list = new ArrayList<Message>(size));
      list.add(msg);
    }

    if (!msgs.isEmpty()) handleBatchReceived(batch.sender(), msgs); // process msgs:
    if (!batch.isEmpty()) up_prot.up(batch);
  }
Beispiel #8
0
  protected List<PingData> read(InputStream in) {
    List<PingData> retval = null;
    try {
      while (true) {
        try {
          String name_str = Util.readToken(in);
          String uuid_str = Util.readToken(in);
          String addr_str = Util.readToken(in);
          String coord_str = Util.readToken(in);
          if (name_str == null || uuid_str == null || addr_str == null || coord_str == null) break;

          UUID uuid = null;
          try {
            long tmp = Long.valueOf(uuid_str);
            uuid = new UUID(0, tmp);
          } catch (Throwable t) {
            uuid = UUID.fromString(uuid_str);
          }

          PhysicalAddress phys_addr = new IpAddress(addr_str);
          boolean is_coordinator = coord_str.trim().equals("T") || coord_str.trim().equals("t");

          if (retval == null) retval = new ArrayList<>();
          retval.add(new PingData(uuid, true, name_str, phys_addr).coord(is_coordinator));
        } catch (Throwable t) {
          log.error(Util.getMessage("FailedReadingLineOfInputStream"), t);
        }
      }
      return retval;
    } finally {
      Util.close(in);
    }
  }
Beispiel #9
0
    public void receive(Message msg) {
      if (!msg.isFlagSet(Message.OOB)) {
        lock.lock();
        lock.unlock();
      }

      msgs.add((Integer) msg.getObject());
    }
Beispiel #10
0
  /**
   * Computes the next view. Returns a copy that has <code>old_mbrs</code> and <code>suspected_mbrs
   * </code> removed and <code>new_mbrs</code> added.
   */
  public View getNextView(
      Collection<Address> new_mbrs,
      Collection<Address> old_mbrs,
      Collection<Address> suspected_mbrs) {
    synchronized (members) {
      ViewId view_id = view != null ? view.getViewId() : null;
      if (view_id == null) {
        log.error("view_id is null");
        return null; // this should *never* happen !
      }
      long vid = Math.max(view_id.getId(), ltime) + 1;
      ltime = vid;
      Membership tmp_mbrs = tmp_members.copy(); // always operate on the temporary membership
      tmp_mbrs.remove(suspected_mbrs);
      tmp_mbrs.remove(old_mbrs);
      tmp_mbrs.add(new_mbrs);
      List<Address> mbrs = tmp_mbrs.getMembers();
      Address new_coord = local_addr;
      if (!mbrs.isEmpty()) new_coord = mbrs.get(0);
      View v = new View(new_coord, vid, mbrs);

      // Update membership (see DESIGN for explanation):
      tmp_members.set(mbrs);

      // Update joining list (see DESIGN for explanation)
      if (new_mbrs != null) {
        for (Address tmp_mbr : new_mbrs) {
          if (!joining.contains(tmp_mbr)) joining.add(tmp_mbr);
        }
      }

      // Update leaving list (see DESIGN for explanations)
      if (old_mbrs != null) {
        for (Address addr : old_mbrs) {
          if (!leaving.contains(addr)) leaving.add(addr);
        }
      }
      if (suspected_mbrs != null) {
        for (Address addr : suspected_mbrs) {
          if (!leaving.contains(addr)) leaving.add(addr);
        }
      }
      return v;
    }
  }
Beispiel #11
0
 /**
  * Add a new channel listener to be notified on the channel's state change.
  *
  * @return true if the listener was added or false if the listener was already in the list.
  */
 public boolean addChannelListener(ChannelListener l) {
   synchronized (additionalChannelListeners) {
     if (additionalChannelListeners.contains(l)) {
       return false;
     }
     additionalChannelListeners.add(l);
     return true;
   }
 }
Beispiel #12
0
  public void testMergeWithAsymetricViewsCoordIsolated() {
    // Isolate the coord
    Address coord = a.getView().getCreator();
    System.out.println("Isolating coord: " + coord);
    List<Address> members = new ArrayList<>();
    members.add(coord);
    View coord_view = new View(coord, 4, members);
    System.out.println("coord_view: " + coord_view);
    Channel coord_channel = findChannel(coord);
    System.out.println("coord_channel: " + coord_channel.getAddress());

    MutableDigest digest = new MutableDigest(coord_view.getMembersRaw());
    NAKACK2 nakack = (NAKACK2) coord_channel.getProtocolStack().findProtocol(NAKACK2.class);
    digest.merge(nakack.getDigest(coord));

    GMS gms = (GMS) coord_channel.getProtocolStack().findProtocol(GMS.class);
    gms.installView(coord_view, digest);
    System.out.println("gms.getView() " + gms.getView());

    System.out.println("Views are:");
    for (JChannel ch : Arrays.asList(a, b, c, d))
      System.out.println(ch.getAddress() + ": " + ch.getView());

    JChannel merge_leader = findChannel(coord);
    MyReceiver receiver = new MyReceiver();
    merge_leader.setReceiver(receiver);

    System.out.println("merge_leader: " + merge_leader.getAddressAsString());

    System.out.println("Injecting MERGE event into merge leader " + merge_leader.getAddress());
    Map<Address, View> merge_views = new HashMap<>(4);
    merge_views.put(a.getAddress(), a.getView());
    merge_views.put(b.getAddress(), b.getView());
    merge_views.put(c.getAddress(), c.getView());
    merge_views.put(d.getAddress(), d.getView());

    gms = (GMS) merge_leader.getProtocolStack().findProtocol(GMS.class);
    gms.up(new Event(Event.MERGE, merge_views));

    Util.waitUntilAllChannelsHaveSameSize(10000, 1000, a, b, c, d);

    System.out.println("Views are:");
    for (JChannel ch : Arrays.asList(a, b, c, d)) {
      View view = ch.getView();
      System.out.println(ch.getAddress() + ": " + view);
      assert view.size() == 4;
    }
    MergeView merge_view = receiver.getView();
    System.out.println("merge_view = " + merge_view);
    assert merge_view.size() == 4;
    assert merge_view.getSubgroups().size() == 2;

    for (View view : merge_view.getSubgroups())
      assert contains(view, a.getAddress())
          || contains(view, b.getAddress(), c.getAddress(), d.getAddress());
  }
Beispiel #13
0
  public static void testPickRandomElement() {
    List<Integer> v = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
      v.add(i);
    }

    Integer el;
    for (int i = 0; i < 10000; i++) {
      el = Util.pickRandomElement(v);
      assert el >= 0 && el < 10;
    }
  }
Beispiel #14
0
    protected void addToQueue(Request req) {
      if (queue.isEmpty()) {
        if (req.type == Type.GRANT_LOCK) queue.add(req);
        return; // RELEASE_LOCK is discarded on an empty queue
      }

      // at this point the queue is not empty
      switch (req.type) {

          // If there is already a lock request from the same owner, discard the new lock request
        case GRANT_LOCK:
          if (!isRequestPresent(Type.GRANT_LOCK, req.owner)) queue.add(req);
          break;

        case RELEASE_LOCK:
          // Release the lock request from the same owner already in the queue
          // If there is no lock request, discard the unlock request
          removeRequest(Type.GRANT_LOCK, req.owner);
          break;
      }
    }
Beispiel #15
0
    public void receive(Message msg) {
      if (!msg.isFlagSet(Message.OOB)) {
        try {
          System.out.println(Thread.currentThread() + ": waiting on latch");
          latch.await(25000, TimeUnit.MILLISECONDS);
          System.out.println(Thread.currentThread() + ": DONE waiting on latch");
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }

      msgs.add((Integer) msg.getObject());
    }
Beispiel #16
0
  protected void _handleMergeRequest(
      Address sender, MergeId merge_id, Collection<? extends Address> mbrs) throws Exception {
    boolean success = matchMergeId(merge_id) || setMergeId(null, merge_id);
    if (!success)
      throw new Exception(
          "merge " + this.merge_id + " is already in progress, received merge-id=" + merge_id);

    /* Clears the view handler queue and discards all JOIN/LEAVE/MERGE requests until after the MERGE  */
    // gms.getViewHandler().suspend();
    if (log.isTraceEnabled())
      log.trace(
          gms.local_addr
              + ": got merge request from "
              + sender
              + ", merge_id="
              + merge_id
              + ", mbrs="
              + mbrs);

    // merge the membership of the current view with mbrs
    List<Address> members = new LinkedList<Address>();
    if (mbrs
        != null) { // didn't use a set because we didn't want to change the membership order at this
      // time (although not incorrect)
      for (Address mbr : mbrs) {
        if (!members.contains(mbr)) members.add(mbr);
      }
    }

    ViewId tmp_vid = gms.getViewId();
    if (tmp_vid != null) tmp_vid = tmp_vid.copy();
    if (tmp_vid == null) throw new Exception("view ID is null; cannot return merge response");

    View view = new View(tmp_vid, new ArrayList<Address>(members));

    // [JGRP-524] - FLUSH and merge: flush doesn't wrap entire merge process
    // [JGRP-770] - Concurrent startup of many channels doesn't stabilize
    // [JGRP-700] - FLUSH: flushing should span merge

    /*if flush is in stack, let this coordinator flush its cluster island */
    if (gms.flushProtocolInStack && !gms.startFlush(view)) throw new Exception("flush failed");

    // we still need to fetch digests from all members, and not just return our own digest
    // (https://issues.jboss.org/browse/JGRP-948)
    Digest digest = fetchDigestsFromAllMembersInSubPartition(members, merge_id);
    if (digest == null || digest.size() == 0)
      throw new Exception(
          "failed fetching digests from subpartition members; dropping merge response");

    sendMergeResponse(sender, view, digest, merge_id);
  }
Beispiel #17
0
  public static void testReadLine() throws IOException {
    final String input = "   hello world\nthis is \r\n just an example\r\nthis is line 2 \r\n";
    String line;
    InputStream in = new BufferedInputStream(new ByteArrayInputStream(input.getBytes()));
    List<String> list = new ArrayList<>(4);

    for (int i = 0; i < 4; i++) {
      line = Util.readLine(in);
      System.out.println("line = \"" + line + "\"");
      list.add(line);
    }

    assert list.size() == 4;
  }
Beispiel #18
0
    /**
     * Merge all MergeData. All MergeData elements should be disjunct (both views and digests).
     * However, this method is prepared to resolve duplicate entries (for the same member).
     * Resolution strategy for views is to merge only 1 of the duplicate members. Resolution
     * strategy for digests is to take the higher seqnos for duplicate digests.
     *
     * <p>After merging all members into a Membership and subsequent sorting, the first member of
     * the sorted membership will be the new coordinator. This method has a lock on merge_rsps.
     *
     * @param merge_rsps A list of MergeData items. Elements with merge_rejected=true were removed
     *     before. Is guaranteed not to be null and to contain at least 1 member.
     */
    private MergeData consolidateMergeData(List<MergeData> merge_rsps) {
      long logical_time = 0; // for new_vid
      List<View> subgroups =
          new ArrayList<View>(11); // contains a list of Views, each View is a subgroup
      Collection<Collection<Address>> sub_mbrships = new ArrayList<Collection<Address>>();

      for (MergeData tmp_data : merge_rsps) {
        View tmp_view = tmp_data.getView();
        if (tmp_view != null) {
          ViewId tmp_vid = tmp_view.getVid();
          if (tmp_vid != null) {
            // compute the new view id (max of all vids +1)
            logical_time = Math.max(logical_time, tmp_vid.getId());
          }
          // merge all membership lists into one (prevent duplicates)
          sub_mbrships.add(new ArrayList<Address>(tmp_view.getMembers()));
          subgroups.add(tmp_view.copy());
        }
      }

      // determine the new digest
      Digest new_digest = consolidateDigests(merge_rsps, merge_rsps.size());
      if (new_digest == null) return null;

      // remove all members from the new member list that are not in the digest
      Collection<Address> digest_mbrs = new_digest.getMembers();
      for (Collection<Address> coll : sub_mbrships) coll.retainAll(digest_mbrs);

      List<Address> merged_mbrs = gms.computeNewMembership(sub_mbrships);

      // the new coordinator is the first member of the consolidated & sorted membership list
      Address new_coord = merged_mbrs.isEmpty() ? null : merged_mbrs.get(0);
      if (new_coord == null) return null;

      // should be the highest view ID seen up to now plus 1
      ViewId new_vid = new ViewId(new_coord, logical_time + 1);

      // determine the new view
      MergeView new_view = new MergeView(new_vid, merged_mbrs, subgroups);

      if (log.isTraceEnabled())
        log.trace(
            gms.local_addr
                + ": consolidated view="
                + new_view
                + "\nconsolidated digest="
                + new_digest);
      return new MergeData(gms.local_addr, new_view, new_digest);
    }
Beispiel #19
0
  public static void testLeftMembers2() {
    final Address a = Util.createRandomAddress(),
        b = Util.createRandomAddress(),
        c = Util.createRandomAddress(),
        d = Util.createRandomAddress();

    List<Address> v1 = new ArrayList<>();
    v1.add(a);
    v1.add(b);
    v1.add(c);
    v1.add(d);

    List<Address> v2 = new ArrayList<>();
    v2.add(c);
    v2.add(d);
    v2.add(a);
    v2.add(b);

    View one = new View(new ViewId(a, 1), v1), two = new View(new ViewId(b, 2), v2);
    List<Address> left = View.leftMembers(one, two);
    System.out.println("left = " + left);
    assert left != null;
    assert left.isEmpty();
  }
Beispiel #20
0
  public static void testPickNext() {
    List<Integer> list = new ArrayList<>(10);
    for (int i = 0; i < 10; i++) list.add(i);
    Integer num = Util.pickNext(list, 5);
    System.out.println("number next to 5: " + num);
    assert num != null;
    assert num.equals(6);

    num = Util.pickNext(list, 9);
    System.out.println("number next to 9: " + num);
    assert num != null;
    assert num.equals(0);

    num = Util.pickNext(list, 11);
    assert num == null;
  }
Beispiel #21
0
  @ManagedOperation(description = "Reads data from local caches and dumps them to a file")
  public void dumpCache(String output_filename) throws Exception {
    Map<Address, PhysicalAddress> cache_contents =
        (Map<Address, PhysicalAddress>)
            down_prot.down(new Event(Event.GET_LOGICAL_PHYSICAL_MAPPINGS, false));

    List<PingData> list = new ArrayList<>(cache_contents.size());
    for (Map.Entry<Address, PhysicalAddress> entry : cache_contents.entrySet()) {
      Address addr = entry.getKey();
      PhysicalAddress phys_addr = entry.getValue();
      PingData data =
          new PingData(addr, true, UUID.get(addr), phys_addr).coord(addr.equals(local_addr));
      list.add(data);
    }
    OutputStream out = new FileOutputStream(output_filename);
    write(list, out);
  }
Beispiel #22
0
    public void run() {
      long end_time, wait_time;
      List<Request> requests = new LinkedList<Request>();
      while (Thread.currentThread().equals(thread) && !suspended) {
        try {
          boolean keepGoing = false;
          end_time = System.currentTimeMillis() + max_bundling_time;
          do {
            Request firstRequest =
                (Request)
                    queue.remove(INTERVAL); // throws a TimeoutException if it runs into timeout
            requests.add(firstRequest);
            if (!view_bundling) break;
            if (queue.size() > 0) {
              Request nextReq = (Request) queue.peek();
              keepGoing = view_bundling && firstRequest.canBeProcessedTogether(nextReq);
            } else {
              wait_time = end_time - System.currentTimeMillis();
              if (wait_time > 0)
                queue.waitUntilClosed(
                    wait_time); // misnomer: waits until element has been added or q closed
              keepGoing =
                  queue.size() > 0 && firstRequest.canBeProcessedTogether((Request) queue.peek());
            }
          } while (keepGoing && System.currentTimeMillis() < end_time);

          try {
            process(requests);
          } finally {
            requests.clear();
          }
        } catch (QueueClosedException e) {
          break;
        } catch (TimeoutException e) {
          break;
        } catch (Throwable catchall) {
          Util.sleep(50);
        }
      }
    }
Beispiel #23
0
    public void addResponse(PingData rsp, boolean overwrite) {
      if (rsp == null) return;
      promise.getLock().lock();
      try {
        if (overwrite) ping_rsps.remove(rsp);

        // https://jira.jboss.org/jira/browse/JGRP-1179
        int index = ping_rsps.indexOf(rsp);
        if (index == -1) {
          ping_rsps.add(rsp);
          promise.getCond().signalAll();
        } else if (rsp.isCoord()) {
          PingData pr = ping_rsps.get(index);

          // Check if the already existing element is not server
          if (!pr.isCoord()) {
            ping_rsps.set(index, rsp);
            promise.getCond().signalAll();
          }
        }
      } finally {
        promise.getLock().unlock();
      }
    }
Beispiel #24
0
  public Object down(Event evt) {
    switch (evt.getType()) {
      case ExecutorEvent.TASK_SUBMIT:
        Runnable runnable = evt.getArg();
        // We are limited to a number of concurrent request id's
        // equal to 2^63-1.  This is quite large and if it
        // overflows it will still be positive
        long requestId = Math.abs(counter.getAndIncrement());
        if (requestId == Long.MIN_VALUE) {
          // TODO: need to fix this it isn't safe for concurrent modifications
          counter.set(0);
          requestId = Math.abs(counter.getAndIncrement());
        }

        // Need to make sure to put the requestId in our map before
        // adding the runnable to awaiting consumer in case if
        // coordinator sent a consumer found and their original task
        // is no longer around
        // see https://issues.jboss.org/browse/JGRP-1744
        _requestId.put(runnable, requestId);

        _awaitingConsumer.add(runnable);

        sendToCoordinator(RUN_REQUEST, requestId, local_addr);
        break;
      case ExecutorEvent.CONSUMER_READY:
        Thread currentThread = Thread.currentThread();
        long threadId = currentThread.getId();
        _consumerId.put(threadId, PRESENT);
        try {
          for (; ; ) {
            CyclicBarrier barrier = new CyclicBarrier(2);
            _taskBarriers.put(threadId, barrier);

            // We only send to the coordinator that we are ready after
            // making the barrier, wait for request to come and let
            // us free
            sendToCoordinator(Type.CONSUMER_READY, threadId, local_addr);

            try {
              barrier.await();
              break;
            } catch (BrokenBarrierException e) {
              if (log.isDebugEnabled())
                log.debug(
                    "Producer timed out before we picked up"
                        + " the task, have to tell coordinator"
                        + " we are still good.");
            }
          }
          // This should always be non nullable since the latch
          // was freed
          runnable = _tasks.remove(threadId);
          _runnableThreads.put(runnable, currentThread);
          return runnable;
        } catch (InterruptedException e) {
          if (log.isDebugEnabled()) log.debug("Consumer " + threadId + " stopped via interrupt");
          sendToCoordinator(Type.CONSUMER_UNREADY, threadId, local_addr);
          Thread.currentThread().interrupt();
        } finally {
          // Make sure the barriers are cleaned up as well
          _taskBarriers.remove(threadId);
          _consumerId.remove(threadId);
        }
        break;
      case ExecutorEvent.TASK_COMPLETE:
        Object arg = evt.getArg();
        Throwable throwable = null;
        if (arg instanceof Object[]) {
          Object[] array = (Object[]) arg;
          runnable = (Runnable) array[0];
          throwable = (Throwable) array[1];
        } else {
          runnable = (Runnable) arg;
        }
        Owner owner = _running.remove(runnable);
        // This won't remove anything if owner doesn't come back
        _runnableThreads.remove(runnable);

        Object value = null;
        boolean exception = false;
        if (throwable != null) {
          // InterruptedException is special telling us that
          // we interrupted the thread while waiting but still got
          // a task therefore we have to reject it.
          if (throwable instanceof InterruptedException) {
            if (log.isDebugEnabled())
              log.debug("Run rejected due to interrupted exception returned");
            sendRequest(owner.address, Type.RUN_REJECTED, owner.requestId, null);
            break;
          }
          value = throwable;
          exception = true;
        } else if (runnable instanceof RunnableFuture<?>) {
          RunnableFuture<?> future = (RunnableFuture<?>) runnable;

          boolean interrupted = false;
          boolean gotValue = false;

          // We have the value, before we interrupt at least get it!
          while (!gotValue) {
            try {
              value = future.get();
              gotValue = true;
            } catch (InterruptedException e) {
              interrupted = true;
            } catch (ExecutionException e) {
              value = e.getCause();
              exception = true;
              gotValue = true;
            }
          }

          if (interrupted) {
            Thread.currentThread().interrupt();
          }
        }

        if (owner != null) {
          final Type type;
          final Object valueToSend;
          if (value == null) {
            type = Type.RESULT_SUCCESS;
            valueToSend = value;
          }
          // Both serializable values and exceptions would go in here
          else if (value instanceof Serializable
              || value instanceof Externalizable
              || value instanceof Streamable) {
            type = exception ? Type.RESULT_EXCEPTION : Type.RESULT_SUCCESS;
            valueToSend = value;
          }
          // This would happen if the value wasn't serializable,
          // so we have to send back to the client that the class
          // wasn't serializable
          else {
            type = Type.RESULT_EXCEPTION;
            valueToSend = new NotSerializableException(value.getClass().getName());
          }

          if (local_addr.equals(owner.getAddress())) {
            if (log.isTraceEnabled())
              log.trace(
                  "[redirect] <--> ["
                      + local_addr
                      + "] "
                      + type.name()
                      + " ["
                      + value
                      + (owner.requestId != -1 ? " request id: " + owner.requestId : "")
                      + "]");
            if (type == Type.RESULT_SUCCESS) {
              handleValueResponse(local_addr, owner.requestId, valueToSend);
            } else if (type == Type.RESULT_EXCEPTION) {
              handleExceptionResponse(local_addr, owner.requestId, (Throwable) valueToSend);
            }
          } else {
            sendRequest(owner.getAddress(), type, owner.requestId, valueToSend);
          }
        } else {
          if (log.isTraceEnabled()) {
            log.trace("Could not return result - most likely because it was interrupted");
          }
        }
        break;
      case ExecutorEvent.TASK_CANCEL:
        Object[] array = evt.getArg();
        runnable = (Runnable) array[0];

        if (_awaitingConsumer.remove(runnable)) {
          _requestId.remove(runnable);
          ExecutorNotification notification = notifiers.remove(runnable);
          if (notification != null) {
            notification.interrupted(runnable);
          }
          if (log.isTraceEnabled())
            log.trace("Cancelled task " + runnable + " before it was picked up");
          return Boolean.TRUE;
        }
        // This is guaranteed to not be null so don't take cost of auto unboxing
        else if (array[1] == Boolean.TRUE) {
          owner = removeKeyForValue(_awaitingReturn, runnable);
          if (owner != null) {
            Long requestIdValue = _requestId.remove(runnable);
            // We only cancel if the requestId is still available
            // this means the result hasn't been returned yet and
            // we still have a chance to interrupt
            if (requestIdValue != null) {
              if (requestIdValue != owner.getRequestId()) {
                log.warn("Cancelling requestId didn't match waiting");
              }
              sendRequest(owner.getAddress(), Type.INTERRUPT_RUN, owner.getRequestId(), null);
            }
          } else {
            if (log.isTraceEnabled()) log.warn("Couldn't interrupt server task: " + runnable);
          }
          ExecutorNotification notification = notifiers.remove(runnable);
          if (notification != null) {
            notification.interrupted(runnable);
          }
          return Boolean.TRUE;
        } else {
          return Boolean.FALSE;
        }
      case ExecutorEvent.ALL_TASK_CANCEL:
        array = evt.getArg();

        // This is a RunnableFuture<?> so this cast is okay
        @SuppressWarnings("unchecked")
        Set<Runnable> runnables = (Set<Runnable>) array[0];
        Boolean booleanValue = (Boolean) array[1];

        List<Runnable> notRan = new ArrayList<>();

        for (Runnable cancelRunnable : runnables) {
          // Removed from the consumer
          if (!_awaitingConsumer.remove(cancelRunnable) && booleanValue == Boolean.TRUE) {
            synchronized (_awaitingReturn) {
              owner = removeKeyForValue(_awaitingReturn, cancelRunnable);
              if (owner != null) {
                Long requestIdValue = _requestId.remove(cancelRunnable);
                if (requestIdValue != owner.getRequestId()) {
                  log.warn("Cancelling requestId didn't match waiting");
                }
                sendRequest(owner.getAddress(), Type.INTERRUPT_RUN, owner.getRequestId(), null);
              }
              ExecutorNotification notification = notifiers.remove(cancelRunnable);
              if (notification != null) {
                log.trace("Notifying listener");
                notification.interrupted(cancelRunnable);
              }
            }
          } else {
            _requestId.remove(cancelRunnable);
            notRan.add(cancelRunnable);
          }
        }
        return notRan;
      case Event.SET_LOCAL_ADDRESS:
        local_addr = evt.getArg();
        break;

      case Event.VIEW_CHANGE:
        handleView(evt.getArg());
        break;
    }
    return down_prot.down(evt);
  }
Beispiel #25
0
 protected List<Address> getMembers(JChannel... channels) {
   List<Address> members = new ArrayList<>(channels.length);
   for (JChannel ch : channels) members.add(ch.getAddress());
   return members;
 }
Beispiel #26
0
  /**
   * Get the view and digest and send back both (MergeData) in the form of a MERGE_RSP to the
   * sender. If a merge is already in progress, send back a MergeData with the merge_rejected field
   * set to true.
   *
   * @param sender The address of the merge leader
   * @param merge_id The merge ID
   * @param mbrs The set of members from which we expect responses
   */
  public void handleMergeRequest(
      Address sender, MergeId merge_id, Collection<? extends Address> mbrs) {
    boolean success = matchMergeId(merge_id) || setMergeId(null, merge_id);
    if (!success) {
      if (log.isWarnEnabled()) log.warn(gms.local_addr + ": merge is already in progress");
      sendMergeRejectedResponse(sender, merge_id);
      return;
    }

    /* Clears the view handler queue and discards all JOIN/LEAVE/MERGE requests until after the MERGE  */
    gms.getViewHandler().suspend(merge_id);
    if (log.isDebugEnabled())
      log.debug(
          gms.local_addr
              + ": got merge request from "
              + sender
              + ", merge_id="
              + merge_id
              + ", mbrs="
              + mbrs);

    // merge the membership of the current view with mbrs
    List<Address> members = new LinkedList<Address>();
    if (mbrs
        != null) { // didn't use a set because we didn't want to change the membership order at this
                   // time (although not incorrect)
      for (Address mbr : mbrs) {
        if (!members.contains(mbr)) members.add(mbr);
      }
    }

    ViewId tmp_vid = gms.view_id != null ? gms.view_id.copy() : null;
    if (tmp_vid == null) {
      log.warn("view ID is null; cannot return merge response");
      sendMergeRejectedResponse(sender, merge_id);
      return;
    }
    View view = new View(tmp_vid, new Vector<Address>(members));

    // [JGRP-524] - FLUSH and merge: flush doesn't wrap entire merge process
    // [JGRP-770] - Concurrent startup of many channels doesn't stabilize
    // [JGRP-700] - FLUSH: flushing should span merge

    /*if flush is in stack, let this coordinator flush its cluster island */
    boolean successfulFlush = gms.startFlush(view);
    if (!successfulFlush) {
      sendMergeRejectedResponse(sender, merge_id);
      if (log.isWarnEnabled())
        log.warn(
            gms.local_addr
                + ": flush failed; sending merge rejected message to "
                + sender
                + ", merge_id="
                + merge_id);
      cancelMerge(merge_id);
      return;
    }
    Digest digest = fetchDigestsFromAllMembersInSubPartition(members);
    if (digest.size() == 0) {
      log.error("failed fetching digests from subpartition members; dropping merge response");
      return;
    }
    sendMergeResponse(sender, view, digest, merge_id);
  }
  protected <T> GroupRequest<T> cast(
      final Collection<Address> dests,
      Message msg,
      RequestOptions options,
      boolean block_for_results,
      FutureListener<RspList<T>> listener)
      throws Exception {
    if (msg.getDest() != null && !(msg.getDest() instanceof AnycastAddress))
      throw new IllegalArgumentException("message destination is non-null, cannot send message");

    if (options != null) {
      msg.setFlag(options.getFlags()).setTransientFlag(options.getTransientFlags());
      if (options.getScope() > 0) msg.setScope(options.getScope());
    }

    List<Address> real_dests;
    // we need to clone because we don't want to modify the original
    if (dests != null) {
      real_dests = new ArrayList<Address>();
      for (Address dest : dests) {
        if (dest instanceof SiteAddress || this.members.contains(dest)) {
          if (!real_dests.contains(dest)) real_dests.add(dest);
        }
      }
    } else real_dests = new ArrayList<Address>(members);

    // if local delivery is off, then we should not wait for the message from the local member.
    // therefore remove it from the membership
    Channel tmp = channel;
    if ((tmp != null && tmp.getDiscardOwnMessages())
        || msg.isTransientFlagSet(Message.TransientFlag.DONT_LOOPBACK)) {
      if (local_addr == null) local_addr = tmp != null ? tmp.getAddress() : null;
      if (local_addr != null) real_dests.remove(local_addr);
    }

    if (options != null && options.hasExclusionList()) {
      Address[] exclusion_list = options.exclusionList();
      for (Address excluding : exclusion_list) real_dests.remove(excluding);
    }

    // don't even send the message if the destination list is empty
    if (log.isTraceEnabled()) log.trace("real_dests=" + real_dests);

    if (real_dests.isEmpty()) {
      if (log.isTraceEnabled()) log.trace("destination list is empty, won't send message");
      return null;
    }

    if (options != null) {
      boolean async = options.getMode() == ResponseMode.GET_NONE;
      if (options.getAnycasting()) {
        if (async) async_anycasts.incrementAndGet();
        else sync_anycasts.incrementAndGet();
      } else {
        if (async) async_multicasts.incrementAndGet();
        else sync_multicasts.incrementAndGet();
      }
    }

    GroupRequest<T> req = new GroupRequest<T>(msg, corr, real_dests, options);
    if (listener != null) req.setListener(listener);
    if (options != null) {
      req.setResponseFilter(options.getRspFilter());
      req.setAnycasting(options.getAnycasting());
    }
    req.setBlockForResults(block_for_results);
    req.execute();
    return req;
  }
Beispiel #28
0
  @SuppressWarnings("unchecked")
  public void testObjectToFromByteBuffer() throws Exception {
    byte[] buf;
    Address addr = Util.createRandomAddress(), addr2;
    List<String> list = new ArrayList<>(), list2;
    list.add("Bela");
    list.add("Jeannette");

    buf = Util.objectToByteBuffer(addr);
    addr2 = (Address) Util.objectFromByteBuffer(buf);
    System.out.println("addr=" + addr + ", addr2=" + addr2);
    Assert.assertEquals(addr, addr2);

    buf = Util.objectToByteBuffer(list);
    list2 = (List<String>) Util.objectFromByteBuffer(buf);
    System.out.println("list=" + list + ", list2=" + list2);
    Assert.assertEquals(list, list2);

    byte[] buffer = {'B', 'e', 'l', 'a', ' ', 'B', 'a', 'n'};
    buf = Util.objectToByteBuffer(buffer);

    byte[] buffer2 = (byte[]) Util.objectFromByteBuffer(buf);
    assert buffer2 != null && buffer.length == buffer2.length;
    assert Arrays.equals(buffer, buffer2);

    Object obj = null;
    buf = Util.objectToByteBuffer(obj);
    assert buf != null;
    assert buf.length > 0;
    obj = Util.objectFromByteBuffer(buf);
    assert obj == null;

    Object[] values = {
      Boolean.TRUE,
      true,
      false,
      Boolean.FALSE,
      (byte) 22,
      new Byte("2"),
      '5',
      3.14,
      352.3f,
      0,
      100,
      322649,
      Integer.MAX_VALUE,
      Integer.MIN_VALUE,
      0L,
      322649L,
      Long.MAX_VALUE - 50,
      Long.MAX_VALUE,
      Long.MIN_VALUE,
      (short) 22,
      Short.MAX_VALUE,
      Short.MIN_VALUE,
      "Bela Ban",
      new byte[] {'H', 'e', 'l', 'l', 'o'},
      Util.generateArray(1024)
    };
    for (int i = 0; i < values.length; i++) {
      Object value = values[i];
      marshal(value);
    }
  }