Author: toad
Date: 2009-04-15 12:11:52 +0000 (Wed, 15 Apr 2009)
New Revision: 26841

Modified:
   trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
   trunk/freenet/src/freenet/keys/ClientSSKBlock.java
Log:
Fix another db4o regression: Detect SSK collision with existing data.


Modified: trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleBlockInserter.java     
2009-04-15 12:04:48 UTC (rev 26840)
+++ trunk/freenet/src/freenet/client/async/SingleBlockInserter.java     
2009-04-15 12:11:52 UTC (rev 26841)
@@ -5,6 +5,7 @@
 
 import java.io.IOException;
 import java.net.MalformedURLException;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -18,14 +19,17 @@
 import freenet.keys.ClientCHKBlock;
 import freenet.keys.ClientKey;
 import freenet.keys.ClientKeyBlock;
+import freenet.keys.ClientSSK;
+import freenet.keys.ClientSSKBlock;
 import freenet.keys.FreenetURI;
 import freenet.keys.InsertableClientSSK;
+import freenet.keys.KeyDecodeException;
 import freenet.keys.KeyEncodeException;
+import freenet.keys.KeyVerifyException;
 import freenet.keys.SSKEncodeException;
 import freenet.node.KeysFetchingLocally;
 import freenet.node.LowLevelPutException;
 import freenet.node.NodeClientCore;
-import freenet.node.NullSendableRequestItem;
 import freenet.node.RequestClient;
 import freenet.node.RequestScheduler;
 import freenet.node.SendableInsert;
@@ -461,10 +465,11 @@
 
                        public boolean send(NodeClientCore core, 
RequestScheduler sched, final ClientContext context, ChosenBlock req) {
                                // Ignore keyNum, key, since we're only sending 
one block.
+                               ClientKeyBlock b;
+                               ClientKey key = null;
+                               if(logMINOR) Logger.minor(this, "Starting 
request: "+SingleBlockInserter.this);
+                               BlockItem block = (BlockItem) req.token;
                                try {
-                                       if(logMINOR) Logger.minor(this, 
"Starting request: "+SingleBlockInserter.this);
-                                       BlockItem block = (BlockItem) req.token;
-                                       ClientKeyBlock b;
                                        try {
                                                b = innerEncode(context.random, 
block.uri, block.copyBucket, block.isMetadata, block.compressionCodec, 
block.sourceLength);
                                        } catch (CHKEncodeException e) {
@@ -477,21 +482,20 @@
                                                throw new 
LowLevelPutException(LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + 
e.getMessage(), e);
                                        } catch (IOException e) {
                                                throw new 
LowLevelPutException(LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + 
e.getMessage(), e);
-                                       } finally {
-                                               block.copyBucket.free();
                                        }
                                        if (b==null) {
                                                Logger.error(this, "Asked to 
send empty block on "+SingleBlockInserter.this, new Exception("error"));
                                                return false;
                                        }
-                                       final ClientKey key = b.getClientKey();
+                                       key = b.getClientKey();
+                                       final ClientKey k = key;
                                        if(block.persistent) {
                                        context.jobRunner.queue(new DBJob() {
 
                                                public void run(ObjectContainer 
container, ClientContext context) {
                                                        
if(!container.ext().isStored(SingleBlockInserter.this)) return;
                                                        
container.activate(SingleBlockInserter.this, 1);
-                                                       onEncode(key, 
container, context);
+                                                       onEncode(k, container, 
context);
                                                        
container.deactivate(SingleBlockInserter.this, 1);
                                                }
                                                
@@ -500,7 +504,7 @@
                                                
context.mainExecutor.execute(new Runnable() {
 
                                                        public void run() {
-                                                               onEncode(key, 
null, context);
+                                                               onEncode(k, 
null, context);
                                                        }
                                                        
                                                }, "Got URI");
@@ -508,9 +512,30 @@
                                        }
                                        core.realPut(b, req.cacheLocalRequests);
                                } catch (LowLevelPutException e) {
+                                       if(e.code == 
LowLevelPutException.COLLISION) {
+                                               // Collision
+                                               try {
+                                                       ClientSSKBlock collided 
= (ClientSSKBlock) core.node.fetch((ClientSSK)key, true);
+                                                       byte[] data = 
collided.memoryDecode(true);
+                                                       byte[] inserting = 
BucketTools.toByteArray(block.copyBucket);
+                                                       
if(collided.isMetadata() == block.isMetadata && collided.getCompressionCodec() 
== block.compressionCodec && Arrays.equals(data, inserting)) {
+                                                               if(logMINOR) 
Logger.minor(this, "Collided with identical data: "+SingleBlockInserter.this);
+                                                               
req.onInsertSuccess(context);
+                                                               return true;
+                                                       }
+                                               } catch (KeyVerifyException e1) 
{
+                                                       Logger.error(this, 
"Caught "+e1+" when checking collision!", e1);
+                                               } catch (KeyDecodeException e1) 
{
+                                                       Logger.error(this, 
"Caught "+e1+" when checking collision!", e1);
+                                               } catch (IOException e1) {
+                                                       Logger.error(this, 
"Caught "+e1+" when checking collision!", e1);
+                                               }
+                                       }
                                        req.onFailure(e, context);
                                        if(logMINOR) Logger.minor(this, 
"Request failed: "+SingleBlockInserter.this+" for "+e);
                                        return true;
+                               } finally {
+                                       block.copyBucket.free();
                                }
                                if(logMINOR) Logger.minor(this, "Request 
succeeded: "+SingleBlockInserter.this);
                                req.onInsertSuccess(context);

Modified: trunk/freenet/src/freenet/keys/ClientSSKBlock.java
===================================================================
--- trunk/freenet/src/freenet/keys/ClientSSKBlock.java  2009-04-15 12:04:48 UTC 
(rev 26840)
+++ trunk/freenet/src/freenet/keys/ClientSSKBlock.java  2009-04-15 12:11:52 UTC 
(rev 26841)
@@ -110,13 +110,17 @@
                return compressionAlgorithm;
        }
        
+       public byte[] memoryDecode() throws KeyDecodeException {
+               return memoryDecode(false);
+       }
+       
     /**
      * Decode into RAM, if short.
      * @throws KeyDecodeException 
      */
-       public byte[] memoryDecode() throws KeyDecodeException {
+       public byte[] memoryDecode(boolean dontDecompress) throws 
KeyDecodeException {
                try {
-                       ArrayBucket a = (ArrayBucket) decode(new 
ArrayBucketFactory(), 32*1024, false);
+                       ArrayBucket a = (ArrayBucket) decode(new 
ArrayBucketFactory(), 32*1024, dontDecompress);
                        return BucketTools.toByteArray(a); // FIXME
                } catch (IOException e) {
                        throw new Error(e);

_______________________________________________
cvs mailing list
[email protected]
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs

Reply via email to