Author: toad
Date: 2009-02-03 12:08:14 +0000 (Tue, 03 Feb 2009)
New Revision: 25486
Modified:
branches/db4o/freenet/src/freenet/support/io/SegmentedBucketChainBucket.java
branches/db4o/freenet/src/freenet/support/io/SegmentedChainBucketSegment.java
Log:
Clear one segment at a time to avoid OOM
Modified:
branches/db4o/freenet/src/freenet/support/io/SegmentedBucketChainBucket.java
===================================================================
---
branches/db4o/freenet/src/freenet/support/io/SegmentedBucketChainBucket.java
2009-02-03 11:49:51 UTC (rev 25485)
+++
branches/db4o/freenet/src/freenet/support/io/SegmentedBucketChainBucket.java
2009-02-03 12:08:14 UTC (rev 25486)
@@ -59,43 +59,52 @@
return null;
}
+ private DBJob freeJob = new DBJob() {
+
+ public void run(ObjectContainer container, ClientContext
context) {
+ SegmentedChainBucketSegment segment = null;
+ synchronized(this) {
+ if(!segments.isEmpty())
+ segment = segments.remove(0);
+ }
+ if(segment != null) {
+ container.activate(segment, 1);
+ if(Logger.shouldLog(Logger.MINOR,
SegmentedBucketChainBucket.this))
+
Logger.minor(SegmentedBucketChainBucket.this, "Freeing segment "+segment);
+ segment.activateBuckets(container);
+ segment.free();
+ segment.removeFrom(container);
+ synchronized(this) {
+ if(!segments.isEmpty()) {
+ dbJobRunner.queue(freeJob,
NativeThread.HIGH_PRIORITY, true);
+ container.store(this);
+ return;
+ }
+ }
+ }
+ container.delete(segments);
+ container.delete(SegmentedBucketChainBucket.this);
+ synchronized(SegmentedBucketChainBucket.this) {
+ if(killMe == null) return;
+ }
+ dbJobRunner.removeRestartJob(killMe,
NativeThread.HIGH_PRIORITY, container);
+ }
+
+ };
+
public void free() {
synchronized(this) {
freed = true;
+ clearing = false;
}
- // Complete the cleanup before returning.
- // SegmentedBucketChainBucket can't be stored to disk so we
will be run on helper threads generally,
- // so we will have to wait for a job to complete on the
database thread, but that is okay.
- dbJobRunner.runBlocking(new DBJob() {
-
- public void run(ObjectContainer container,
ClientContext context) {
- SegmentedChainBucketSegment[] segs;
- synchronized(this) {
- segs = segments.toArray(new
SegmentedChainBucketSegment[segments.size()]);
- segments.clear();
- }
- for(int i=0;i<segs.length;i++) {
- SegmentedChainBucketSegment segment =
segs[i];
- segs[i] = null;
- container.activate(segment, 1);
- if(Logger.shouldLog(Logger.MINOR,
SegmentedBucketChainBucket.this))
-
Logger.minor(SegmentedBucketChainBucket.this, "Freeing segment "+segment);
- segment.activateBuckets(container);
- segment.free();
- segment.removeFrom(container);
- }
- synchronized(SegmentedBucketChainBucket.this) {
- if(killMe == null) return;
- }
- dbJobRunner.removeRestartJob(killMe,
NativeThread.HIGH_PRIORITY, container);
- }
-
- }, NativeThread.HIGH_PRIORITY);
+
+ // Due to memory issues, we cannot complete the cleanup before
returning, especially if we are already on the database thread...
+ dbJobRunner.queue(freeJob, NativeThread.HIGH_PRIORITY, true);
}
public InputStream getInputStream() throws IOException {
synchronized(this) {
- if(freed) throw new IOException("Freed");
+ if(freed || clearing) throw new IOException("Freed");
}
return new InputStream() {
@@ -197,7 +206,7 @@
final SegmentedChainBucketSegment[] segs;
synchronized(this) {
if(readOnly) throw new IOException("Read-only");
- if(freed) throw new IOException("Freed");
+ if(freed || clearing) throw new IOException("Freed");
size = 0;
segs = segments.toArray(new
SegmentedChainBucketSegment[segments.size()]);
segments.clear();
@@ -414,24 +423,47 @@
}
return buckets;
}
+
+ private final DBJob clearJob = new DBJob() {
+
+ public void run(ObjectContainer container, ClientContext
context) {
+ SegmentedChainBucketSegment segment = null;
+ synchronized(this) {
+ if(!segments.isEmpty())
+ segment = segments.remove(0);
+ }
+ if(segment != null) {
+ container.activate(segment, 1);
+ if(Logger.shouldLog(Logger.MINOR,
SegmentedBucketChainBucket.this))
+
Logger.minor(SegmentedBucketChainBucket.this, "Freeing segment "+segment);
+ segment.clear(container);
+ synchronized(this) {
+ if(!segments.isEmpty()) {
+ dbJobRunner.queue(clearJob,
NativeThread.HIGH_PRIORITY, true);
+ container.store(segments);
+
container.store(SegmentedBucketChainBucket.this);
+ return;
+ }
+ }
+ }
+ container.delete(segments);
+ container.delete(SegmentedBucketChainBucket.this);
+ synchronized(SegmentedBucketChainBucket.this) {
+ if(killMe == null) return;
+ }
+ dbJobRunner.removeRestartJob(killMe,
NativeThread.HIGH_PRIORITY, container);
+ }
+ };
+
+ private boolean clearing;
+
public synchronized void clear() {
- dbJobRunner.runBlocking(new DBJob() {
-
- public void run(ObjectContainer container,
ClientContext context) {
- for(SegmentedChainBucketSegment segment :
segments) {
- container.activate(segment, 1);
- segment.clear(container, context);
- }
-
container.delete(SegmentedBucketChainBucket.class);
- synchronized(SegmentedBucketChainBucket.this) {
- if(killMe == null) return;
- }
- dbJobRunner.removeRestartJob(killMe,
NativeThread.HIGH_PRIORITY, container);
- }
-
- }, NativeThread.HIGH_PRIORITY);
- segments.clear();
+ // Due to memory issues, we cannot complete this before we
return
+ synchronized(this) {
+ clearing = true;
+ }
+ dbJobRunner.queue(clearJob, NativeThread.HIGH_PRIORITY-1, true);
}
/**
@@ -452,9 +484,13 @@
}
if(logMINOR) Logger.minor(this, "Removing segment
"+seg);
container.activate(seg, 1);
- seg.activateBuckets(container);
- seg.free();
- seg.removeFrom(container);
+ if(clearing) {
+ seg.clear(container);
+ } else {
+ seg.activateBuckets(container);
+ seg.free();
+ seg.removeFrom(container);
+ }
if(segments.size() > 0) {
container.store(segments);
container.store(this);
Modified:
branches/db4o/freenet/src/freenet/support/io/SegmentedChainBucketSegment.java
===================================================================
---
branches/db4o/freenet/src/freenet/support/io/SegmentedChainBucketSegment.java
2009-02-03 11:49:51 UTC (rev 25485)
+++
branches/db4o/freenet/src/freenet/support/io/SegmentedChainBucketSegment.java
2009-02-03 12:08:14 UTC (rev 25486)
@@ -73,7 +73,7 @@
container.activate(bucket, 1); // will cascade
}
- public void clear(ObjectContainer container, ClientContext context) {
+ public void clear(ObjectContainer container) {
buckets.clear();
container.delete(buckets);
container.delete(this);
_______________________________________________
cvs mailing list
[email protected]
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs