Beginning implementation of &on_change for tables.

This commit is contained in:
Johanna Amann 2020-01-09 12:47:16 -05:00
parent f6a1a7053b
commit bf31587c2c
7 changed files with 92 additions and 2 deletions

View file

@ -482,6 +482,71 @@ void Attributes::CheckAttr(Attr* a)
} }
break; break;
case ATTR_ON_CHANGE:
{
if ( type->Tag() != TYPE_TABLE )
{
Error("&on_change only applicable to tables");
break;
}
const Expr *change_func = a->AttrExpr();
if ( change_func->Type()->Tag() != TYPE_FUNC || change_func->Type()->AsFuncType()->Flavor() != FUNC_FLAVOR_FUNCTION )
Error("&on_change attribute is not a function");
const FuncType *c_ft = change_func->Type()->AsFuncType();
if ( c_ft->YieldType()->Tag() != TYPE_BOOL )
{
Error("&on_change must yield a value of type bool");
break;
}
const TableType *the_table = type->AsTableType();
if (the_table->IsUnspecifiedTable())
break;
const type_list* args = c_ft->ArgTypes()->Types();
const type_list* t_indexes = the_table->IndexTypes();
if ( args->length() != 3 + t_indexes->length() )
{
Error("&on_change function has incorrect number of arguments");
break;
}
if ( ! same_type((*args)[0], the_table->AsTableType()) )
{
Error("&on_change: first argument must be of same type as table");
break;
}
// can't check exact type here yet - the data structures don't exist yet.
if ( (*args)[1]->Tag() != TYPE_ENUM )
{
Error("&on_change: second argument must be a TableChange enum");
break;
}
bool indexmatch = true;
for ( int i = 0; i < t_indexes->length(); i++ )
{
if ( ! same_type((*args)[2+i], (*t_indexes)[i]) )
{
Error("&on_change: index types do not match table");
break;
}
}
if ( ! same_type((*args)[2+t_indexes->length()], the_table->YieldType()) )
{
Error("&on_change: value type does not match table");
break;
}
}
break;
case ATTR_TRACKED: case ATTR_TRACKED:
// FIXME: Check here for global ID? // FIXME: Check here for global ID?
break; break;

View file

@ -27,6 +27,7 @@ typedef enum {
ATTR_ERROR_HANDLER, ATTR_ERROR_HANDLER,
ATTR_TYPE_COLUMN, // for input framework ATTR_TYPE_COLUMN, // for input framework
ATTR_TRACKED, // hidden attribute, tracked by NotifierRegistry ATTR_TRACKED, // hidden attribute, tracked by NotifierRegistry
ATTR_ON_CHANGE, // for table change tracking
ATTR_DEPRECATED, ATTR_DEPRECATED,
#define NUM_ATTRS (int(ATTR_DEPRECATED) + 1) #define NUM_ATTRS (int(ATTR_DEPRECATED) + 1)
} attr_tag; } attr_tag;

View file

@ -1340,6 +1340,7 @@ TableVal::~TableVal()
Unref(def_val); Unref(def_val);
Unref(expire_func); Unref(expire_func);
Unref(expire_time); Unref(expire_time);
Unref(change_func);
} }
void TableVal::RemoveAll() void TableVal::RemoveAll()
@ -1391,6 +1392,12 @@ void TableVal::SetAttrs(Attributes* a)
expire_func = ef->AttrExpr(); expire_func = ef->AttrExpr();
expire_func->Ref(); expire_func->Ref();
} }
auto cf = attrs->FindAttr(ATTR_ON_CHANGE);
if ( cf )
{
change_func = cf->AttrExpr();
change_func->Ref();
}
} }
void TableVal::CheckExpireAttr(attr_tag at) void TableVal::CheckExpireAttr(attr_tag at)
@ -1926,6 +1933,13 @@ ListVal* TableVal::RecoverIndex(const HashKey* k) const
Val* TableVal::Delete(const Val* index) Val* TableVal::Delete(const Val* index)
{ {
HashKey* k = ComputeHash(index); HashKey* k = ComputeHash(index);
if ( k && change_func )
{
auto el = AsTable()->Lookup(k);
if ( el )
{
}
}
TableEntryVal* v = k ? AsNonConstTable()->RemoveEntry(k) : 0; TableEntryVal* v = k ? AsNonConstTable()->RemoveEntry(k) : 0;
Val* va = v ? (v->Value() ? v->Value() : this->Ref()) : 0; Val* va = v ? (v->Value() ? v->Value() : this->Ref()) : 0;

View file

@ -933,6 +933,7 @@ protected:
IterCookie* expire_cookie; IterCookie* expire_cookie;
PrefixTable* subnets; PrefixTable* subnets;
Val* def_val; Val* def_val;
Expr* change_func = nullptr;
}; };
class RecordVal : public Val, public notifier::Modifiable { class RecordVal : public Val, public notifier::Modifiable {

View file

@ -5,7 +5,7 @@
// Switching parser table type fixes ambiguity problems. // Switching parser table type fixes ambiguity problems.
%define lr.type ielr %define lr.type ielr
%expect 105 %expect 111
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
@ -24,7 +24,7 @@
%token TOK_ATTR_ADD_FUNC TOK_ATTR_DEFAULT TOK_ATTR_OPTIONAL TOK_ATTR_REDEF %token TOK_ATTR_ADD_FUNC TOK_ATTR_DEFAULT TOK_ATTR_OPTIONAL TOK_ATTR_REDEF
%token TOK_ATTR_DEL_FUNC TOK_ATTR_EXPIRE_FUNC %token TOK_ATTR_DEL_FUNC TOK_ATTR_EXPIRE_FUNC
%token TOK_ATTR_EXPIRE_CREATE TOK_ATTR_EXPIRE_READ TOK_ATTR_EXPIRE_WRITE %token TOK_ATTR_EXPIRE_CREATE TOK_ATTR_EXPIRE_READ TOK_ATTR_EXPIRE_WRITE
%token TOK_ATTR_RAW_OUTPUT %token TOK_ATTR_RAW_OUTPUT TOK_ATTR_ON_CHANGE
%token TOK_ATTR_PRIORITY TOK_ATTR_LOG TOK_ATTR_ERROR_HANDLER %token TOK_ATTR_PRIORITY TOK_ATTR_LOG TOK_ATTR_ERROR_HANDLER
%token TOK_ATTR_TYPE_COLUMN TOK_ATTR_DEPRECATED %token TOK_ATTR_TYPE_COLUMN TOK_ATTR_DEPRECATED
@ -1327,6 +1327,8 @@ attr:
{ $$ = new Attr(ATTR_ADD_FUNC, $3); } { $$ = new Attr(ATTR_ADD_FUNC, $3); }
| TOK_ATTR_DEL_FUNC '=' expr | TOK_ATTR_DEL_FUNC '=' expr
{ $$ = new Attr(ATTR_DEL_FUNC, $3); } { $$ = new Attr(ATTR_DEL_FUNC, $3); }
| TOK_ATTR_ON_CHANGE '=' expr
{ $$ = new Attr(ATTR_ON_CHANGE, $3); }
| TOK_ATTR_EXPIRE_FUNC '=' expr | TOK_ATTR_EXPIRE_FUNC '=' expr
{ $$ = new Attr(ATTR_EXPIRE_FUNC, $3); } { $$ = new Attr(ATTR_EXPIRE_FUNC, $3); }
| TOK_ATTR_EXPIRE_CREATE '=' expr | TOK_ATTR_EXPIRE_CREATE '=' expr

View file

@ -298,6 +298,7 @@ when return TOK_WHEN;
&read_expire return TOK_ATTR_EXPIRE_READ; &read_expire return TOK_ATTR_EXPIRE_READ;
&redef return TOK_ATTR_REDEF; &redef return TOK_ATTR_REDEF;
&write_expire return TOK_ATTR_EXPIRE_WRITE; &write_expire return TOK_ATTR_EXPIRE_WRITE;
&on_change return TOK_ATTR_ON_CHANGE;
@deprecated.* { @deprecated.* {
auto num_files = file_stack.length(); auto num_files = file_stack.length();

View file

@ -225,6 +225,12 @@ type gtp_qos_profile: record;
type gtp_private_extension: record; type gtp_private_extension: record;
type gtp_gsn_addr: record; type gtp_gsn_addr: record;
enum TableChange %{
TABLE_ELEMENT_NEW,
TABLE_ELEMENT_CHANGED,
TABLE_ELEMENT_REMOVED,
%}
module Reporter; module Reporter;
enum Level %{ enum Level %{