InputReader can read Sets.

This commit is contained in:
Bernhard Amann 2011-11-15 10:57:45 -08:00
parent cde8153c18
commit 4a3c992325
6 changed files with 310 additions and 162 deletions

View file

@ -234,11 +234,14 @@ bool InputMgr::IsCompatibleType(BroType* t)
case TYPE_TABLE: case TYPE_TABLE:
return false; {
return IsCompatibleType(t->AsSetType()->Indices()->PureType());
}
case TYPE_VECTOR: case TYPE_VECTOR:
{ {
return IsCompatibleType(t->AsVectorType()->YieldType()); return false; // do me...
//return IsCompatibleType(t->AsVectorType()->YieldType());
} }
default: default:
@ -329,6 +332,9 @@ bool InputMgr::UnrollRecordType(vector<LogField*> *fields, const RecordType *rec
LogField* field = new LogField(); LogField* field = new LogField();
field->name = nameprepend + rec->FieldName(i); field->name = nameprepend + rec->FieldName(i);
field->type = rec->FieldType(i)->Tag(); field->type = rec->FieldType(i)->Tag();
if ( field->type == TYPE_TABLE ) {
field->set_type = rec->FieldType(i)->AsSetType()->Indices()->PureType()->Tag();
}
fields->push_back(field); fields->push_back(field);
} }
@ -810,11 +816,10 @@ Val* InputMgr::LogValToRecordVal(const LogVal* const *vals, RecordType *request_
} }
HashKey* InputMgr::HashLogVals(const int num_elements, const LogVal* const *vals) {
int InputMgr::GetLogValLength(const LogVal* val) {
int length = 0; int length = 0;
for ( int i = 0; i < num_elements; i++ ) {
const LogVal* val = vals[i];
switch (val->type) { switch (val->type) {
case TYPE_BOOL: case TYPE_BOOL:
case TYPE_INT: case TYPE_INT:
@ -849,10 +854,95 @@ HashKey* InputMgr::HashLogVals(const int num_elements, const LogVal* const *vals
length += sizeof(val->val.subnet_val.net); length += sizeof(val->val.subnet_val.net);
break; break;
default: case TYPE_TABLE: {
reporter->InternalError("unsupported type for hashlogvals"); for ( int i = 0; i < val->val.set_val.size; i++ ) {
length += GetLogValLength(val->val.set_val.vals[i]);
}
break;
} }
default:
reporter->InternalError("unsupported type %d for GetLogValLength", val->type);
}
return length;
}
int InputMgr::CopyLogVal(char *data, const int startpos, const LogVal* val) {
switch ( val->type ) {
case TYPE_BOOL:
case TYPE_INT:
//reporter->Error("Adding field content to pos %d: %lld", val->val.int_val, startpos);
memcpy(data+startpos, (const void*) &(val->val.int_val), sizeof(val->val.int_val));
//*(data+startpos) = val->val.int_val;
return sizeof(val->val.int_val);
break;
case TYPE_COUNT:
case TYPE_COUNTER:
case TYPE_PORT:
//*(data+startpos) = val->val.uint_val;
memcpy(data+startpos, (const void*) &(val->val.uint_val), sizeof(val->val.uint_val));
return sizeof(val->val.uint_val);
break;
case TYPE_DOUBLE:
case TYPE_TIME:
case TYPE_INTERVAL:
//*(data+startpos) = val->val.double_val;
memcpy(data+startpos, (const void*) &(val->val.double_val), sizeof(val->val.double_val));
return sizeof(val->val.double_val);
break;
case TYPE_STRING:
case TYPE_ENUM:
{
memcpy(data+startpos, val->val.string_val->c_str(), val->val.string_val->length());
return val->val.string_val->size();
break;
}
case TYPE_ADDR:
memcpy(data+startpos, val->val.addr_val, NUM_ADDR_WORDS*sizeof(uint32_t));
return NUM_ADDR_WORDS*sizeof(uint32_t);
break;
case TYPE_SUBNET: {
int length = 0;
memcpy(data+startpos,(const char*) &(val->val.subnet_val.width), sizeof(val->val.subnet_val.width) );
length += sizeof(val->val.subnet_val.width);
memcpy(data+startpos, (const char*) &(val->val.subnet_val.net), sizeof(val->val.subnet_val.net) );
length += sizeof(val->val.subnet_val.net);
return length;
break;
}
case TYPE_TABLE: {
int length = 0;
for ( int i = 0; i < val->val.set_val.size; i++ ) {
length += CopyLogVal(data, startpos+length, val->val.set_val.vals[i]);
}
return length;
break;
}
default:
reporter->InternalError("unsupported type %d for CopyLogVal", val->type);
return 0;
}
reporter->InternalError("internal error");
return 0;
}
HashKey* InputMgr::HashLogVals(const int num_elements, const LogVal* const *vals) {
int length = 0;
for ( int i = 0; i < num_elements; i++ ) {
const LogVal* val = vals[i];
length += GetLogValLength(val);
} }
//reporter->Error("Length: %d", length); //reporter->Error("Length: %d", length);
@ -864,56 +954,7 @@ HashKey* InputMgr::HashLogVals(const int num_elements, const LogVal* const *vals
} }
for ( int i = 0; i < num_elements; i++ ) { for ( int i = 0; i < num_elements; i++ ) {
const LogVal* val = vals[i]; const LogVal* val = vals[i];
switch ( val->type ) { position += CopyLogVal(data, position, val);
case TYPE_BOOL:
case TYPE_INT:
//reporter->Error("Adding field content to pos %d: %lld", val->val.int_val, position);
memcpy(data+position, (const void*) &(val->val.int_val), sizeof(val->val.int_val));
//*(data+position) = val->val.int_val;
position += sizeof(val->val.int_val);
break;
case TYPE_COUNT:
case TYPE_COUNTER:
case TYPE_PORT:
//*(data+position) = val->val.uint_val;
memcpy(data+position, (const void*) &(val->val.uint_val), sizeof(val->val.uint_val));
position += sizeof(val->val.uint_val);
break;
case TYPE_DOUBLE:
case TYPE_TIME:
case TYPE_INTERVAL:
//*(data+position) = val->val.double_val;
memcpy(data+position, (const void*) &(val->val.double_val), sizeof(val->val.double_val));
position += sizeof(val->val.double_val);
break;
case TYPE_STRING:
case TYPE_ENUM:
{
memcpy(data+position, val->val.string_val->c_str(), val->val.string_val->length());
position += val->val.string_val->size();
break;
}
case TYPE_ADDR:
memcpy(data+position, val->val.addr_val, NUM_ADDR_WORDS*sizeof(uint32_t));
position += NUM_ADDR_WORDS*sizeof(uint32_t);
break;
case TYPE_SUBNET:
memcpy(data+position,(const char*) &(val->val.subnet_val.width), sizeof(val->val.subnet_val.width) );
position += sizeof(val->val.subnet_val.width);
memcpy(data+position, (const char*) &(val->val.subnet_val.net), sizeof(val->val.subnet_val.net) );
position += sizeof(val->val.subnet_val.net);
break;
default:
reporter->InternalError("unsupported type for hashlogvals2");
}
} }
assert(position == length); assert(position == length);
@ -966,6 +1007,29 @@ Val* InputMgr::LogValToVal(const LogVal* val, TypeTag request_type) {
return new SubNetVal(val->val.subnet_val.net, val->val.subnet_val.width); return new SubNetVal(val->val.subnet_val.net, val->val.subnet_val.width);
break; break;
case TYPE_TABLE: {
if ( val->val.set_val.size == 0 ) {
// empty table
TypeList* set_index = new TypeList(base_type(TYPE_ANY));
// iim quite sure this does not work... we probably need the internal set type for this...
reporter->InternalError("Implement me.");
return new TableVal(new SetType(set_index, 0));
} else {
// all entries have to have the same type...
TypeTag type = val->val.set_val.vals[0]->type;
TypeList* set_index = new TypeList(base_type(type));
set_index->Append(base_type(type));
SetType* s = new SetType(set_index, 0);
TableVal* t = new TableVal(s);
for ( int i = 0; i < val->val.set_val.size; i++ ) {
assert( val->val.set_val.vals[i]->type == type);
t->Assign(LogValToVal( val->val.set_val.vals[i], type ), 0);
}
return t;
}
break;
}
case TYPE_ENUM: case TYPE_ENUM:
reporter->InternalError("Sorry, Enum reading does not yet work, missing internal inferface"); reporter->InternalError("Sorry, Enum reading does not yet work, missing internal inferface");

View file

@ -52,6 +52,8 @@ private:
void SendEvent(const string& name, EnumVal* event, Val* left, Val* right); void SendEvent(const string& name, EnumVal* event, Val* left, Val* right);
HashKey* HashLogVals(const int num_elements, const LogVal* const *vals); HashKey* HashLogVals(const int num_elements, const LogVal* const *vals);
int GetLogValLength(const LogVal* val);
int CopyLogVal(char *data, const int startpos, const LogVal* val);
Val* LogValToVal(const LogVal* val, TypeTag request_type = TYPE_ANY); Val* LogValToVal(const LogVal* val, TypeTag request_type = TYPE_ANY);
Val* LogValToIndexVal(int num_fields, const RecordType* type, const LogVal* const *vals); Val* LogValToIndexVal(int num_fields, const RecordType* type, const LogVal* const *vals);

View file

@ -11,12 +11,22 @@ FieldMapping::FieldMapping(const string& arg_name, const TypeTag& arg_type, int
position = arg_position; position = arg_position;
} }
FieldMapping::FieldMapping(const string& arg_name, const TypeTag& arg_type, const TypeTag& arg_set_type, int arg_position)
: name(arg_name), type(arg_type), set_type(arg_set_type)
{
position = arg_position;
}
FieldMapping::FieldMapping(const FieldMapping& arg) FieldMapping::FieldMapping(const FieldMapping& arg)
: name(arg.name), type(arg.type) : name(arg.name), type(arg.type), set_type(arg.set_type)
{ {
position = arg.position; position = arg.position;
} }
FieldMapping FieldMapping::setType() {
return FieldMapping(name, set_type, position);
}
InputReaderAscii::InputReaderAscii() InputReaderAscii::InputReaderAscii()
{ {
//DBG_LOG(DBG_LOGGING, "input reader initialized"); //DBG_LOG(DBG_LOGGING, "input reader initialized");
@ -81,7 +91,7 @@ bool InputReaderAscii::ReadHeader() {
const LogField* field = fields[i]; const LogField* field = fields[i];
if ( field->name == s ) { if ( field->name == s ) {
// cool, found field. note position // cool, found field. note position
FieldMapping f(field->name, field->type, i); FieldMapping f(field->name, field->type, field->set_type, i);
columnMap.push_back(f); columnMap.push_back(f);
wantFields++; wantFields++;
break; // done with searching break; // done with searching
@ -126,77 +136,13 @@ bool InputReaderAscii::GetLine(string& str) {
return false; return false;
} }
// read the entire file and send appropriate thingies back to InputMgr
bool InputReaderAscii::DoUpdate() {
// dirty, fix me. (well, apparently after trying seeking, etc - this is not that bad) LogVal* InputReaderAscii::EntryToVal(string s, FieldMapping field) {
if ( file && file->is_open() ) {
file->close();
}
file = new ifstream(fname.c_str());
if ( !file->is_open() ) {
Error(Fmt("cannot open %s", fname.c_str()));
return false;
}
//
// file->seekg(0, ios::beg); // do not forget clear. LogVal* val = new LogVal(field.type, true);
if ( ReadHeader() == false ) {
return false;
}
// TODO: all the stuff we need for a second reading.
// *cough*
//
//
// new keymap
//map<string, string> *newKeyMap = new map<string, string>();
string line;
while ( GetLine(line ) ) {
// split on tabs
istringstream splitstream(line);
string s;
LogVal** fields = new LogVal*[num_fields];
//string string_fields[num_fields];
unsigned int currTab = 0;
unsigned int currField = 0;
while ( splitstream ) {
if ( !getline(splitstream, s, '\t') )
break;
if ( currTab >= columnMap.size() ) {
Error("Tabs in heading do not match tabs in data?");
//disabled = true;
return false;
}
FieldMapping currMapping = columnMap[currTab];
currTab++;
if ( currMapping.IsEmpty() ) {
// well, that was easy
continue;
}
if ( currField >= num_fields ) {
Error("internal error - fieldnum greater as possible");
return false;
}
LogVal* val = new LogVal(currMapping.type, true);
//bzero(val, sizeof(LogVal)); //bzero(val, sizeof(LogVal));
switch ( currMapping.type ) { switch ( field.type ) {
case TYPE_ENUM: case TYPE_ENUM:
case TYPE_STRING: case TYPE_STRING:
val->val.string_val = new string(s); val->val.string_val = new string(s);
@ -253,13 +199,140 @@ bool InputReaderAscii::DoUpdate() {
break; break;
} }
case TYPE_TABLE: {
// construct a table from entry...
// for the moment assume, that entries are split by ",".
if ( s == "-" ) {
// empty
val->val.set_val.size = 0;
break;
}
// how many entries do we have...
unsigned int length = 1;
for ( unsigned int i = 0; i < s.size(); i++ )
if ( s[i] == ',') length++;
unsigned int pos = 0;
LogVal** lvals = new LogVal* [length];
val->val.set_val.vals = lvals;
val->val.set_val.size = length;
istringstream splitstream(s);
while ( splitstream ) {
string element;
if ( pos >= length ) {
Error(Fmt("Internal error while parsing set. pos %d > length %d", pos, length));
break;
}
if ( !getline(splitstream, element, ',') )
break;
LogVal* newval = EntryToVal(element, field.setType());
if ( newval == 0 ) {
Error("Error while reading set");
return 0;
}
lvals[pos] = newval;
pos++;
}
if ( pos != length ) {
Error("Internal error while parsing set: did not find all elements");
return 0;
}
break;
}
default: default:
Error(Fmt("unsupported field format %d for %s", currMapping.type, Error(Fmt("unsupported field format %d for %s", field.type,
currMapping.name.c_str())); field.name.c_str()));
return 0;
}
return val;
}
// read the entire file and send appropriate thingies back to InputMgr
bool InputReaderAscii::DoUpdate() {
// dirty, fix me. (well, apparently after trying seeking, etc - this is not that bad)
if ( file && file->is_open() ) {
file->close();
}
file = new ifstream(fname.c_str());
if ( !file->is_open() ) {
Error(Fmt("cannot open %s", fname.c_str()));
return false;
}
//
// file->seekg(0, ios::beg); // do not forget clear.
if ( ReadHeader() == false ) {
return false; return false;
} }
// TODO: all the stuff we need for a second reading.
// *cough*
//
//
// new keymap
//map<string, string> *newKeyMap = new map<string, string>();
string line;
while ( GetLine(line ) ) {
// split on tabs
istringstream splitstream(line);
LogVal** fields = new LogVal*[num_fields];
//string string_fields[num_fields];
unsigned int currTab = 0;
unsigned int currField = 0;
while ( splitstream ) {
string s;
if ( !getline(splitstream, s, '\t') )
break;
if ( currTab >= columnMap.size() ) {
Error("Tabs in heading do not match tabs in data?");
//disabled = true;
return false;
}
FieldMapping currMapping = columnMap[currTab];
currTab++;
if ( currMapping.IsEmpty() ) {
// well, that was easy
continue;
}
if ( currField >= num_fields ) {
Error("internal error - fieldnum greater as possible");
return false;
}
LogVal* val = EntryToVal(s, currMapping);
if ( val == 0 ) {
return false;
}
fields[currMapping.position] = val; fields[currMapping.position] = val;
//string_fields[currMapping.position] = s; //string_fields[currMapping.position] = s;

View file

@ -12,11 +12,15 @@
struct FieldMapping { struct FieldMapping {
string name; string name;
TypeTag type; TypeTag type;
TypeTag set_type;
int position; int position;
FieldMapping(const string& arg_name, const TypeTag& arg_type, int arg_position); FieldMapping(const string& arg_name, const TypeTag& arg_type, int arg_position);
FieldMapping(const string& arg_name, const TypeTag& arg_type, const TypeTag& arg_set_type, int arg_position);
FieldMapping(const FieldMapping& arg); FieldMapping(const FieldMapping& arg);
FieldMapping() { position = -1; } FieldMapping() { position = -1; }
FieldMapping setType();
bool IsEmpty() { return position == -1; } bool IsEmpty() { return position == -1; }
}; };
@ -38,6 +42,7 @@ protected:
private: private:
bool ReadHeader(); bool ReadHeader();
LogVal* EntryToVal(string s, FieldMapping type);
bool GetLine(string& str); bool GetLine(string& str);

View file

@ -81,16 +81,18 @@ struct LogMgr::Stream {
bool LogField::Read(SerializationFormat* fmt) bool LogField::Read(SerializationFormat* fmt)
{ {
int t; int t;
int it;
bool success = (fmt->Read(&name, "name") && fmt->Read(&t, "type")); bool success = (fmt->Read(&name, "name") && fmt->Read(&t, "type") && fmt->Read(&it, "set_type") );
type = (TypeTag) t; type = (TypeTag) t;
set_type = (TypeTag) it;
return success; return success;
} }
bool LogField::Write(SerializationFormat* fmt) const bool LogField::Write(SerializationFormat* fmt) const
{ {
return (fmt->Write(name, "name") && fmt->Write((int)type, "type")); return (fmt->Write(name, "name") && fmt->Write((int)type, "type") && fmt->Write((int)set_type, "set_type"));
} }
LogVal::~LogVal() LogVal::~LogVal()

View file

@ -15,10 +15,12 @@ class SerializationFormat;
struct LogField { struct LogField {
string name; string name;
TypeTag type; TypeTag type;
// needed by input framework. otherwise it cannot determine the inner type of a set.
TypeTag set_type;
LogField() { } LogField() { }
LogField(const LogField& other) LogField(const LogField& other)
: name(other.name), type(other.type) { } : name(other.name), type(other.type), set_type(other.set_type) { }
// (Un-)serialize. // (Un-)serialize.
bool Read(SerializationFormat* fmt); bool Read(SerializationFormat* fmt);