Author: toad
Date: 2009-02-03 21:17:41 +0000 (Tue, 03 Feb 2009)
New Revision: 25518
Modified:
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucket.java
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
Log:
Shadow blob buckets
Modified:
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucket.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucket.java
2009-02-03 21:17:21 UTC (rev 25517)
+++ branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucket.java
2009-02-03 21:17:41 UTC (rev 25518)
@@ -18,7 +18,7 @@
public class PersistentBlobTempBucket implements Bucket {
public final long blockSize;
- private long size;
+ long size;
public final PersistentBlobTempBucketFactory factory;
/** The index into the blob file of this specific bucket */
final long index;
@@ -29,27 +29,32 @@
private boolean persisted;
private final int hashCode;
final PersistentBlobTempBucketTag tag;
+ private boolean shadow;
public int hashCode() {
return hashCode;
}
- public PersistentBlobTempBucket(PersistentBlobTempBucketFactory
factory2, long blockSize2, long slot, PersistentBlobTempBucketTag tag) {
+ public PersistentBlobTempBucket(PersistentBlobTempBucketFactory
factory2, long blockSize2, long slot, PersistentBlobTempBucketTag tag, boolean
shadow) {
factory = factory2;
blockSize = blockSize2;
index = slot;
hashCode = super.hashCode();
- if(tag == null) throw new NullPointerException();
+ if(tag == null && !shadow) throw new NullPointerException();
this.tag = tag;
+ this.shadow = shadow;
+ this.readOnly = shadow;
}
public Bucket createShadow() throws IOException {
- // TODO Auto-generated method stub
- return null;
+ return factory.createShadow(this);
}
public void free() {
- factory.freeBucket(index, this); // will call onFree(): always
take the outer lock first.
+ if(shadow)
+ factory.freeShadow(index, this);
+ else
+ factory.freeBucket(index, this); // will call onFree():
always take the outer lock first.
}
public boolean freed() {
@@ -86,10 +91,12 @@
if(freed) throw new IOException("Bucket
freed during read");
max = Math.min(blockSize, size);
}
+ if(length == 0) return 0;
if(bufOffset < 0) return -1; // throw new
EOFException() ???
if(offset + length >= max)
length = (int) Math.min(max - offset,
Integer.MAX_VALUE);
if(length == 0) return -1;
+ if(length < 0) throw new
IllegalStateException("offset="+bufOffset+" length="+length+"buf len =
"+buffer.length);
ByteBuffer buf = ByteBuffer.wrap(buffer,
bufOffset, length);
int read = channel.read(buf, blockSize * index
+ offset);
if(read > 0) offset += read;
@@ -119,6 +126,7 @@
public OutputStream getOutputStream() throws IOException {
if(freed) throw new IOException("Already freed");
if(readOnly) throw new IOException("Read-only");
+ if(shadow) throw new IOException("Shadow");
final FileChannel channel = factory.channel;
return new OutputStream() {
@@ -178,6 +186,9 @@
// temporary map, unless we have been freed.
public void storeTo(ObjectContainer container) {
+ if(shadow) {
+ throw new UnsupportedOperationException("Can't store a
shadow");
+ }
boolean p;
// Race conditions with storeTo and removeFrom running on
different threads
// in parallel are possible... that sort of behaviour *should*
be very rare,
@@ -192,6 +203,7 @@
}
public boolean objectCanNew(ObjectContainer container) {
+ if(shadow) throw new UnsupportedOperationException("Can't store
a shadow");
synchronized(this) {
if(persisted) return true;
}
@@ -201,6 +213,7 @@
}
public void removeFrom(ObjectContainer container) {
+ if(shadow) throw new UnsupportedOperationException("Can't store
a shadow");
boolean p;
synchronized(this) {
p = persisted;
Modified:
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
===================================================================
---
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
2009-02-03 21:17:21 UTC (rev 25517)
+++
branches/db4o/freenet/src/freenet/support/io/PersistentBlobTempBucketFactory.java
2009-02-03 21:17:41 UTC (rev 25518)
@@ -23,6 +23,7 @@
import freenet.client.async.DBJobRunner;
import freenet.node.Ticker;
import freenet.support.Logger;
+import freenet.support.api.Bucket;
/**
* Simple temporary storage mechanism using a single file (or a small number
of
@@ -55,6 +56,8 @@
* Similar to notCommittedBlobs. */
private transient TreeMap<Long,PersistentBlobTempBucketTag>
almostFreeSlots;
+ private transient TreeMap<Long,PersistentBlobTempBucket> shadows;
+
private transient DBJobRunner jobRunner;
private transient Random weakRandomSource;
@@ -87,6 +90,7 @@
notCommittedBlobs = new
TreeMap<Long,PersistentBlobTempBucket>();
freeSlots = new TreeMap<Long,PersistentBlobTempBucketTag>();
almostFreeSlots = new
TreeMap<Long,PersistentBlobTempBucketTag>();
+ shadows = new TreeMap<Long,PersistentBlobTempBucket>();
jobRunner = jobRunner2;
weakRandomSource = fastWeakRandom;
this.ticker = ticker;
@@ -251,7 +255,7 @@
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, tag);
+ PersistentBlobTempBucket bucket = new
PersistentBlobTempBucket(this, blockSize, slot, tag, false);
notCommittedBlobs.put(slot, bucket);
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Using slot "+slot+" for "+bucket);
return bucket;
@@ -266,7 +270,7 @@
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, tag);
+ PersistentBlobTempBucket bucket = new
PersistentBlobTempBucket(this, blockSize, slot, tag, false);
notCommittedBlobs.put(slot, bucket);
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Using slot "+slot+" for "+bucket+" (after waiting)");
return bucket;
@@ -284,6 +288,10 @@
// If it hasn't been written to the database, it
doesn't need to be removed, so removeFrom() won't be called.
freeSlots.put(index, bucket.tag);
}
+ PersistentBlobTempBucket shadow = shadows.get(index);
+ if(shadow != null) {
+ shadow.freed();
+ }
}
private long lastCheckedEnd = -1;
@@ -504,4 +512,24 @@
almostFreeSlots.clear();
}
+ public Bucket createShadow(PersistentBlobTempBucket bucket) {
+ long index = bucket.index;
+ Long i = index;
+ synchronized(this) {
+ if(shadows.containsKey(i)) return null;
+ PersistentBlobTempBucket shadow = new
PersistentBlobTempBucket(this, blockSize, index, null, true);
+ shadow.size = bucket.size;
+ shadows.put(i, shadow);
+ return shadow;
+ }
+ }
+
+ public synchronized void freeShadow(long index,
PersistentBlobTempBucket bucket) {
+ PersistentBlobTempBucket temp = shadows.remove(index);
+ if(temp != bucket) {
+ Logger.error(this, "Freed wrong shadow: "+temp+" should
be "+bucket);
+ shadows.put(index, temp);
+ }
+ }
+
}
_______________________________________________
cvs mailing list
[email protected]
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs