/**
   * Canonicalize an ordered set of exceptions. In the canonical form, none of the RVVExceptions
   * have any received versions.
   *
   * @param exceptions
   * @return The canonicalized set of exceptions.
   */
  protected List<RVVException> canonicalExceptions(List<RVVException> exceptions) {
    LinkedList<RVVException> canon = new LinkedList<RVVException>();
    if (exceptions != null) {
      // Iterate through the set of exceptions
      for (RVVException exception : exceptions) {
        if (exception.isEmpty()) {
          canon.add(exception);
        } else {
          long previous = exception.previousVersion;
          // Iterate through the set of received versions for this exception
          int insertAt = canon.size();
          for (ReceivedVersionsIterator it = exception.receivedVersionsIterator(); it.hasNext(); ) {
            Long received = it.next();
            // If we find a gap between the previous received version and the
            // next received version, add an exception.
            if (received != previous + 1) {
              canon.add(insertAt, RVVException.createException(previous, received));
            }
            // move the previous reference
            previous = received;
          }

          // if there is a gap between the last received version and the next
          // version, add an exception
          // this also handles the case where the RVV has no received versions,
          // because previous==exception.previousVersion in that case.
          if (exception.nextVersion != previous + 1) {
            canon.add(insertAt, RVVException.createException(previous, exception.nextVersion));
          }
        }
      }
    }
    return canon;
  }
 /** Add an exception that is older than this.bitSetVersion. */
 protected synchronized void addException(long previousVersion, long nextVersion) {
   if (this.exceptions == null) {
     this.exceptions = new LinkedList<RVVException>();
   }
   int i = 0;
   for (Iterator<RVVException> it = this.exceptions.iterator(); it.hasNext(); i++) {
     RVVException e = it.next();
     if (previousVersion >= e.nextVersion) {
       RVVException except = RVVException.createException(previousVersion, nextVersion);
       this.exceptions.add(i, except);
       return;
     }
   }
   this.exceptions.add(RVVException.createException(previousVersion, nextVersion));
 }
 /* (non-Javadoc)
  * @see com.gemstone.gemfire.DataSerializable#fromData(java.io.DataInput)
  */
 public void fromData(DataInput in) throws IOException {
   this.version = InternalDataSerializer.readUnsignedVL(in);
   int size = (int) InternalDataSerializer.readUnsignedVL(in);
   this.isDepartedMember = in.readBoolean();
   if (size > 0) {
     this.exceptions = new LinkedList<RVVException>();
     for (int i = 0; i < size; i++) {
       RVVException e = RVVException.createException(in);
       this.exceptions.add(e);
     }
   }
 }
  /**
   * Initialize this version holder from another version holder This is called during GII.
   *
   * <p>It's more likely that the other holder has seen most of the versions, and this version
   * holder only has a few updates that happened since the GII started. So we apply our seen
   * versions to the other version holder and then initialize this version holder from the other
   * version holder.
   */
  public synchronized void initializeFrom(RegionVersionHolder<T> source) {
    // Make sure the bitsets are merged in both the source
    // and this vector
    mergeBitSet();

    RegionVersionHolder<T> other = source.clone();
    other.mergeBitSet();
    // Get a copy of the local version and exceptions
    long myVersion = this.version;

    // initialize our version and exceptions to match the others
    this.exceptions = other.exceptions;
    this.version = other.version;

    // Initialize the bit set to be empty. Merge bit set should
    // have already done this, but just to be sure.
    if (this.bitSet != null) {
      this.bitSetVersion = this.version;
      // Make sure the bit set is empty except for the first, bit, indicating
      // that the version has been received.
      this.bitSet.set(0);
    }

    // Now if this.version/exceptions overlap with myVersion/myExceptions, use this'
    // The only case needs special handling is: if myVersion is newer than this.version,
    // should create an exception (this.version+1, myversion) and set this.version=myversion
    if (myVersion > this.version) {
      RVVException e = RVVException.createException(this.version, myVersion + 1);
      // add special exception
      if (this.exceptions == null) {
        this.exceptions = new LinkedList<RVVException>();
      }
      int i = 0;
      for (RVVException exception : this.exceptions) {
        if (e.compareTo(exception) >= 0) {
          break;
        }
        i++;
      }
      this.exceptions.add(i, e);
      this.version = myVersion;
    }
  }