/* ===============================================================================
*
* Part of the InfoGlue Content Management Platform (www.infoglue.org)
*
* ===============================================================================
*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2, as published by the
* Free Software Foundation. See the file LICENSE.html for more information.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc. / 59 Temple
* Place, Suite 330 / Boston, MA 02111-1307 / USA.
*
* ===============================================================================
*/
package org.infoglue.deliver.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import org.apache.log4j.Logger;
import org.infoglue.cms.util.sorters.AverageInvokingTimeComparator;
import org.infoglue.deliver.applications.databeans.CacheEvictionBean;
import org.infoglue.deliver.invokers.ComponentBasedHTMLPageInvoker;
/**
* @author mattias
*
* This class contains a lot of statistics. Badly implemented now that Atomic operations are part of Java.
*/
public class Counter
{
private final static Logger logger = Logger.getLogger(Counter.class.getName());
private static Integer count = new Integer(0);
private static Integer activeCount = new Integer(0);
private static Integer totalCount = new Integer(0);
private static Integer approximateNumberOfDatabaseQueries = new Integer(0);
private static Long totalElapsedTime = new Long(0);
private static Long maxElapsedTime = new Long(0);
private static Map allComponentsStatistics = new HashMap();
private static Map allPageStatistics = new HashMap();
private static LinkedBlockingQueue<String> latestPageStatistics = new LinkedBlockingQueue<String>(100);
private static LinkedBlockingQueue<CacheEvictionBean> latestPublications = new LinkedBlockingQueue<CacheEvictionBean>(2000);
private static List<CacheEvictionBean> ongoingPublications = new ArrayList<CacheEvictionBean>();
private static Integer numberOfPublicationsSinceStart = new Integer(0);
private Counter(){}
static int getNumberOfCurrentRequests()
{
return count.intValue();
}
static int getNumberOfActiveRequests()
{
return activeCount.intValue();
}
static int getTotalNumberOfRequests()
{
return totalCount.intValue();
}
static long getAverageElapsedTime()
{
if(totalElapsedTime != null && totalCount.intValue() != 0)
return totalElapsedTime.longValue() / totalCount.intValue();
else
return 0;
}
static long getMaxElapsedTime()
{
return maxElapsedTime.longValue();
}
static int getApproximateNumberOfDatabaseQueries()
{
return approximateNumberOfDatabaseQueries.intValue();
}
static void incApproximateNumberOfDatabaseQueries()
{
approximateNumberOfDatabaseQueries = new Integer(approximateNumberOfDatabaseQueries.intValue() + 1);
}
static void decApproximateNumberOfDatabaseQueries()
{
if(approximateNumberOfDatabaseQueries > 0)
approximateNumberOfDatabaseQueries = new Integer(approximateNumberOfDatabaseQueries.intValue() - 1);
}
static List<CacheEvictionBean> getLatestPublications()
{
List<CacheEvictionBean> latestPublicationsList = new ArrayList<CacheEvictionBean>();
synchronized (latestPublications)
{
Iterator<CacheEvictionBean> latestPublicationsIterator = latestPublications.iterator();
while(latestPublicationsIterator.hasNext())
{
latestPublicationsList.add(latestPublicationsIterator.next());
}
}
return latestPublicationsList;
}
static List<String> getLatestPageStatistics()
{
List<String> latestPagesList = new ArrayList<String>();
synchronized (latestPageStatistics)
{
Iterator<String> latestPageStatisticsIterator = latestPageStatistics.iterator();
while(latestPageStatisticsIterator.hasNext())
{
latestPagesList.add(latestPageStatisticsIterator.next());
}
}
return latestPagesList;
}
static void resetLatestPublications()
{
synchronized (latestPublications)
{
latestPublications.clear();
numberOfPublicationsSinceStart = 0;
}
}
static List<CacheEvictionBean> getOngoingPublications()
{
List<CacheEvictionBean> ongoingPublicationsList = new ArrayList<CacheEvictionBean>();
synchronized (ongoingPublications)
{
Iterator<CacheEvictionBean> ongoingPublicationsIterator = ongoingPublications.iterator();
while(ongoingPublicationsIterator.hasNext())
{
ongoingPublicationsList.add(ongoingPublicationsIterator.next());
}
}
return ongoingPublicationsList;
}
static Integer getNumberOfPublicationsSinceStart()
{
synchronized (latestPublications)
{
return latestPublications.size();
}
//return numberOfPublicationsSinceStart;
}
synchronized static void addPublication(CacheEvictionBean bean)
{
if(bean.getClassName().indexOf("ServerNodeProperties") == -1)
numberOfPublicationsSinceStart++;
synchronized (latestPublications)
{
if(latestPublications.remainingCapacity() == 0)
latestPublications.poll();
latestPublications.add(bean);
}
}
synchronized static void addOngoingPublication(CacheEvictionBean bean)
{
synchronized (ongoingPublications)
{
ongoingPublications.add(bean);
}
}
synchronized static void removeOngoingPublication(CacheEvictionBean bean)
{
synchronized (ongoingPublications)
{
ongoingPublications.remove(bean);
}
}
synchronized static void incNumberOfCurrentRequests(boolean active)
{
count = new Integer(count.intValue() + 1);
if(active)
activeCount = new Integer(activeCount.intValue() + 1);
}
synchronized static void decNumberOfCurrentRequests(long elapsedTime)
{
if(count > 0)
count = new Integer(count.intValue() - 1);
if(elapsedTime != -1 && activeCount > 0)
activeCount = new Integer(activeCount.intValue() - 1);
totalCount = new Integer(totalCount.intValue() + 1);
if(elapsedTime != -1)
{
totalElapsedTime = new Long(totalElapsedTime.longValue() + elapsedTime);
if(elapsedTime > maxElapsedTime.longValue())
maxElapsedTime = new Long(elapsedTime);
}
}
synchronized static Set getAllComponentNames()
{
synchronized (allComponentsStatistics)
{
return allComponentsStatistics.keySet();
}
}
synchronized static Set getAllPageUrls()
{
synchronized (allPageStatistics)
{
return allPageStatistics.keySet();
}
}
synchronized private static Map getComponentStatistics(String componentName)
{
Map componentStatistics = (Map)allComponentsStatistics.get(componentName);
if(componentStatistics == null)
{
componentStatistics = new HashMap();
componentStatistics.put("totalElapsedTime", new Long(0));
componentStatistics.put("totalNumberOfInvokations", new Integer(0));
allComponentsStatistics.put(componentName, componentStatistics);
}
return componentStatistics;
}
synchronized private static Map getPageStatistics(String pageUrl)
{
Map pageStatistics = (Map)allPageStatistics.get(pageUrl);
if(pageStatistics == null)
{
pageStatistics = new HashMap();
pageStatistics.put("totalElapsedTime", new Long(0));
pageStatistics.put("totalNumberOfInvokations", new Integer(0));
allPageStatistics.put(pageUrl, pageStatistics);
}
return pageStatistics;
}
static void registerComponentStatistics(String componentName, long elapsedTime)
{
Map componentStatistics = getComponentStatistics(componentName);
//synchronized (componentStatistics)
try
{
Long oldTotalElapsedTime = (Long)componentStatistics.get("totalElapsedTime");
Long totalElapsedTime = new Long(oldTotalElapsedTime.longValue() + elapsedTime);
componentStatistics.put("totalElapsedTime", totalElapsedTime);
Integer oldTotalNumberOfInvokations = (Integer)componentStatistics.get("totalNumberOfInvokations");
Integer totalNumberOfInvokations = new Integer(oldTotalNumberOfInvokations.intValue() + 1);
componentStatistics.put("totalNumberOfInvokations", totalNumberOfInvokations);
}
catch (Exception e)
{
logger.error("Error in registerComponentStatistics: " + e.getMessage());
}
}
static void registerPageStatistics(String pageUrl, long elapsedTime)
{
Map pageStatistics = getPageStatistics(pageUrl);
//synchronized (pageStatistics)
try
{
Long oldTotalElapsedTime = (Long)pageStatistics.get("totalElapsedTime");
Long totalElapsedTime = new Long(oldTotalElapsedTime.longValue() + elapsedTime);
pageStatistics.put("totalElapsedTime", totalElapsedTime);
pageStatistics.put("lastEventDate", new Date());
Integer oldTotalNumberOfInvokations = (Integer)pageStatistics.get("totalNumberOfInvokations");
Integer totalNumberOfInvokations = new Integer(oldTotalNumberOfInvokations.intValue() + 1);
pageStatistics.put("totalNumberOfInvokations", totalNumberOfInvokations);
}
catch (Exception e)
{
logger.error("Error in registerPageStatistics: " + e.getMessage());
}
}
static void registerLatestPageStatistics(String pageUrl)
{
synchronized (latestPageStatistics)
{
if(latestPageStatistics.remainingCapacity() == 0)
latestPageStatistics.poll();
latestPageStatistics.add(pageUrl);
}
}
static long getAverageElapsedTime(String componentName)
{
Map componentStatistics = getComponentStatistics(componentName);
synchronized (componentStatistics)
{
Long totalElapsedTime = (Long)componentStatistics.get("totalElapsedTime");
Integer oldTotalNumberOfInvokations = (Integer)componentStatistics.get("totalNumberOfInvokations");
return totalElapsedTime.longValue() / oldTotalNumberOfInvokations.intValue();
}
}
static int getNumberOfHits(String componentName)
{
Map componentStatistics = getComponentStatistics(componentName);
synchronized (componentStatistics)
{
return ((Integer)componentStatistics.get("totalNumberOfInvokations")).intValue();
}
}
static long getPageAverageElapsedTime(String pageUrl)
{
Map pageStatistics = getPageStatistics(pageUrl);
synchronized (pageStatistics)
{
Long totalElapsedTime = (Long)pageStatistics.get("totalElapsedTime");
Integer oldTotalNumberOfInvokations = (Integer)pageStatistics.get("totalNumberOfInvokations");
if(totalElapsedTime != null && totalElapsedTime != 0 && oldTotalNumberOfInvokations != null && oldTotalNumberOfInvokations != 0)
return totalElapsedTime.longValue() / oldTotalNumberOfInvokations.intValue();
else
return -1;
}
}
static Date getLastEventDate(String pageUrl)
{
Map pageStatistics = getPageStatistics(pageUrl);
synchronized (pageStatistics)
{
Date lastEventDate = (Date)pageStatistics.get("lastEventDate");
return lastEventDate;
}
}
static int getPageNumberOfHits(String pageUrl)
{
Map pageStatistics = getPageStatistics(pageUrl);
synchronized (pageStatistics)
{
return ((Integer)pageStatistics.get("totalNumberOfInvokations")).intValue();
}
}
static void resetComponentStatistics()
{
synchronized (allComponentsStatistics)
{
allComponentsStatistics.clear();
}
}
static void resetPageStatistics()
{
synchronized (allPageStatistics)
{
allPageStatistics.clear();
}
}
static void shortenPageStatistics()
{
logger.info("shortenPageStatistics");
try
{
synchronized (allPageStatistics)
{
if(allPageStatistics.size() > 50)
{
Map shortPageStatistics = new HashMap();
List unsortedPageUrls = new ArrayList();
Set pageUrls = allPageStatistics.keySet();
Iterator pageUrlsIterator = pageUrls.iterator();
while(pageUrlsIterator.hasNext())
{
String pageUrl = (String)pageUrlsIterator.next();
Map pageStatistics = (Map)allPageStatistics.get(pageUrl);
synchronized (pageStatistics)
{
Long totalElapsedTime = (Long)pageStatistics.get("totalElapsedTime");
Integer pageNumberOfHits = (Integer)pageStatistics.get("totalNumberOfInvokations");
long pageAverageElapsedTime = totalElapsedTime / pageNumberOfHits;
unsortedPageUrls.add(getList("" + pageUrl, new Long(pageAverageElapsedTime)));
}
}
Collections.sort(unsortedPageUrls, new AverageInvokingTimeComparator());
if(unsortedPageUrls.size() > 50)
unsortedPageUrls = unsortedPageUrls.subList(0, 50);
Iterator unsortedPageUrlsIterator = unsortedPageUrls.iterator();
while(unsortedPageUrlsIterator.hasNext())
{
List item = (List)unsortedPageUrlsIterator.next();
if(item.size() > 1)
{
String pageUrl = (String)item.get(0);
shortPageStatistics.put(pageUrl, allPageStatistics.get(pageUrl));
}
}
allPageStatistics = shortPageStatistics;
}
}
}
catch (Exception e)
{
logger.error("Error in shortenPageStatistics:" + e.getMessage());
}
try
{
logger.info("Shortening allComponentsStatistics: " + allComponentsStatistics.size());
synchronized (allComponentsStatistics)
{
if(allComponentsStatistics.size() > 500)
{
Map shortComponentsStatistics = new HashMap();
List unsortedComponentStatistics = new ArrayList();
Set componentUrls = allComponentsStatistics.keySet();
Iterator componentUrlsIterator = componentUrls.iterator();
while(componentUrlsIterator.hasNext())
{
String componentUrl = (String)componentUrlsIterator.next();
Map componentStatistics = (Map)allComponentsStatistics.get(componentUrl);
synchronized (componentStatistics)
{
Long totalElapsedTime = (Long)componentStatistics.get("totalElapsedTime");
Integer componentNumberOfHits = (Integer)componentStatistics.get("totalNumberOfInvokations");
long componentAverageElapsedTime = totalElapsedTime / componentNumberOfHits;
unsortedComponentStatistics.add(getList("" + componentUrl, new Long(componentAverageElapsedTime)));
}
}
Collections.sort(unsortedComponentStatistics, new AverageInvokingTimeComparator());
if(unsortedComponentStatistics.size() > 500)
unsortedComponentStatistics = unsortedComponentStatistics.subList(0, 500);
Iterator unsortedComponentUrlsIterator = unsortedComponentStatistics.iterator();
while(unsortedComponentUrlsIterator.hasNext())
{
List item = (List)unsortedComponentUrlsIterator.next();
if(item.size() > 1)
{
String componentUrl = (String)item.get(0);
shortComponentsStatistics.put(componentUrl, allComponentsStatistics.get(componentUrl));
}
}
allComponentsStatistics = shortComponentsStatistics;
}
}
logger.info("After resizing....:" + allComponentsStatistics.size());
}
catch (Exception e)
{
logger.error("Error in shortenComponentStatistics:" + e.getMessage());
}
}
static List getList(String key, Object value)
{
List list = new ArrayList();
list.add(key);
list.add(value);
return list;
}
static void resetAverageResponseTimeStatistics()
{
totalElapsedTime = new Long(0);
totalCount = new Integer(0);
}
}