com.gemstone.gemfire.internal.cache.versions.RVVExceptionB Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gemfire-core Show documentation
Show all versions of gemfire-core Show documentation
SnappyData store based off Pivotal GemFireXD
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;
}
}
}
}