Author: toad
Date: 2006-01-12 18:39:32 +0000 (Thu, 12 Jan 2006)
New Revision: 7845
Modified:
trunk/freenet/src/freenet/crypt/DSAPublicKey.java
trunk/freenet/src/freenet/io/comm/UdpSocketManager.java
trunk/freenet/src/freenet/keys/InsertableClientSSK.java
trunk/freenet/src/freenet/keys/NodeSSK.java
trunk/freenet/src/freenet/keys/SSKBlock.java
trunk/freenet/src/freenet/node/Node.java
trunk/freenet/src/freenet/node/RequestHandler.java
trunk/freenet/src/freenet/node/RequestSender.java
trunk/freenet/src/freenet/node/Version.java
trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java
trunk/freenet/src/freenet/store/FreenetStore.java
Log:
343: (mandatory)
SSKs *sometimes* work. :)
Modified: trunk/freenet/src/freenet/crypt/DSAPublicKey.java
===================================================================
--- trunk/freenet/src/freenet/crypt/DSAPublicKey.java 2006-01-12 18:33:28 UTC
(rev 7844)
+++ trunk/freenet/src/freenet/crypt/DSAPublicKey.java 2006-01-12 18:39:32 UTC
(rev 7845)
@@ -13,6 +13,8 @@
private final BigInteger y;
/** A cache of the hexadecimal string representation of y */
private final String yAsHexString;
+
+ public static final int PADDED_SIZE = 660;
private final DSAGroup group;
@@ -131,6 +133,17 @@
return bytes;
}
+ public byte[] asPaddedBytes() {
+ byte[] asBytes = asBytes();
+ if(asBytes.length == PADDED_SIZE)
+ return asBytes;
+ if(asBytes.length > PADDED_SIZE)
+ throw new Error("Cannot fit key in "+PADDED_SIZE+" - real size
is "+asBytes.length);
+ byte[] padded = new byte[PADDED_SIZE];
+ System.arraycopy(asBytes, 0, padded, 0, asBytes.length);
+ return padded;
+ }
+
public byte[] fingerprint() {
synchronized(this) {
if(fingerprint == null)
Modified: trunk/freenet/src/freenet/io/comm/UdpSocketManager.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/UdpSocketManager.java 2006-01-12
18:33:28 UTC (rev 7844)
+++ trunk/freenet/src/freenet/io/comm/UdpSocketManager.java 2006-01-12
18:39:32 UTC (rev 7845)
@@ -322,10 +322,11 @@
i.remove();
ret = m;
Logger.debug(this, "Matching from
_unclaimed");
+ break;
}
}
- Logger.minor(this, "Not in _unclaimed");
if (ret == null) {
+ Logger.minor(this, "Not in _unclaimed");
// Insert filter into filter list in order of
timeout
ListIterator i = _filters.listIterator();
while (true) {
@@ -354,7 +355,7 @@
// Precaution against filter getting
matched between being added to _filters and
// here - bug discovered by Mason
boolean fmatched = false;
- while(!(fmatched = filter.matched() ||
filter.droppedConnection() != null)) {
+ while(!(fmatched = (filter.matched() ||
filter.droppedConnection() != null))) {
long wait =
filter.getTimeout()-System.currentTimeMillis();
if(wait > 0)
filter.wait(wait);
Modified: trunk/freenet/src/freenet/keys/InsertableClientSSK.java
===================================================================
--- trunk/freenet/src/freenet/keys/InsertableClientSSK.java 2006-01-12
18:33:28 UTC (rev 7844)
+++ trunk/freenet/src/freenet/keys/InsertableClientSSK.java 2006-01-12
18:39:32 UTC (rev 7845)
@@ -97,6 +97,7 @@
aes.initialize(origDataHash);
PCFBMode pcfb = new PCFBMode(aes);
+ pcfb.reset(origDataHash);
pcfb.blockEncipher(data, 0, data.length);
Modified: trunk/freenet/src/freenet/keys/NodeSSK.java
===================================================================
--- trunk/freenet/src/freenet/keys/NodeSSK.java 2006-01-12 18:33:28 UTC (rev
7844)
+++ trunk/freenet/src/freenet/keys/NodeSSK.java 2006-01-12 18:39:32 UTC (rev
7845)
@@ -99,7 +99,7 @@
public void setPubKey(DSAPublicKey pubKey2) {
if(pubKey == pubKey2) return;
- if(pubKey != null) throw new IllegalStateException("Already
assigned pubkey to different value! Old="+pubKey.writeAsField()+",
new="+pubKey2.writeAsField());
+ if(pubKey != null && !pubKey.equals(pubKey2)) throw new
IllegalStateException("Already assigned pubkey to different value!
Old="+pubKey.writeAsField()+", new="+pubKey2.writeAsField());
this.pubKey = pubKey2;
}
Modified: trunk/freenet/src/freenet/keys/SSKBlock.java
===================================================================
--- trunk/freenet/src/freenet/keys/SSKBlock.java 2006-01-12 18:33:28 UTC
(rev 7844)
+++ trunk/freenet/src/freenet/keys/SSKBlock.java 2006-01-12 18:39:32 UTC
(rev 7845)
@@ -132,4 +132,8 @@
return data;
}
+ public DSAPublicKey getPubKey() {
+ return pubKey;
+ }
+
}
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2006-01-12 18:33:28 UTC (rev
7844)
+++ trunk/freenet/src/freenet/node/Node.java 2006-01-12 18:39:32 UTC (rev
7845)
@@ -129,6 +129,8 @@
private final FreenetStore chkDatastore;
/** The SSK datastore */
private final FreenetStore sskDatastore;
+ /** The store of DSAPublicKeys (by hash) */
+ private final FreenetStore pubKeyDatastore;
/** RequestSender's currently running, by KeyHTLPair */
private final HashMap requestSenders;
/** RequestSender's currently transferring, by key */
@@ -357,6 +359,7 @@
try {
chkDatastore = new
BerkeleyDBFreenetStore(prefix+"store-"+portNumber, maxStoreKeys, 32768,
CHKBlock.TOTAL_HEADERS_LENGTH);
sskDatastore = new
BerkeleyDBFreenetStore(prefix+"sskstore-"+portNumber, maxStoreKeys, 1024,
SSKBlock.TOTAL_HEADERS_LENGTH);
+ pubKeyDatastore = new
BerkeleyDBFreenetStore(prefix+"pubkeystore-"+portNumber, maxStoreKeys,
DSAPublicKey.PADDED_SIZE, 0);
} catch (FileNotFoundException e1) {
Logger.error(this, "Could not open datastore: "+e1, e1);
System.err.println("Could not open datastore: "+e1);
@@ -548,6 +551,7 @@
case RequestSender.GENERATED_REJECTED_OVERLOAD:
case RequestSender.TIMED_OUT:
throw new
LowLevelGetException(LowLevelGetException.REJECTED_OVERLOAD);
+ case RequestSender.INTERNAL_ERROR:
default:
Logger.error(this, "Unknown RequestSender code
in getCHK: "+rs.getStatus()+" on "+rs);
throw new
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR);
@@ -570,7 +574,9 @@
Object o = makeRequestSender(key.getNodeKey(), MAX_HTL, uid, null,
lm.loc.getValue(), localOnly, cache);
if(o instanceof SSKBlock) {
try {
- return new ClientSSKBlock((SSKBlock)o, key);
+ SSKBlock block = (SSKBlock)o;
+ key.setPublicKey(block.getPubKey());
+ return new ClientSSKBlock(block, key);
} catch (SSKVerifyException e) {
Logger.error(this, "Does not verify: "+e, e);
throw new
LowLevelGetException(LowLevelGetException.DECODE_FAILED);
@@ -610,7 +616,9 @@
if(rs.getStatus() == RequestSender.SUCCESS) {
try {
- return new ClientSSKBlock(rs.getSSKBlock(),
key);
+ SSKBlock block = rs.getSSKBlock();
+ key.setPublicKey(block.getPubKey());
+ return new ClientSSKBlock(block, key);
} catch (SSKVerifyException e) {
Logger.error(this, "Does not verify: "+e, e);
throw new
LowLevelGetException(LowLevelGetException.DECODE_FAILED);
@@ -632,6 +640,7 @@
case RequestSender.GENERATED_REJECTED_OVERLOAD:
case RequestSender.TIMED_OUT:
throw new
LowLevelGetException(LowLevelGetException.REJECTED_OVERLOAD);
+ case RequestSender.INTERNAL_ERROR:
default:
Logger.error(this, "Unknown RequestSender code
in getCHK: "+rs.getStatus()+" on "+rs);
throw new
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR);
@@ -958,9 +967,16 @@
try {
if(key instanceof NodeCHK)
chk = chkDatastore.fetch((NodeCHK)key, !cache);
- else if(key instanceof NodeSSK)
- chk = sskDatastore.fetch((NodeSSK)key, !cache);
- else
+ else if(key instanceof NodeSSK) {
+ NodeSSK k = (NodeSSK)key;
+ DSAPublicKey pubKey = k.getPubKey();
+ if(pubKey == null) {
+ pubKey = getKey(k.getPubKeyHash());
+ k.setPubKey(pubKey);
+ }
+ if(pubKey != null)
+ chk = sskDatastore.fetch((NodeSSK)key, !cache);
+ } else
throw new IllegalStateException("Unknown key type:
"+key.getClass());
} catch (IOException e) {
Logger.error(this, "Error accessing store: "+e, e);
@@ -1049,6 +1065,7 @@
public synchronized void store(SSKBlock block) {
try {
sskDatastore.put(block);
+ cacheKey(((NodeSSK)block.getKey()).getPubKeyHash(),
((NodeSSK)block.getKey()).getPubKey());
} catch (IOException e) {
Logger.error(this, "Cannot store data: "+e, e);
}
@@ -1153,6 +1170,10 @@
public synchronized SSKInsertSender makeInsertSender(SSKBlock block, short
htl, long uid, PeerNode source,
boolean fromStore, double closestLoc, boolean cache) {
NodeSSK key = (NodeSSK) block.getKey();
+ if(key.getPubKey() == null) {
+ throw new IllegalArgumentException("No pub key when inserting");
+ }
+ cacheKey(key.getPubKeyHash(), key.getPubKey());
Logger.minor(this,
"makeInsertSender("+key+","+htl+","+uid+","+source+",...,"+fromStore);
KeyHTLPair kh = new KeyHTLPair(key, htl);
SSKInsertSender is = (SSKInsertSender) insertSenders.get(kh);
@@ -1335,9 +1356,21 @@
ImmutableByteArrayWrapper w = new
ImmutableByteArrayWrapper(hash);
synchronized(cachedPubKeys) {
DSAPublicKey key = (DSAPublicKey) cachedPubKeys.get(w);
- if(key != null)
+ if(key != null) {
cachedPubKeys.push(w, key);
+ return key;
+ }
+ }
+ try {
+ DSAPublicKey key = pubKeyDatastore.fetchPubKey(hash,
false);
+ if(key != null) {
+ cacheKey(hash, key);
+ }
return key;
+ } catch (IOException e) {
+ // FIXME deal with disk full, access perms etc; tell
user about it.
+ Logger.error(this, "Error accessing pubkey store: "+e,
e);
+ return null;
}
}
@@ -1354,5 +1387,11 @@
while(cachedPubKeys.size() > MAX_CACHED_KEYS)
cachedPubKeys.popKey();
}
+ try {
+ pubKeyDatastore.put(hash, key);
+ } catch (IOException e) {
+ // FIXME deal with disk full, access perms etc; tell
user about it.
+ Logger.error(this, "Error accessing pubkey store: "+e,
e);
+ }
}
}
Modified: trunk/freenet/src/freenet/node/RequestHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestHandler.java 2006-01-12 18:33:28 UTC
(rev 7844)
+++ trunk/freenet/src/freenet/node/RequestHandler.java 2006-01-12 18:39:32 UTC
(rev 7845)
@@ -25,6 +25,7 @@
private short htl;
final PeerNode source;
private double closestLoc;
+ private boolean needsPubKey;
final Key key;
public String toString() {
@@ -44,6 +45,8 @@
double keyLoc = key.toNormalizedDouble();
if(Math.abs(keyLoc - myLoc) < Math.abs(keyLoc - closestLoc))
closestLoc = myLoc;
+ if(key instanceof NodeSSK)
+ needsPubKey = m.getBoolean(DMT.NEED_PUB_KEY);
}
public void run() {
@@ -59,6 +62,12 @@
KeyBlock block = (KeyBlock) o;
Message df = createDataFound(block);
source.send(df);
+ if(key instanceof NodeSSK) {
+ if(needsPubKey) {
+ Message pk = DMT.createFNPSSKPubKey(uid,
((NodeSSK)block.getKey()).getPubKey().asBytes());
+ source.send(pk);
+ }
+ }
if(block instanceof CHKBlock) {
PartiallyReceivedBlock prb =
new PartiallyReceivedBlock(Node.PACKETS_IN_BLOCK,
Node.PACKET_SIZE, block.getRawData());
@@ -108,6 +117,7 @@
return;
case RequestSender.GENERATED_REJECTED_OVERLOAD:
case RequestSender.TIMED_OUT:
+ case RequestSender.INTERNAL_ERROR:
// Locally generated.
// Propagate back to source who needs to reduce send rate
Message reject = DMT.createFNPRejectedOverload(uid, true);
@@ -122,10 +132,14 @@
if(key instanceof NodeSSK) {
Message df = DMT.createFNPSSKDataFound(uid,
rs.getHeaders(), rs.getSSKData());
source.send(df);
+ if(needsPubKey) {
+ Message pk = DMT.createFNPSSKPubKey(uid,
((NodeSSK)rs.getSSKBlock().getKey()).getPubKey().asBytes());
+ source.send(df);
+ }
} else if(!rs.transferStarted()) {
Logger.error(this, "Status is SUCCESS but we
never started a transfer on "+uid);
}
- case RequestSender.TRANSFER_FAILED:
+ return;
case RequestSender.VERIFY_FAILURE:
if(key instanceof NodeCHK) {
if(shouldHaveStartedTransfer)
@@ -133,6 +147,18 @@
shouldHaveStartedTransfer = true;
continue; // should have started transfer
}
+ reject = DMT.createFNPRejectedOverload(uid, true);
+ source.sendAsync(reject, null);
+ return;
+ case RequestSender.TRANSFER_FAILED:
+ if(key instanceof NodeCHK) {
+ if(shouldHaveStartedTransfer)
+ throw new IllegalStateException("Got
status code "+status+" but transfer not started");
+ shouldHaveStartedTransfer = true;
+ continue; // should have started transfer
+ }
+ // Other side knows, right?
+ return;
default:
throw new IllegalStateException("Unknown status code
"+status);
}
Modified: trunk/freenet/src/freenet/node/RequestSender.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestSender.java 2006-01-12 18:33:28 UTC
(rev 7844)
+++ trunk/freenet/src/freenet/node/RequestSender.java 2006-01-12 18:39:32 UTC
(rev 7845)
@@ -8,12 +8,10 @@
import freenet.io.comm.DisconnectedException;
import freenet.io.comm.Message;
import freenet.io.comm.MessageFilter;
-import freenet.io.comm.NotConnectedException;
import freenet.io.comm.RetrievalException;
import freenet.io.xfer.BlockReceiver;
import freenet.io.xfer.PartiallyReceivedBlock;
import freenet.keys.CHKBlock;
-import freenet.keys.CHKVerifyException;
import freenet.keys.Key;
import freenet.keys.KeyVerifyException;
import freenet.keys.NodeCHK;
@@ -69,6 +67,7 @@
static final int VERIFY_FAILURE = 5;
static final int TIMED_OUT = 6;
static final int GENERATED_REJECTED_OVERLOAD = 7;
+ static final int INTERNAL_ERROR = 8;
@@ -225,8 +224,12 @@
MessageFilter mfDF = makeDataFoundFilter(next);
MessageFilter mfRouteNotFound =
MessageFilter.create().setSource(next).setField(DMT.UID,
uid).setTimeout(FETCH_TIMEOUT).setType(DMT.FNPRouteNotFound);
MessageFilter mfRejectedOverload =
MessageFilter.create().setSource(next).setField(DMT.UID,
uid).setTimeout(FETCH_TIMEOUT).setType(DMT.FNPRejectedOverload);
- MessageFilter mf =
mfDNF.or(mfDF.or(mfRouteNotFound.or(mfRejectedOverload)));
+ MessageFilter mfPubKey =
MessageFilter.create().setSource(next).setField(DMT.UID,
uid).setTimeout(FETCH_TIMEOUT).setType(DMT.FNPSSKPubKey);
+ MessageFilter mfRealDFCHK =
MessageFilter.create().setSource(next).setField(DMT.UID,
uid).setTimeout(FETCH_TIMEOUT).setType(DMT.FNPCHKDataFound);
+ MessageFilter mfRealDFSSK =
MessageFilter.create().setSource(next).setField(DMT.UID,
uid).setTimeout(FETCH_TIMEOUT).setType(DMT.FNPSSKDataFound);
+ MessageFilter mf =
mfDNF.or(mfRouteNotFound.or(mfRejectedOverload.or(mfDF.or(mfPubKey.or(mfRealDFCHK.or(mfRealDFSSK))))));
+
try {
msg = node.usm.waitFor(mf);
} catch (DisconnectedException e) {
@@ -333,6 +336,7 @@
byte[] pubkeyAsBytes =
((ShortBuffer)msg.getObject(DMT.PUBKEY_AS_BYTES)).getData();
try {
pubKey = new
DSAPublicKey(pubkeyAsBytes);
+ ((NodeSSK)key).setPubKey(pubKey);
} catch (IOException e) {
Logger.error(this, "Invalid pubkey from
"+source+" on "+uid);
finish(VERIFY_FAILURE, next);
@@ -349,7 +353,7 @@
Logger.minor(this, "Got data on "+uid);
- if(!(key instanceof NodeCHK)) {
+ if(!(key instanceof NodeSSK)) {
Logger.error(this, "Got "+msg+" but expected a
different key type from "+next);
break;
}
@@ -371,6 +375,7 @@
}
} catch (Throwable t) {
Logger.error(this, "Caught "+t, t);
+ finish(INTERNAL_ERROR, null);
} finally {
Logger.minor(this, "Leaving RequestSender.run() for "+uid);
node.completed(uid);
@@ -384,17 +389,21 @@
node.store(block);
finish(SUCCESS, next);
} catch (SSKVerifyException e) {
- Logger.error(this, "Failed to verify: "+e+" from
"+next);
+ Logger.error(this, "Failed to verify: "+e+" from
"+next, e);
finish(VERIFY_FAILURE, next);
return;
}
}
+ /**
+ * Note that this must be first on the list.
+ */
private MessageFilter makeDataFoundFilter(PeerNode next) {
if(key instanceof NodeCHK)
return MessageFilter.create().setSource(next).setField(DMT.UID,
uid).setTimeout(FETCH_TIMEOUT).setType(DMT.FNPCHKDataFound);
- else if(key instanceof NodeSSK)
+ else if(key instanceof NodeSSK) {
return MessageFilter.create().setSource(next).setField(DMT.UID,
uid).setTimeout(FETCH_TIMEOUT).setType(DMT.FNPSSKDataFound);
+ }
else throw new IllegalStateException("Unknown keytype: "+key);
}
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-01-12 18:33:28 UTC (rev
7844)
+++ trunk/freenet/src/freenet/node/Version.java 2006-01-12 18:39:32 UTC (rev
7845)
@@ -20,10 +20,10 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- public static final int buildNumber = 342;
+ public static final int buildNumber = 343;
/** Oldest build of Fred we will talk to */
- public static final int lastGoodBuild = 342;
+ public static final int lastGoodBuild = 343;
/** The highest reported build of fred */
public static int highestSeenBuild = buildNumber;
Modified: trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java
===================================================================
--- trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java 2006-01-12
18:33:28 UTC (rev 7844)
+++ trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java 2006-01-12
18:39:32 UTC (rev 7845)
@@ -23,6 +23,7 @@
import com.sleepycat.je.SecondaryKeyCreator;
import com.sleepycat.je.Transaction;
+import freenet.crypt.DSAPublicKey;
import freenet.keys.CHKBlock;
import freenet.keys.CHKVerifyException;
import freenet.keys.KeyBlock;
@@ -31,6 +32,7 @@
import freenet.keys.SSKBlock;
import freenet.keys.SSKVerifyException;
import freenet.support.Fields;
+import freenet.support.HexUtil;
import freenet.support.Logger;
/**
@@ -264,7 +266,7 @@
Logger.minor(this, "Data: "+data.length+" bytes, hash
"+data);
}catch(SSKVerifyException ex){
- Logger.normal(this, "Does not verify, setting
accessTime to 0 for : "+chk);
+ Logger.normal(this, "Does not verify, setting
accessTime to 0 for : "+chk, ex);
storeBlock.setRecentlyUsedToZero();
DatabaseEntry updateDBE = new DatabaseEntry();
storeBlockTupleBinding.objectToEntry(storeBlock,
updateDBE);
@@ -286,6 +288,78 @@
// return null;
}
+ // FIXME do this with interfaces etc.
+
+ /**
+ * Retrieve a block.
+ * @param dontPromote If true, don't promote data if fetched.
+ * @return null if there is no such block stored, otherwise the block.
+ */
+ public DSAPublicKey fetchPubKey(byte[] hash, boolean dontPromote) throws
IOException
+ {
+ if(closed)
+ return null;
+
+ DatabaseEntry routingkeyDBE = new DatabaseEntry(hash);
+ DatabaseEntry blockDBE = new DatabaseEntry();
+ Cursor c = null;
+ try{
+ Transaction t = environment.beginTransaction(null,null);
+ c = chkDB.openCursor(t,null);
+
+ if(c.getSearchKey(routingkeyDBE,blockDBE,LockMode.DEFAULT)
+ !=OperationStatus.SUCCESS) {
+ c.close();
+ t.abort();
+ return null;
+ }
+
+ StoreBlock storeBlock = (StoreBlock)
storeBlockTupleBinding.entryToObject(blockDBE);
+
+ DSAPublicKey block = null;
+
+ byte[] data = new byte[dataBlockSize];
+ synchronized(chkStore) {
+
chkStore.seek(storeBlock.offset*(long)(dataBlockSize+headerBlockSize));
+ chkStore.read(data);
+ }
+
+ try {
+ block = new DSAPublicKey(data);
+ } catch (IOException e) {
+ Logger.error(this, "Could not read key");
+ return null;
+ }
+
+ if(!dontPromote)
+ {
+ storeBlock.updateRecentlyUsed();
+ DatabaseEntry updateDBE = new DatabaseEntry();
+
storeBlockTupleBinding.objectToEntry(storeBlock, updateDBE);
+ c.putCurrent(updateDBE);
+ c.close();
+ t.commit();
+ }else{
+ c.close();
+ t.abort();
+ }
+
+ Logger.minor(this, "Get key:
"+HexUtil.bytesToHex(hash));
+ Logger.minor(this, "Data: "+data.length+" bytes, hash
"+data);
+
+ return block;
+ }catch(Exception ex) { // FIXME: ugly
+ if(c!=null) {
+ try{c.close();}catch(DatabaseException ex2){}
+ }
+ Logger.error(this, "Caught "+ex, ex);
+ ex.printStackTrace();
+ throw new IOException(ex.getMessage());
+ }
+
+// return null;
+ }
+
/**
* Store a block.
*/
@@ -360,6 +434,72 @@
}
}
+ /**
+ * Store a block.
+ */
+ public void put(byte[] hash, DSAPublicKey key) throws IOException
+ {
+ if(closed)
+ return;
+
+ byte[] routingkey = hash;
+ byte[] data = key.asBytes();
+
+ if(data.length!=dataBlockSize) {
+ Logger.minor(this, "This data is "+data.length+" bytes. Should
be "+dataBlockSize);
+ return;
+ }
+
+ Transaction t = null;
+
+ try{
+ t = environment.beginTransaction(null,null);
+ DatabaseEntry routingkeyDBE = new DatabaseEntry(routingkey);
+
+ synchronized(chkStore) {
+ if(chkBlocksInStore<maxChkBlocks) {
+ // Expand the store file
+ int byteOffset =
chkBlocksInStore*(dataBlockSize+headerBlockSize);
+ StoreBlock storeBlock = new
StoreBlock(chkBlocksInStore);
+ DatabaseEntry blockDBE = new DatabaseEntry();
+ storeBlockTupleBinding.objectToEntry(storeBlock,
blockDBE);
+ chkDB.put(t,routingkeyDBE,blockDBE);
+ chkStore.seek(byteOffset);
+ chkStore.write(data);
+ t.commit();
+ chkBlocksInStore++;
+ }else{
+ // Overwrite an other block
+ Cursor c = chkDB_accessTime.openCursor(t,null);
+ DatabaseEntry keyDBE = new DatabaseEntry();
+ DatabaseEntry dataDBE = new DatabaseEntry();
+ c.getFirst(keyDBE,dataDBE,null);
+ StoreBlock oldStoreBlock = (StoreBlock)
storeBlockTupleBinding.entryToObject(dataDBE);
+ c.delete();
+ c.close();
+ StoreBlock storeBlock = new
StoreBlock(oldStoreBlock.getOffset());
+ DatabaseEntry blockDBE = new DatabaseEntry();
+
storeBlockTupleBinding.objectToEntry(storeBlock, blockDBE);
+ chkDB.put(t,routingkeyDBE,blockDBE);
+
chkStore.seek(storeBlock.getOffset()*(long)(dataBlockSize+headerBlockSize));
+ chkStore.write(data);
+ t.commit();
+ }
+ }
+
+ Logger.minor(this, "Put key: "+HexUtil.bytesToHex(hash));
+ Logger.minor(this, "Data: "+data.length+" bytes, hash
"+Fields.hashCode(data));
+
+ }catch(Exception ex) { // FIXME: ugly
+ if(t!=null){
+ try{t.abort();}catch(DatabaseException ex2){};
+ }
+ Logger.error(this, "Caught "+ex, ex);
+ ex.printStackTrace();
+ throw new IOException(ex.getMessage());
+ }
+ }
+
private class StoreBlock
{
private long recentlyUsed;
Modified: trunk/freenet/src/freenet/store/FreenetStore.java
===================================================================
--- trunk/freenet/src/freenet/store/FreenetStore.java 2006-01-12 18:33:28 UTC
(rev 7844)
+++ trunk/freenet/src/freenet/store/FreenetStore.java 2006-01-12 18:39:32 UTC
(rev 7845)
@@ -2,6 +2,7 @@
import java.io.IOException;
+import freenet.crypt.DSAPublicKey;
import freenet.keys.CHKBlock;
import freenet.keys.Key;
import freenet.keys.KeyBlock;
@@ -29,7 +30,17 @@
public SSKBlock fetch(NodeSSK key, boolean dontPromote) throws IOException;
/**
+ * Fetch a public key.
+ */
+ public DSAPublicKey fetchPubKey(byte[] hash, boolean dontPromote) throws
IOException;
+
+ /**
* Store a block.
*/
public void put(KeyBlock block) throws IOException;
-}
\ No newline at end of file
+
+ /**
+ * Store a public key.
+ */
+ public void put(byte[] hash, DSAPublicKey key) throws IOException;
+}