/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "base/polygraph.h"
#include "xstd/h/os_std.h"
#include "xstd/gadgets.h"
#include "base/ILog.h"
#include "base/polyLogCats.h"
#include "base/polyLogTags.h"
/* LogEntryPx */
// XXX: we should log lgEnd/lgcEnd instead of using current constants!
bool LogEntryPx::good() const {
return
0 <= theCat && theCat < lgcEnd &&
0 <= theTag && theTag < lgEnd &&
0 < theSize && theSize <= 10*1024*1024;
}
// XXX: we should log lgEnd/lgcEnd instead of using current constants!
ILog &LogEntryPx::load(ILog &il) {
int h;
il >> theSize >> h;
theTag = (h << 16) >> 16;
theCat = h >> 16; // XXX: assumes sizeof(int) == 32
return il;
}
ostream &LogEntryPx::print(ostream &os) const {
return os
<< "tag: " << theCat << '/' << theTag
<< " size: " << theSize;
}
/* ILog */
ILog::ILog(): theStream(0), theEntryEnd(-1) {
}
ILog::~ILog() {
}
void ILog::stream(const String &aFileName, istream *aStream) {
theFileName = aFileName;
theStream = aStream;
getHeader();
}
// loads prefix of the current entry
// transparently loads progress entries
LogEntryPx ILog::begEntry() {
theEntryEnd = theStream->tellg();
while (theCurPx.load(*this)) {
if (theCurPx && !theCurPx.good()) {
const streampos startOff = theEntryEnd;
clog << fileName() << ':' << theEntryEnd
<< ": warning: corrupted log entry: " << theCurPx << endl;
do {
theEntryEnd += 1;
endEntry();
theCurPx.load(*this);
} while (*theStream && !(theCurPx.theTag == lgProgress && theCurPx.theSize > 0 && theCurPx.theSize < 1024));
if (!*theStream)
break;
clog << fileName() << ':' << theEntryEnd
<< ": maybe recovered after skipping " << (theEntryEnd-startOff)
<< " bytes: " << theCurPx << endl;
}
theEntryEnd += theCurPx.theSize;
if (theCurPx.theTag != lgProgress)
return theCurPx;
theProgress.load(*this);
endEntry();
}
theCurPx = LogEntryPx();
return theCurPx;
}
void ILog::endEntry() {
theStream->seekg(theEntryEnd);
theCurPx = LogEntryPx();
}
void ILog::getHeader() {
Assert(theStream);
// check magic
if (geti() != lgMagic1 || geti() != lgMagic2 || geti() != 0) {
if (theStream->bad())
cerr << theFileName << ": read error; " << Error::Last() << endl;
else
cerr << theFileName << ": unknown log file format" << endl;
exit(-2);
}
const int sver = 11; // supported version
const int cver = geti(); // current log version
const int rver = geti(); // required min version to support
const int skip = geti(); // size of extra headers
if (sver < rver) {
cerr << theFileName << ": log version " << cver << endl;
cerr << theFileName << ": requires support for log version " << rver << " or higher" << endl;
cerr << theFileName << ": this program supports version " << sver << endl;
exit(-2);
}
if (sver != cver) {
cerr << theFileName << ": log version " << cver << endl;
cerr << theFileName << ": this program supports version " << sver << endl;
cerr << theFileName << ": continuing at your own risk..." << endl;
sleep(3);
}
theStream->ignore(skip);
}
int ILog::geti(int *&xs, int &count) {
Must(geti(count) >= 0);
xs = new int[count];
for (int i = 0; i < count; ++i)
geti(xs[i]);
return count;
}
String &ILog::gets(String &s) {
const int sz = geti();
if (Should(sz >= 0)) {
if (sz > 0) {
char *buf = s.alloc(sz);
get(buf, sz);
return s;
}
}
s = String();
return s;
}
syntax highlighted by Code2HTML, v. 0.9.1