/* * � Copyright IBM Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.ibm.domino.das.servlet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * Encapsulates a map of the statistics for all DAS services * on this server. */ public class DasStats { private static DasStats s_stats = new DasStats(); private Map<String, Object> statsMap = new ConcurrentHashMap<String, Object>(); /** * Mutable version of the Integer class. * * <p>The DasStats class uses MutableInteger to store int values to avoid * creating a new instance of Integer everytime the stat is incremented. */ public class MutableInteger { private int _value = 0; public MutableInteger(int value) { _value = value; } /** * @return the value */ public int getValue() { return _value; } /** * @param value the value to set */ public void setValue(int value) { _value = value; } } /** * Mutable version of Double class. * * <p>The DasStats class uses MutableDouble to store double values to avoid * creating a new instance of Double everytime the stat is changed. */ public class MutableDouble { private double _value = 0; public MutableDouble(double value) { _value = value; } /** * @return the value */ public double getValue() { return _value; } /** * @param value the value to set */ public void setValue(double value) { _value = value; } } private DasStats() { // Private because this is a singleton } public static DasStats get() { return s_stats; } /** * Creates a new integer stat. If the stat already exists, this * method replaces it. * * @param key * @param value */ public void setInteger(String key, int value) { Object current = statsMap.get(key); if ( current instanceof MutableInteger ) { // Synchronize because an assigment isn't // guaranteed to be atomic synchronized(current) { ((MutableInteger)current).setValue(value); } } else { statsMap.put(key, new MutableInteger(value)); } } /** * Adds to an existing integer stat. If the stat doesn't exist, * this method creates it. * * @param key * @param value */ public int addInteger(String key, int value) { int newValue = value; // TODO: Handle the race condition where two threads // are creating the same new stat at the same time. Object current = statsMap.get(key); if ( current instanceof MutableInteger ) { synchronized(current) { newValue = ((MutableInteger)current).getValue() + value; ((MutableInteger)current).setValue(newValue); } } else { setInteger(key, value); } return newValue; } /** * Reads an integer stat. * * @param key * @return */ public int getInteger(String key) { int value = 0; Object current = statsMap.get(key); if ( current instanceof MutableInteger ) { value = ((MutableInteger)current).getValue(); } return value; } /** * Creates a new text stat. * * @param key * @param value */ public void setText(String key, String value) { } /** * Creates a new number stat. * * @param key * @param value */ public void setNumber(String key, double value) { Object current = statsMap.get(key); if ( current instanceof MutableDouble ) { // Synchronize because a double assigment isn't // guaranteed to be atomic synchronized(current) { ((MutableDouble)current).setValue(value); } } else { statsMap.put(key, new MutableDouble(value)); } } /** * Adds to an existing number stat. If the stat doesn't exist, * this method creates it. * * @param key * @param value */ public double addNumber(String key, double value) { double newValue = value; // TODO: Handle the race condition where two threads // are creating the same new stat at the same time. Object current = statsMap.get(key); if ( current instanceof MutableDouble ) { synchronized(current) { newValue = ((MutableDouble)current).getValue() + value; ((MutableDouble)current).setValue(newValue); } } else { setNumber(key, value); } return newValue; } /** * Reads a number stat. * * @param key * @return */ public double getNumber(String key) { double value = 0; Object current = statsMap.get(key); if ( current instanceof MutableDouble ) { value = ((MutableDouble)current).getValue(); } return value; } /** * Gets a set containing all the stats. * * @return */ public Set<Map.Entry<String, Object>> getEntries() { return statsMap.entrySet(); } }