/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program is distributed
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even 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.hyperic.hq.product;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import org.hyperic.util.encoding.Base64;
public class RtStat implements Serializable {
public static final String NULL_IP = "0.0.0.0";
public static final String NULL_URL = "?unknown-url?";
private String ip = null;
private String url = null;
private long begin = Long.MAX_VALUE;
private long end = Long.MIN_VALUE;
private double min = Double.NaN;
private double max = Double.NEGATIVE_INFINITY;
private double total = 0;
private int count = 0;
private Hashtable status = null;
private Integer svcID;
private int svcType = RtPlugin.UNKNOWN;
// Only useful for testing. Will cause NPEs in a running server. Do not
// use this API unless it is for a test.
public RtStat() {}
public RtStat(Integer svcID) {
this(svcID, RtPlugin.UNKNOWN);
}
public RtStat(Integer svcID, String ip) {
this(svcID, RtPlugin.UNKNOWN, ip);
}
public RtStat(Integer svcID, int svcType) {
this(svcID, svcType, null);
}
public RtStat(Integer svcID, int svcType, String ip) {
this.ip = ip;
this.svcID = svcID;
this.svcType = svcType;
status = new Hashtable();
}
public void recompute(String givenurl, Date date, double timetaken,
Integer statcode) {
if (url == null) {
url = givenurl;
}
long finish = date.getTime() + (long)timetaken;
long start = date.getTime();
if (start < begin) {
begin = start;
}
if (finish > end) {
end = finish;
}
if (statcode.compareTo(new Integer(200)) >= 0 &&
statcode.compareTo(new Integer(300)) < 0) {
count++;
total += timetaken;
if ((timetaken < min || Double.isNaN(min)) && timetaken >= 0) {
min = timetaken;
}
if (timetaken > max) {
max = timetaken;
}
}
else {
if (status.get(statcode) == null) {
status.put(statcode, new Integer(1));
}
else {
Integer number = (Integer)status.get(statcode);
status.put(statcode, new Integer(number.intValue() + 1));
}
}
}
public void recompute(RtStat rs) {
if (rs == null) {
return;
}
if (svcType == RtPlugin.UNKNOWN) {
svcType = rs.svcType;
}
if (url == null) {
url = rs.url;
}
if (ip == null) {
ip = rs.ip;
}
if (rs.getBegin() < begin) {
begin = rs.begin;
}
if (rs.getEnd() > end) {
end = rs.end;
}
if (rs.count > 0) {
count += rs.count;
if (rs.min > 0) {
total += rs.total;
}
if ((rs.min < min || Double.isNaN(min)) && rs.min >= 0) {
min = rs.min;
}
if (rs.max > max) {
max = rs.max;
}
}
else {
Enumeration en = rs.status.keys();
while (en.hasMoreElements()) {
Integer stat = (Integer)en.nextElement();
Integer number = (Integer)status.get(stat);
if (number == null) {
number = new Integer(0);
}
status.put(stat, new Integer(number.intValue() +
((Integer)rs.status.get(stat)).intValue()));
}
}
}
/**
* XXX: For 3.0 we should validate the IP address passed into setIp is
* valid
*/
public String getIp() {
if (ip == null || ip.length() == 0) {
return NULL_IP;
} else {
return this.ip;
}
}
public void setIp(String ip) { this.ip = ip; }
public void resetIp() { this.ip = null; }
public String getUrl() { return (url == null) ? NULL_URL : url; }
public void setUrl(String u) { url = u; }
public long getBegin() { return begin; }
public void setBegin(long d) { begin = d; }
public long getEnd() { return end; }
public void setEnd(long d) { end = d; }
public double getMin() { return min; }
public void setMin(double min) { this.min = min; }
public double getMax() { return max; }
public void setMax(double max) { this.max = max; }
public double getTotal() { return total; }
public void setTotal(double total) { this.total = total; }
public int getCount() { return count; }
public void setCount(int count) { this.count = count; }
public Hashtable getStatus() { return status; }
public void setStatus( Hashtable st ) { this.status = st; }
public Integer getSvcID() { return svcID; }
public void setSvcID(Integer ID) { svcID = ID; }
public int getSvcType() { return svcType; }
public void setSvcType(int st) { svcType = st; }
public double getAverage() { return (count == 0) ? 0 : (total / count); }
public boolean isEndUser() { return (svcType == RtPlugin.ENDUSER); }
public String getIpUrlKey () { return getIp() + ":" + getUrl(); }
public String toString () {
StringBuffer sb = new StringBuffer ();
sb.append("[RtStat")
.append(" svcid=").append(svcID)
.append(" ip=").append(getIp())
.append(" url=").append(getUrl())
.append(" min=").append(min)
.append(" max=").append(max)
.append(" count=").append(count)
.append(" total=").append(total)
.append(" begin=").append(begin)
.append(" end=").append(end)
.append(" status=").append(status)
.append("]");
return sb.toString();
}
public String encode() throws IOException {
ByteArrayOutputStream bOs = null;
DataOutputStream dOs = null;
try {
bOs = new ByteArrayOutputStream();
dOs = new DataOutputStream(bOs);
dOs.writeUTF(getIp());
dOs.writeUTF(url);
dOs.writeLong(begin);
dOs.writeLong(end);
dOs.writeDouble(min);
dOs.writeDouble(max);
dOs.writeDouble(total);
dOs.writeInt(count);
dOs.writeInt(svcType);
dOs.writeInt(svcID.intValue());
dOs.writeInt(status.size());
Enumeration keys = status.keys();
while (keys.hasMoreElements()) {
Integer key = (Integer)keys.nextElement();
int val = ((Integer)status.get(key)).intValue();
dOs.writeInt(key.intValue());
dOs.writeInt(val);
}
return Base64.encode(bOs.toByteArray());
} finally {
dOs.close();
bOs.close();
}
}
public static RtStat decode(String val) throws IOException {
ByteArrayInputStream bIs = null;
DataInputStream dIs = null;
RtStat rs = new RtStat();
try {
bIs = new ByteArrayInputStream(Base64.decode(val));
dIs = new DataInputStream(bIs);
rs.ip = dIs.readUTF();
rs.url = dIs.readUTF();
rs.begin = dIs.readLong();
rs.end = dIs.readLong();
rs.min = dIs.readDouble();
rs.max = dIs.readDouble();
rs.total = dIs.readDouble();
rs.count = dIs.readInt();
rs.svcType = dIs.readInt();
rs.svcID = new Integer(dIs.readInt());
int numEntries = dIs.readInt();
rs.status = new Hashtable(numEntries);
while (numEntries > 0) {
Integer key = new Integer(dIs.readInt());
Integer value = new Integer(dIs.readInt());
rs.status.put(key, value);
numEntries--;
}
return rs;
} finally {
dIs.close();
bIs.close();
}
}
public boolean equals(Object obj) {
if (!(obj instanceof RtStat)) return false;
RtStat o = (RtStat) obj;
return (getIp().equals(o.getIp()) &&
url.equals(o.url) &&
begin == o.begin &&
end == o.end &&
(Double.isNaN(min) && Double.isNaN(o.min)) &&
max == o.max &&
total == o.total &&
count == o.count &&
svcType == o.svcType &&
svcID.equals(o.svcID) &&
status.equals(o.status));
}
}