Пример #1
0
  /**
   * Return a context w/ an aggregated count for each counter id.
   *
   * @param left counter context.
   * @param right counter context.
   */
  public ByteBuffer merge(ByteBuffer left, ByteBuffer right) {
    boolean leftIsSuperSet = true;
    boolean rightIsSuperSet = true;

    int globalCount = 0;
    int localCount = 0;
    int remoteCount = 0;

    ContextState leftState = ContextState.wrap(left);
    ContextState rightState = ContextState.wrap(right);

    while (leftState.hasRemaining() && rightState.hasRemaining()) {
      int cmp = leftState.compareIdTo(rightState);
      if (cmp == 0) {
        Relationship rel = compare(leftState, rightState);
        if (rel == Relationship.GREATER_THAN) rightIsSuperSet = false;
        else if (rel == Relationship.LESS_THAN) leftIsSuperSet = false;
        else if (rel == Relationship.DISJOINT) leftIsSuperSet = rightIsSuperSet = false;

        if (leftState.isGlobal() || rightState.isGlobal()) globalCount += 1;
        else if (leftState.isLocal() || rightState.isLocal()) localCount += 1;
        else remoteCount += 1;

        leftState.moveToNext();
        rightState.moveToNext();
      } else if (cmp > 0) {
        leftIsSuperSet = false;

        if (rightState.isGlobal()) globalCount += 1;
        else if (rightState.isLocal()) localCount += 1;
        else remoteCount += 1;

        rightState.moveToNext();
      } else // cmp < 0
      {
        rightIsSuperSet = false;

        if (leftState.isGlobal()) globalCount += 1;
        else if (leftState.isLocal()) localCount += 1;
        else remoteCount += 1;

        leftState.moveToNext();
      }
    }

    if (leftState.hasRemaining()) rightIsSuperSet = false;
    else if (rightState.hasRemaining()) leftIsSuperSet = false;

    // if one of the contexts is a superset, return it early.
    if (leftIsSuperSet) return left;
    else if (rightIsSuperSet) return right;

    while (leftState.hasRemaining()) {
      if (leftState.isGlobal()) globalCount += 1;
      else if (leftState.isLocal()) localCount += 1;
      else remoteCount += 1;

      leftState.moveToNext();
    }

    while (rightState.hasRemaining()) {
      if (rightState.isGlobal()) globalCount += 1;
      else if (rightState.isLocal()) localCount += 1;
      else remoteCount += 1;

      rightState.moveToNext();
    }

    leftState.reset();
    rightState.reset();

    return merge(
        ContextState.allocate(globalCount, localCount, remoteCount), leftState, rightState);
  }