/** Run a checkpoint of the crawler */ public synchronized String requestCrawlCheckpoint() throws IllegalStateException { if (isCheckpointing()) { throw new IllegalStateException("Checkpoint already running."); } // prevent redundant auto-checkpoints when crawler paused if (controller.isPaused()) { if (controller.getStatisticsTracker().getSnapshot().sameProgressAs(lastCheckpointSnapshot)) { LOGGER.info("no progress since last checkpoint; ignoring"); System.err.println("no progress since last checkpoint; ignoring"); return null; } } Map<String, Checkpointable> toCheckpoint = appCtx.getBeansOfType(Checkpointable.class); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("checkpointing beans " + toCheckpoint); } checkpointInProgress = new Checkpoint(); try { checkpointInProgress.generateFrom(getCheckpointsDir(), getNextCheckpointNumber()); // pre (incl. acquire necessary locks) // long startMs = System.currentTimeMillis(); for (Checkpointable c : toCheckpoint.values()) { c.startCheckpoint(checkpointInProgress); } // long duration = System.currentTimeMillis() - startMs; // System.err.println("all startCheckpoint() completed in "+duration+"ms"); // flush/write for (Checkpointable c : toCheckpoint.values()) { // long doMs = System.currentTimeMillis(); c.doCheckpoint(checkpointInProgress); // long doDuration = System.currentTimeMillis() - doMs; // System.err.println("doCheckpoint() "+c+" in "+doDuration+"ms"); } checkpointInProgress.setSuccess(true); appCtx.publishEvent(new CheckpointSuccessEvent(this, checkpointInProgress)); } catch (Exception e) { checkpointFailed(e); } finally { checkpointInProgress.writeValidity(controller.getStatisticsTracker().getProgressStamp()); lastCheckpointSnapshot = controller.getStatisticsTracker().getSnapshot(); // close (incl. release locks) for (Checkpointable c : toCheckpoint.values()) { c.finishCheckpoint(checkpointInProgress); } } this.nextCheckpointNumber++; LOGGER.info("finished checkpoint " + checkpointInProgress.getName()); String nameToReport = checkpointInProgress.getSuccess() ? checkpointInProgress.getName() : null; this.checkpointInProgress = null; return nameToReport; }