private void writeDbValues() {
    if (localDB != null) {
      try {
        localDB.put(LocalDB.DB.PWM_STATS, DB_KEY_CUMULATIVE, statsCummulative.output());
        localDB.put(LocalDB.DB.PWM_STATS, currentDailyKey.toString(), statsDaily.output());

        for (final Statistic.EpsType loopEpsType : Statistic.EpsType.values()) {
          for (final Statistic.EpsDuration loopEpsDuration : Statistic.EpsDuration.values()) {
            final String key = "EPS-" + loopEpsType.toString();
            final String mapKey = loopEpsType.toString() + loopEpsDuration.toString();
            final String value = JsonUtil.serialize(this.epsMeterMap.get(mapKey));
            localDB.put(LocalDB.DB.PWM_STATS, key, value);
          }
        }
      } catch (LocalDBException e) {
        LOGGER.error("error outputting pwm statistics: " + e.getMessage());
      }
    }
  }
 public BigDecimal readEps(final Statistic.EpsType type, final Statistic.EpsDuration duration) {
   return epsMeterMap.get(type.toString() + duration.toString()).readEventRate();
 }
 public void updateEps(final Statistic.EpsType type, final int itemCount) {
   for (final Statistic.EpsDuration duration : Statistic.EpsDuration.values()) {
     epsMeterMap.get(type.toString() + duration.toString()).markEvents(itemCount);
   }
 }
  public void init(PwmApplication pwmApplication) throws PwmException {
    for (final Statistic.EpsType type : Statistic.EpsType.values()) {
      for (final Statistic.EpsDuration duration : Statistic.EpsDuration.values()) {
        epsMeterMap.put(
            type.toString() + duration.toString(), new EventRateMeter(duration.getTimeDuration()));
      }
    }

    status = STATUS.OPENING;
    this.localDB = pwmApplication.getLocalDB();
    this.pwmApplication = pwmApplication;

    if (localDB == null) {
      LOGGER.error("LocalDB is not available, will remain closed");
      status = STATUS.CLOSED;
      return;
    }

    {
      final String storedCummulativeBundleStr =
          localDB.get(LocalDB.DB.PWM_STATS, DB_KEY_CUMULATIVE);
      if (storedCummulativeBundleStr != null && storedCummulativeBundleStr.length() > 0) {
        statsCummulative = StatisticsBundle.input(storedCummulativeBundleStr);
      }
    }

    {
      for (final Statistic.EpsType loopEpsType : Statistic.EpsType.values()) {
        for (final Statistic.EpsType loopEpsDuration : Statistic.EpsType.values()) {
          final String key = "EPS-" + loopEpsType.toString() + loopEpsDuration.toString();
          final String storedValue = localDB.get(LocalDB.DB.PWM_STATS, key);
          if (storedValue != null && storedValue.length() > 0) {
            try {
              final EventRateMeter eventRateMeter =
                  JsonUtil.deserialize(storedValue, EventRateMeter.class);
              epsMeterMap.put(loopEpsType.toString() + loopEpsDuration.toString(), eventRateMeter);
            } catch (Exception e) {
              LOGGER.error(
                  "unexpected error reading last EPS rate for "
                      + loopEpsType
                      + " from LocalDB: "
                      + e.getMessage());
            }
          }
        }
      }
    }

    {
      final String storedInitialString =
          localDB.get(LocalDB.DB.PWM_STATS, DB_KEY_INITIAL_DAILY_KEY);
      if (storedInitialString != null && storedInitialString.length() > 0) {
        initialDailyKey = new DailyKey(storedInitialString);
      }
    }

    {
      currentDailyKey = new DailyKey(new Date());
      final String storedDailyStr = localDB.get(LocalDB.DB.PWM_STATS, currentDailyKey.toString());
      if (storedDailyStr != null && storedDailyStr.length() > 0) {
        statsDaily = StatisticsBundle.input(storedDailyStr);
      }
    }

    try {
      localDB.put(
          LocalDB.DB.PWM_STATS,
          DB_KEY_TEMP,
          PwmConstants.DEFAULT_DATETIME_FORMAT.format(new Date()));
    } catch (IllegalStateException e) {
      LOGGER.error("unable to write to localDB, will remain closed, error: " + e.getMessage());
      status = STATUS.CLOSED;
      return;
    }

    localDB.put(LocalDB.DB.PWM_STATS, DB_KEY_VERSION, DB_VALUE_VERSION);
    localDB.put(LocalDB.DB.PWM_STATS, DB_KEY_INITIAL_DAILY_KEY, initialDailyKey.toString());

    { // setup a timer to roll over at 0 Zula and one to write current stats every 10 seconds
      final String threadName = Helper.makeThreadName(pwmApplication, this.getClass()) + " timer";
      daemonTimer = new Timer(threadName, true);
      daemonTimer.schedule(new FlushTask(), 10 * 1000, DB_WRITE_FREQUENCY_MS);
      daemonTimer.schedule(new NightlyTask(), Helper.nextZuluZeroTime());
    }

    if (pwmApplication.getApplicationMode() == PwmApplication.MODE.RUNNING) {
      if (pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.PUBLISH_STATS_ENABLE)) {
        long lastPublishTimestamp = pwmApplication.getInstallTime().getTime();
        {
          final String lastPublishDateStr =
              localDB.get(LocalDB.DB.PWM_STATS, KEY_CLOUD_PUBLISH_TIMESTAMP);
          if (lastPublishDateStr != null && lastPublishDateStr.length() > 0) {
            try {
              lastPublishTimestamp = Long.parseLong(lastPublishDateStr);
            } catch (Exception e) {
              LOGGER.error(
                  "unexpected error reading last publish timestamp from PwmDB: " + e.getMessage());
            }
          }
        }
        final Date nextPublishTime =
            new Date(
                lastPublishTimestamp
                    + PwmConstants.STATISTICS_PUBLISH_FREQUENCY_MS
                    + (long) PwmRandom.getInstance().nextInt(3600 * 1000));
        daemonTimer.schedule(
            new PublishTask(), nextPublishTime, PwmConstants.STATISTICS_PUBLISH_FREQUENCY_MS);
      }
    }

    status = STATUS.OPEN;
  }