summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2013-07-10 16:06:57 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2013-07-10 16:06:57 +0200
commitf8f87de0a5111b02b35057005949986ab8616802 (patch)
treeec33d9036c2cb48b3b4e1a0477c9db028b624488
parent7e6cb8885e36d158c29f3b10be8d41d5884763f4 (diff)
downloadrsyslog-f8f87de0a5111b02b35057005949986ab8616802.tar.gz
rsyslog-f8f87de0a5111b02b35057005949986ab8616802.tar.bz2
rsyslog-f8f87de0a5111b02b35057005949986ab8616802.zip
milestone: basic lookup() functionality is present
done the naive way, string indzes only
-rw-r--r--grammar/rainerscript.c50
-rw-r--r--grammar/rainerscript.h3
-rw-r--r--runtime/lookup.c60
-rw-r--r--runtime/lookup.h2
4 files changed, 106 insertions, 9 deletions
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index e3e7cb32..ef44a410 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -1334,6 +1334,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
int bMustFree;
es_str_t *estr;
char *str;
+ char *s;
uchar *resStr;
int retval;
struct var r[CNFFUNC_MAX_ARGS];
@@ -1471,6 +1472,20 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
ret->d.n = 1;
ret->datatype = 'N';
break;
+ case CNFFUNC_LOOKUP:
+dbgprintf("DDDD: executing lookup\n");
+ ret->datatype = 'S';
+ if(func->funcdata == NULL) {
+ ret->d.estr = es_newStrFromCStr("TABLE-NOT-FOUND", sizeof("TABLE-NOT-FOUND")-1);
+ break;
+ }
+ cnfexprEval(func->expr[1], &r[1], usrptr);
+ str = (char*) var2CString(&r[1], &bMustFree);
+ s = (char*)lookupKey(func->funcdata, (uchar*)str);
+ ret->d.estr = es_newStrFromCStr(s, strlen(s));
+ if(bMustFree) free(str);
+ if(r[1].datatype == 'S') es_deleteStr(r[1].d.estr);
+ break;
default:
if(Debug) {
fname = es_str2cstr(func->fname, NULL);
@@ -3233,6 +3248,13 @@ funcName2ID(es_str_t *fname, unsigned short nParams)
return CNFFUNC_INVALID;
}
return CNFFUNC_PRIFILT;
+ } else if(!es_strbufcmp(fname, (unsigned char*)"lookup", sizeof("lookup") - 1)) {
+ if(nParams != 2) {
+ parser_errmsg("number of parameters for lookup() must be two "
+ "but is %d.", nParams);
+ return CNFFUNC_INVALID;
+ }
+ return CNFFUNC_LOOKUP;
} else {
return CNFFUNC_INVALID;
}
@@ -3297,6 +3319,31 @@ finalize_it:
}
+static inline rsRetVal
+initFunc_lookup(struct cnffunc *func)
+{
+ struct funcData_prifilt *pData;
+ uchar *cstr = NULL;
+ DEFiRet;
+
+ func->funcdata = NULL;
+ if(func->expr[0]->nodetype != 'S') {
+ parser_errmsg("table name (param 1) of lookup() must be a constant string");
+ FINALIZE;
+ }
+
+ cstr = (uchar*)es_str2cstr(((struct cnfstringval*) func->expr[0])->estr, NULL);
+ if((func->funcdata = lookupFindTable(cstr)) == NULL) {
+ parser_errmsg("lookup table '%s' not found", cstr);
+ FINALIZE;
+ }
+
+finalize_it:
+ free(cstr);
+ RETiRet;
+}
+
+
struct cnffunc *
cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
{
@@ -3334,6 +3381,9 @@ cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
case CNFFUNC_PRIFILT:
initFunc_prifilt(func);
break;
+ case CNFFUNC_LOOKUP:
+ initFunc_lookup(func);
+ break;
default:break;
}
}
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index cb8c968f..5c9a05ac 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -232,7 +232,8 @@ enum cnffuncid {
CNFFUNC_RE_MATCH,
CNFFUNC_RE_EXTRACT,
CNFFUNC_FIELD,
- CNFFUNC_PRIFILT
+ CNFFUNC_PRIFILT,
+ CNFFUNC_LOOKUP
};
struct cnffunc {
diff --git a/runtime/lookup.c b/runtime/lookup.c
index 7ee2eba3..e83f5979 100644
--- a/runtime/lookup.c
+++ b/runtime/lookup.c
@@ -98,7 +98,7 @@ lookupInitCnf(lookup_tables_t *lu_tabs)
}
-/* comparison function for qsort() and bsearch() string array compare
+/* comparison function for qsort() and string array compare
* this is for the string lookup table type
*/
static int
@@ -106,6 +106,14 @@ qs_arrcmp_strtab(const void *s1, const void *s2)
{
return ustrcmp(((lookup_string_tab_etry_t*)s1)->key, ((lookup_string_tab_etry_t*)s2)->key);
}
+/* comparison function for bsearch() and string array compare
+ * this is for the string lookup table type
+ */
+static int
+bs_arrcmp_strtab(const void *s1, const void *s2)
+{
+ return strcmp((char*)s1, (char*)((lookup_string_tab_etry_t*)s2)->key);
+}
rsRetVal
lookupBuildTable(lookup_t *pThis, struct json_object *jroot)
@@ -120,11 +128,6 @@ lookupBuildTable(lookup_t *pThis, struct json_object *jroot)
jnomatch = json_object_object_get(jroot, "nomatch");
jtype = json_object_object_get(jroot, "type");
jtab = json_object_object_get(jroot, "table");
-DBGPRINTF("DDDD: version: %d, nomatch %s, type %s, table: '%s'\n",
- json_object_get_int(jversion),
- json_object_get_string(jnomatch),
- json_object_get_string(jtype),
- json_object_get_string(jtab));
pThis->nmemb = json_object_array_length(jtab);
CHKmalloc(pThis->d.strtab = malloc(pThis->nmemb * sizeof(lookup_string_tab_etry_t)));
@@ -142,10 +145,48 @@ DBGPRINTF("DDDD: version: %d, nomatch %s, type %s, table: '%s'\n",
dbgprintf("DDDD: table loaded (max size %u):\n", maxStrSize);
for(i = 0 ; i < pThis->nmemb ; ++i)
dbgprintf("key: '%s', val: '%s'\n", pThis->d.strtab[i].key, pThis->d.strtab[i].val);
+
finalize_it:
RETiRet;
}
+
+/* find a lookup table. This is a naive O(n) algo, but this really
+ * doesn't matter as it is called only a few times during config
+ * load. The function returns either a pointer to the requested
+ * table or NULL, if not found.
+ */
+lookup_t *
+lookupFindTable(uchar *name)
+{
+ lookup_t *curr;
+
+ for(curr = loadConf->lu_tabs.root ; curr != NULL ; curr = curr->next) {
+ if(!ustrcmp(curr->name, name))
+ break;
+ }
+ return curr;
+}
+
+
+/* returns either a pointer to the value (read only!) or NULL
+ * if either the key could not be found or an error occured.
+ */
+uchar *
+lookupKey(lookup_t *pThis, uchar *key)
+{
+ lookup_string_tab_etry_t *etry;
+ uchar *r;
+ etry = bsearch(key, pThis->d.strtab, pThis->nmemb, sizeof(lookup_string_tab_etry_t), bs_arrcmp_strtab);
+ if(etry == NULL) {
+ r = (uchar*)""; // TODO: use set default
+ } else {
+ r = etry->val;
+ }
+ return r;
+}
+
+
/* note: widely-deployed json_c 0.9 does NOT support incremental
* parsing. In order to keep compatible with e.g. Ubuntu 12.04LTS,
* we read the file into one big memory buffer and parse it at once.
@@ -157,7 +198,7 @@ rsRetVal
lookupReadFile(lookup_t *pThis)
{
struct json_tokener *tokener = NULL;
- struct json_object *json;
+ struct json_object *json = NULL;
int eno = errno;
char errStr[1024];
char *iobuf = NULL;
@@ -187,7 +228,6 @@ lookupReadFile(lookup_t *pThis)
tokener = json_tokener_new();
nread = read(fd, iobuf, sb.st_size);
-dbgprintf("DDDD: read buffer of %lld bytes: '%s'\n", (long long) sb.st_size, iobuf);
if(nread != (ssize_t) sb.st_size) {
eno = errno;
errmsg.LogError(0, RS_RET_READ_ERR,
@@ -203,6 +243,8 @@ dbgprintf("DDDD: read buffer of %lld bytes: '%s'\n", (long long) sb.st_size, iob
pThis->filename);
ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR);
}
+ free(iobuf); /* early free to sever resources*/
+ iobuf = NULL; /* make sure no double-free */
/* got json object, now populate our own in-memory structure */
CHKiRet(lookupBuildTable(pThis, json));
@@ -211,6 +253,8 @@ finalize_it:
free(iobuf);
if(tokener != NULL)
json_tokener_free(tokener);
+ if(json != NULL)
+ json_object_put(json);
RETiRet;
}
diff --git a/runtime/lookup.h b/runtime/lookup.h
index 5dd02283..db2737a2 100644
--- a/runtime/lookup.h
+++ b/runtime/lookup.h
@@ -44,6 +44,8 @@ struct lookup_s {
/* prototypes */
void lookupInitCnf(lookup_tables_t *lu_tabs);
rsRetVal lookupProcessCnf(struct cnfobj *o);
+lookup_t *lookupFindTable(uchar *name);
+uchar *lookupKey(lookup_t *pThis, uchar *key);
void lookupDestruct(lookup_t *pThis);
void lookupClassExit(void);
rsRetVal lookupClassInit(void);