Author: toad
Date: 2008-10-24 12:26:09 +0000 (Fri, 24 Oct 2008)
New Revision: 23077
Removed:
branches/db4o/freenet/src/freenet/support/io/PersistentBlobFreeSlotTag.java
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTakenSlotTag.java
Modified:
branches/db4o/freenet/src/freenet/node/Node.java
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucket.java
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
Log:
Refactor blob buckets, greatly improve performance.
Modified: branches/db4o/freenet/src/freenet/node/Node.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/Node.java 2008-10-24 12:19:55 UTC
(rev 23076)
+++ branches/db4o/freenet/src/freenet/node/Node.java 2008-10-24 12:26:09 UTC
(rev 23077)
@@ -834,10 +834,8 @@
dbConfig.objectClass(freenet.client.async.InsertCompressor.class).objectField("nodeDBHandle").indexed(true);
dbConfig.objectClass(freenet.node.fcp.FCPClient.class).objectField("name").indexed(true);
dbConfig.objectClass(freenet.client.async.DatastoreCheckerItem.class).objectField("prio").indexed(true);
-
dbConfig.objectClass(freenet.support.io.PersistentBlobFreeSlotTag.class).objectField("index").indexed(true);
-
dbConfig.objectClass(freenet.support.io.PersistentBlobFreeSlotTag.class).objectField("factory").indexed(true);
-
dbConfig.objectClass(freenet.support.io.PersistentBlobTakenSlotTag.class).objectField("index").indexed(true);
-
dbConfig.objectClass(freenet.support.io.PersistentBlobTakenSlotTag.class).objectField("factory").indexed(true);
+
dbConfig.objectClass(freenet.support.io.PersistentBlobTempBucketTag.class).objectField("index").indexed(true);
+
/*
* HashMap: don't enable cascade on update/delete/activate,
db4o handles this
* internally through the TMap translator.
Deleted:
branches/db4o/freenet/src/freenet/support/io/PersistentBlobFreeSlotTag.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/PersistentBlobFreeSlotTag.java
2008-10-24 12:19:55 UTC (rev 23076)
+++ branches/db4o/freenet/src/freenet/support/io/PersistentBlobFreeSlotTag.java
2008-10-24 12:26:09 UTC (rev 23077)
@@ -1,11 +0,0 @@
-package freenet.support.io;
-
-public class PersistentBlobFreeSlotTag {
- final long index;
- final PersistentBlobTempBucketFactory factory;
-
- PersistentBlobFreeSlotTag(long index, PersistentBlobTempBucketFactory
factory) {
- this.index = index;
- this.factory = factory;
- }
-}
Deleted:
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTakenSlotTag.java
===================================================================
---
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTakenSlotTag.java
2008-10-24 12:19:55 UTC (rev 23076)
+++
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTakenSlotTag.java
2008-10-24 12:26:09 UTC (rev 23077)
@@ -1,13 +0,0 @@
-package freenet.support.io;
-
-public class PersistentBlobTakenSlotTag {
- final long index;
- final PersistentBlobTempBucketFactory factory;
- final PersistentBlobTempBucket bucket;
-
- PersistentBlobTakenSlotTag(long index, PersistentBlobTempBucketFactory
factory, PersistentBlobTempBucket bucket) {
- this.index = index;
- this.factory = factory;
- this.bucket = bucket;
- }
-}
Modified:
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucket.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucket.java
2008-10-24 12:19:55 UTC (rev 23076)
+++ branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucket.java
2008-10-24 12:26:09 UTC (rev 23077)
@@ -28,16 +28,18 @@
* map in the factory. */
private boolean persisted;
private final int hashCode;
+ final PersistentBlobTempBucketTag tag;
public int hashCode() {
return hashCode;
}
- public PersistentBlobTempBucket(PersistentBlobTempBucketFactory
factory2, long blockSize2, long slot) {
+ public PersistentBlobTempBucket(PersistentBlobTempBucketFactory
factory2, long blockSize2, long slot, PersistentBlobTempBucketTag tag) {
factory = factory2;
blockSize = blockSize2;
index = slot;
hashCode = super.hashCode();
+ this.tag = tag;
}
public Bucket createShadow() throws IOException {
Modified:
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
===================================================================
---
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
2008-10-24 12:19:55 UTC (rev 23076)
+++
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
2008-10-24 12:26:09 UTC (rev 23077)
@@ -8,7 +8,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
-import java.util.TreeSet;
+import java.util.TreeMap;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
@@ -44,7 +44,7 @@
/** Non-exhaustive list of free slots. If we run out we need to query
for
* more. */
- private transient TreeSet<Long> freeSlots;
+ private transient TreeMap<Long,PersistentBlobTempBucketTag> freeSlots;
private transient DBJobRunner jobRunner;
@@ -72,7 +72,7 @@
raf = new RandomAccessFile(storageFile, "rw");
channel = raf.getChannel();
notCommittedBlobs = new
HashMap<Long,PersistentBlobTempBucket>();
- freeSlots = new TreeSet<Long>();
+ freeSlots = new TreeMap<Long,PersistentBlobTempBucketTag>();
jobRunner = jobRunner2;
weakRandomSource = fastWeakRandom;
}
@@ -89,26 +89,21 @@
if(freeSlots.size() > 1024) return;
}
Query query = container.query();
-
query.constrain(PersistentBlobFreeSlotTag.class).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
- ObjectSet<PersistentBlobFreeSlotTag> tags =
query.execute();
+
query.constrain(PersistentBlobTempBucketTag.class).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this).and(query.descend("bucket").constrain(null)));
+ ObjectSet<PersistentBlobTempBucketTag> tags =
query.execute();
Long[] notCommitted;
int added = 0;
synchronized(PersistentBlobTempBucketFactory.this) {
while(tags.hasNext()) {
- PersistentBlobFreeSlotTag tag =
tags.next();
- if(notCommittedBlobs.get(tag.index) !=
null) continue;
- if(freeSlots.contains(tag.index))
continue;
- Query check = container.query();
-
check.constrain(PersistentBlobTakenSlotTag.class);
-
check.descend("index").constrain(tag.index).and(check.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
- ObjectSet<PersistentBlobTakenSlotTag>
checkResults = check.execute();
- if(checkResults.hasNext()) {
- Logger.error(this, "slot
"+tag.index+" is already taken by "+checkResults.next().bucket+", but also has
a FreeSlotTag! total matches: "+(checkResults.size()+1));
- container.delete(tag);
+ PersistentBlobTempBucketTag tag =
tags.next();
+
if(notCommittedBlobs.containsKey(tag.index)) continue;
+ if(freeSlots.containsKey(tag.index))
continue;
+ if(tag.bucket != null) {
+ Logger.error(this, "Bucket is
occupied but not in notCommittedBlobs?!: "+tag+" : "+tag.bucket);
continue;
}
if(logMINOR) Logger.minor(this, "Adding
slot "+tag.index+" to freeSlots (has a free tag and no taken tag)");
- freeSlots.add(tag.index);
+ freeSlots.put(tag.index, tag);
added++;
if(added > 1024) return;
}
@@ -124,7 +119,7 @@
long blocks = size / blockSize;
long ptr = blocks - 1;
query = container.query();
- query.constrain(PersistentBlobTakenSlotTag.class);
+ query.constrain(PersistentBlobTempBucketTag.class);
query.descend("index").constrain(ptr).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
// Try from the end, until we find no more.
while(ptr > 0 && !query.execute().hasNext()) {
@@ -132,26 +127,21 @@
synchronized(PersistentBlobTempBucketFactory.this) {
stored = notCommittedBlobs.get(ptr) ==
null;
if(stored) {
- if(freeSlots.contains(ptr))
break;
- if(notCommittedBlobs.get(ptr)
!= null) continue;
- freeSlots.add(ptr);
+ if(freeSlots.containsKey(ptr))
break;
+ if(notCommittedBlobs.get(ptr)
!= null) {
+ ptr--;
+ continue;
+ }
+ PersistentBlobTempBucketTag tag
= new PersistentBlobTempBucketTag(PersistentBlobTempBucketFactory.this, ptr);
+ container.store(tag);
+ freeSlots.put(ptr, tag);
+ added++;
+ if(logMINOR)
+ Logger.minor(this,
"Adding slot "+ptr+" to freeSlots, searching for free slots from the end");
+ if(added > 1024) return;
+ ptr--;
}
}
- query = container.query();
-
query.constrain(PersistentBlobFreeSlotTag.class);
-
query.descend("index").constrain(ptr).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
- if(query.execute().hasNext()) break;
- if(stored) {
- container.store(new
PersistentBlobFreeSlotTag(ptr, PersistentBlobTempBucketFactory.this));
- added++;
- }
- if(logMINOR)
- Logger.minor(this, "Adding slot "+ptr+"
to freeSlots, searching for free slots from the end");
- if(added > 1024) return;
- ptr--;
- query = container.query();
-
query.constrain(PersistentBlobTakenSlotTag.class);
-
query.descend("index").constrain(ptr).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
}
// We haven't done an exhaustive search for freeable
slots, slots
// with no tag at all etc. This happens on startup.
@@ -177,11 +167,16 @@
}
for(int i=0;i<addBlocks;i++) {
ptr = blocks + i;
- container.store(new
PersistentBlobFreeSlotTag(ptr, PersistentBlobTempBucketFactory.this));
+ query = container.query();
+
query.constrain(PersistentBlobTempBucketTag.class);
+
query.descend("index").constrain(ptr).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
+ if(query.execute().hasNext()) continue;
+ PersistentBlobTempBucketTag tag = new
PersistentBlobTempBucketTag(PersistentBlobTempBucketFactory.this, ptr);
+ container.store(tag);
synchronized(PersistentBlobTempBucketFactory.this) {
- freeSlots.add(ptr);
if(logMINOR)
Logger.minor(this, "Adding slot
"+ptr+" to freeSlots while extending storage file");
+ freeSlots.put(ptr, tag);
}
}
}
@@ -193,16 +188,15 @@
*/
public PersistentBlobTempBucket makeBucket() {
// Find a free slot.
- long slotNo;
synchronized(this) {
if(!freeSlots.isEmpty()) {
- Long slot = freeSlots.first();
- freeSlots.remove(slot);
+ Long slot = freeSlots.firstKey();
+ PersistentBlobTempBucketTag tag =
freeSlots.remove(slot);
if(notCommittedBlobs.get(slot) != null) {
Logger.error(this, "Slot "+slot+"
already occupied by a not committed blob despite being in freeSlots!!");
return null;
}
- PersistentBlobTempBucket bucket = new
PersistentBlobTempBucket(this, blockSize, slot);
+ PersistentBlobTempBucket bucket = new
PersistentBlobTempBucket(this, blockSize, slot, tag);
notCommittedBlobs.put(slot, bucket);
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Using slot "+slot+" for "+bucket);
return bucket;
@@ -211,15 +205,15 @@
jobRunner.runBlocking(slotFinder, NativeThread.HIGH_PRIORITY);
synchronized(this) {
if(!freeSlots.isEmpty()) {
- Long slot = freeSlots.first();
- freeSlots.remove(slot);
+ Long slot = freeSlots.firstKey();
+ PersistentBlobTempBucketTag tag =
freeSlots.remove(slot);
if(notCommittedBlobs.get(slot) != null) {
- Logger.error(this, "Slot "+slot+"
already occupied by a not committed blob despite being in freeSlots!! (after
waiting)");
+ Logger.error(this, "Slot "+slot+"
already occupied by a not committed blob despite being in freeSlots!!");
return null;
}
- PersistentBlobTempBucket bucket = new
PersistentBlobTempBucket(this, blockSize, slot);
+ PersistentBlobTempBucket bucket = new
PersistentBlobTempBucket(this, blockSize, slot, tag);
notCommittedBlobs.put(slot, bucket);
- if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Using slot "+slot+" for "+bucket+" (2)");
+ if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Using slot "+slot+" for "+bucket);
return bucket;
}
}
@@ -236,62 +230,36 @@
public synchronized void remove(PersistentBlobTempBucket bucket,
ObjectContainer container) {
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Removing bucket "+bucket+" for slot
"+bucket.index+" from database");
+ long index = bucket.index;
+ PersistentBlobTempBucketTag tag = bucket.tag;
+ container.activate(tag, 1);
if(!bucket.persisted()) return;
if(!bucket.freed()) {
Logger.error(this, "Removing bucket "+bucket+" for slot
"+bucket.index+" but not freed!", new Exception("debug"));
+ notCommittedBlobs.put(index, bucket);
+ } else {
+ freeSlots.put(index, tag);
}
- Query query = container.query();
- long index = bucket.index;
- freeSlots.add(index);
- query.constrain(PersistentBlobTakenSlotTag.class);
-
query.descend("index").constrain(index).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
- ObjectSet<PersistentBlobTakenSlotTag> tags = query.execute();
- while(tags.hasNext()) {
- PersistentBlobTakenSlotTag tag = tags.next();
- if(Logger.shouldLog(Logger.MINOR, this))
- Logger.minor(this, "Deleting taken slot tag for
index "+index+" : "+tag+" : "+tag.index);
- container.delete(tag);
- }
- query = container.query();
-
query.constrain(PersistentBlobFreeSlotTag.class).and(query.descend("index").constrain(index).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this)));
- if(!query.execute().hasNext()) {
- PersistentBlobFreeSlotTag tag = new
PersistentBlobFreeSlotTag(index, this);
- container.store(tag);
- }
+ tag.bucket = null;
+ container.store(tag);
+ container.delete(bucket);
bucket.onRemove();
}
public void store(PersistentBlobTempBucket bucket, ObjectContainer
container) {
-
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Storing bucket "+bucket+" for slot
"+bucket.index+" to database");
long index = bucket.index;
- // FIXME paranoid check, remove
- Query query = container.query();
- query.constrain(PersistentBlobTakenSlotTag.class);
-
query.descend("index").constrain(index).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
- ObjectSet<PersistentBlobTakenSlotTag> taken = query.execute();
- if(taken.hasNext()) {
- PersistentBlobTakenSlotTag tag = taken.next();
+ PersistentBlobTempBucketTag tag = bucket.tag;
+ container.activate(tag, 1);
+ if(tag.bucket != null && tag.bucket != bucket) {
Logger.error(this, "Slot "+index+" already occupied!:
"+tag.bucket+" for "+tag.index);
throw new IllegalStateException("Slot "+index+" already
occupied!");
}
- // Now the normal bit
+ container.store(tag);
synchronized(this) {
notCommittedBlobs.remove(index);
}
- query = container.query();
- query.constrain(PersistentBlobFreeSlotTag.class);
-
query.descend("index").constrain(index).and(query.descend("factory").constrain(PersistentBlobTempBucketFactory.this));
- ObjectSet<PersistentBlobFreeSlotTag> results = query.execute();
- while(results.hasNext()) {
- PersistentBlobFreeSlotTag tag = results.next();
- if(Logger.shouldLog(Logger.MINOR, this))
- Logger.minor(this, "Deleting free slot tag for
index "+index+" : "+tag+" : "+tag.index);
- container.delete(tag);
- }
- PersistentBlobTakenSlotTag tag = new
PersistentBlobTakenSlotTag(index, this, bucket);
- container.store(tag);
}
}