package org.opensolaris.os.dtrace;
import java.util.*;
import java.io.*;
import java.beans.*;
public final class ProbeData implements Serializable, Comparable <ProbeData> {
static final long serialVersionUID = -7021504416192099215L;
static {
try {
BeanInfo info = Introspector.getBeanInfo(ProbeData.class);
PersistenceDelegate persistenceDelegate =
new DefaultPersistenceDelegate(
new String[] {"enabledProbeID", "CPU",
"enabledProbeDescription", "flow", "records"});
BeanDescriptor d = info.getBeanDescriptor();
d.setValue("persistenceDelegate", persistenceDelegate);
} catch (IntrospectionException e) {
System.out.println(e);
}
}
private static Comparator <ProbeData> DEFAULT_CMP;
static {
try {
DEFAULT_CMP = ProbeData.getComparator(KeyField.RECORDS,
KeyField.EPID);
} catch (Throwable e) {
e.printStackTrace();
System.exit(1);
}
}
private int epid;
private int cpu;
private ProbeDescription enabledProbeDescription;
private Flow flow;
private transient List <Record> nativeElements;
private List <Record> records;
public enum KeyField {
CPU,
PROBE,
EPID,
RECORDS
}
private
ProbeData(int enabledProbeID, int cpuID, ProbeDescription p,
Flow f, int nativeElementCount)
{
epid = enabledProbeID;
cpu = cpuID;
enabledProbeDescription = p;
flow = f;
nativeElements = new ArrayList <Record> (nativeElementCount);
records = new ArrayList <Record> ();
validate();
}
public
ProbeData(int enabledProbeID, int cpuID, ProbeDescription p,
Flow f, List <Record> recordList)
{
epid = enabledProbeID;
cpu = cpuID;
enabledProbeDescription = p;
flow = f;
records = new ArrayList <Record> (recordList.size());
records.addAll(recordList);
validate();
}
private final void
validate()
{
if (enabledProbeDescription == null) {
throw new NullPointerException(
"enabled probe description is null");
}
if (records == null) {
throw new NullPointerException("record list is null");
}
}
private void
addDataElement(Record o)
{
Record r = Record.class.cast(o);
nativeElements.add(o);
}
private void
addRecord(Record record)
{
records.add(record);
}
private void
addTraceRecord(int i)
{
int len = nativeElements.size();
Record rec = null;
for (; ((rec = nativeElements.get(i)) == null) && (i < len); ++i);
records.add(rec);
}
private void
addSymbolRecord(int i, String lookupString)
{
int len = nativeElements.size();
Record rec = null;
for (; ((rec = nativeElements.get(i)) == null) && (i < len); ++i);
SymbolValueRecord symbol = SymbolValueRecord.class.cast(rec);
if (symbol instanceof KernelSymbolRecord) {
KernelSymbolRecord.class.cast(symbol).setSymbol(lookupString);
} else if (symbol instanceof UserSymbolRecord) {
UserSymbolRecord.class.cast(symbol).setSymbol(lookupString);
} else {
throw new IllegalStateException("no symbol record at index " + i);
}
records.add(symbol);
}
private void
addStackRecord(int i, String framesString)
{
int len = nativeElements.size();
Record rec = null;
for (; ((rec = nativeElements.get(i)) == null) && (i < len); ++i);
StackValueRecord stack = StackValueRecord.class.cast(rec);
StackFrame[] frames = KernelStackRecord.parse(framesString);
if (stack instanceof KernelStackRecord) {
KernelStackRecord.class.cast(stack).setStackFrames(frames);
} else if (stack instanceof UserStackRecord) {
UserStackRecord.class.cast(stack).setStackFrames(frames);
} else {
throw new IllegalStateException("no stack record at index " + i);
}
records.add(stack);
}
private void
addPrintfRecord()
{
records.add(new PrintfRecord());
}
private void
addPrintaRecord(long snaptimeNanos, boolean isFormatString)
{
records.add(new PrintaRecord(snaptimeNanos, isFormatString));
}
private PrintaRecord
getLastPrinta()
{
ListIterator <Record> itr = records.listIterator(records.size());
PrintaRecord printa = null;
Record record;
while (itr.hasPrevious() && (printa == null)) {
record = itr.previous();
if (record instanceof PrintaRecord) {
printa = PrintaRecord.class.cast(record);
}
}
return printa;
}
private void
addAggregationRecord(String aggregationName, long aggid,
AggregationRecord rec)
{
PrintaRecord printa = getLastPrinta();
if (printa == null) {
throw new IllegalStateException(
"No PrintaRecord in this ProbeData");
}
printa.addRecord(aggregationName, aggid, rec);
}
private void
invalidatePrintaRecord()
{
PrintaRecord printa = getLastPrinta();
if (printa == null) {
throw new IllegalStateException(
"No PrintaRecord in this ProbeData");
}
printa.invalidate();
}
private void
addPrintaFormattedString(Tuple tuple, String s)
{
PrintaRecord printa = getLastPrinta();
if (printa == null) {
throw new IllegalStateException(
"No PrintaRecord in this ProbeData");
}
printa.addFormattedString(tuple, s);
}
private void
addExitRecord(int i)
{
int len = nativeElements.size();
Record rec = null;
for (; ((rec = nativeElements.get(i)) == null) && (i < len); ++i);
ScalarRecord scalar = ScalarRecord.class.cast(rec);
Integer exitStatus = Integer.class.cast(scalar.getValue());
records.add(new ExitRecord(exitStatus));
}
private void
attachRecordElements(int first, int last)
{
Record record = records.get(records.size() - 1);
if (record instanceof PrintfRecord) {
PrintfRecord printf = PrintfRecord.class.cast(record);
Record e;
for (int i = first; i <= last; ++i) {
e = nativeElements.get(i);
if (e == null) {
continue;
}
printf.addUnformattedElement(ScalarRecord.class.cast(e));
}
}
}
void
clearNativeElements()
{
nativeElements = null;
}
private void
setFormattedString(String s)
{
Record record = records.get(records.size() - 1);
if (record instanceof PrintfRecord) {
PrintfRecord printf = PrintfRecord.class.cast(record);
printf.setFormattedString(s);
}
}
public static Comparator <ProbeData>
getComparator(KeyField ... f)
{
return new Cmp(f);
}
private static class Cmp implements Comparator <ProbeData> {
private KeyField[] sortFields;
private
Cmp(KeyField ... f)
{
sortFields = f;
}
public int
compare(ProbeData d1, ProbeData d2)
{
return ProbeData.compare(d1, d2, sortFields);
}
}
static int
compareUnsigned(int i1, int i2)
{
int cmp;
if (i1 < 0) {
if (i2 < 0) {
cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
} else {
cmp = 1;
}
} else if (i2 < 0) {
cmp = -1;
} else {
cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
}
return cmp;
}
static int
compareUnsigned(long i1, long i2)
{
int cmp;
if (i1 < 0) {
if (i2 < 0) {
cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
} else {
cmp = 1;
}
} else if (i2 < 0) {
cmp = -1;
} else {
cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
}
return cmp;
}
static int
compareUnsigned(byte i1, byte i2)
{
int cmp;
if (i1 < 0) {
if (i2 < 0) {
cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
} else {
cmp = 1;
}
} else if (i2 < 0) {
cmp = -1;
} else {
cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
}
return cmp;
}
static int
compareByteArrays(byte[] a1, byte[] a2)
{
int cmp = 0;
int len1 = a1.length;
int len2 = a2.length;
for (int i = 0; (cmp == 0) && (i < len1) && (i < len2); ++i) {
cmp = compareUnsigned(a1[i], a2[i]);
}
if (cmp == 0) {
cmp = (len1 < len2 ? -1 : (len1 > len2 ? 1 : 0));
}
return cmp;
}
@SuppressWarnings("unchecked")
static int
compareUnsigned(Comparable v1, Comparable v2)
{
int cmp;
if (v1 instanceof Integer) {
int i1 = Integer.class.cast(v1);
int i2 = Integer.class.cast(v2);
cmp = compareUnsigned(i1, i2);
} else if (v1 instanceof Long) {
long i1 = Long.class.cast(v1);
long i2 = Long.class.cast(v2);
cmp = compareUnsigned(i1, i2);
} else {
cmp = v1.compareTo(v2);
}
return cmp;
}
@SuppressWarnings("unchecked")
private static int
compareRecords(Record r1, Record r2)
{
int cmp;
if (r1 instanceof ScalarRecord) {
ScalarRecord t1 = ScalarRecord.class.cast(r1);
ScalarRecord t2 = ScalarRecord.class.cast(r2);
Object o1 = t1.getValue();
Object o2 = t2.getValue();
if (o1 instanceof byte[]) {
byte[] a1 = byte[].class.cast(o1);
byte[] a2 = byte[].class.cast(o2);
cmp = compareByteArrays(a1, a2);
} else {
Comparable v1 = Comparable.class.cast(o1);
Comparable v2 = Comparable.class.cast(o2);
cmp = v1.compareTo(v2);
}
} else if (r1 instanceof Comparable) {
Comparable v1 = Comparable.class.cast(r1);
Comparable v2 = Comparable.class.cast(r2);
cmp = v1.compareTo(v2);
} else if (r1 instanceof ExitRecord) {
ExitRecord e1 = ExitRecord.class.cast(r1);
ExitRecord e2 = ExitRecord.class.cast(r2);
int status1 = e1.getStatus();
int status2 = e2.getStatus();
cmp = (status1 < status2 ? -1 : (status1 > status2 ? 1 : 0));
} else {
r1.getClass().cast(r2);
String s1 = r1.toString();
String s2 = r2.toString();
cmp = s1.compareTo(s2);
}
return cmp;
}
private static int
compareRecordLists(ProbeData d1, ProbeData d2)
{
List <Record> list1 = d1.getRecords();
List <Record> list2 = d2.getRecords();
int len1 = list1.size();
int len2 = list2.size();
if (len1 != len2) {
throw new ClassCastException("Record lists of different " +
"length are not comparable (lengths are " +
len1 + " and " + len2 + ").");
}
int cmp;
Record r1;
Record r2;
for (int i = 0; (i < len1) && (i < len2); ++i) {
r1 = list1.get(i);
r2 = list2.get(i);
cmp = compareRecords(r1, r2);
if (cmp != 0) {
return cmp;
}
}
return 0;
}
private static int
compare(ProbeData d1, ProbeData d2, KeyField[] comparedFields)
{
int cmp;
for (KeyField f : comparedFields) {
switch (f) {
case CPU:
int cpu1 = d1.getCPU();
int cpu2 = d2.getCPU();
cmp = (cpu1 < cpu2 ? -1 : (cpu1 > cpu2 ? 1 : 0));
break;
case PROBE:
ProbeDescription p1 = d1.getEnabledProbeDescription();
ProbeDescription p2 = d2.getEnabledProbeDescription();
cmp = p1.compareTo(p2);
break;
case EPID:
int epid1 = d1.getEnabledProbeID();
int epid2 = d2.getEnabledProbeID();
cmp = (epid1 < epid2 ? -1 : (epid1 > epid2 ? 1 : 0));
break;
case RECORDS:
cmp = compareRecordLists(d1, d2);
break;
default:
throw new IllegalArgumentException(
"Unexpected sort field " + f);
}
if (cmp != 0) {
return cmp;
}
}
return 0;
}
public int
getEnabledProbeID()
{
return epid;
}
public int
getCPU()
{
return cpu;
}
public ProbeDescription
getEnabledProbeDescription()
{
return enabledProbeDescription;
}
public Flow
getFlow()
{
return flow;
}
public List <Record>
getRecords()
{
return Collections. <Record> unmodifiableList(records);
}
public int
compareTo(ProbeData d)
{
return DEFAULT_CMP.compare(this, d);
}
private void
readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
int len = records.size();
ArrayList <Record> copy = new ArrayList <Record> (len);
copy.addAll(records);
records = copy;
try {
validate();
} catch (Exception e) {
InvalidObjectException x = new InvalidObjectException(
e.getMessage());
x.initCause(e);
throw x;
}
}
public String
toString()
{
StringBuilder buf = new StringBuilder();
buf.append(ProbeData.class.getName());
buf.append("[epid = ");
buf.append(epid);
buf.append(", cpu = ");
buf.append(cpu);
buf.append(", enabledProbeDescription = ");
buf.append(enabledProbeDescription);
buf.append(", flow = ");
buf.append(flow);
buf.append(", records = ");
Record record;
Object value;
buf.append('[');
for (int i = 0; i < records.size(); ++i) {
if (i > 0) {
buf.append(", ");
}
record = records.get(i);
if (record instanceof ValueRecord) {
value = ValueRecord.class.cast(record).getValue();
if (value instanceof String) {
buf.append("\"");
buf.append(String.class.cast(value));
buf.append("\"");
} else {
buf.append(record);
}
} else {
buf.append(record);
}
}
buf.append(']');
buf.append(']');
return buf.toString();
}
}