diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 4ba32f2d9c..0dedd1c25f 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,5 +1,6 @@ ## Fixed Issues: #XXXX: Complex @contexts of subscriptions weren't persisted in mongodb + #1708: Reloaded hosted contexts were not persisted in mongo, only the context cache ## New Features: * Support for ... diff --git a/src/lib/logMsg/traceLevels.h b/src/lib/logMsg/traceLevels.h index 81c340c1c0..7cb05597da 100644 --- a/src/lib/logMsg/traceLevels.h +++ b/src/lib/logMsg/traceLevels.h @@ -134,6 +134,11 @@ typedef enum TraceLevels // LmtSubordinate = 140, + // + // Context Cache + // + LmtContextCachePersist = 150, // Persisting contexts in DB + // // Misc // diff --git a/src/lib/orionld/context/orionldContextFromUrl.cpp b/src/lib/orionld/context/orionldContextFromUrl.cpp index dda3c26323..d42d40b706 100644 --- a/src/lib/orionld/context/orionldContextFromUrl.cpp +++ b/src/lib/orionld/context/orionldContextFromUrl.cpp @@ -337,7 +337,7 @@ OrionldContext* orionldContextFromUrl(char* url, char* id) contextP->origin = OrionldContextDownloaded; contextP->usedAt = orionldState.requestTime; - orionldContextCachePersist(contextP); + orionldContextCachePersist(contextP, false); } // Remove the 'url' from the contextDownloadList and persist it to DB diff --git a/src/lib/orionld/contextCache/orionldContextCachePersist.cpp b/src/lib/orionld/contextCache/orionldContextCachePersist.cpp index 7ae1deb7e1..e50c01a329 100644 --- a/src/lib/orionld/contextCache/orionldContextCachePersist.cpp +++ b/src/lib/orionld/contextCache/orionldContextCachePersist.cpp @@ -54,7 +54,7 @@ extern "C" // "value": JSON Array|Object representation of the VALUE of the @context (i.e. NOT containing the @context member) // } // -void orionldContextCachePersist(OrionldContext* contextP) +void orionldContextCachePersist(OrionldContext* contextP, bool reload) { KjNode* contextObjP = kjObject(orionldState.kjsonP, NULL); KjNode* idP; @@ -98,5 +98,5 @@ void orionldContextCachePersist(OrionldContext* contextP) valueP->name = (char*) "value"; kjChildAdd(contextObjP, valueP); - mongocContextCachePersist(contextObjP); + mongocContextCachePersist(contextObjP, reload); } diff --git a/src/lib/orionld/contextCache/orionldContextCachePersist.h b/src/lib/orionld/contextCache/orionldContextCachePersist.h index 2a37916154..3c62ddcad6 100644 --- a/src/lib/orionld/contextCache/orionldContextCachePersist.h +++ b/src/lib/orionld/contextCache/orionldContextCachePersist.h @@ -33,6 +33,6 @@ // // orionldContextCachePersist - // -extern void orionldContextCachePersist(OrionldContext* contextP); +extern void orionldContextCachePersist(OrionldContext* contextP, bool reload); #endif // SRC_LIB_ORIONLD_CONTEXTCACHE_ORIONLDCONTEXTCACHEPERSIST_H_ diff --git a/src/lib/orionld/mhd/mhdConnectionTreat.cpp b/src/lib/orionld/mhd/mhdConnectionTreat.cpp index 4c8f4eec64..646470bf98 100644 --- a/src/lib/orionld/mhd/mhdConnectionTreat.cpp +++ b/src/lib/orionld/mhd/mhdConnectionTreat.cpp @@ -1241,7 +1241,7 @@ MHD_Result mhdConnectionTreat(void) { orionldState.contextP->origin = OrionldContextFromInline; orionldState.contextP->kind = OrionldContextHosted; - orionldContextCachePersist(orionldState.contextP); + orionldContextCachePersist(orionldState.contextP, false); } } diff --git a/src/lib/orionld/mongoc/mongocContextCachePersist.cpp b/src/lib/orionld/mongoc/mongocContextCachePersist.cpp index d0098c4124..098ba2ff91 100644 --- a/src/lib/orionld/mongoc/mongocContextCachePersist.cpp +++ b/src/lib/orionld/mongoc/mongocContextCachePersist.cpp @@ -27,6 +27,7 @@ extern "C" { #include "kjson/KjNode.h" // KjNode +#include "kjson/kjLookup.h" // kjLookup } #include "logMsg/logMsg.h" // LM_* @@ -43,23 +44,44 @@ extern "C" // // mongocContextCachePersist - // -void mongocContextCachePersist(KjNode* contextObject) +void mongocContextCachePersist(KjNode* contextObject, bool reload) { - bson_t bson; - - mongocKjTreeToBson(contextObject, &bson); + bson_error_t error; mongocConnectionGet(NULL, DbContexts); - sem_wait(&mongocContextsSem); - bson_error_t mcError; - bool r = mongoc_collection_insert_one(orionldState.mongoc.contextsP, &bson, NULL, NULL, &mcError); + // + // If the context is to be reloaded, it is REMOVED before inserted + // + if (reload == true) + { + KjNode* urlNodeP = kjLookup(contextObject, "url"); + char* url = (urlNodeP != NULL)? urlNodeP->value.s : NULL; + + if (url != NULL) + { + bson_t mongoFilter; + + bson_init(&mongoFilter); + bson_append_utf8(&mongoFilter, "url", 3, url, -1); + + // Remove the context + if (mongoc_collection_remove(orionldState.mongoc.contextsP, MONGOC_REMOVE_SINGLE_REMOVE, &mongoFilter, NULL, &error) == false) + LM_E(("Database Error (mongoc_collection_remove returned %d.%d:%s)", error.domain, error.code, error.message)); + bson_destroy(&mongoFilter); + } + } + + bson_t bson; + mongocKjTreeToBson(contextObject, &bson); + + bool r = mongoc_collection_insert_one(orionldState.mongoc.contextsP, &bson, NULL, NULL, &error); sem_post(&mongocContextsSem); if (r == false) - LM_E(("Database Error (persisting context: %s)", mcError.message)); + LM_E(("Database Error (persisting context: %s)", error.message)); bson_destroy(&bson); diff --git a/src/lib/orionld/mongoc/mongocContextCachePersist.h b/src/lib/orionld/mongoc/mongocContextCachePersist.h index 58b276a35b..a267c17883 100644 --- a/src/lib/orionld/mongoc/mongocContextCachePersist.h +++ b/src/lib/orionld/mongoc/mongocContextCachePersist.h @@ -37,6 +37,6 @@ extern "C" // // mongocContextCachePersist - // -extern void mongocContextCachePersist(KjNode* contextObject); +extern void mongocContextCachePersist(KjNode* contextObject, bool reload); #endif // SRC_LIB_ORIONLD_MONGOC_MONGOCCONTEXTCACHEPERSIST_H_ diff --git a/src/lib/orionld/serviceRoutines/orionldDeleteContext.cpp b/src/lib/orionld/serviceRoutines/orionldDeleteContext.cpp index a6646a523a..8a0d9e158b 100644 --- a/src/lib/orionld/serviceRoutines/orionldDeleteContext.cpp +++ b/src/lib/orionld/serviceRoutines/orionldDeleteContext.cpp @@ -38,6 +38,7 @@ extern "C" #include "orionld/contextCache/orionldContextCacheLookup.h" // orionldContextCacheLookup #include "orionld/contextCache/orionldContextCacheDelete.h" // orionldContextCacheDelete #include "orionld/contextCache/orionldContextCacheInsert.h" // orionldContextCacheInsert +#include "orionld/contextCache/orionldContextCachePersist.h" // orionldContextCachePersist #include "orionld/serviceRoutines/orionldDeleteContext.h" // Own Interface @@ -111,6 +112,9 @@ bool orionldDeleteContext(void) // Free the kj tree of the now obsolete old context kjFree(oldContextP->tree); + + // Update mongo with the new context + orionldContextCachePersist(contextP, true); } else { diff --git a/src/lib/orionld/serviceRoutines/orionldPostContexts.cpp b/src/lib/orionld/serviceRoutines/orionldPostContexts.cpp index b58f4381d6..ac1a4ad140 100644 --- a/src/lib/orionld/serviceRoutines/orionldPostContexts.cpp +++ b/src/lib/orionld/serviceRoutines/orionldPostContexts.cpp @@ -88,7 +88,7 @@ bool orionldPostContexts(void) httpHeaderLocationAdd(contextP->url, NULL, NULL); - orionldContextCachePersist(contextP); + orionldContextCachePersist(contextP, false); orionldState.httpStatusCode = 201; return true; diff --git a/test/functionalTest/cases/0000_ngsild/ngsild_dynamic_context.test b/test/functionalTest/cases/0000_ngsild/ngsild_dynamic_context.test index d54f21f50f..5a0faaf87c 100644 --- a/test/functionalTest/cases/0000_ngsild/ngsild_dynamic_context.test +++ b/test/functionalTest/cases/0000_ngsild/ngsild_dynamic_context.test @@ -375,6 +375,13 @@ MongoDB server version: REGEX(.*) "unit" : "%", "en" : "Humidity", "el" : "Υγρασία" + }, + "pressure" : { + "@id" : "myAttributes:pressure", + "@type" : "xsd:integer", + "unit" : "bar", + "en" : "Pressure", + "el" : "Υγρασία" } } }