All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gemstone.gemfire.internal.cache.versions.RVVExceptionB Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License. You
 * may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License. See accompanying
 * LICENSE file.
 */
package com.gemstone.gemfire.internal.cache.versions;

import java.io.DataOutput;
import java.io.IOException;
import java.util.BitSet;
import java.util.NoSuchElementException;

import com.gemstone.gemfire.internal.InternalDataSerializer;

public class RVVExceptionB extends RVVException {

  /**
   * received represents individual received versions that fall within this
   * exception.  position 0 corresponds to version receivedBaseVersion.
   */
  BitSet received;
  private long receivedBaseVersion;
  
  public RVVExceptionB(long previousVersion, long nextVersion) {
    super(previousVersion, nextVersion);
  }


  /**
   * add a received version
   */
  public void add(long receivedVersion) {
//    String me = this.toString();
//    long oldv = this.nextVersion;
    if (receivedVersion == this.previousVersion+1) {
      this.previousVersion = receivedVersion;
      if (this.received != null) {
        addReceived(receivedVersion);
        consumeReceivedVersions();
      }
    } else if (receivedVersion == this.nextVersion-1) {
      this.nextVersion = receivedVersion;
      if (this.received != null) {
        addReceived(receivedVersion);
        consumeReceivedVersions();
      }
    } else if (this.previousVersion < receivedVersion  &&  receivedVersion < this.nextVersion) {
      addReceived(receivedVersion);
    }
//    if (this.nextVersion == 29 && oldv != 29) {
//      System.out.println("before=" + me + "\nafter=" + this + "\nadded "+receivedVersion);
//    }
  }

  
  protected void addReceived(long rv) {
    if (this.received == null) {
      this.receivedBaseVersion = this.previousVersion+1;
      if (this.nextVersion > this.previousVersion) { // next version not known during deserialization
        long size = this.nextVersion - this.previousVersion;
        this.received = new BitSet((int)size);
      }
      else {
        this.received = new BitSet();
      }
    }
//    Assert.assertTrue(this.receivedBaseVersion > 0, "should not have a base version of zero.  rv=" + rv + " ex=" + this);
//    Assert.assertTrue(rv >= this.receivedBaseVersion,
//        "attempt to record a version not in this exception. version=" + rv + " exception=" + this);
    this.received.set((int)(rv - this.receivedBaseVersion));
  }
  
  /**
   * checks to see if any of the received versions can be merged into the
   * start/end version numbers
   */
  private void consumeReceivedVersions() {
    int idx = (int)(this.previousVersion - this.receivedBaseVersion + 1);
    while (this.previousVersion < this.nextVersion && this.received.get(idx)) {
      idx++;
      this.previousVersion++;
    }
    if (this.previousVersion < this.nextVersion) {
      idx = (int)(this.nextVersion - this.receivedBaseVersion)-1;
      while (this.previousVersion < this.nextVersion && this.received.get(idx)) {
        idx--;
        this.nextVersion--;
      }
    }
  }
  

  /* (non-Javadoc)
   * @see java.lang.Comparable#compareTo(java.lang.Object)
   */
  public int compareTo(RVVException o) {
    long thisVal = this.previousVersion;
    long anotherVal = o.previousVersion;
    return (thisVal=0) {
        sb.append(i);
        for (i=this.received.nextSetBit(i+1); (0 < i) && (i < lastBit); i=this.received.nextSetBit(i+1)) {
          sb.append(',').append(i);
        }
      }
      sb.append(']');
      return sb.toString();
    }
    return "e(n="+this.nextVersion+" p=" + this.previousVersion + "; rb=[])";
  }

//  @Override
//  public int hashCode() {
//    final int prime = 31;
//    int result = 1;
//    result = prime * result + (int) (nextVersion ^ (nextVersion >>> 32));
//    result = prime * result
//        + (int) (previousVersion ^ (previousVersion >>> 32));
//    result = prime * result + ((this.received == null) ? 0 : this.received.hashCode());
//    return result;
//  }

  /** For test purposes only. This
   * isn't quite accurate, because I think two
   * RVVs that have effectively same exceptions
   * may represent the exceptions differently. This
   * method is testing for an exact match of exception format.
   */
  @Override
  public boolean sameAs(RVVException ex) {
    if (ex instanceof RVVExceptionT) {
      return ((RVVExceptionT)ex).sameAs(this); 
    }
    if (!super.sameAs(ex)) {
      return false;
    }
    RVVExceptionB other = (RVVExceptionB) ex;
    if (this.received == null) {
      if (other.received != null && !other.received.isEmpty()) {
        return false;
      }
    } else if (!this.received.equals(other.received))
      return false;
    return true;
  }
  
  /** has the given version been recorded as having been received? */
  public boolean contains(long version) {
    if (version <= this.previousVersion) {
      return false;
    }
    return (this.received != null && this.received.get((int)(version-this.receivedBaseVersion)));
  }

  /** return false if any revisions have been recorded in the range of this exception */
  public boolean isEmpty() {
    return (this.received == null) || (this.received.isEmpty());
  }
  
  public ReceivedVersionsIterator receivedVersionsIterator() {
    ReceivedVersionsIteratorB result = new ReceivedVersionsIteratorB();
    result.initForForwardIteration();
    return result;
  }
  
  @Override
  public long getHighestReceivedVersion() {
    if(isEmpty()) {
      return this.previousVersion;
    } else {
      //Note, the "length" of the bitset is the highest set bit + 1,
      //see the javadocs. That's why this works to return the highest
      //received version
      return receivedBaseVersion + received.length() - 1;
    }
    
  }




  /** it's a shame that BitSet has no iterator */
  protected class ReceivedVersionsIteratorB extends ReceivedVersionsIterator  {
    int index;
    int nextIndex;

    void initForForwardIteration() {
      this.index = -1;
      if (received == null) {
        this.nextIndex = -1;
      } else {
        this.nextIndex = received.nextSetBit((int)(previousVersion - receivedBaseVersion + 1));
        if (this.nextIndex + receivedBaseVersion >= nextVersion) {
          this.nextIndex = -1;
        }
      }
    }
    
    boolean hasNext() {
      return this.nextIndex >= 0;
    }
    
    long next() {
      this.index = this.nextIndex;
      if (this.index < 0) {
        throw new NoSuchElementException("no more elements available"); 
      }
      advance();
      return this.index + receivedBaseVersion;
    }
    
    void remove() {
      if (this.index < 0) {
        throw new NoSuchElementException("no more elements available"); 
      }
      received.clear(this.index);
    }

    private void advance() {
      this.nextIndex = received.nextSetBit(this.index+1);
      if ((this.nextIndex + receivedBaseVersion) >= nextVersion) {
        this.nextIndex = -1;
      }
    }
    
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy