View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.monitoring.store;
18  
19  import org.apache.commons.monitoring.Role;
20  import org.apache.commons.monitoring.configuration.Configuration;
21  import org.apache.commons.monitoring.counters.Counter;
22  import org.apache.commons.monitoring.counters.DefaultCounter;
23  import org.apache.commons.monitoring.gauges.Gauge;
24  
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.Map;
28  import java.util.TreeMap;
29  import java.util.concurrent.ConcurrentHashMap;
30  import java.util.concurrent.ConcurrentMap;
31  import java.util.concurrent.ConcurrentSkipListMap;
32  import java.util.concurrent.locks.Lock;
33  
34  public class DefaultDataStore implements DataStore {
35      private final ConcurrentMap<Counter.Key, Counter> counters = new ConcurrentHashMap<Counter.Key, Counter>(50);
36      private final Map<Role, Map<Long, Double>> gauges = new ConcurrentHashMap<Role, Map<Long, Double>>();
37  
38      @Override
39      public Counter getOrCreateCounter(final Counter.Key key) {
40          Counter counter = counters.get(key);
41          if (counter == null) {
42              counter = new DefaultCounter(key, this);
43              final Counter previous = counters.putIfAbsent(key, counter);
44              if (previous != null) {
45                  counter = previous;
46              }
47          }
48          return counter;
49      }
50  
51      @Override
52      public void clearCounters() {
53          counters.clear();
54      }
55  
56      @Override
57      public Collection<Counter> getCounters() {
58          return counters.values();
59      }
60  
61      @Override
62      public void addToCounter(final Counter counter, final double delta) {
63          if (!DefaultCounter.class.isInstance(counter)) {
64              throw new IllegalArgumentException(DefaultDataStore.class.getName() + " only supports " + DefaultCounter.class.getName());
65          }
66  
67          final DefaultCounter defaultCounter = DefaultCounter.class.cast(counter);
68          final Lock lock = defaultCounter.getLock();
69          lock.lock();
70          try {
71              defaultCounter.addInternal(delta);
72          } finally {
73              lock.unlock();
74          }
75      }
76  
77      @Override
78      public Map<Long, Double> getGaugeValues(GaugeValuesRequest gaugeValuesRequest) {
79          final Map<Long, Double> map = gauges.get(gaugeValuesRequest.getRole());
80          if (map == null) {
81              return Collections.emptyMap();
82          }
83  
84          final Map<Long, Double> copy = new TreeMap<Long, Double>( map );
85  
86          final Map<Long, Double> out = new TreeMap<Long, Double>();
87          for (final Map.Entry<Long, Double> entry : copy.entrySet()) {
88              final long time = entry.getKey();
89              if (time >= gaugeValuesRequest.getStart() && time <= gaugeValuesRequest.getEnd()) {
90                  out.put(time, entry.getValue());
91              }
92          }
93          return out;
94      }
95  
96      @Override
97      public void createOrNoopGauge(final Role role) {
98          gauges.put(role, new FixedSizedMap());
99      }
100 
101     @Override
102     public void addToGauge(final Gauge gauge, final long time, final double value) {
103         gauges.get(gauge.role()).put(time, value);
104     }
105 
106     // no perf issues here normally since add is called not that often
107     protected static class FixedSizedMap extends ConcurrentSkipListMap<Long, Double> {
108         private static final int MAX_SIZE = Configuration.getInteger(Configuration.COMMONS_MONITORING_PREFIX + "gauge.max-size", 100);
109 
110         protected FixedSizedMap() {
111             // no-op
112         }
113 
114         protected FixedSizedMap(final Map<Long, Double> value) {
115             super(value);
116         }
117 
118         @Override
119         public Double put(final Long key, final Double value) {
120             if (size() >= MAX_SIZE) {
121                 remove(keySet().iterator().next());
122             }
123             return super.put(key, value);
124         }
125     }
126 }