@Override
 protected final void cleanup() {
   LOG.info("Shutting down Monitoring Controller (" + this.getName() + ")");
   // this.saveMetadataAsRecord();
   this.probeController.terminate();
   this.registryController.terminate();
   this.timeSourceController.terminate();
   this.writerController.terminate();
   this.jmxController.terminate();
   this.samplingController.terminate();
   this.stateController.terminate();
 }
 @Override
 protected void cleanup() {
   if (this.out != null) {
     try {
       final ByteBuffer buffer = this.byteBuffer;
       buffer.flip();
       while (buffer.hasRemaining()) {
         this.channel.write(buffer);
       }
       buffer.clear();
       this.channel.force(false);
       this.out.close();
     } catch (final IOException ex) {
       LOG.error("Failed to close channel.", ex);
     }
   }
 }
  /**
   * This is a factory method creating a new monitoring controller instance using the given
   * configuration.
   *
   * @param configuration The configuration for the new controller.
   * @return A new controller.
   */
  public static final IMonitoringController createInstance(final Configuration configuration) {
    final MonitoringController monitoringController = new MonitoringController(configuration);
    // Initialize and handle early Termination (once for each Controller!)
    monitoringController.stateController.setMonitoringController(monitoringController);
    if (monitoringController.stateController.isTerminated()) {
      monitoringController.terminate();
    }
    monitoringController.samplingController.setMonitoringController(monitoringController);
    if (monitoringController.samplingController.isTerminated()) {
      monitoringController.terminate();
    }
    monitoringController.jmxController.setMonitoringController(monitoringController);
    if (monitoringController.jmxController.isTerminated()) {
      monitoringController.terminate();
    }
    monitoringController.writerController.setMonitoringController(monitoringController);
    if (monitoringController.writerController.isTerminated()) {
      monitoringController.terminate();
    }
    monitoringController.timeSourceController.setMonitoringController(monitoringController);
    if (monitoringController.timeSourceController.isTerminated()) {
      monitoringController.terminate();
    }
    monitoringController.registryController.setMonitoringController(monitoringController);
    if (monitoringController.registryController.isTerminated()) {
      monitoringController.terminate();
    }
    monitoringController.probeController.setMonitoringController(monitoringController);
    if (monitoringController.probeController.isTerminated()) {
      monitoringController.terminate();
    }
    monitoringController.setMonitoringController(monitoringController);
    if (monitoringController.isTerminated()) {
      return monitoringController;
    }

    if (configuration.getBooleanProperty(ConfigurationFactory.USE_SHUTDOWN_HOOK)) {
      // This ensures that the terminateMonitoring() method is always called before shutting down
      // the JVM. This method ensures that necessary cleanup steps are
      // finished and no information is lost due to asynchronous writers.
      try {
        Runtime.getRuntime()
            .addShutdownHook(
                new Thread() {

                  @Override
                  public void run() {
                    if (!monitoringController.isMonitoringTerminated()) {
                      // WONTFIX: We should not use a logger in shutdown hooks, logger may already
                      // be down! (#26)
                      LOG.info(
                          "ShutdownHook notifies controller to initiate shutdown in "
                              + SHUTDOWN_DELAY_MILLIS
                              + " milliseconds");
                      // System.err.println(monitoringController.toString());
                      try {
                        Thread.sleep(SHUTDOWN_DELAY_MILLIS);
                      } catch (final InterruptedException e) {
                        LOG.warn("ShutdownHook was interrupted while waiting");
                      }
                      monitoringController.terminateMonitoring();
                    }
                  }
                });
      } catch (final Exception e) { // NOPMD NOCS (Exception)
        LOG.warn("Failed to add shutdownHook");
      }
    } else {
      LOG.warn("Shutdown Hook is disabled, loss of monitoring data might occur.");
    }
    LOG.info(monitoringController.toString());
    return monitoringController;
  }