00001 package edu.rice.cs.hpc.traceviewer.data.db;
00002
00003 import java.util.Arrays;
00004 import java.util.Vector;
00005
00006 import edu.rice.cs.hpc.data.experiment.extdata.AbstractBaseData;
00007 import edu.rice.cs.hpc.data.util.Constants;
00008 import edu.rice.cs.hpc.traceviewer.data.util.Debugger;
00009
00010 public class TraceDataByRank {
00011
00012
00013 public final static int HeaderSzMin = Header.MagicLen + Header.VersionLen + Header.EndianLen + Header.FlagsLen;
00014 public final static int RecordSzMin = Constants.SIZEOF_LONG
00015 + Constants.SIZEOF_INT;
00016
00017
00019 public Header header;
00020 private AbstractBaseData data;
00021 private int numPixelH;
00022 int rank;
00023
00024 protected Vector<DataRecord> listcpid;
00025
00026
00027
00028
00029
00030
00031
00032
00033 public TraceDataByRank(AbstractBaseData _data, int _rank, int _numPixelH)
00034 {
00035
00036
00037
00038
00039 data = _data;
00040 rank = _rank;
00041 numPixelH = _numPixelH;
00042
00043 final long offsets[] = data.getOffsets();
00044 final long begHeader = offsets[rank];
00045 header = getHeader(begHeader);
00046
00047 listcpid = new Vector<DataRecord>(numPixelH);
00048 }
00049
00050 public boolean isEmpty() {
00051 return listcpid == null || listcpid.size()==0;
00052 }
00053
00054 public TraceDataByRank(DataRecord[] data) {
00055 listcpid = new Vector<DataRecord>(Arrays.asList(data));
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065 public void getData(long timeStart, long timeRange, double pixelLength)
00066 {
00067
00068 long minloc = data.getMinLoc(rank);
00069 long maxloc = data.getMaxLoc(rank, header.RecordSz);
00070
00071 Debugger.printDebug(4, "getData loc [" + minloc+","+ maxloc + "]");
00072
00073
00074 final long startLoc = this.findTimeInInterval(timeStart, minloc, maxloc);
00075
00076
00077 final long endTime = timeStart + timeRange;
00078 final long endLoc = Math.min(this.findTimeInInterval(endTime, minloc, maxloc) + header.RecordSz, maxloc );
00079
00080
00081 final long numRec = 1+this.getNumberOfRecords(startLoc, endLoc);
00082
00083
00084
00085
00086
00087 if (numRec<=numPixelH) {
00088
00089
00090 for(long i=startLoc;i<=endLoc; ) {
00091 listcpid.add(getData(i));
00092
00093 i = i + header.RecordSz;
00094 }
00095
00096 } else {
00097
00098
00099
00100
00101 this.sampleTimeLine(startLoc, endLoc, 0, numPixelH, 0, pixelLength, timeStart);
00102
00103 }
00104
00105
00106
00107
00108
00109 if (endLoc < maxloc) {
00110 final DataRecord dataLast = this.getData(endLoc);
00111 this.addSample(listcpid.size(), dataLast);
00112 }
00113
00114
00115
00116
00117
00118 if ( startLoc > minloc ) {
00119 final DataRecord dataFirst = this.getData(startLoc - header.RecordSz);
00120 this.addSample(0, dataFirst);
00121 }
00122
00123
00124 postProcess();
00125
00126 }
00127
00128
00130 public long getTime(int sample)
00131 {
00132 if(sample<0)
00133 return 0;
00134
00135 final int last_index = listcpid.size();
00136 if(sample>=last_index) {
00137 return listcpid.get(last_index-1).timestamp;
00138 }
00139 return listcpid.get(sample).timestamp;
00140 }
00141
00143 public int getCpid(int sample)
00144 {
00145 return listcpid.get(sample).cpId;
00146 }
00147
00148 public int getMetricId(int sample)
00149 {
00150 return listcpid.get(sample).metricId;
00151 }
00152
00153
00155 public void shiftTimeBy(long lowestStartingTime)
00156 {
00157 for(int i = 0; i<listcpid.size(); i++)
00158 {
00159 DataRecord timecpid = listcpid.get(i);
00160 timecpid.timestamp = timecpid.timestamp - lowestStartingTime;
00161 listcpid.set(i,timecpid);
00162 }
00163 }
00164
00165
00166
00168 public int size()
00169 {
00170 return listcpid.size();
00171 }
00172
00173
00179 public int findMidpointBefore(long time, boolean usingMidpoint)
00180 {
00181 if (listcpid.size()==0)
00182 return 0;
00183
00184 int low = 0;
00185 int high = listcpid.size() - 1;
00186
00187 long timeMin = listcpid.get(low).timestamp;
00188 long timeMax = listcpid.get(high).timestamp;
00189
00190
00191 if (time<timeMin || time>timeMax)
00192 return -1;
00193
00194 int mid = ( low + high ) / 2;
00195
00196 while( low != mid )
00197 {
00198 final long time_current = (usingMidpoint ? getTimeMidPoint(mid,mid+1) : listcpid.get(mid).timestamp);
00199
00200 if (time > time_current)
00201 low = mid;
00202 else
00203 high = mid;
00204 mid = ( low + high ) / 2;
00205
00206 }
00207 if (usingMidpoint)
00208 {
00209 if (time >= getTimeMidPoint(low,low+1))
00210 return low+1;
00211 else
00212 return low;
00213 } else
00214 {
00215
00216
00217 return low;
00218 }
00219 }
00220
00221
00222
00223 private long getTimeMidPoint(int left, int right) {
00224 return (listcpid.get(left).timestamp + listcpid.get(right).timestamp) / 2;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 private int sampleTimeLine(long minLoc, long maxLoc, int startPixel, int endPixel, int minIndex,
00244 double pixelLength, long startingTime)
00245 {
00246 int midPixel = (startPixel+endPixel)/2;
00247 if (midPixel == startPixel)
00248 return 0;
00249
00250 long loc = findTimeInInterval((long)(midPixel*pixelLength)+startingTime, minLoc, maxLoc);
00251
00252 final DataRecord nextData = this.getData(loc);
00253
00254 addSample(minIndex, nextData);
00255
00256 int addedLeft = sampleTimeLine(minLoc, loc, startPixel, midPixel, minIndex, pixelLength, startingTime);
00257 int addedRight = sampleTimeLine(loc, maxLoc, midPixel, endPixel, minIndex+addedLeft+1, pixelLength, startingTime);
00258
00259 return (addedLeft+addedRight+1);
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269 private long findTimeInInterval(long time, long left_boundary_offset, long right_boundary_offset)
00270 {
00271 if (left_boundary_offset == right_boundary_offset) return left_boundary_offset;
00272
00273 long left_index = getRelativeLocation(left_boundary_offset);
00274 long right_index = getRelativeLocation(right_boundary_offset);
00275
00276 long left_time = data.getLong(left_boundary_offset);
00277 long right_time = data.getLong(right_boundary_offset);
00278
00279
00280 while (right_index - left_index > 1) {
00281 long predicted_index;
00282 double rate = (right_time - left_time) / (right_index - left_index);
00283 long mtime = (right_time - left_time) / 2;
00284 if (time <= mtime) {
00285 predicted_index = Math.max((long) ((time - left_time) / rate) + left_index, left_index);
00286 } else {
00287 predicted_index = Math.min((right_index - (long) ((right_time - time) / rate)), right_index);
00288
00289
00290
00291
00292
00293
00294
00295 }
00296
00297
00298
00299
00300 if (predicted_index <= left_index)
00301 predicted_index = left_index + 1;
00302 if (predicted_index >= right_index)
00303 predicted_index = right_index - 1;
00304
00305 long temp = data.getLong(getAbsoluteLocation(predicted_index));
00306 if (time >= temp) {
00307 left_index = predicted_index;
00308 left_time = temp;
00309 } else {
00310 right_index = predicted_index;
00311 right_time = temp;
00312 }
00313 }
00314 long left_offset = getAbsoluteLocation(left_index);
00315 long right_offset = getAbsoluteLocation(right_index);
00316
00317 left_time = data.getLong(left_offset);
00318 right_time = data.getLong(right_offset);
00319
00320
00321
00322 final boolean is_left_closer = Math.abs(time - left_time) < Math.abs(right_time - time);
00323 long maxloc = data.getMaxLoc(rank, header.RecordSz);
00324
00325 if ( is_left_closer ) return left_offset;
00326 else if (right_offset < maxloc) return right_offset;
00327 else return maxloc;
00328 }
00329
00330 private long getAbsoluteLocation(long relativePosition)
00331 {
00332 return data.getMinLoc(rank) + (relativePosition * header.RecordSz);
00333 }
00334
00335 private long getRelativeLocation(long absolutePosition)
00336 {
00337 return (absolutePosition-data.getMinLoc(rank)) / header.RecordSz;
00338 }
00339
00340
00342 public void addSample( int index, DataRecord datacpid)
00343 {
00344 if (index == listcpid.size())
00345 {
00346 this.listcpid.add(datacpid);
00347 }
00348 else
00349 {
00350 this.listcpid.add(index, datacpid);
00351 }
00352 }
00353
00354
00355 public Vector<DataRecord> getListOfData()
00356 {
00357 return this.listcpid;
00358 }
00359
00360
00361 public void setListOfData(Vector<DataRecord> anotherList)
00362 {
00363 this.listcpid = anotherList;
00364 }
00365
00366
00367 private Header getHeader(long begHeader)
00368 {
00369 int headerSz = 0;
00370 final String filename = "";
00371
00372 final long begMagic = begHeader;
00373 final long begVersion = begMagic + Header.MagicLen;
00374 final long begEndian = begVersion + Header.VersionLen;
00375 final long begFlags = begEndian + Header.EndianLen;
00376
00377 final String magicStr = data.getString(begMagic, Header.MagicLen);
00378 headerSz += Header.MagicLen;
00379 if (!magicStr.contentEquals(Header.Magic)) {
00380 System.err.println("Error: trace file has bad header: " + filename);
00381 }
00382
00383 final String versionStr = data.getString(begVersion, Header.VersionLen);
00384 headerSz += Header.VersionLen;
00385 final double version = new Double(versionStr);
00386 if ( !(version >= 1.0) ) {
00387 System.err.println("Error: trace file has bad version: " + filename);
00388 }
00389
00390 final String endianStr = data.getString(begEndian, Header.EndianLen);
00391 headerSz += Header.EndianLen;
00392 if (!endianStr.contentEquals(Header.Endian)) {
00393 System.err.println("Error: trace file has bad endianness: " + filename);
00394 }
00395
00396 long flags = 0;
00397 if (version > 1.00) {
00398 flags = data.getLong(begFlags);
00399 headerSz += Header.FlagsLen;
00400 }
00401
00402 if (data.getHeaderSize() != headerSz) {
00403 System.err.println("Error: trace file has unknown header: " + filename);
00404 }
00405
00406 return new Header(version, flags);
00407 }
00408
00409
00410 private DataRecord getData(long location)
00411 {
00412 final long time = data.getLong(location);
00413 final int cpId = data.getInt(location + Constants.SIZEOF_LONG);
00414 int metricId = edu.rice.cs.hpc.traceviewer.data.util.Constants.dataIdxNULL;
00415 if (header.isDataCentric) {
00416 metricId = data.getInt(location + Constants.SIZEOF_LONG + Constants.SIZEOF_INT);
00417 }
00418
00419 return new DataRecord(time, cpId, metricId);
00420 }
00421
00422 private long getNumberOfRecords(long start, long end)
00423 {
00424 return (end-start) / (header.RecordSz);
00425 }
00426
00427
00428
00429
00430
00431
00432 private void postProcess()
00433 {
00434 int len = listcpid.size();
00435 for(int i = 0; i < len-2; i++)
00436 {
00437 while(i < len-1 && listcpid.get(i).timestamp==(listcpid.get(i+1).timestamp))
00438 {
00439 listcpid.remove(i+1);
00440 len--;
00441 }
00442 }
00443 }
00444
00445 public int getRank()
00446 {
00447 return rank;
00448 }
00449 }