support for filters and little event fix

This commit is contained in:
Bernhard Amann 2011-11-04 12:41:10 -07:00
parent 4845c3a9a6
commit 2e3874331d
4 changed files with 210 additions and 31 deletions

View file

@ -11,6 +11,16 @@ export {
destination: any; destination: any;
reader: Reader &default=default_reader; reader: Reader &default=default_reader;
}; };
type Filter: record {
name: string;
## descriptive name. for later removal
pred: function(typ: Input::Event, left: any, right: any): bool &optional;
## decision function, that decides if an inserton, update or removal should really be executed
};
} }
@load base/input.bif @load base/input.bif

View file

@ -24,6 +24,11 @@ public:
declare(PDict, InputHash); declare(PDict, InputHash);
struct InputMgr::Filter {
EnumVal* id;
string name;
Func* pred;
};
struct InputMgr::ReaderInfo { struct InputMgr::ReaderInfo {
EnumVal* id; EnumVal* id;
@ -39,10 +44,17 @@ struct InputMgr::ReaderInfo {
PDict(InputHash)* currDict; PDict(InputHash)* currDict;
PDict(InputHash)* lastDict; PDict(InputHash)* lastDict;
list<string>* events; // events we fire when "something" happens list<string> events; // events we fire when "something" happens
list<InputMgr::Filter> filters; // events we fire when "something" happens
// ~ReaderInfo();
}; };
//void InputMgr::~ReaderInfo() {
//
//}
struct InputReaderDefinition { struct InputReaderDefinition {
bro_int_t type; // the type bro_int_t type; // the type
const char *name; // descriptive name for error messages const char *name; // descriptive name for error messages
@ -167,8 +179,6 @@ InputReader* InputMgr::CreateReader(EnumVal* id, RecordVal* description)
info->currDict = new PDict(InputHash); info->currDict = new PDict(InputHash);
info->lastDict = new PDict(InputHash); info->lastDict = new PDict(InputHash);
info->events = new list<string>();
int success = reader_obj->Init(source, fieldsV.size(), idxfields, fields); int success = reader_obj->Init(source, fieldsV.size(), idxfields, fields);
if ( success == false ) { if ( success == false ) {
RemoveReader(id); RemoveReader(id);
@ -264,7 +274,7 @@ bool InputMgr::RegisterEvent(const EnumVal* id, string eventName) {
return false; return false;
} }
i->events->push_back(eventName); i->events.push_back(eventName);
return true; return true;
} }
@ -276,21 +286,23 @@ bool InputMgr::UnregisterEvent(const EnumVal* id, string eventName) {
return false; return false;
} }
bool erased = false; //bool erased = false;
std::list<string>::iterator it = i->events->begin(); std::list<string>::iterator it = i->events.begin();
while ( it != i->events->end() ) while ( it != i->events.end() )
{ {
if ( *it == eventName ) { if ( *it == eventName ) {
it = i->events->erase(it); it = i->events.erase(it);
erased = true; return true;
// erased = true;
} }
else else
++it; ++it;
} }
return erased; return false;
//return erased;
} }
@ -337,6 +349,59 @@ bool InputMgr::ForceUpdate(const EnumVal* id)
return i->reader->Update(); return i->reader->Update();
} }
bool InputMgr::AddFilter(EnumVal *id, RecordVal* fval) {
ReaderInfo *i = FindReader(id);
if ( i == 0 ) {
reporter->InternalError("Reader not found");
return false;
}
RecordType* rtype = fval->Type()->AsRecordType();
if ( ! same_type(rtype, BifType::Record::Input::Filter, 0) )
{
reporter->Error("filter argument not of right type");
return false;
}
Val* name = fval->Lookup(rtype->FieldOffset("name"));
Val* pred = fval->Lookup(rtype->FieldOffset("pred"));
Filter filter;
filter.name = name->AsString()->CheckString();
filter.id = id->Ref()->AsEnumVal();
filter.pred = pred ? pred->AsFunc() : 0;
i->filters.push_back(filter);
return true;
}
bool InputMgr::RemoveFilter(EnumVal* id, const string &name) {
ReaderInfo *i = FindReader(id);
if ( i == 0 ) {
reporter->InternalError("Reader not found");
return false;
}
std::list<InputMgr::Filter>::iterator it = i->filters.begin();
while ( it != i->filters.end() )
{
if ( (*it).name == name ) {
it = i->filters.erase(it);
return true;
break;
}
else
++it;
}
return false;;
}
Val* InputMgr::LogValToIndexVal(int num_fields, const RecordType *type, const LogVal* const *vals) { Val* InputMgr::LogValToIndexVal(int num_fields, const RecordType *type, const LogVal* const *vals) {
Val* idxval; Val* idxval;
int position = 0; int position = 0;
@ -398,6 +463,7 @@ void InputMgr::SendEntry(const InputReader* reader, const LogVal* const *vals) {
i->lastDict->Remove(idxhash); i->lastDict->Remove(idxhash);
delete(h); delete(h);
updated = true; updated = true;
} }
} }
@ -437,6 +503,48 @@ void InputMgr::SendEntry(const InputReader* reader, const LogVal* const *vals) {
valval = r; valval = r;
} }
Val* oldval = 0;
if ( updated == true ) {
// in that case, we need the old value to send the event (if we send an event).
oldval = i->tab->Lookup(idxval);
}
// call filters first do determine if we really add / change the entry
std::list<InputMgr::Filter>::iterator it = i->filters.begin();
while ( it != i->filters.end() ) {
if (! (*it).pred ) {
continue;
}
EnumVal* ev;
Ref(idxval);
Ref(valval);
if ( updated ) {
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED, BifType::Enum::Input::Event);
} else {
ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event);
}
val_list vl(3);
vl.append(ev);
vl.append(idxval);
vl.append(valval);
Val* v = (*it).pred->Call(&vl);
bool result = v->AsBool();
Unref(v);
if ( result == false ) {
// throw away. Hence - we quit.
return;
}
++it;
}
//i->tab->Assign(idxval, valval); //i->tab->Assign(idxval, valval);
HashKey* k = i->tab->ComputeHash(idxval); HashKey* k = i->tab->ComputeHash(idxval);
if ( !k ) { if ( !k ) {
@ -454,22 +562,29 @@ void InputMgr::SendEntry(const InputReader* reader, const LogVal* const *vals) {
i->currDict->Insert(idxhash, ih); i->currDict->Insert(idxhash, ih);
std::list<string>::iterator it = i->events->begin(); // send events now that we are kind of finished.
while ( it != i->events->end() ) { std::list<string>::iterator filter_iterator = i->events.begin();
while ( filter_iterator != i->events.end() ) {
EnumVal* ev; EnumVal* ev;
if ( updated ) { Ref(idxval);
if ( updated ) { // in case of update send back the old value.
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED, BifType::Enum::Input::Event); ev = new EnumVal(BifEnum::Input::EVENT_CHANGED, BifType::Enum::Input::Event);
assert ( oldval != 0 );
Ref(oldval);
SendEvent(*filter_iterator, ev, idxval, oldval);
} else { } else {
ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event); ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event);
}
Ref(idxval);
Ref(valval); Ref(valval);
SendEvent(*it, ev, idxval, valval); SendEvent(*filter_iterator, ev, idxval, valval);
++it;
} }
++filter_iterator;
}
} }
@ -484,14 +599,49 @@ void InputMgr::EndCurrentSend(const InputReader* reader) {
InputHash* ih; InputHash* ih;
while ( ( ih = i->lastDict->NextEntry(c) ) ) { while ( ( ih = i->lastDict->NextEntry(c) ) ) {
if ( i->events->size() > 0 ) { if ( i->events.size() != 0 || i->filters.size() != 0 ) // we have a filter or an event
{
ListVal *idx = i->tab->RecoverIndex(ih->idxkey); ListVal *idx = i->tab->RecoverIndex(ih->idxkey);
assert(idx != 0); assert(idx != 0);
Val *val = i->tab->Lookup(idx); Val *val = i->tab->Lookup(idx);
assert(val != 0); assert(val != 0);
std::list<string>::iterator it = i->events->begin();
while ( it != i->events->end() ) { {
// ask filter, if we want to expire this element...
std::list<InputMgr::Filter>::iterator it = i->filters.begin();
while ( it != i->filters.end() ) {
if (! (*it).pred ) {
continue;
}
EnumVal* ev = new EnumVal(BifEnum::Input::EVENT_REMOVED, BifType::Enum::Input::Event);
Ref(idx);
Ref(val);
val_list vl(3);
vl.append(ev);
vl.append(idx);
vl.append(val);
Val* v = (*it).pred->Call(&vl);
bool result = v->AsBool();
Unref(v);
if ( result == false ) {
// throw away. Hence - we quit and simply go to the next entry of lastDict
continue;
}
++it;
}
}
//
{
std::list<string>::iterator it = i->events.begin();
while ( it != i->events.end() ) {
Ref(idx); Ref(idx);
Ref(val); Ref(val);
EnumVal *ev = new EnumVal(BifEnum::Input::EVENT_REMOVED, BifType::Enum::Input::Event); EnumVal *ev = new EnumVal(BifEnum::Input::EVENT_REMOVED, BifType::Enum::Input::Event);
@ -500,7 +650,9 @@ void InputMgr::EndCurrentSend(const InputReader* reader) {
} }
} }
reporter->Error("Expiring element"); }
//reporter->Error("Expiring element");
i->tab->Delete(ih->idxkey); i->tab->Delete(ih->idxkey);
} }

View file

@ -26,6 +26,9 @@ public:
bool RegisterEvent(const EnumVal* id, string eventName); bool RegisterEvent(const EnumVal* id, string eventName);
bool UnregisterEvent(const EnumVal* id, string eventName); bool UnregisterEvent(const EnumVal* id, string eventName);
bool AddFilter(EnumVal *id, RecordVal* filter);
bool RemoveFilter(EnumVal* id, const string &name);
protected: protected:
friend class InputReader; friend class InputReader;
@ -62,6 +65,8 @@ private:
string Hash(const string &input); string Hash(const string &input);
struct Filter;
}; };
extern InputMgr* input_mgr; extern InputMgr* input_mgr;

View file

@ -8,34 +8,46 @@ module Input;
%%} %%}
type ReaderDescription: record; type ReaderDescription: record;
type Filter: record;
function Input::__create_reader%(id: ID, description: Input::ReaderDescription%) : bool function Input::__create_reader%(id: Log::ID, description: Input::ReaderDescription%) : bool
%{ %{
InputReader *the_reader = input_mgr->CreateReader(id->AsEnumVal(), description->AsRecordVal()); InputReader *the_reader = input_mgr->CreateReader(id->AsEnumVal(), description->AsRecordVal());
return new Val( the_reader != 0, TYPE_BOOL ); return new Val( the_reader != 0, TYPE_BOOL );
%} %}
function Input::__force_update%(id: ID%) : bool function Input::__force_update%(id: Log::ID%) : bool
%{ %{
bool res = input_mgr->ForceUpdate(id->AsEnumVal()); bool res = input_mgr->ForceUpdate(id->AsEnumVal());
return new Val( res, TYPE_BOOL ); return new Val( res, TYPE_BOOL );
%} %}
function Input::__add_event%(id: ID, name: string%) : bool function Input::__add_event%(id: Log::ID, name: string%) : bool
%{ %{
bool res = input_mgr->RegisterEvent(id->AsEnumVal(), name->AsString()->CheckString()); bool res = input_mgr->RegisterEvent(id->AsEnumVal(), name->AsString()->CheckString());
return new Val( res, TYPE_BOOL ); return new Val( res, TYPE_BOOL );
%} %}
function Input::__remove_event%(id: ID, name: string%) : bool function Input::__remove_event%(id: Log::ID, name: string%) : bool
%{ %{
bool res = input_mgr->UnregisterEvent(id->AsEnumVal(), name->AsString()->CheckString()); bool res = input_mgr->UnregisterEvent(id->AsEnumVal(), name->AsString()->CheckString());
return new Val( res, TYPE_BOOL ); return new Val( res, TYPE_BOOL );
%} %}
function Input::__remove_reader%(id: ID%) : bool function Input::__remove_reader%(id: Log::ID%) : bool
%{ %{
bool res = input_mgr->RemoveReader(id->AsEnumVal()); bool res = input_mgr->RemoveReader(id->AsEnumVal());
return new Val( res, TYPE_BOOL ); return new Val( res, TYPE_BOOL );
%} %}
function Input::__add_filter%(id: Log::ID, filter: Input::Filter%) : bool
%{
bool res = input_mgr->AddFilter(id->AsEnumVal(), filter->AsRecordVal());
return new Val( res, TYPE_BOOL );
%}
function Input::__remove_filter%(id: Log::ID, name: string%) : bool
%{
bool res = input_mgr->RemoveFilter(id->AsEnumVal(), name->AsString()->CheckString());
return new Val( res, TYPE_BOOL);
%}