internetarchive$heritrix3
// wait up to 3 seconds for stop
                for(int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(300);
boolean
boolean teardown()
void
void reset()
https://github.com/internetarchive/heritrix3/blob/ace6d95ab88d82689674a3978c51b9faac7573e7/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Fframework%2FCrawlController.java
https://api.github.com/repos/internetarchive/heritrix3/contents/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Fframework%2FCrawlController.java?ref=ace6d95ab88d82689674a3978c51b9faac7573e7
engine/src/main/java/org/archive/crawler/framework/CrawlController.java
    public boolean isFinished() {
        return state == State.FINISHED;
    }
    
engine/src/main/java/org/archive/crawler/framework/CrawlController.java
return state == State.FINISHED;
boolean isFinished()
@@ -477,6 +477,10 @@ public boolean isStateRunning() {
         return state == State.RUNNING;
     }
 
+    public boolean isFinished() {
+        return state == State.FINISHED;
+    }
+    
     /**
      * Resume crawl from paused state
      */
https://github.com/internetarchive/heritrix3/raw/ace6d95ab88d82689674a3978c51b9faac7573e7/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Fframework%2FCrawlController.java
c297add3d2da541e6a50b19d50de602a0ad939df
modified
https://github.com/internetarchive/heritrix3/blob/ace6d95ab88d82689674a3978c51b9faac7573e7/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Fframework%2FCrawlJob.java
https://api.github.com/repos/internetarchive/heritrix3/contents/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Fframework%2FCrawlJob.java?ref=ace6d95ab88d82689674a3978c51b9faac7573e7
engine/src/main/java/org/archive/crawler/framework/CrawlJob.java
    public boolean teardown() {
                // wait up to 3 seconds for stop
                for(int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        // do nothing
                    }
                    if(cc.isFinished()) {
                        break;
                    }
                }
                if(!cc.isFinished()) {
                    return false; 
                }
        return true; 

engine/src/main/java/org/archive/crawler/framework/CrawlJob.java
// wait up to 3 seconds for stop
                for(int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(300);
boolean teardown()
    public void reset() {
            }
            if(ac.isRunning()) {
                ac.stop(); 

engine/src/main/java/org/archive/crawler/framework/CrawlJob.java
void reset()
@@ -482,20 +482,32 @@ public boolean isUnpausable() {
      * Ensure a fresh start for any configuration changes or relaunches,
      * by stopping and discarding an existing ApplicationContext.
      */
-    public void reset() {
+    public boolean teardown() {
         if(ac!=null) {
             CrawlController cc = getCrawlController();
             if(cc!=null) {
                 cc.requestCrawlStop();
                 // TODO: wait for stop?
-            }
-            if(ac.isRunning()) {
-                ac.stop(); 
+                // wait up to 3 seconds for stop
+                for(int i = 0; i < 10; i++) {
+                    try {
+                        Thread.sleep(300);
+                    } catch (InterruptedException e) {
+                        // do nothing
+                    }
+                    if(cc.isFinished()) {
+                        break;
+                    }
+                }
+                if(!cc.isFinished()) {
+                    return false; 
+                }
             }
             ac = null;
         }
         xmlOkAt = new DateTime(0); 
         getJobLogger().log(Level.INFO,"Job instance discarded");
+        return true; 
     }
 
     /**

https://github.com/internetarchive/heritrix3/raw/ace6d95ab88d82689674a3978c51b9faac7573e7/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Fframework%2FCrawlJob.java
d286e27e1e5ee0e905af17497e2d725d7efe79a5
modified
https://github.com/internetarchive/heritrix3/blob/ace6d95ab88d82689674a3978c51b9faac7573e7/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Frestlet%2FJobResource.java
https://api.github.com/repos/internetarchive/heritrix3/contents/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Frestlet%2FJobResource.java?ref=ace6d95ab88d82689674a3978c51b9faac7573e7
engine/src/main/java/org/archive/crawler/restlet/JobResource.java
        Flash.renderFlashesHTML(pw, getRequest());
        
            if(!cj.teardown()) {
                Flash.addFlash(getResponse(), "waiting for job to finish", Flash.Kind.NACK);
            }

            cj.reset(); 

@@ -104,6 +104,8 @@ protected void writeHtml(Writer writer) {
         }
         pw.println(")</h1>");
         
+        Flash.renderFlashesHTML(pw, getRequest());
+        
         if(cj.isProfile()) {
             pw.print(
                 "<p>As a <i>profile</i>, this job may be built for " +
@@ -381,7 +383,9 @@ public void acceptRepresentation(Representation entity) throws ResourceException
         } else if("build".equals(action)||"validate".equals(action)) {
             cj.validateConfiguration();
         } else if("teardown".equals(action)) {
-            cj.reset(); 
+            if(!cj.teardown()) {
+                Flash.addFlash(getResponse(), "waiting for job to finish", Flash.Kind.NACK);
+            }
         } else if("pause".equals(action)) {
             cj.getCrawlController().requestCrawlPause();
         } else if("unpause".equals(action)) {

https://github.com/internetarchive/heritrix3/raw/ace6d95ab88d82689674a3978c51b9faac7573e7/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Frestlet%2FJobResource.java
7bfebecb75cc6f0ce88c888a394673547f423407
modified
https://github.com/internetarchive/heritrix3/blob/ace6d95ab88d82689674a3978c51b9faac7573e7/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Futil%2FBdbUriUniqFilter.java
https://api.github.com/repos/internetarchive/heritrix3/contents/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Futil%2FBdbUriUniqFilter.java?ref=ace6d95ab88d82689674a3978c51b9faac7573e7
engine/src/main/java/org/archive/crawler/util/BdbUriUniqFilter.java
    public synchronized long getCacheMisses() {
        try {
            long cacheMiss = this.alreadySeen.getEnvironment().
            // FIXME: get shouldn't define intervals (should be idempotent)
            this.lastCacheMissDiff = cacheMiss - this.lastCacheMiss;
            this.lastCacheMiss = cacheMiss;
            return this.lastCacheMiss;
        } catch (DatabaseException de) {
            return 0;
        }
        
engine/src/main/java/org/archive/crawler/util/BdbUriUniqFilter.java
try {
            long cacheMiss = this.alreadySeen.getEnvironment().
            // FIXME: get shouldn't define intervals (should be idempotent)
            this.lastCacheMissDiff = cacheMiss - this.lastCacheMiss;
            this.lastCacheMiss = cacheMiss;
            return this.lastCacheMiss;
long getCacheMisses()
    public synchronized long getCacheMisses() throws DatabaseException {
        long cacheMiss = this.alreadySeen.getEnvironment().
        // FIXME: get shouldn't define intervals (should be idempotent)
        this.lastCacheMissDiff = cacheMiss - this.lastCacheMiss;
        this.lastCacheMiss = cacheMiss;
        return this.lastCacheMiss;
@@ -261,16 +261,21 @@ public synchronized void close() {
         }
     }
     
-    public synchronized long getCacheMisses() throws DatabaseException {
+    public synchronized long getCacheMisses() {
         if(alreadySeen==null) {
             return 0;
         }
-        long cacheMiss = this.alreadySeen.getEnvironment().
+        try {
+            long cacheMiss = this.alreadySeen.getEnvironment().
             getStats(null).getNCacheMiss();
-        // FIXME: get shouldn't define intervals (should be idempotent)
-        this.lastCacheMissDiff = cacheMiss - this.lastCacheMiss;
-        this.lastCacheMiss = cacheMiss;
-        return this.lastCacheMiss;
+            // FIXME: get shouldn't define intervals (should be idempotent)
+            this.lastCacheMissDiff = cacheMiss - this.lastCacheMiss;
+            this.lastCacheMiss = cacheMiss;
+            return this.lastCacheMiss;
+        } catch (DatabaseException de) {
+            return 0;
+        }
+        
     }
     
     public long getLastCacheMissDiff() {
https://github.com/internetarchive/heritrix3/raw/ace6d95ab88d82689674a3978c51b9faac7573e7/engine%2Fsrc%2Fmain%2Fjava%2Forg%2Farchive%2Fcrawler%2Futil%2FBdbUriUniqFilter.java
d37fbff2cc69fbbec84e707f6095c17a6167a65b
modified
internetarchive$heritrix3
// wait up to 3 seconds for stop
                for(int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(300);
boolean
boolean teardown()
void
void reset()