Skip to content

Commit

Permalink
Added SeqnoList and test
Browse files Browse the repository at this point in the history
  • Loading branch information
belaban committed Dec 21, 2011
1 parent e79485a commit 2c7feec
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 0 deletions.
149 changes: 149 additions & 0 deletions src/org/jgroups/util/SeqnoList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package org.jgroups.util;

import java.io.DataInput;
import java.io.DataOutput;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

/**
* A list of sequence numbers (seqnos). Seqnos have to be added in ascending order, and can be single seqnos
* or seqno ranges (e.g. [5-10]). This class is unsynchronized. Note that for serialization, we assume that the
* lowest and highest seqno in the list are not more than 2 ^ 31 apart.
* @author Bela Ban
* @since 3.1
*/
public class SeqnoList implements Streamable, Iterable<Long> {
protected final List<Seqno> seqnos=new ArrayList<Seqno>();

public SeqnoList() {
}

/** Adds a single seqno */
public SeqnoList add(long seqno) {
seqnos.add(new Seqno(seqno));
return this;
}

public SeqnoList add(long ... seqnos) {
if(seqnos != null) {
for(long seqno: seqnos)
add(seqno);
}
return this;
}

/** Adds a seqno range */
public SeqnoList add(long from, long to) {
seqnos.add(new SeqnoRange(from, to));
return this;
}

public void writeTo(DataOutput out) throws Exception {
out.writeInt(seqnos.size());
for(Seqno seqno: seqnos) {
if(seqno instanceof SeqnoRange) {
SeqnoRange range=(SeqnoRange)seqno;
out.writeBoolean(true);
Util.writeLongSequence(range.from, range.to, out);
}
else {
out.writeBoolean(false);
Util.writeLong(seqno.from, out);
}
}
}

public void readFrom(DataInput in) throws Exception {
int len=in.readInt();
for(int i=0; i < len; i++) {
if(in.readBoolean()) {
long[] tmp=Util.readLongSequence(in);
seqnos.add(new SeqnoRange(tmp[0], tmp[1]));
}
else {
seqnos.add(new Seqno(Util.readLong(in)));
}
}
}

public int size() {
int retval=0;
for(Seqno seqno: seqnos) {
if(seqno instanceof SeqnoRange) {
SeqnoRange range=(SeqnoRange)seqno;
retval+=(range.to - range.from +1);
}
else
retval++;
}

return retval;
}

public String toString() {
return seqnos.toString();
}

public Iterator<Long> iterator() {
return new Iterator<Long>() {
protected int index=0;
protected SeqnoRange range=null;
protected long range_index=-1;

public boolean hasNext() {
return index +1 <= seqnos.size();
}

public Long next() {
if(range != null) {
if(range_index +1 <= range.to)
return range_index++;
else
range=null;
}
if(index >= seqnos.size())
throw new NoSuchElementException("index " + index + " is >= size " + seqnos.size());
Seqno next=seqnos.get(index++);
if(next instanceof SeqnoRange) {
range=(SeqnoRange)next;
range_index=range.from;
return range_index;
}
else
return next.from;
}

public void remove() { // not supported
}
};
}

protected static class Seqno {
protected long from;

public Seqno(long num) {
this.from=num;
}

public String toString() {
return String.valueOf(from);
}
}

protected static class SeqnoRange extends Seqno {
protected long to;

public SeqnoRange(long from, long to) {
super(from);
this.to=to;
if(to < from)
throw new IllegalArgumentException("to (" + to + ") needs to be >= from (" + from + ")");
}

public String toString() {
return super.toString() + "-" + to;
}
}
}
46 changes: 46 additions & 0 deletions tests/junit-functional/org/jgroups/tests/SeqnoListTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.jgroups.tests;

import org.jgroups.Global;
import org.jgroups.util.SeqnoList;
import org.jgroups.util.Util;
import org.testng.annotations.Test;

/**
* @author Bela Ban
* @since 3.1
*/
@Test(groups=Global.FUNCTIONAL)
public class SeqnoListTest {

public void testAddition() {
SeqnoList list=new SeqnoList().add(1).add(5,10).add(15);
System.out.println("list = " + list);
assert list.size() == 8;
}

public void testIteration() {
SeqnoList list=new SeqnoList().add(1).add(5,10).add(15);
System.out.println("list = " + list);
int count=0;
for(long num: list) {
System.out.print(num + " ");
count++;
}

assert count == list.size();
}

public void testSerialization() throws Exception {
SeqnoList list=new SeqnoList().add(1, 10, 50)
.add(100,150).add(152,153).add(200,205).add(300,304,306).add(400,450).add(500);
for(int i=502; i < 550; i+=2)
list.add(i);


System.out.println("list.size()=" + list.size() + "\nlist = " + list);
byte[] buf=Util.streamableToByteBuffer(list);
SeqnoList list2=(SeqnoList)Util.streamableFromByteBuffer(SeqnoList.class,buf);
System.out.println("list2.size()=" + list2.size() + "\nlist2 = " + list2);
assert list.size() == list2.size();
}
}

0 comments on commit 2c7feec

Please sign in to comment.