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

Reply via email to