public Optional<MetricSet> getValues(String metricName, Interval interval) { Instant now = Clock.systemUTC().instant(); Optional<RetentionLevel> accessLevel = environment.retentions().findAccessLevelForMetric(metricName); Optional<MetricSet> setWithHighestQoS = Optional.empty(); double highestAvailableQoS = 0; if (!accessLevel.isPresent()) { return Optional.empty(); } EvictionStrategy evictionStrategy = findEvictionStrategyForAccessLevel(accessLevel.get()).get(); evictionStrategy.accessing(metricName); while (accessLevel.isPresent() && caches.containsKey(accessLevel.get().name())) { log.trace("Found accessLevel " + accessLevel.get().name()); Optional<CachingLevel> cachingLevel = environment.cachingConfiguration().findLevelForLevelName(accessLevel.get().name()); if (cachingLevel.isPresent()) { long cachingLevelStart = now.minusSeconds(cachingLevel.get().cacheLineWidth() * accessLevel.get().frequency()) .getEpochSecond(); if (cachingLevelStart < interval.start()) { Optional<MetricSet> metricSet = doGetValues(metricName, interval, cachingLevel.get()); if (!metricSet.isPresent()) { try { createNewCacheLines(metricName).get(); } catch (InterruptedException | ExecutionException e) { log.warn("Exception while waiting for threads loading metrics", e); } metricSet = doGetValues(metricName, interval, cachingLevel.get()); } if (metricSet.isPresent()) { log.trace("metricSet contains {} timestamps", metricSet.get().size()); log.trace("accesslevel: {} | metricSet: {}", accessLevel.get().name(), metricSet.get()); OptionalDouble serviceAvailable = calculateQoS(interval, metricSet.get()); if (serviceAvailable.isPresent() && serviceAvailable.getAsDouble() >= environment.cachingConfiguration().qualityOfService()) { log.trace("returning metricSet"); return metricSet; } else if (serviceAvailable.isPresent() && serviceAvailable.getAsDouble() > highestAvailableQoS) { log.trace("new highestAvailable set"); highestAvailableQoS = serviceAvailable.getAsDouble(); setWithHighestQoS = metricSet; } } else { log.debug( "no metricSet for cacheLevel {} metric {} found!", accessLevel.get().name(), metricName); } } } accessLevel = environment.retentions().getNextLevel(accessLevel.get()); } log.trace("service requested not available, returning highest available"); return setWithHighestQoS; }
@Override public void run() { Instant now = Clock.systemUTC().instant(); Optional<RetentionLevel> accessLevel = environment.retentions().findAccessLevelForMetric(metricName); if (accessLevel.isPresent()) { if (caches.get(accessLevel.get().name()).containsMetric(metricName)) { return; } Optional<RetentionLevel> highestLevel = accessLevel; while (highestLevel.isPresent() && highestLevel.get().next() != null) { highestLevel = environment.retentions().getNextLevel(highestLevel.get()); } Optional<CachingLevel> cachingLevel = environment.cachingConfiguration().findLevelForLevelName(highestLevel.get().name()); if (cachingLevel.isPresent()) { List<Future<?>> futures = new ArrayList<>(); ArrayList<Metric> databaseMetricsList = new ArrayList<>(); long intervalStart = now.minusSeconds(cachingLevel.get().cacheLineWidth() * highestLevel.get().frequency()) .getEpochSecond(); Interval interval = new Interval(intervalStart, now.getEpochSecond()); Stream<Metric> databaseMetrics = environment.cassandraAccessLayer().loadMetrics(metricName, interval); Iterator<Metric> databaseMetricsIterator = databaseMetrics.iterator(); while (databaseMetricsIterator.hasNext()) { Metric m = databaseMetricsIterator.next(); databaseMetricsList.add(m); } while (accessLevel.isPresent()) { LoadMetrics loadMetrics = new LoadMetrics(accessLevel.get(), metricName, databaseMetricsList, interval); futures.add(loadMetricsThreadPool.submit(Executors.callable(loadMetrics))); accessLevel = environment.retentions().getNextLevel(accessLevel.get()); } for (Future<?> f : futures) { try { f.get(); } catch (InterruptedException | ExecutionException e) { log.warn("Exception while waiting for insertion of metrics into cache", e); } } } } log.trace("all new cache lines created for metric {}", metricName); }