Update of /cvsroot/freenet/Freenet0.7Rewrite/src/freenet/support
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7319/src/freenet/support
Modified Files:
Serializer.java
Added Files:
NumberedRecentItems.java NumberedItem.java
Log Message:
Build 136:
Initial publish/subscribe support.
Publish works. Subscribe requests are not yet routed; we just subscribe
locally, if the stream happens to pass through us.
--- NEW FILE: NumberedRecentItems.java ---
package freenet.support;
import java.util.Arrays;
import java.util.Comparator;
/**
* Keep the last N NumberedItem's by number. Supports fetching
* by number, fetching all items with number greater than a
* certain value, and inserting an item with a given number.
* Any items that don't fit are dropped from the end with the
* lower numerical value.
*/
public class NumberedRecentItems {
private NumberedItem[] items;
private int count;
private Comparator myComparator;
private boolean wrapAround;
/**
* Create a NumberedRecentItems list.
* @param maxSize The maximum number of NumberedItems to keep.
* @param wrap If true, comparisons are modulo 2^63-1.
* We calculate the direct and wrapped distance, and use
* whichever is shorter to determine the direction.
*/
public NumberedRecentItems(int maxSize, boolean wrap) {
items = new NumberedItem[maxSize];
count = 0;
wrapAround = wrap;
myComparator =
new Comparator() {
public int compare(Object o1, Object o2) {
int x = ocompare(o1, o2);
Logger.minor(this, "compare("+o1+","+o2+") = "+x);
return x;
}
public int ocompare(Object o1, Object o2) {
// Nulls at the end of the list
if(o1 == null && o2 == null)
return 0; // null == null
if(o1 != null && o2 == null)
return 1; // anything > null
if(o2 != null && o1 == null)
return -1;
long i1, i2;
if(o1 instanceof NumberedItem)
i1 = ((NumberedItem)o1).getNumber();
else if(o1 instanceof Long)
i1 = ((Long)o1).longValue();
else throw new ClassCastException(o1.toString());
if(o2 instanceof NumberedItem)
i2 = ((NumberedItem)o2).getNumber();
else if(o2 instanceof Long)
i2 = ((Long)o2).longValue();
else throw new ClassCastException(o2.toString());
if(i1 == i2) return 0;
if(!wrapAround) {
if(i1 > i2) return 1;
else return -1;
} else {
long firstDistance, secondDistance;
if(i1 > i2) {
firstDistance = i1 - i2; // smaller => i1 > i2
secondDistance = i2 + Long.MAX_VALUE - i1; // smaller
=> i2 > i1
} else {
secondDistance = i2 - i1; // smaller => i2 > i1
firstDistance = i1 + Long.MAX_VALUE - i2; // smaller =>
i1 > i2
}
if(Math.abs(firstDistance) < Math.abs(secondDistance)) {
return 1; // i1>i2
} else //if(Math.abs(secondDistance) <
Math.abs(firstDistance)) {
return -1; // i2>i1
// REDFLAG: base must be odd, so we never get ==
}
}
};
}
public synchronized NumberedItem get(int num) {
int x = java.util.Arrays.binarySearch(items, new Integer(num),
myComparator);
if(x >= 0) return items[x];
return null;
}
/**
* Add an item.
* @return True if we added a new item. Must return false if
* it was already present. Also returns false if the data is
* so old that we don't want it.
*/
public synchronized boolean add(NumberedItem item) {
long num = item.getNumber();
int x = Arrays.binarySearch(items, new Long(num), myComparator);
Logger.minor(this, "Search pos: "+x);
if(x >= 0) return false; // already present
count++;
if(x == -1) {
// insertion point = 0
// [0] > item
// do nothing
return false;
// if(count < items.length) {
//
// System.arraycopy(items, 0, items, 1, items.length);
// items[0] = item;
// } else {
// // [0] is greater than item, drop it
// return false;
// }
}
if(x == -(items.length)-1) {
// All items less than this item
// Shift back one, then set last item
System.arraycopy(items, 1, items, 0, items.length-1);
items[items.length-1] = item;
} else if(x == -2) {
// [1] is greater than item, [0] is less
items[0] = item;
} else {
// In the middle somewhere
int firstGreaterItem = (-x)-1;
// [firstGreaterItem]...[size-1] remain constant
// move the rest back one
System.arraycopy(items, 1, items, 0, firstGreaterItem-1);
items[firstGreaterItem-1] = item;
}
// FIXME: remove when confident
checkSorted();
return true;
}
private synchronized void checkSorted() {
long prevNum = -1;
for(int i=0;i<Math.min(count, items.length);i++) {
NumberedItem item = items[i];
long num = item == null ? -1 : item.getNumber();
if(item != null && num < 0)
throw new IllegalStateException("getNumber() must return
positive numbers");
if(num < prevNum || num != -1 && num == prevNum) {
throw new IllegalStateException("Must be higher than prev:
"+num+" "+prevNum);
}
prevNum = num;
}
}
public synchronized NumberedItem[] getAfter(int target) {
int x = Arrays.binarySearch(items, new Integer(target), myComparator);
if(x == items.length-1) return null;
if(x >= 0) {
NumberedItem[] out = new NumberedItem[items.length-x-1];
System.arraycopy(items, x+1, out, 0, items.length-x-1);
return out;
}
// Otherwise is not an exact match
if(x == -items.length-1) return null;
int firstGreater = (-x)-1;
NumberedItem[] out = new NumberedItem[items.length-firstGreater];
System.arraycopy(items, firstGreater, out, 0,
items.length-firstGreater);
return out;
}
}
--- NEW FILE: NumberedItem.java ---
package freenet.support;
/**
* An object with a number.
*/
public interface NumberedItem {
long getNumber();
}
Index: Serializer.java
===================================================================
RCS file:
/cvsroot/freenet/Freenet0.7Rewrite/src/freenet/support/Serializer.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -w -r1.4 -r1.5
--- Serializer.java 25 Aug 2005 17:28:19 -0000 1.4
+++ Serializer.java 15 Sep 2005 18:16:04 -0000 1.5
@@ -22,6 +22,7 @@
import freenet.io.*;
import freenet.io.comm.*;
import freenet.keys.Key;
+import freenet.keys.PublishStreamKey;
import java.io.*;
import java.util.*;
@@ -77,6 +78,8 @@
return new BitArray(dis);
} else if (type.equals(Key.class)) {
return Key.read(dis);
+ } else if (type.equals(PublishStreamKey.class)) {
+ return PublishStreamKey.read(dis, true);
} else {
throw new RuntimeException("Unrecognised field type: "
+ type);
}