Author: toad
Date: 2008-10-31 18:13:07 +0000 (Fri, 31 Oct 2008)
New Revision: 23264

Modified:
   
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
   branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketTag.java
Log:
db4o doesn't like looking up a null in an index, so add an explicit isFree 
variable.
Optimise adding blocks after extending file, one query instead of one per block 
(up to 16384).


Modified: 
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
   2008-10-31 18:11:45 UTC (rev 23263)
+++ 
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
   2008-10-31 18:13:07 UTC (rev 23264)
@@ -5,7 +5,9 @@
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Random;
 import java.util.TreeMap;
@@ -81,21 +83,36 @@
                return storageFile.getPath();
        }

+       static final int MAX_FREE = 2048;
+       
        private final DBJob slotFinder = new DBJob() {

                public void run(ObjectContainer container, ClientContext 
context) {
                        boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
                        synchronized(PersistentBlobTempBucketFactory.this) {
-                               if(freeSlots.size() > 1024) return;
+                               if(freeSlots.size() > MAX_FREE) return;
                        }
                        Query query = container.query();
-                       
query.constrain(PersistentBlobTempBucketTag.class).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this).and(query.descend("bucket").constrain(null)));
+                       query.constrain(PersistentBlobTempBucketTag.class);
+                       query.descend("isFree").constrain(true);
                        ObjectSet<PersistentBlobTempBucketTag> tags = 
query.execute();
                        Long[] notCommitted;
                        int added = 0;
                        synchronized(PersistentBlobTempBucketFactory.this) {
                                while(tags.hasNext()) {
                                        PersistentBlobTempBucketTag tag = 
tags.next();
+                                       if(!tag.isFree) {
+                                               Logger.error(this, "Tag is 
free! "+tag.index);
+                                               if(tag.bucket == null) {
+                                                       Logger.error(this, "Tag 
flagged free yet has no bucket for index "+tag.index);
+                                                       tag.isFree = true;
+                                               } else continue;
+                                       }
+                                       if(tag.bucket != null) {
+                                               Logger.error(this, "Query 
returned tag with valid bucket!");
+                                               continue;
+                                       }
+                                       if(tag.factory != 
PersistentBlobTempBucketFactory.this) continue;
                                        
if(notCommittedBlobs.containsKey(tag.index)) continue;
                                        if(freeSlots.containsKey(tag.index)) 
continue;
                                        if(tag.bucket != null) {
@@ -105,7 +122,7 @@
                                        if(logMINOR) Logger.minor(this, "Adding 
slot "+tag.index+" to freeSlots (has a free tag and no taken tag)");
                                        freeSlots.put(tag.index, tag);
                                        added++;
-                                       if(added > 1024) return;
+                                       if(added > MAX_FREE) return;
                                }
                        }
                        long size;
@@ -138,7 +155,7 @@
                                                added++;
                                                if(logMINOR)
                                                        Logger.minor(this, 
"Adding slot "+ptr+" to freeSlots, searching for free slots from the end");
-                                               if(added > 1024) return;
+                                               if(added > MAX_FREE) return;
                                                ptr--;
                                        }
                                }
@@ -165,12 +182,22 @@
                                        break;
                                }
                        }
+                       query.constrain(PersistentBlobTempBucketTag.class);
+                       
query.descend("index").constrain(blocks-1).greater().and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
+                       HashSet<Long> taken = null;
+                       ObjectSet<PersistentBlobTempBucketTag> results = 
query.execute();
+                       while(results.hasNext()) {
+                               PersistentBlobTempBucketTag tag = 
results.next();
+                               if(!tag.isFree) {
+                                       Logger.error(this, "Block already 
exists beyond the end of the file, yet is occupied: block "+tag.index);
+                               }
+                               if(taken == null) taken = new HashSet<Long>();
+                               taken.add(tag.index);
+                       }
+                       
                        for(int i=0;i<addBlocks;i++) {
                                ptr = blocks + i;
-                               query = container.query();
-                               
query.constrain(PersistentBlobTempBucketTag.class);
-                               
query.descend("index").constrain(ptr).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
-                               if(query.execute().hasNext()) continue;
+                               if(taken != null && taken.contains(ptr)) 
continue;
                                PersistentBlobTempBucketTag tag = new 
PersistentBlobTempBucketTag(PersistentBlobTempBucketFactory.this, ptr);
                                container.store(tag);
                                
synchronized(PersistentBlobTempBucketFactory.this) {
@@ -241,6 +268,7 @@
                        freeSlots.put(index, tag);
                }
                tag.bucket = null;
+               tag.isFree = true;
                container.store(tag);
                container.delete(bucket);
                bucket.onRemove();
@@ -257,6 +285,7 @@
                        throw new IllegalStateException("Slot "+index+" already 
occupied!");
                }
                tag.bucket = bucket;
+               tag.isFree = false;
                container.store(tag);
                synchronized(this) {
                        notCommittedBlobs.remove(index);

Modified: 
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketTag.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketTag.java   
    2008-10-31 18:11:45 UTC (rev 23263)
+++ 
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketTag.java   
    2008-10-31 18:13:07 UTC (rev 23264)
@@ -5,10 +5,15 @@
        final PersistentBlobTempBucketFactory factory;
        final long index;
        PersistentBlobTempBucket bucket;
+       /** db4o bug: http://tracker.db4o.com/browse/COR-1446
+        * We cannot just query for bucket == null, because it will instantiate 
every
+        * object with bucket != null during the query even though we have an 
index. */
+       boolean isFree;

        PersistentBlobTempBucketTag(PersistentBlobTempBucketFactory f, long 
idx) {
                factory = f;
                index = idx;
+               isFree = true;
        }

 }


Reply via email to