/** Helper method called for given "date directory", to do recursively clean up. */
 protected void _cleanDateDir(DirByDate dateDir, FileCleanupStats stats) {
   int remaining = 0, deleted = 0;
   for (DirByTime timeDir : dateDir.listTimeDirs(stats)) {
     if (shouldStop()) {
       _reportProblem("Terminating file cleanup pre-maturely, due to stop request");
       return;
     }
     // ok; we know rough time by now...
     long msecsAgo = _timeMaster.currentTimeMillis() - timeDir.getRawCreateTime();
     // ancient?
     if (msecsAgo > _maxTimeToLiveMsecs) {
       int failedFiles = timeDir.nuke(stats, _shutdown);
       if (failedFiles == 0) {
         ++deleted;
         continue;
       }
       _reportProblem(
           "Failed to nuke directory "
               + timeDir.toString()
               + "; "
               + failedFiles
               + " files remain, must skip");
     } else {
       // otherwise just weed out empty dirs
       if (timeDir.removeEmpty(stats, _shutdown)) {
         ++deleted;
         continue;
       }
     }
     stats.addRemainingDir();
     ++remaining;
   }
   // how about date dir itself... empty by now?
   if (remaining == 0 && !_shutdown.get()) {
     File dir = dateDir.getDirectory();
     if (dir.delete()) {
       if (deleted == 0) { // was already empty
         stats.addDeletedEmptyDir();
       } else {
         stats.addDeletedDir();
       }
       return;
     }
     _reportProblem("Failed to nuke directory " + dir + " for some reason, must skip");
   }
   stats.addRemainingDir();
 }
 protected void _reportEndSuccess(FileCleanupStats stats, File skippedDir) {
   if (LOG != null) {
     LOG.info(
         "Completed file clean up (skipped the last date-dir, '{}'): {}",
         skippedDir.getAbsolutePath(),
         stats);
   }
 }