diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2013-07-20 14:54:06 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2013-07-20 14:54:06 +0200 |
commit | db5c9793205232b0c0e6ba4a85baec9e26e37264 (patch) | |
tree | 9ab136c6554de454262b01c073978bb98e8704ad /runtime/msg.c | |
parent | 3885eb7a350389c3f4dd823351ec3de34382615d (diff) | |
parent | 58b5616b41cd2cacf0b3039c8ebbd204d8918201 (diff) | |
download | rsyslog-db5c9793205232b0c0e6ba4a85baec9e26e37264.tar.gz rsyslog-db5c9793205232b0c0e6ba4a85baec9e26e37264.tar.bz2 rsyslog-db5c9793205232b0c0e6ba4a85baec9e26e37264.zip |
Merge branch 'master-localvars'
Diffstat (limited to 'runtime/msg.c')
-rw-r--r-- | runtime/msg.c | 179 |
1 files changed, 130 insertions, 49 deletions
diff --git a/runtime/msg.c b/runtime/msg.c index 67d957d1..73fa0367 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -317,9 +317,10 @@ static pthread_mutex_t mutTrimCtr; /* mutex to handle malloc trim */ /* some forward declarations */ static int getAPPNAMELen(msg_t *pM, sbool bLockMutex); -static rsRetVal jsonPathFindParent(msg_t *pM, uchar *name, uchar *leaf, struct json_object **parent, int bCreate); +static rsRetVal jsonPathFindParent(struct json_object *jroot, uchar *name, uchar *leaf, struct json_object **parent, int bCreate); static uchar * jsonPathGetLeaf(uchar *name, int lenName); static struct json_object *jsonDeepCopy(struct json_object *src); +static rsRetVal msgAddJSONObj(msg_t *pM, uchar *name, struct json_object *json, struct json_object **pjroot); /* the locking and unlocking implementations: */ @@ -536,6 +537,8 @@ propNameStrToID(uchar *pName, propid_t *pPropID) *pPropID = PROP_CEE_ALL_JSON; } else if(!strncmp((char*) pName, "$!", 2)) { *pPropID = PROP_CEE; + } else if(!strncmp((char*) pName, "$.", 2)) { + *pPropID = PROP_LOCAL_VAR; } else if(!strcmp((char*) pName, "$bom")) { *pPropID = PROP_SYS_BOM; } else if(!strcmp((char*) pName, "$uptime")) { @@ -634,6 +637,8 @@ uchar *propIDToName(propid_t propID) return UCHAR_CONSTANT("$MYHOSTNAME"); case PROP_CEE: return UCHAR_CONSTANT("*CEE-based property*"); + case PROP_LOCAL_VAR: + return UCHAR_CONSTANT("*LOCAL_VARIABLE*"); case PROP_CEE_ALL_JSON: return UCHAR_CONSTANT("$!all-json"); case PROP_SYS_BOM: @@ -708,6 +713,7 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis) pM->rcvFrom.pRcvFrom = NULL; pM->pRuleset = NULL; pM->json = NULL; + pM->localvars = NULL; memset(&pM->tRcvdAt, 0, sizeof(pM->tRcvdAt)); memset(&pM->tTIMESTAMP, 0, sizeof(pM->tTIMESTAMP)); pM->TAG.pszTAG = NULL; @@ -853,6 +859,8 @@ CODESTARTobjDestruct(msg) rsCStrDestruct(&pThis->pCSMSGID); if(pThis->json != NULL) json_object_put(pThis->json); + if(pThis->localvars != NULL) + json_object_put(pThis->localvars); if(pThis->pszUUID != NULL) free(pThis->pszUUID); # ifndef HAVE_ATOMIC_BUILTINS @@ -1002,6 +1010,8 @@ msg_t* MsgDup(msg_t* pOld) if(pOld->json != NULL) pNew->json = jsonDeepCopy(pOld->json); + if(pOld->localvars != NULL) + pNew->localvars = jsonDeepCopy(pOld->localvars); /* we do not copy all other cache properties, as we do not even know * if they are needed once again. So we let them re-create if needed. @@ -1060,6 +1070,10 @@ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm) psz = (uchar*) json_object_get_string(pThis->json); CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("json"), PROPTYPE_PSZ, (void*) psz)); } + if(pThis->localvars != NULL) { + psz = (uchar*) json_object_get_string(pThis->localvars); + CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("localvars"), PROPTYPE_PSZ, (void*) psz)); + } objSerializePTR(pStrm, pCSStrucData, CSTR); objSerializePTR(pStrm, pCSAPPNAME, CSTR); @@ -1202,6 +1216,14 @@ MsgDeserialize(msg_t *pMsg, strm_t *pStrm) reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } + if(isProp("localvars")) { + tokener = json_tokener_new(); + pMsg->localvars = json_tokener_parse_ex(tokener, (char*)rsCStrGetSzStrNoNULL(pVar->val.pStr), + cstrLen(pVar->val.pStr)); + json_tokener_free(tokener); + reinitVar(pVar); + CHKiRet(objDeserializeProperty(pVar, pStrm)); + } if(isProp("pCSStrucData")) { MsgSetStructuredData(pMsg, (char*) rsCStrGetSzStrNoNULL(pVar->val.pStr)); reinitVar(pVar); @@ -2510,9 +2532,9 @@ static uchar *getNOW(eNOWType eNow, struct syslogTime *t) #undef tmpBUFSIZE /* clean up */ -/* Get a CEE-Property as string value*/ -rsRetVal -getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed) +/* Get a JSON-Property as string value (used for various types of JSON-based vars) */ +static rsRetVal +getJSONPropVal(struct json_object *jroot, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed) { uchar *name = NULL; uchar *leaf; @@ -2524,14 +2546,14 @@ getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, un free(*pRes); *pRes = NULL; // TODO: mutex? - if(pM->json == NULL) goto finalize_it; + if(jroot == NULL) goto finalize_it; if(!es_strbufcmp(propName, (uchar*)"!", 1)) { - field = pM->json; + field = jroot; } else { name = (uchar*)es_str2cstr(propName, NULL); leaf = jsonPathGetLeaf(name, ustrlen(name)); - CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 1)); + CHKiRet(jsonPathFindParent(jroot, name, leaf, &parent, 1)); field = json_object_object_get(parent, (char*)leaf); } if(field != NULL) { @@ -2550,11 +2572,22 @@ finalize_it: RETiRet; } +rsRetVal +getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed) +{ + return getJSONPropVal(pM->json, propName, pRes, buflen, pbMustBeFreed); +} -/* Get a CEE-Property as native json object - */ rsRetVal -msgGetCEEPropJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson) +getLocalVarPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed) +{ + return getJSONPropVal(pM->localvars, propName, pRes, buflen, pbMustBeFreed); +} + + +/* Get a JSON-based-variable as native json object */ +rsRetVal +msgGetJSONPropJSON(struct json_object *jroot, es_str_t *propName, struct json_object **pjson) { uchar *name = NULL; uchar *leaf; @@ -2562,17 +2595,17 @@ msgGetCEEPropJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson) DEFiRet; // TODO: mutex? - if(pM->json == NULL) { + if(jroot == NULL) { ABORT_FINALIZE(RS_RET_NOT_FOUND); } if(!es_strbufcmp(propName, (uchar*)"!", 1)) { - *pjson = pM->json; + *pjson = jroot; FINALIZE; } name = (uchar*)es_str2cstr(propName, NULL); leaf = jsonPathGetLeaf(name, ustrlen(name)); - CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 1)); + CHKiRet(jsonPathFindParent(jroot, name, leaf, &parent, 1)); *pjson = json_object_object_get(parent, (char*)leaf); if(*pjson == NULL) { ABORT_FINALIZE(RS_RET_NOT_FOUND); @@ -2583,6 +2616,17 @@ finalize_it: RETiRet; } +rsRetVal +msgGetCEEPropJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson) +{ + return msgGetJSONPropJSON(pM->json, propName, pjson); +} + +rsRetVal +msgGetLocalVarJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson) +{ + return msgGetJSONPropJSON(pM->localvars, propName, pjson); +} /* Encode a JSON value and add it to provided string. Note that * the string object may be NULL. In this case, it is created @@ -2981,6 +3025,9 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, case PROP_CEE: getCEEPropVal(pMsg, propName, &pRes, &bufLen, pbMustBeFreed); break; + case PROP_LOCAL_VAR: + getLocalVarPropVal(pMsg, propName, &pRes, &bufLen, pbMustBeFreed); + break; case PROP_SYS_BOM: if(*pbMustBeFreed == 1) free(pRes); @@ -3648,15 +3695,15 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, } -/* The function returns a cee variable suitable for use with RainerScript. +/* The function returns a json variable suitable for use with RainerScript. * Note: caller must free the returned string. * Note that we need to do a lot of conversions between es_str_t and cstr -- this will go away once * we have moved larger parts of rsyslog to es_str_t. Acceptable for the moment, especially as we intend * to rewrite the script engine as well! * rgerhards, 2010-12-03 */ -es_str_t* -msgGetCEEVarNew(msg_t *pMsg, char *name) +static es_str_t* +msgGetJSONVarNew(msg_t *pMsg, struct json_object *jroot, char *name) { uchar *leaf; char *val; @@ -3665,12 +3712,12 @@ msgGetCEEVarNew(msg_t *pMsg, char *name) ISOBJ_TYPE_assert(pMsg, msg); - if(pMsg->json == NULL) { + if(jroot == NULL) { estr = es_newStr(1); goto done; } leaf = jsonPathGetLeaf((uchar*)name, strlen(name)); - if(jsonPathFindParent(pMsg, (uchar*)name, leaf, &parent, 1) != RS_RET_OK) { + if(jsonPathFindParent(jroot, (uchar*)name, leaf, &parent, 1) != RS_RET_OK) { estr = es_newStr(1); goto done; } @@ -3681,6 +3728,17 @@ done: return estr; } +es_str_t* +msgGetCEEVarNew(msg_t *pMsg, char *name) +{ + return msgGetJSONVarNew(pMsg, pMsg->json, name); +} + +es_str_t* +msgGetLocalVarNew(msg_t *pMsg, char *name) +{ + return msgGetJSONVarNew(pMsg, pMsg->localvars, name); +} /* Return an es_str_t for given message property. */ @@ -3809,16 +3867,22 @@ static uchar * jsonPathGetLeaf(uchar *name, int lenName) { int i; - for(i = lenName ; name[i] != '!' && i >= 0 ; --i) - /* just skip */; - if(name[i] == '!') + for(i = lenName ; i >= 0 ; --i) + if(i == 0) { + if(name[0] == '.' || name[0] == '!') + break; + } else { + if(name[i] == '!') + break; + } + if(name[i] == '!' || name[i] == '.') ++i; return name + i; } static rsRetVal -jsonPathFindNext(struct json_object *root, uchar **name, uchar *leaf, +jsonPathFindNext(struct json_object *root, uchar *namestart, uchar **name, uchar *leaf, struct json_object **found, int bCreate) { uchar namebuf[1024]; @@ -3827,9 +3891,9 @@ jsonPathFindNext(struct json_object *root, uchar **name, uchar *leaf, uchar *p = *name; DEFiRet; - if(*p == '!') + if(*p == '!' || (*name == namestart && *p == '.')) ++p; - for(i = 0 ; *p && *p != '!' && p != leaf && i < sizeof(namebuf)-1 ; ++i, ++p) + for(i = 0 ; *p && !(p == namestart && *p == '.') && *p != '!' && p != leaf && i < sizeof(namebuf)-1 ; ++i, ++p) namebuf[i] = *p; if(i > 0) { namebuf[i] = '\0'; @@ -3853,12 +3917,14 @@ finalize_it: } static rsRetVal -jsonPathFindParent(msg_t *pM, uchar *name, uchar *leaf, struct json_object **parent, int bCreate) +jsonPathFindParent(struct json_object *jroot, uchar *name, uchar *leaf, struct json_object **parent, int bCreate) { + uchar *namestart; DEFiRet; - *parent = pM->json; + namestart = name; + *parent = jroot; while(name < leaf-1) { - jsonPathFindNext(*parent, &name, leaf, parent, bCreate); + jsonPathFindNext(*parent, namestart, &name, leaf, parent, bCreate); } RETiRet; } @@ -3885,7 +3951,7 @@ DBGPRINTF("AAAA jsonMerge adds '%s'\n", it.key); /* find a JSON structure element (field or container doesn't matter). */ rsRetVal -jsonFind(msg_t *pM, es_str_t *propName, struct json_object **jsonres) +jsonFind(struct json_object *jroot, es_str_t *propName, struct json_object **jsonres) { uchar *name = NULL; uchar *leaf; @@ -3893,17 +3959,17 @@ jsonFind(msg_t *pM, es_str_t *propName, struct json_object **jsonres) struct json_object *field; DEFiRet; - if(pM->json == NULL) { + if(jroot == NULL) { field = NULL; goto finalize_it; } if(!es_strbufcmp(propName, (uchar*)"!", 1)) { - field = pM->json; + field = jroot; } else { name = (uchar*)es_str2cstr(propName, NULL); leaf = jsonPathGetLeaf(name, ustrlen(name)); - CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 0)); + CHKiRet(jsonPathFindParent(jroot, name, leaf, &parent, 0)); field = json_object_object_get(parent, (char*)leaf); } *jsonres = field; @@ -3913,8 +3979,8 @@ finalize_it: RETiRet; } -rsRetVal -msgAddJSON(msg_t *pM, uchar *name, struct json_object *json) +static rsRetVal +msgAddJSONObj(msg_t *pM, uchar *name, struct json_object *json, struct json_object **pjroot) { /* TODO: error checks! This is a quick&dirty PoC! */ struct json_object *parent, *leafnode; @@ -3922,24 +3988,24 @@ msgAddJSON(msg_t *pM, uchar *name, struct json_object *json) DEFiRet; MsgLock(pM); - if(name[0] == '!' && name[1] == '\0') { - if(pM->json == NULL) - pM->json = json; + if((name[0] == '!' || name[0] == '.') && name[1] == '\0') { + if(*pjroot == NULL) + *pjroot = json; else - CHKiRet(jsonMerge(pM->json, json)); + CHKiRet(jsonMerge(*pjroot, json)); } else { - if(pM->json == NULL) { + if(*pjroot == NULL) { /* now we need a root obj */ - pM->json = json_object_new_object(); + *pjroot = json_object_new_object(); } leaf = jsonPathGetLeaf(name, ustrlen(name)); - CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 1)); + CHKiRet(jsonPathFindParent(*pjroot, name, leaf, &parent, 1)); leafnode = json_object_object_get(parent, (char*)leaf); if(leafnode == NULL) { json_object_object_add(parent, (char*)leaf, json); } else { if(json_object_get_type(json) == json_type_object) { - CHKiRet(jsonMerge(pM->json, json)); + CHKiRet(jsonMerge(*pjroot, json)); } else { //dbgprintf("AAAA: leafnode already exists, type is %d, update with %d\n", (int)json_object_get_type(leafnode), (int)json_object_get_type(json)); /* TODO: improve the code below, however, the current @@ -3970,7 +4036,12 @@ finalize_it: } rsRetVal -msgDelJSON(msg_t *pM, uchar *name) +msgAddJSON(msg_t *pM, uchar *name, struct json_object *json) { + return msgAddJSONObj(pM, name, json, &pM->json); +} + +rsRetVal +msgDelJSONVar(msg_t *pM, struct json_object **jroot, uchar *name) { struct json_object *parent, *leafnode; uchar *leaf; @@ -3978,20 +4049,20 @@ msgDelJSON(msg_t *pM, uchar *name) dbgprintf("AAAA: unset variable '%s'\n", name); MsgLock(pM); - if(name[0] == '!' && name[1] == '\0') { + if((name[0] == '!' || name[0] == '.') && name[1] == '\0') { /* strange, but I think we should permit this. After all, * we trust rsyslog.conf to be written by the admin. */ DBGPRINTF("unsetting JSON root object\n"); - json_object_put(pM->json); - pM->json = NULL; + json_object_put(*jroot); + *jroot = NULL; } else { - if(pM->json == NULL) { + if(*jroot == NULL) { /* now we need a root obj */ - pM->json = json_object_new_object(); + *jroot = json_object_new_object(); } leaf = jsonPathGetLeaf(name, ustrlen(name)); - CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 1)); + CHKiRet(jsonPathFindParent(*jroot, name, leaf, &parent, 1)); leafnode = json_object_object_get(parent, (char*)leaf); DBGPRINTF("AAAA: unset found JSON value path '%s', " "leaf '%s', leafnode %p\n", name, leaf, leafnode); if(leafnode == NULL) { @@ -4010,6 +4081,12 @@ finalize_it: RETiRet; } +rsRetVal +msgDelJSON(msg_t *pM, uchar *name) +{ + return msgDelJSONVar(pM, &pM->json, name); +} + static struct json_object * jsonDeepCopy(struct json_object *src) { @@ -4079,7 +4156,11 @@ msgSetJSONFromVar(msg_t *pMsg, uchar *varname, struct var *v) v->datatype); ABORT_FINALIZE(RS_RET_ERR); } - msgAddJSON(pMsg, varname+1, json); + /* we always know strlen(varname) > 2 */ + if(varname[1] == '.') + msgAddJSONObj(pMsg, varname+1, json, &pMsg->localvars); + else + msgAddJSONObj(pMsg, varname+1, json, &pMsg->json); finalize_it: RETiRet; } |