diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index e8e4f037c2..9845fc4305 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -2,6 +2,7 @@ * #1535: Ignore Subscription::q when matching subscriptions for deletion of an entity * #1542: Array Reduction (arrays of one single element are "flattened" to that very element) * SOF: https://stackoverflow.com/questions/77911109/fiware-to-payload-too-large + * #1551: format=simplified for distribute GET /entities gave Normalized for entities from other brokers ## New Features: * Support for attributes of type VocabularyProperty @@ -12,3 +13,7 @@ ## Notes * TRoE is still not prepared for attributes of type Vocab/Json/Language, so, attributes of those types are not stored in the historical database + * Modified the @context hosting feature to be according to API spec + * Support for URI param 'kind' for GET Contexts + * Improved counters for GET Context/Contexts + * API spec compliance for GET Context/Contexts diff --git a/src/app/orionld/orionld.cpp b/src/app/orionld/orionld.cpp index 155ab6d330..abf34aaf81 100644 --- a/src/app/orionld/orionld.cpp +++ b/src/app/orionld/orionld.cpp @@ -243,6 +243,7 @@ bool debugCurl = false; uint32_t cSubCounters; char coreContextVersion[64]; bool triggerOperation = false; +bool noprom = false; @@ -335,6 +336,7 @@ bool triggerOperation = false; #define DEBUG_CURL_DESC "turn on debugging of libcurl - to the broker's logfile" #define CSUBCOUNTERS_DESC "number of subscription counter updates before flush from sub-cache to DB (0: never, 1: always)" #define CORE_CONTEXT_DESC "core context version (v1.0|v1.3|v1.4|v1.5|v1.6|v1.7) - v1.6 is default" +#define NO_PROM_DESC "run without Prometheus metrics" @@ -438,6 +440,7 @@ PaArgument paArgs[] = { "-lmtmp", &lmtmp, "TMP_TRACES", PaBool, PaHid, true, false, true, TMPTRACES_DESC }, { "-debugCurl", &debugCurl, "DEBUG_CURL", PaBool, PaHid, false, false, true, DEBUG_CURL_DESC }, { "-lmtmp", &lmtmp, "TMP_TRACES", PaBool, PaHid, true, false, true, TMPTRACES_DESC }, + { "-noprom", &noprom, "NO_PROM", PaBool, PaHid, false, false, true, NO_PROM_DESC }, PA_END_OF_ARGS }; @@ -1130,7 +1133,9 @@ int main(int argC, char* argV[]) if (fg == false) daemonize(); - if (promInit(8000) != 0) + if (noprom == true) + LM_W(("Running without Prometheus metrics")); + else if (promInit(8000) != 0) LM_W(("Error initializing Prometheus Metrics library")); IpVersion ipVersion = IPDUAL; diff --git a/src/lib/logMsg/traceLevels.h b/src/lib/logMsg/traceLevels.h index 72cf8cee67..6d6542199c 100644 --- a/src/lib/logMsg/traceLevels.h +++ b/src/lib/logMsg/traceLevels.h @@ -101,6 +101,7 @@ typedef enum TraceLevels LmtContexts = 100, // Contexts LmtContextTree, // Context Tree LmtContextCache, // Context Cache + LmtContextCacheStats, // Context Cache Statistics LmtContextDownload, // Context Download LmtCoreContext, // Core Context @@ -142,6 +143,7 @@ typedef enum TraceLevels LmtDateTime, // DateTime (ISO8601) conversion LmtMimeType, // MimeType LmtArrayReduction, // Arrays of only one item are reduced to the item + LmtFormat, // Normalized, Concise, Simplified // // Legacy diff --git a/src/lib/orionld/apiModel/ntocAttribute.cpp b/src/lib/orionld/apiModel/ntocAttribute.cpp index 33761db2dd..7d08db5792 100644 --- a/src/lib/orionld/apiModel/ntocAttribute.cpp +++ b/src/lib/orionld/apiModel/ntocAttribute.cpp @@ -57,6 +57,8 @@ void ntocAttribute(KjNode* attrP, const char* lang, bool sysAttrs) return; } + kjTreeLog(attrP, "attribute to convert from Normalized to Concise", LmtFormat); + // 1. Remove the sysAttrs, if so requested if (sysAttrs == false) kjSysAttrsRemove(attrP, 0); diff --git a/src/lib/orionld/common/orionldState.cpp b/src/lib/orionld/common/orionldState.cpp index 68d12ed049..1aa16c5006 100644 --- a/src/lib/orionld/common/orionldState.cpp +++ b/src/lib/orionld/common/orionldState.cpp @@ -118,6 +118,7 @@ bool entityMapsEnabled = false; mongoc_uri_t* mongocUri; mongoc_client_pool_t* mongocPool; sem_t mongocContextsSem; +sem_t mongocConnectionSem; char mongocServerVersion[128]; char postgresServerVersion[128]; diff --git a/src/lib/orionld/common/orionldState.h b/src/lib/orionld/common/orionldState.h index 34578b3094..82717be144 100644 --- a/src/lib/orionld/common/orionldState.h +++ b/src/lib/orionld/common/orionldState.h @@ -170,6 +170,8 @@ typedef struct OrionldUriParams bool entityMap; char* format; + OrionldContextKind kind; + double observedAtAsDouble; uint64_t mask; } OrionldUriParams; @@ -639,6 +641,7 @@ extern mongoc_collection_t* mongoRegistrationsCollectionP; // Deprecated extern mongoc_uri_t* mongocUri; extern mongoc_client_pool_t* mongocPool; extern sem_t mongocContextsSem; +extern sem_t mongocConnectionSem; extern char mongocServerVersion[128]; extern char postgresServerVersion[128]; diff --git a/src/lib/orionld/context/CMakeLists.txt b/src/lib/orionld/context/CMakeLists.txt index 6eb25ee032..8995d7b351 100644 --- a/src/lib/orionld/context/CMakeLists.txt +++ b/src/lib/orionld/context/CMakeLists.txt @@ -42,7 +42,6 @@ SET (SOURCES orionldContextItemAlreadyExpanded.cpp orionldAttributeExpand.cpp orionldSubAttributeExpand.cpp - orionldContextOriginName.cpp orionldEntityExpand.cpp orionldEntityCompact.cpp ) diff --git a/src/lib/orionld/context/orionldContextCreate.cpp b/src/lib/orionld/context/orionldContextCreate.cpp index 8f322a0e7e..4ea978d21d 100644 --- a/src/lib/orionld/context/orionldContextCreate.cpp +++ b/src/lib/orionld/context/orionldContextCreate.cpp @@ -37,25 +37,6 @@ extern "C" -// ----------------------------------------------------------------------------- -// -// orionldOriginFromString - FIXME: move to its own module -// -OrionldContextOrigin orionldOriginFromString(const char* s) -{ - if (strcmp(s, "UnknownOrigin") == 0) return OrionldContextUnknownOrigin; - else if (strcmp(s, "Inline") == 0) return OrionldContextFromInline; - else if (strcmp(s, "Downloaded") == 0) return OrionldContextDownloaded; - else if (strcmp(s, "FileCached") == 0) return OrionldContextFileCached; - else if (strcmp(s, "ForNotifications") == 0) return OrionldContextForNotifications; - else if (strcmp(s, "ForForwarding") == 0) return OrionldContextForForwarding; - else if (strcmp(s, "UserCreated") == 0) return OrionldContextUserCreated; - - return OrionldContextUnknownOrigin; -} - - - // ----------------------------------------------------------------------------- // // orionldContextCreate - @@ -72,6 +53,7 @@ OrionldContext* orionldContextCreate(const char* url, OrionldContextOrigin origi LM_X(1, ("out of memory - trying to allocate a OrionldContext of %d bytes", sizeof(OrionldContext))); contextP->origin = origin; + contextP->kind = OrionldContextCached; // By defaukt. Changed later to Hosted/Implicit if needed contextP->parent = NULL; // NULL URL means NOT to be saved - will live just inside the request-thread @@ -95,7 +77,7 @@ OrionldContext* orionldContextCreate(const char* url, OrionldContextOrigin origi } contextP->keyValues = keyValues; - contextP->lookups = 0; + contextP->lookups = 1; return contextP; } diff --git a/src/lib/orionld/context/orionldContextFromBuffer.cpp b/src/lib/orionld/context/orionldContextFromBuffer.cpp index a0b9885180..17014a8f86 100644 --- a/src/lib/orionld/context/orionldContextFromBuffer.cpp +++ b/src/lib/orionld/context/orionldContextFromBuffer.cpp @@ -67,7 +67,7 @@ OrionldContext* orionldContextFromBuffer(char* url, OrionldContextOrigin origin, KjNode* contextNodeP = kjLookup(tree, "@context"); if (contextNodeP == NULL) { - orionldError(OrionldBadRequestData, "Invalid context - @context field missing", url, 400); + orionldError(OrionldInvalidRequest, "Invalid context - @context field missing", url, 400); return NULL; } diff --git a/src/lib/orionld/context/orionldContextFromUrl.cpp b/src/lib/orionld/context/orionldContextFromUrl.cpp index abcf4fda18..0d00aaae70 100644 --- a/src/lib/orionld/context/orionldContextFromUrl.cpp +++ b/src/lib/orionld/context/orionldContextFromUrl.cpp @@ -251,6 +251,11 @@ OrionldContext* orionldContextFromUrl(char* url, char* id) if (contextP != NULL) { + contextP->usedAt = orionldState.requestTime; + + contextP->lookups += 1; + LM_T(LmtContextCacheStats, ("Context '%s': %d lookups", url, contextP->lookups)); + LM_T(LmtContextDownload, ("Found already downloaded URL '%s'", url)); return contextP; } diff --git a/src/lib/orionld/context/orionldContextItemAliasLookup.cpp b/src/lib/orionld/context/orionldContextItemAliasLookup.cpp index 13b8e3b0ff..aba5daa37c 100644 --- a/src/lib/orionld/context/orionldContextItemAliasLookup.cpp +++ b/src/lib/orionld/context/orionldContextItemAliasLookup.cpp @@ -59,10 +59,15 @@ char* orionldContextItemAliasLookup if (contextItemPP != NULL) *contextItemPP = NULL; + if (contextP == NULL) + contextP = orionldCoreContextP; // 1. Is it the default URL? if (strncmp(longName, orionldDefaultUrl, orionldDefaultUrlLen) == 0) + { + orionldCoreContextP->compactions += 1; return (char*) &longName[orionldDefaultUrlLen]; + } // 2. Found in Core Context? contextItemP = orionldContextItemValueLookup(orionldCoreContextP, longName); @@ -91,5 +96,6 @@ char* orionldContextItemAliasLookup *contextItemPP = contextItemP; // Return the short name + contextP->compactions += 1; return contextItemP->name; } diff --git a/src/lib/orionld/context/orionldContextItemExpand.cpp b/src/lib/orionld/context/orionldContextItemExpand.cpp index b353d22477..00c383a71f 100644 --- a/src/lib/orionld/context/orionldContextItemExpand.cpp +++ b/src/lib/orionld/context/orionldContextItemExpand.cpp @@ -96,6 +96,8 @@ char* orionldContextItemExpand if (contextItemPP != NULL) *contextItemPP = NULL; + orionldCoreContextP->expansions += 1; // Really, @vocab expansions of the core context + return longName; } @@ -106,5 +108,7 @@ char* orionldContextItemExpand if (contextItemPP != NULL) *contextItemPP = contextItemP; + contextP->expansions += 1; // Really, @vocab expansions of the core context + return contextItemP->id; } diff --git a/src/lib/orionld/context/orionldContextItemLookup.cpp b/src/lib/orionld/context/orionldContextItemLookup.cpp index 45d15ca868..ada8f9762d 100644 --- a/src/lib/orionld/context/orionldContextItemLookup.cpp +++ b/src/lib/orionld/context/orionldContextItemLookup.cpp @@ -62,12 +62,17 @@ OrionldContextItem* orionldContextItemLookup(OrionldContext* contextP, const cha } } - if (valueMayBeCompactedP != NULL) + if (itemP != NULL) { - if ((itemP->type != NULL) && (strcmp(itemP->type, "@vocab") == 0)) - *valueMayBeCompactedP = true; - else - *valueMayBeCompactedP = false; + contextP->expansions += 1; + + if (valueMayBeCompactedP != NULL) + { + if ((itemP->type != NULL) && (strcmp(itemP->type, "@vocab") == 0)) + *valueMayBeCompactedP = true; + else + *valueMayBeCompactedP = false; + } } return itemP; diff --git a/src/lib/orionld/contextCache/orionldContextCacheGet.cpp b/src/lib/orionld/contextCache/orionldContextCacheGet.cpp index be492d1abd..f9bad90565 100644 --- a/src/lib/orionld/contextCache/orionldContextCacheGet.cpp +++ b/src/lib/orionld/contextCache/orionldContextCacheGet.cpp @@ -32,12 +32,11 @@ extern "C" #include "logMsg/logMsg.h" // LM_* #include "logMsg/traceLevels.h" // Lmt* -#include "orionld/types/OrionldContext.h" // OrionldContext +#include "orionld/types/OrionldContext.h" // OrionldContext, orionldOriginToString, OrionldContextKind #include "orionld/types/OrionldContextItem.h" // OrionldContextItem #include "orionld/common/orionldState.h" // orionldState #include "orionld/common/numberToDate.h" // numberToDate #include "orionld/context/orionldCoreContext.h" // orionldCoreContextP -#include "orionld/context/orionldContextOriginName.h" // orionldContextOriginName #include "orionld/contextCache/orionldContextCache.h" // Context Cache Internals #include "orionld/contextCache/orionldContextCacheGet.h" // Own interface @@ -45,101 +44,136 @@ extern "C" // ----------------------------------------------------------------------------- // -// orionldContextCacheGet - +// orionldContextWithDetails - FIXME: rename and put in separate module // -KjNode* orionldContextCacheGet(KjNode* arrayP, bool details) +KjNode* orionldContextWithDetails(OrionldContext* contextP) { - for (int ix = 0; ix < orionldContextCacheSlotIx; ix++) + char createdAtString[64]; + char lastUseString[64]; + + numberToDate(contextP->createdAt, createdAtString, sizeof(createdAtString)); + numberToDate(contextP->usedAt, lastUseString, sizeof(lastUseString)); + + // + // Details, according to spec: + // URL + // localId + // kind (Hosted, Cached, ImplicitlyCreated) + // createdAt + // lastUsage (optional) + // numberOfHits (optional) + // extraInfo (object with broker specific fields, like "type", "origin") + // + + KjNode* contextObjP = kjObject(orionldState.kjsonP, NULL); + + KjNode* urlStringP = kjString(orionldState.kjsonP, "URL", contextP->url); + KjNode* idStringP = kjString(orionldState.kjsonP, "localId", (contextP->id == NULL)? "None" : contextP->id); + KjNode* kindP = kjString(orionldState.kjsonP, "kind", orionldKindToString(contextP->kind)); + KjNode* createdAtP = kjString(orionldState.kjsonP, "createdAt", createdAtString); + KjNode* extraInfoP = kjObject(orionldState.kjsonP, "extraInfo"); + KjNode* typeStringP = kjString(orionldState.kjsonP, "type", (contextP->keyValues == true)? "hash-table" : "array"); + KjNode* originP = kjString(orionldState.kjsonP, "origin", orionldOriginToString(contextP->origin)); + KjNode* compactionsP = kjInteger(orionldState.kjsonP, "compactions", contextP->compactions); + KjNode* expansionsP = kjInteger(orionldState.kjsonP, "expansions", contextP->expansions); + + kjChildAdd(contextObjP, urlStringP); + kjChildAdd(contextObjP, idStringP); + kjChildAdd(contextObjP, kindP); + kjChildAdd(contextObjP, createdAtP); + kjChildAdd(contextObjP, extraInfoP); + + + if (contextP != orionldCoreContextP) { - OrionldContext* contextP = orionldContextCacheArray[ix]; + KjNode* usedAtP = kjString(orionldState.kjsonP, "lastUsage", lastUseString); + KjNode* lookupsP = kjInteger(orionldState.kjsonP, "numberOfHits", contextP->lookups); + kjChildAdd(contextObjP, usedAtP); + kjChildAdd(contextObjP, lookupsP); + } - if (contextP == NULL) - continue; + kjChildAdd(extraInfoP, typeStringP); + kjChildAdd(extraInfoP, originP); + kjChildAdd(extraInfoP, compactionsP); + kjChildAdd(extraInfoP, expansionsP); - if (details == true) + if (contextP->parent != NULL) + { + KjNode* parentP = kjString(orionldState.kjsonP, "parent", contextP->parent); + kjChildAdd(extraInfoP, parentP); + } + + if (contextP->keyValues) + { + // Show a maximum of 5 items from the hash-table + KjNode* hashTableObjectP = kjObject(orionldState.kjsonP, "hash-table"); + KHashTable* htP = contextP->context.hash.nameHashTable; + int noOfItems = 0; + + for (int slot = 0; slot < ORIONLD_CONTEXT_CACHE_HASH_ARRAY_SIZE; ++slot) { - char createdAtString[64]; - char lastUseString[64]; - - numberToDate(contextP->createdAt, createdAtString, sizeof(createdAtString)); - numberToDate(contextP->usedAt, lastUseString, sizeof(lastUseString)); - - KjNode* contextObjP = kjObject(orionldState.kjsonP, NULL); - KjNode* urlStringP = kjString(orionldState.kjsonP, "url", contextP->url); - KjNode* idStringP = kjString(orionldState.kjsonP, "id", (contextP->id == NULL)? "None" : contextP->id); - KjNode* typeStringP = kjString(orionldState.kjsonP, "type", contextP->keyValues? "hash-table" : "array"); - KjNode* originP = kjString(orionldState.kjsonP, "origin", orionldContextOriginName(contextP->origin)); - KjNode* createdAtP = kjString(orionldState.kjsonP, "createdAt", createdAtString); - - kjChildAdd(contextObjP, urlStringP); - kjChildAdd(contextObjP, idStringP); - kjChildAdd(contextObjP, typeStringP); - kjChildAdd(contextObjP, originP); - kjChildAdd(contextObjP, createdAtP); - - if (contextP != orionldCoreContextP) + KHashListItem* itemP = htP->array[slot]; + + while (itemP != 0) { - KjNode* usedAtP = kjString(orionldState.kjsonP, "lastUse", lastUseString); - KjNode* lookupsP = kjInteger(orionldState.kjsonP, "lookups", contextP->lookups); + OrionldContextItem* hashItemP = (OrionldContextItem*) itemP->data; + KjNode* hashItemStringP = kjString(orionldState.kjsonP, hashItemP->name, hashItemP->id); - kjChildAdd(contextObjP, usedAtP); - kjChildAdd(contextObjP, lookupsP); - } + kjChildAdd(hashTableObjectP, hashItemStringP); - if (contextP->parent != NULL) - { - KjNode* parentP = kjString(orionldState.kjsonP, "parent", contextP->parent); + ++noOfItems; + if (noOfItems >= 5) + break; - kjChildAdd(contextObjP, parentP); + itemP = itemP->next; } - if (contextP->keyValues) - { - // Show a maximum of 5 items from the hash-table - KjNode* hashTableObjectP = kjObject(orionldState.kjsonP, "hash-table"); - KHashTable* htP = contextP->context.hash.nameHashTable; - int noOfItems = 0; + if (noOfItems >= 5) + break; + } - for (int slot = 0; slot < ORIONLD_CONTEXT_CACHE_HASH_ARRAY_SIZE; ++slot) - { - KHashListItem* itemP = htP->array[slot]; + kjChildAdd(extraInfoP, hashTableObjectP); + } + else + { + // + // If ARRAY - show all the URLs in the array + // + KjNode* urlArrayP = kjArray(orionldState.kjsonP, "URLs"); - while (itemP != 0) - { - OrionldContextItem* hashItemP = (OrionldContextItem*) itemP->data; - KjNode* hashItemStringP = kjString(orionldState.kjsonP, hashItemP->name, hashItemP->id); + for (int aIx = 0; aIx < contextP->context.array.items; ++aIx) + { + KjNode* urlStringP = kjString(orionldState.kjsonP, NULL, contextP->context.array.vector[aIx]->url); - kjChildAdd(hashTableObjectP, hashItemStringP); + kjChildAdd(urlArrayP, urlStringP); + } + kjChildAdd(extraInfoP, urlArrayP); + } - ++noOfItems; - if (noOfItems >= 5) - break; + return contextObjP; +} - itemP = itemP->next; - } - if (noOfItems >= 5) - break; - } - kjChildAdd(contextObjP, hashTableObjectP); - } - else - { - // - // If ARRAY - show all the URLs in the array - // - KjNode* urlArrayP = kjArray(orionldState.kjsonP, "URLs"); - - for (int aIx = 0; aIx < contextP->context.array.items; ++aIx) - { - KjNode* urlStringP = kjString(orionldState.kjsonP, NULL, contextP->context.array.vector[aIx]->url); - - kjChildAdd(urlArrayP, urlStringP); - } - kjChildAdd(contextObjP, urlArrayP); - } +// ----------------------------------------------------------------------------- +// +// orionldContextCacheGet - +// +KjNode* orionldContextCacheGet(KjNode* arrayP, bool details, OrionldContextKind kind) +{ + for (int ix = 0; ix < orionldContextCacheSlotIx; ix++) + { + OrionldContext* contextP = orionldContextCacheArray[ix]; + + if (contextP == NULL) + continue; + if ((kind != OrionldContextUnknownKind) && (contextP->kind != kind)) + continue; + + if (details == true) + { + KjNode* contextObjP = orionldContextWithDetails(contextP); kjChildAdd(arrayP, contextObjP); } else diff --git a/src/lib/orionld/contextCache/orionldContextCacheGet.h b/src/lib/orionld/contextCache/orionldContextCacheGet.h index 05ee192240..0cdf55b346 100644 --- a/src/lib/orionld/contextCache/orionldContextCacheGet.h +++ b/src/lib/orionld/contextCache/orionldContextCacheGet.h @@ -30,12 +30,14 @@ extern "C" #include "kjson/KjNode.h" // KjNode } +#include "orionld/types/OrionldContext.h" // OrionldContextKind + // ----------------------------------------------------------------------------- // // orionldContextCacheGet - // -extern KjNode* orionldContextCacheGet(KjNode* arrayP, bool details); +extern KjNode* orionldContextCacheGet(KjNode* arrayP, bool details, OrionldContextKind kind); #endif // SRC_LIB_ORIONLD_CONTEXTCACHE_ORIONLDCONTEXTCACHEGET_H_ diff --git a/src/lib/orionld/contextCache/orionldContextCacheLookup.cpp b/src/lib/orionld/contextCache/orionldContextCacheLookup.cpp index 5afce5dd7f..7edbf5a4b4 100644 --- a/src/lib/orionld/contextCache/orionldContextCacheLookup.cpp +++ b/src/lib/orionld/contextCache/orionldContextCacheLookup.cpp @@ -49,16 +49,11 @@ OrionldContext* orionldContextCacheLookup(const char* url) if (strcmp(url, orionldContextCache[ix]->url) == 0) contextP = orionldContextCache[ix]; - - if ((orionldContextCache[ix]->id != NULL) && (strcmp(url, orionldContextCache[ix]->id) == 0)) + else if ((orionldContextCache[ix]->id != NULL) && (strcmp(url, orionldContextCache[ix]->id) == 0)) contextP = orionldContextCache[ix]; if (contextP != NULL) - { - contextP->usedAt = orionldState.requestTime; - contextP->lookups += 1; return contextP; - } } return NULL; diff --git a/src/lib/orionld/contextCache/orionldContextCachePersist.cpp b/src/lib/orionld/contextCache/orionldContextCachePersist.cpp index 0e778a58a1..7ae1deb7e1 100644 --- a/src/lib/orionld/contextCache/orionldContextCachePersist.cpp +++ b/src/lib/orionld/contextCache/orionldContextCachePersist.cpp @@ -31,11 +31,10 @@ extern "C" #include "logMsg/logMsg.h" // LM_* #include "logMsg/traceLevels.h" // Lmt* -#include "orionld/types/OrionldContext.h" // OrionldContext +#include "orionld/types/OrionldContext.h" // OrionldContext, orionldOriginToString, orionldKindToString #include "orionld/common/orionldState.h" // orionldState #include "orionld/common/uuidGenerate.h" // uuidGenerate #include "orionld/context/orionldContextUrlGenerate.h" // orionldContextUrlGenerate -#include "orionld/context/orionldContextOriginName.h" // orionldContextOriginName #include "orionld/mongoc/mongocContextCachePersist.h" // mongocContextCachePersist - FIXME: Use dbContextCachePersist #include "orionld/contextCache/orionldContextCachePersist.h" // Own interface @@ -61,7 +60,8 @@ void orionldContextCachePersist(OrionldContext* contextP) KjNode* idP; KjNode* urlP = kjString(orionldState.kjsonP, "url", contextP->url); KjNode* parentP; - KjNode* originP = kjString(orionldState.kjsonP, "origin", orionldContextOriginName(contextP->origin)); + KjNode* originP = kjString(orionldState.kjsonP, "origin", orionldOriginToString(contextP->origin)); + KjNode* kindP = kjString(orionldState.kjsonP, "kind", orionldKindToString(contextP->kind)); KjNode* createdAtP = kjFloat(orionldState.kjsonP, "createdAt", orionldState.requestTime); // FIXME: make sure it's not overwritten if already exists KjNode* valueP = contextP->tree; @@ -88,6 +88,9 @@ void orionldContextCachePersist(OrionldContext* contextP) // Field: "origin" kjChildAdd(contextObjP, originP); + // Field: "kind" + kjChildAdd(contextObjP, kindP); + // Field: "createdAt" kjChildAdd(contextObjP, createdAtP); diff --git a/src/lib/orionld/dbModel/dbModelToApiSubscription.cpp b/src/lib/orionld/dbModel/dbModelToApiSubscription.cpp index dee719efc9..4fa86cf462 100644 --- a/src/lib/orionld/dbModel/dbModelToApiSubscription.cpp +++ b/src/lib/orionld/dbModel/dbModelToApiSubscription.cpp @@ -548,7 +548,6 @@ KjNode* dbModelToApiSubscription } - // // origin // diff --git a/src/lib/orionld/distOp/distOpResponseMergeIntoEntityArray.cpp b/src/lib/orionld/distOp/distOpResponseMergeIntoEntityArray.cpp index 6a3732a800..b2ba46f8c8 100644 --- a/src/lib/orionld/distOp/distOpResponseMergeIntoEntityArray.cpp +++ b/src/lib/orionld/distOp/distOpResponseMergeIntoEntityArray.cpp @@ -34,6 +34,8 @@ extern "C" #include "orionld/types/DistOp.h" // DistOp #include "orionld/common/orionldState.h" // orionldState, entityMaps #include "orionld/kjTree/kjEntityIdLookupInEntityArray.h" // kjEntityIdLookupInEntityArray +#include "orionld/kjTree/kjEntityNormalizedToConcise.h" // kjEntityNormalizedToConcise +#include "orionld/kjTree/kjEntityNormalizedToSimplified.h" // kjEntityNormalizedToSimplified #include "orionld/distOp/distOpEntityMerge.h" // distOpEntityMerge #include "orionld/distOp/distOpResponseMergeIntoEntityArray.h" // Own interface @@ -57,6 +59,7 @@ void distOpResponseMergeIntoEntityArray(DistOp* distOpP, KjNode* entityArray) KjNode* entityP = distOpP->responseBody->value.firstChildP; KjNode* next; + while (entityP != NULL) { next = entityP->next; @@ -91,4 +94,3 @@ void distOpResponseMergeIntoEntityArray(DistOp* distOpP, KjNode* entityArray) } } } - diff --git a/src/lib/orionld/mhd/mhdConnectionInit.cpp b/src/lib/orionld/mhd/mhdConnectionInit.cpp index c8a71badfc..993673b2e0 100644 --- a/src/lib/orionld/mhd/mhdConnectionInit.cpp +++ b/src/lib/orionld/mhd/mhdConnectionInit.cpp @@ -852,6 +852,18 @@ MHD_Result orionldUriArgumentGet(void* cbDataP, MHD_ValueKind kind, const char* orionldState.uriParams.subscriptionId = (char*) value; orionldState.uriParams.mask |= ORIONLD_URIPARAM_SUBSCRIPTION_ID; } + else if (strcmp(key, "kind") == 0) + { + orionldState.uriParams.kind = orionldKindFromString(value); + + if (orionldState.uriParams.kind == OrionldContextUnknownKind) + { + orionldError(OrionldBadRequestData, "Invalid value for uri parameter /kind/", value, 400); + return MHD_YES; + } + + orionldState.uriParams.mask |= ORIONLD_URIPARAM_KIND; + } else if (strcmp(key, "location") == 0) { if (strcmp(value, "true") == 0) diff --git a/src/lib/orionld/mongoc/mongocAttributeDelete.cpp b/src/lib/orionld/mongoc/mongocAttributeDelete.cpp index 71e8306ef9..755f39cecd 100644 --- a/src/lib/orionld/mongoc/mongocAttributeDelete.cpp +++ b/src/lib/orionld/mongoc/mongocAttributeDelete.cpp @@ -54,10 +54,7 @@ extern "C" // bool mongocAttributeDelete(const char* entityId, const char* attrName) { - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); bson_t selector; bson_init(&selector); diff --git a/src/lib/orionld/mongoc/mongocAttributeReplace.cpp b/src/lib/orionld/mongoc/mongocAttributeReplace.cpp index 6188a9cfc4..a162f82699 100644 --- a/src/lib/orionld/mongoc/mongocAttributeReplace.cpp +++ b/src/lib/orionld/mongoc/mongocAttributeReplace.cpp @@ -47,10 +47,7 @@ extern "C" // bool mongocAttributeReplace(const char* entityId, KjNode* dbAttrP, char** detailP) { - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); bson_t selector; bson_init(&selector); diff --git a/src/lib/orionld/mongoc/mongocAttributesAdd.cpp b/src/lib/orionld/mongoc/mongocAttributesAdd.cpp index 73e8ff49a0..f88c4ed9f2 100644 --- a/src/lib/orionld/mongoc/mongocAttributesAdd.cpp +++ b/src/lib/orionld/mongoc/mongocAttributesAdd.cpp @@ -60,10 +60,7 @@ bool mongocAttributesAdd bool singleAttribute ) { - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); bson_t selector; bson_init(&selector); diff --git a/src/lib/orionld/mongoc/mongocConnectionGet.cpp b/src/lib/orionld/mongoc/mongocConnectionGet.cpp index 6a24459e7f..8b42f6d425 100644 --- a/src/lib/orionld/mongoc/mongocConnectionGet.cpp +++ b/src/lib/orionld/mongoc/mongocConnectionGet.cpp @@ -23,9 +23,11 @@ * Author: Ken Zangelin */ #include // NULL +#include // sem_wait, sem_post #include // mongoc driver #include "orionld/common/orionldState.h" // orionldState, mongocPool +#include "orionld/types/OrionldTenant.h" // OrionldTenant #include "orionld/mongoc/mongocConnectionGet.h" // Own interface @@ -34,8 +36,36 @@ // // mongocConnectionGet - // -void mongocConnectionGet(void) +void mongocConnectionGet(OrionldTenant* tenantP, DbCollection dbCollection) { + sem_wait(&mongocConnectionSem); + if (orionldState.mongoc.client == NULL) orionldState.mongoc.client = mongoc_client_pool_pop(mongocPool); + + if ((dbCollection & DbEntities) == DbEntities) + { + if (orionldState.mongoc.entitiesP == NULL) + orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, tenantP->mongoDbName, "entities"); + } + + if ((dbCollection & DbSubscriptions) == DbSubscriptions) + { + if (orionldState.mongoc.subscriptionsP == NULL) + orionldState.mongoc.subscriptionsP = mongoc_client_get_collection(orionldState.mongoc.client, tenantP->mongoDbName, "csubs"); + } + + if ((dbCollection & DbRegistrations) == DbRegistrations) + { + if (orionldState.mongoc.registrationsP == NULL) + orionldState.mongoc.registrationsP = mongoc_client_get_collection(orionldState.mongoc.client, tenantP->mongoDbName, "registrations"); + } + + if ((dbCollection & DbContexts) == DbContexts) + { + if (orionldState.mongoc.contextsP == NULL) + orionldState.mongoc.contextsP = mongoc_client_get_collection(orionldState.mongoc.client, "orionld", "contexts"); + } + + sem_post(&mongocConnectionSem); } diff --git a/src/lib/orionld/mongoc/mongocConnectionGet.h b/src/lib/orionld/mongoc/mongocConnectionGet.h index 6a08fba1c1..13801e3f55 100644 --- a/src/lib/orionld/mongoc/mongocConnectionGet.h +++ b/src/lib/orionld/mongoc/mongocConnectionGet.h @@ -25,6 +25,22 @@ * * Author: Ken Zangelin */ +#include "orionld/types/OrionldTenant.h" // OrionldTenant + + + +// ----------------------------------------------------------------------------- +// +// DbCollection - move to orionld/types/DbCollection.h +// +typedef enum DbCollection +{ + DbNone = 1, + DbEntities = 2, + DbSubscriptions = 4, + DbRegistrations = 8, + DbContexts = 16 +} DbCollection; @@ -32,6 +48,6 @@ // // mongocConnectionGet - // -extern void mongocConnectionGet(void); +extern void mongocConnectionGet(OrionldTenant* tenantP, DbCollection dbCollection); #endif // SRC_LIB_ORIONLD_MONGOC_MONGOCCONNECTIONGET_H_ diff --git a/src/lib/orionld/mongoc/mongocContextCacheDelete.cpp b/src/lib/orionld/mongoc/mongocContextCacheDelete.cpp index fd83abd317..4c70b89dc0 100644 --- a/src/lib/orionld/mongoc/mongocContextCacheDelete.cpp +++ b/src/lib/orionld/mongoc/mongocContextCacheDelete.cpp @@ -22,6 +22,7 @@ * * Author: Ken Zangelin */ +#include // sem_wait, sem_post #include // bson_t, ... #include // mongoc driver @@ -46,10 +47,7 @@ void mongocContextCacheDelete(const char* id) { bson_t selector; - mongocConnectionGet(); - - if (orionldState.mongoc.contextsP == NULL) - orionldState.mongoc.contextsP = mongoc_client_get_collection(orionldState.mongoc.client, "orionld", "contexts"); + mongocConnectionGet(NULL, DbContexts); bson_init(&selector); bson_append_utf8(&selector, "_id", 3, id, -1); diff --git a/src/lib/orionld/mongoc/mongocContextCacheGet.cpp b/src/lib/orionld/mongoc/mongocContextCacheGet.cpp index 19ab15caf0..edbb1bc512 100644 --- a/src/lib/orionld/mongoc/mongocContextCacheGet.cpp +++ b/src/lib/orionld/mongoc/mongocContextCacheGet.cpp @@ -55,10 +55,7 @@ KjNode* mongocContextCacheGet(void) bson_t* query = bson_new(); // Empty - to find all the contexts in the DB KjNode* contextArray = kjArray(orionldState.kjsonP, NULL); - mongocConnectionGet(); - - if (orionldState.mongoc.contextsP == NULL) - orionldState.mongoc.contextsP = mongoc_client_get_collection(orionldState.mongoc.client, "orionld", "contexts"); + mongocConnectionGet(NULL, DbContexts); sem_wait(&mongocContextsSem); diff --git a/src/lib/orionld/mongoc/mongocContextCachePersist.cpp b/src/lib/orionld/mongoc/mongocContextCachePersist.cpp index 64ff5f4d5d..d0098c4124 100644 --- a/src/lib/orionld/mongoc/mongocContextCachePersist.cpp +++ b/src/lib/orionld/mongoc/mongocContextCachePersist.cpp @@ -49,10 +49,7 @@ void mongocContextCachePersist(KjNode* contextObject) mongocKjTreeToBson(contextObject, &bson); - mongocConnectionGet(); - - if (orionldState.mongoc.contextsP == NULL) - orionldState.mongoc.contextsP = mongoc_client_get_collection(orionldState.mongoc.client, "orionld", "contexts"); + mongocConnectionGet(NULL, DbContexts); sem_wait(&mongocContextsSem); diff --git a/src/lib/orionld/mongoc/mongocEntitiesDelete.cpp b/src/lib/orionld/mongoc/mongocEntitiesDelete.cpp index fa97d5036f..6812c2218d 100644 --- a/src/lib/orionld/mongoc/mongocEntitiesDelete.cpp +++ b/src/lib/orionld/mongoc/mongocEntitiesDelete.cpp @@ -48,10 +48,7 @@ extern "C" // bool mongocEntitiesDelete(KjNode* entityIdArray) { - mongocConnectionGet(); // mongocConnectionGet(MONGO_ENTITIES) - do the mongoc_client_get_collection also - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); mongoc_bulk_operation_t* bulkP; diff --git a/src/lib/orionld/mongoc/mongocEntitiesExist.cpp b/src/lib/orionld/mongoc/mongocEntitiesExist.cpp index d4897ae52a..f8cb4a1d02 100644 --- a/src/lib/orionld/mongoc/mongocEntitiesExist.cpp +++ b/src/lib/orionld/mongoc/mongocEntitiesExist.cpp @@ -117,10 +117,7 @@ KjNode* mongocEntitiesExist(KjNode* entityIdArray, bool entityType) bson_append_document(&options, "projection", 10, &projection); bson_destroy(&projection); - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); mongoCursorP = mongoc_collection_find_with_opts(orionldState.mongoc.entitiesP, &mongoFilter, &options, readPrefs); bson_destroy(&options); diff --git a/src/lib/orionld/mongoc/mongocEntitiesGet.cpp b/src/lib/orionld/mongoc/mongocEntitiesGet.cpp index f9ed8293c8..737d0458d9 100644 --- a/src/lib/orionld/mongoc/mongocEntitiesGet.cpp +++ b/src/lib/orionld/mongoc/mongocEntitiesGet.cpp @@ -96,10 +96,7 @@ KjNode* mongocEntitiesGet(char** fieldV, int fields, bool entityIdPresent) bson_t mongoFilter; bson_init(&mongoFilter); - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); // // Run the query diff --git a/src/lib/orionld/mongoc/mongocEntitiesQuery.cpp b/src/lib/orionld/mongoc/mongocEntitiesQuery.cpp index 7d2d7c0b83..48a104ec4a 100644 --- a/src/lib/orionld/mongoc/mongocEntitiesQuery.cpp +++ b/src/lib/orionld/mongoc/mongocEntitiesQuery.cpp @@ -775,10 +775,7 @@ KjNode* mongocEntitiesQuery bson_append_document(&options, "projection", 10, &projection); bson_destroy(&projection); - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); // semTake(&mongoEntitiesSem); diff --git a/src/lib/orionld/mongoc/mongocEntitiesQuery2.cpp b/src/lib/orionld/mongoc/mongocEntitiesQuery2.cpp index fff07f9d54..2cd5ddba00 100644 --- a/src/lib/orionld/mongoc/mongocEntitiesQuery2.cpp +++ b/src/lib/orionld/mongoc/mongocEntitiesQuery2.cpp @@ -347,10 +347,7 @@ KjNode* mongocEntitiesQuery2 bson_append_document(&options, "projection", 10, &projection); bson_destroy(&projection); - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); // count? if (orionldState.uriParams.count == true) diff --git a/src/lib/orionld/mongoc/mongocEntitiesUpsert.cpp b/src/lib/orionld/mongoc/mongocEntitiesUpsert.cpp index 82cea850a9..2dbd9d3ed1 100644 --- a/src/lib/orionld/mongoc/mongocEntitiesUpsert.cpp +++ b/src/lib/orionld/mongoc/mongocEntitiesUpsert.cpp @@ -48,13 +48,9 @@ extern "C" // bool mongocEntitiesUpsert(KjNode* createArrayP, KjNode* updateArrayP) { - mongocConnectionGet(); // mongocConnectionGet(MONGO_ENTITIES) - do the mongoc_client_get_collection also - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); mongoc_bulk_operation_t* bulkP; - bulkP = mongoc_collection_create_bulk_operation_with_opts(orionldState.mongoc.entitiesP, NULL); if (createArrayP != NULL) diff --git a/src/lib/orionld/mongoc/mongocEntityDelete.cpp b/src/lib/orionld/mongoc/mongocEntityDelete.cpp index 7e6ab15883..c1f2c07974 100644 --- a/src/lib/orionld/mongoc/mongocEntityDelete.cpp +++ b/src/lib/orionld/mongoc/mongocEntityDelete.cpp @@ -44,10 +44,7 @@ extern "C" // bool mongocEntityDelete(const char* entityId, char** detailP) { - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "csubs"); + mongocConnectionGet(orionldState.tenantP, DbEntities); bson_t selector; bson_error_t error; diff --git a/src/lib/orionld/mongoc/mongocEntityGet.cpp b/src/lib/orionld/mongoc/mongocEntityGet.cpp index 505525fab5..4ef5660a30 100644 --- a/src/lib/orionld/mongoc/mongocEntityGet.cpp +++ b/src/lib/orionld/mongoc/mongocEntityGet.cpp @@ -91,10 +91,7 @@ KjNode* mongocEntityGet(const char* entityId, const char** projectionV, bool inc // // Get the connection // - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); // // Perform the query diff --git a/src/lib/orionld/mongoc/mongocEntityInsert.cpp b/src/lib/orionld/mongoc/mongocEntityInsert.cpp index 46096cb806..d1a1737165 100644 --- a/src/lib/orionld/mongoc/mongocEntityInsert.cpp +++ b/src/lib/orionld/mongoc/mongocEntityInsert.cpp @@ -51,10 +51,7 @@ bool mongocEntityInsert(KjNode* dbEntityP, const char* entityId) bson_t document; bson_t reply; - mongocConnectionGet(); // mongocConnectionGet(MONGO_ENTITIES) - do the mongoc_client_get_collection also - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); bson_init(&document); bson_init(&reply); diff --git a/src/lib/orionld/mongoc/mongocEntityLookup.cpp b/src/lib/orionld/mongoc/mongocEntityLookup.cpp index 1d3734af4c..a99cfa1e0c 100644 --- a/src/lib/orionld/mongoc/mongocEntityLookup.cpp +++ b/src/lib/orionld/mongoc/mongocEntityLookup.cpp @@ -78,10 +78,7 @@ KjNode* mongocEntityLookup(const char* entityId, const char* entityType, StringA if (entityType != NULL) bson_append_utf8(&mongoFilter, "_id.type", 8, entityType, -1); - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); // // Projection (will be added to if attrList != NULL) diff --git a/src/lib/orionld/mongoc/mongocEntityReplace.cpp b/src/lib/orionld/mongoc/mongocEntityReplace.cpp index 7c34edbad4..f00e9d22c6 100644 --- a/src/lib/orionld/mongoc/mongocEntityReplace.cpp +++ b/src/lib/orionld/mongoc/mongocEntityReplace.cpp @@ -51,10 +51,7 @@ bool mongocEntityReplace(KjNode* dbEntityP, const char* entityId) bson_t replacement; bson_t reply; - mongocConnectionGet(); // mongocConnectionGet(MONGO_ENTITIES) - do the mongoc_client_get_collection also - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); bson_init(&selector); bson_init(&replacement); diff --git a/src/lib/orionld/mongoc/mongocEntityRetrieve.cpp b/src/lib/orionld/mongoc/mongocEntityRetrieve.cpp index c093ac3d35..53d1858b70 100644 --- a/src/lib/orionld/mongoc/mongocEntityRetrieve.cpp +++ b/src/lib/orionld/mongoc/mongocEntityRetrieve.cpp @@ -412,10 +412,7 @@ KjNode* mongocEntityRetrieve bson_init(&mongoFilter); bson_append_utf8(&mongoFilter, "_id.id", 6, entityId, -1); - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); // // Run the query diff --git a/src/lib/orionld/mongoc/mongocEntityTypeGet.cpp b/src/lib/orionld/mongoc/mongocEntityTypeGet.cpp index 216fff4e7f..ca4b5403de 100644 --- a/src/lib/orionld/mongoc/mongocEntityTypeGet.cpp +++ b/src/lib/orionld/mongoc/mongocEntityTypeGet.cpp @@ -79,10 +79,7 @@ KjNode* mongocEntityTypeGet(OrionldProblemDetails* pdP, const char* typeLongName mongoc_read_prefs_t* readPrefs = mongoc_read_prefs_new(MONGOC_READ_NEAREST); - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); mongoc_cursor_t* mongoCursorP; mongoCursorP = mongoc_collection_find_with_opts(orionldState.mongoc.entitiesP, &mongoFilter, &options, readPrefs); diff --git a/src/lib/orionld/mongoc/mongocEntityTypesFromRegistrationsGet.cpp b/src/lib/orionld/mongoc/mongocEntityTypesFromRegistrationsGet.cpp index 724fe1c475..0f2b2dd3ff 100644 --- a/src/lib/orionld/mongoc/mongocEntityTypesFromRegistrationsGet.cpp +++ b/src/lib/orionld/mongoc/mongocEntityTypesFromRegistrationsGet.cpp @@ -76,10 +76,7 @@ KjNode* mongocEntityTypesFromRegistrationsGet(bool details) bson_destroy(&projection); // Connection - mongocConnectionGet(); - - if (orionldState.mongoc.registrationsP == NULL) - orionldState.mongoc.registrationsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "registrations"); + mongocConnectionGet(orionldState.tenantP, DbRegistrations); // // Run the query diff --git a/src/lib/orionld/mongoc/mongocEntityUpdate.cpp b/src/lib/orionld/mongoc/mongocEntityUpdate.cpp index 5a5696af53..e4ca518d25 100644 --- a/src/lib/orionld/mongoc/mongocEntityUpdate.cpp +++ b/src/lib/orionld/mongoc/mongocEntityUpdate.cpp @@ -270,10 +270,7 @@ static bool patchApply // bool mongocEntityUpdate(const char* entityId, KjNode* patchTree) { - mongocConnectionGet(); - - if (orionldState.mongoc.entitiesP == NULL) - orionldState.mongoc.entitiesP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "entities"); + mongocConnectionGet(orionldState.tenantP, DbEntities); bson_t selector; bson_init(&selector); diff --git a/src/lib/orionld/mongoc/mongocGeoIndexCreate.cpp b/src/lib/orionld/mongoc/mongocGeoIndexCreate.cpp index a4cc6346f2..aeb37d9b45 100644 --- a/src/lib/orionld/mongoc/mongocGeoIndexCreate.cpp +++ b/src/lib/orionld/mongoc/mongocGeoIndexCreate.cpp @@ -59,7 +59,7 @@ bool mongocGeoIndexCreate(OrionldTenant* tenantP, const char* attrLongName) bson_init(&key); BSON_APPEND_UTF8(&key, indexPath, "2dsphere"); - mongocConnectionGet(); + mongocConnectionGet(NULL, DbNone); mongoc_database_t* dbP = mongoc_client_get_database(orionldState.mongoc.client, tenantP->mongoDbName); char* indexName = mongoc_collection_keys_to_index_string(&key); diff --git a/src/lib/orionld/mongoc/mongocGeoIndexInit.cpp b/src/lib/orionld/mongoc/mongocGeoIndexInit.cpp index c6151b7837..eb534323f1 100644 --- a/src/lib/orionld/mongoc/mongocGeoIndexInit.cpp +++ b/src/lib/orionld/mongoc/mongocGeoIndexInit.cpp @@ -55,7 +55,7 @@ bool mongocGeoIndexInit(void) // // DB Connection // - mongocConnectionGet(); + mongocConnectionGet(NULL, DbNone); // // Loop over all tenants @@ -72,6 +72,8 @@ bool mongocGeoIndexInit(void) // Get handle to collection // mCollectionP = mongoc_client_get_collection(orionldState.mongoc.client, tenantP->mongoDbName, "entities"); + if (mCollectionP == NULL) + LM_X(1, ("mongoc_client_get_collection failed for 'entities' collection on tenant '%s'", tenantP->mongoDbName)); // Aggregation pipeline diff --git a/src/lib/orionld/mongoc/mongocIdIndexCreate.cpp b/src/lib/orionld/mongoc/mongocIdIndexCreate.cpp index 08975babe5..561f520dfd 100644 --- a/src/lib/orionld/mongoc/mongocIdIndexCreate.cpp +++ b/src/lib/orionld/mongoc/mongocIdIndexCreate.cpp @@ -52,7 +52,7 @@ bool mongocIdIndexCreate(OrionldTenant* tenantP) bson_init(&key); BSON_APPEND_INT32(&key, "_id.id", 1); - mongocConnectionGet(); + mongocConnectionGet(NULL, DbNone); mongoc_database_t* dbP = mongoc_client_get_database(orionldState.mongoc.client, tenantP->mongoDbName); char* indexName = mongoc_collection_keys_to_index_string(&key); diff --git a/src/lib/orionld/mongoc/mongocInit.cpp b/src/lib/orionld/mongoc/mongocInit.cpp index 0e027b627a..37a5b95b42 100644 --- a/src/lib/orionld/mongoc/mongocInit.cpp +++ b/src/lib/orionld/mongoc/mongocInit.cpp @@ -318,6 +318,11 @@ void mongocInit // sem_init(&mongocContextsSem, 0, 1); // 0: shared between threads of the same process. 1: free to be taken + // + // Semaphore for getting a connection/collection for mongo + // + sem_init(&mongocConnectionSem, 0, 1); // 0: shared between threads of the same process. 1: free to be taken + if (mongocTenantsGet() == false) LM_X(1, ("Unable to extract tenants from the database - fatal error")); diff --git a/src/lib/orionld/mongoc/mongocRegistrationDelete.cpp b/src/lib/orionld/mongoc/mongocRegistrationDelete.cpp index c851836c65..3c68527cff 100644 --- a/src/lib/orionld/mongoc/mongocRegistrationDelete.cpp +++ b/src/lib/orionld/mongoc/mongocRegistrationDelete.cpp @@ -39,14 +39,11 @@ // bool mongocRegistrationDelete(const char* registrationId) { - mongocConnectionGet(); - - if (orionldState.mongoc.registrationsP == NULL) - orionldState.mongoc.registrationsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "registrations"); - bson_t selector; bson_error_t error; + mongocConnectionGet(orionldState.tenantP, DbRegistrations); + // // Create the filter for the query // diff --git a/src/lib/orionld/mongoc/mongocRegistrationExists.cpp b/src/lib/orionld/mongoc/mongocRegistrationExists.cpp index 3e5055b4ff..736215203a 100644 --- a/src/lib/orionld/mongoc/mongocRegistrationExists.cpp +++ b/src/lib/orionld/mongoc/mongocRegistrationExists.cpp @@ -52,10 +52,7 @@ bool mongocRegistrationExists(const char* registrationId, bool* foundP) bson_init(&mongoFilter); bson_append_utf8(&mongoFilter, "_id", 3, registrationId, -1); - mongocConnectionGet(); - - if (orionldState.mongoc.registrationsP == NULL) - orionldState.mongoc.registrationsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "registrations"); + mongocConnectionGet(orionldState.tenantP, DbRegistrations); // // Run the query diff --git a/src/lib/orionld/mongoc/mongocRegistrationGet.cpp b/src/lib/orionld/mongoc/mongocRegistrationGet.cpp index db59e1015d..6623bb839b 100644 --- a/src/lib/orionld/mongoc/mongocRegistrationGet.cpp +++ b/src/lib/orionld/mongoc/mongocRegistrationGet.cpp @@ -58,10 +58,7 @@ KjNode* mongocRegistrationGet(const char* registrationId) bson_init(&mongoFilter); bson_append_utf8(&mongoFilter, "_id", 3, registrationId, -1); - mongocConnectionGet(); - - if (orionldState.mongoc.registrationsP == NULL) - orionldState.mongoc.registrationsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "registrations"); + mongocConnectionGet(orionldState.tenantP, DbRegistrations); // // Run the query diff --git a/src/lib/orionld/mongoc/mongocRegistrationInsert.cpp b/src/lib/orionld/mongoc/mongocRegistrationInsert.cpp index 56273dec0c..0246706168 100644 --- a/src/lib/orionld/mongoc/mongocRegistrationInsert.cpp +++ b/src/lib/orionld/mongoc/mongocRegistrationInsert.cpp @@ -51,10 +51,7 @@ bool mongocRegistrationInsert(KjNode* dbRegistrationP, const char* registrationI bson_t document; bson_t reply; - mongocConnectionGet(); - - if (orionldState.mongoc.registrationsP == NULL) - orionldState.mongoc.registrationsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "registrations"); + mongocConnectionGet(orionldState.tenantP, DbRegistrations); bson_init(&document); bson_init(&reply); diff --git a/src/lib/orionld/mongoc/mongocRegistrationLookup.cpp b/src/lib/orionld/mongoc/mongocRegistrationLookup.cpp index 4b700d9a65..7db6efe322 100644 --- a/src/lib/orionld/mongoc/mongocRegistrationLookup.cpp +++ b/src/lib/orionld/mongoc/mongocRegistrationLookup.cpp @@ -61,10 +61,7 @@ KjNode* mongocRegistrationLookup(const char* entityId, const char* attribute, in // { $or: [ { "contextRegistration.attrs": { $size: 0 }}, { "contextRegistration.attrs.name": 'attribute' } ] } ??? } - mongocConnectionGet(); - - if (orionldState.mongoc.registrationsP == NULL) - orionldState.mongoc.registrationsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "registrations"); + mongocConnectionGet(orionldState.tenantP, DbRegistrations); // // Run the query diff --git a/src/lib/orionld/mongoc/mongocRegistrationReplace.cpp b/src/lib/orionld/mongoc/mongocRegistrationReplace.cpp index ec5f8700ef..5ea25ef773 100644 --- a/src/lib/orionld/mongoc/mongocRegistrationReplace.cpp +++ b/src/lib/orionld/mongoc/mongocRegistrationReplace.cpp @@ -49,10 +49,7 @@ bool mongocRegistrationReplace(const char* registrationId, KjNode* dbRegistratio bson_t replacement; bson_t reply; - mongocConnectionGet(); - - if (orionldState.mongoc.registrationsP == NULL) - orionldState.mongoc.registrationsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "registrations"); + mongocConnectionGet(orionldState.tenantP, DbRegistrations); bson_init(&selector); bson_init(&replacement); diff --git a/src/lib/orionld/mongoc/mongocRegistrationsGet.cpp b/src/lib/orionld/mongoc/mongocRegistrationsGet.cpp index 6dc6222668..9ab69b20ae 100644 --- a/src/lib/orionld/mongoc/mongocRegistrationsGet.cpp +++ b/src/lib/orionld/mongoc/mongocRegistrationsGet.cpp @@ -79,11 +79,7 @@ KjNode* mongocRegistrationsGet(int64_t* countP) // bson_init(&mongoFilter); - mongocConnectionGet(); - - if (orionldState.mongoc.registrationsP == NULL) - orionldState.mongoc.registrationsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "registrations"); - + mongocConnectionGet(orionldState.tenantP, DbRegistrations); // count? if (orionldState.uriParams.count == true) diff --git a/src/lib/orionld/mongoc/mongocRegistrationsIter.cpp b/src/lib/orionld/mongoc/mongocRegistrationsIter.cpp index c8f7f8a8cd..57a0cb3601 100644 --- a/src/lib/orionld/mongoc/mongocRegistrationsIter.cpp +++ b/src/lib/orionld/mongoc/mongocRegistrationsIter.cpp @@ -62,13 +62,16 @@ int mongocRegistrationsIter(RegCache* rcP, RegCacheIterFunc callback) // bson_init(&mongoFilter); - mongocConnectionGet(); + mongocConnectionGet(NULL, DbNone); // // Can't use the "orionldState.mongoc.registrationsP" here, as we'll deal with not one single tenant but all of them // mongoc_collection_t* regsCollectionP = mongoc_client_get_collection(orionldState.mongoc.client, rcP->tenantP->mongoDbName, "registrations"); + if (regsCollectionP == NULL) + LM_X(1, ("mongoc_client_get_collection failed for 'registrations' collection on tenant '%s'", rcP->tenantP->mongoDbName)); + // // Run the query // diff --git a/src/lib/orionld/mongoc/mongocServerVersionGet.cpp b/src/lib/orionld/mongoc/mongocServerVersionGet.cpp index d72a99bf47..e8c7047eea 100644 --- a/src/lib/orionld/mongoc/mongocServerVersionGet.cpp +++ b/src/lib/orionld/mongoc/mongocServerVersionGet.cpp @@ -52,7 +52,7 @@ bool mongocServerVersionGet(char* serverVersionBuf) bson_init(&command); bson_init(&reply); - mongocConnectionGet(); + mongocConnectionGet(NULL, DbNone); bson_append_int32(&command, "buildinfo", 9, 1); diff --git a/src/lib/orionld/mongoc/mongocSubCachePopulateByTenant.cpp b/src/lib/orionld/mongoc/mongocSubCachePopulateByTenant.cpp index 12f16f5fe7..18f3f3ce5e 100644 --- a/src/lib/orionld/mongoc/mongocSubCachePopulateByTenant.cpp +++ b/src/lib/orionld/mongoc/mongocSubCachePopulateByTenant.cpp @@ -78,6 +78,9 @@ bool mongocSubCachePopulateByTenant(OrionldTenant* tenantP, bool refresh) mongoc_client_t* connectionP = mongoc_client_pool_pop(mongocPool); mongoc_collection_t* subscriptionsP = mongoc_client_get_collection(connectionP, tenantP->mongoDbName, "csubs"); + if (subscriptionsP == NULL) + LM_X(1, ("mongoc_client_get_collection failed for 'csubs' collection on tenant '%s'", tenantP->mongoDbName)); + // // Run the query // diff --git a/src/lib/orionld/mongoc/mongocSubCountersUpdate.cpp b/src/lib/orionld/mongoc/mongocSubCountersUpdate.cpp index a723d75cbe..3154d66640 100644 --- a/src/lib/orionld/mongoc/mongocSubCountersUpdate.cpp +++ b/src/lib/orionld/mongoc/mongocSubCountersUpdate.cpp @@ -83,6 +83,9 @@ void mongocSubCountersUpdate bson_t selector; bson_t inc; + if (subscriptionsP == NULL) + LM_X(1, ("mongoc_client_get_collection failed for 'csubs' collection on tenant '%s'", tenantP->mongoDbName)); + bson_init(&reply); bson_init(&selector); bson_init(&inc); diff --git a/src/lib/orionld/mongoc/mongocSubscriptionDelete.cpp b/src/lib/orionld/mongoc/mongocSubscriptionDelete.cpp index 54b6183a3e..1697260a9e 100644 --- a/src/lib/orionld/mongoc/mongocSubscriptionDelete.cpp +++ b/src/lib/orionld/mongoc/mongocSubscriptionDelete.cpp @@ -39,10 +39,7 @@ // bool mongocSubscriptionDelete(const char* subscriptionId) { - mongocConnectionGet(); - - if (orionldState.mongoc.subscriptionsP == NULL) - orionldState.mongoc.subscriptionsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "csubs"); + mongocConnectionGet(orionldState.tenantP, DbSubscriptions); bson_t selector; bson_error_t error; diff --git a/src/lib/orionld/mongoc/mongocSubscriptionExists.cpp b/src/lib/orionld/mongoc/mongocSubscriptionExists.cpp index 389933f78a..2eb5e42789 100644 --- a/src/lib/orionld/mongoc/mongocSubscriptionExists.cpp +++ b/src/lib/orionld/mongoc/mongocSubscriptionExists.cpp @@ -51,10 +51,7 @@ bool mongocSubscriptionExists(const char* subscriptionId, char** detailP) bson_init(&mongoFilter); bson_append_utf8(&mongoFilter, "_id", 3, subscriptionId, -1); - mongocConnectionGet(); - - if (orionldState.mongoc.subscriptionsP == NULL) - orionldState.mongoc.subscriptionsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "csubs"); + mongocConnectionGet(orionldState.tenantP, DbSubscriptions); // // Run the query diff --git a/src/lib/orionld/mongoc/mongocSubscriptionInsert.cpp b/src/lib/orionld/mongoc/mongocSubscriptionInsert.cpp index 83915aa2f4..13cb72316b 100644 --- a/src/lib/orionld/mongoc/mongocSubscriptionInsert.cpp +++ b/src/lib/orionld/mongoc/mongocSubscriptionInsert.cpp @@ -52,10 +52,7 @@ bool mongocSubscriptionInsert(KjNode* dbSubscriptionP, const char* subscriptionI bson_t document; bson_t reply; - mongocConnectionGet(); - - if (orionldState.mongoc.subscriptionsP == NULL) - orionldState.mongoc.subscriptionsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "csubs"); + mongocConnectionGet(orionldState.tenantP, DbSubscriptions); bson_init(&document); bson_init(&reply); diff --git a/src/lib/orionld/mongoc/mongocSubscriptionLookup.cpp b/src/lib/orionld/mongoc/mongocSubscriptionLookup.cpp index ffccc7f427..7242fd4348 100644 --- a/src/lib/orionld/mongoc/mongocSubscriptionLookup.cpp +++ b/src/lib/orionld/mongoc/mongocSubscriptionLookup.cpp @@ -59,10 +59,7 @@ KjNode* mongocSubscriptionLookup(const char* subscriptionId) bson_init(&mongoFilter); bson_append_utf8(&mongoFilter, "_id", 3, subscriptionId, -1); - mongocConnectionGet(); - - if (orionldState.mongoc.subscriptionsP == NULL) - orionldState.mongoc.subscriptionsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "csubs"); + mongocConnectionGet(orionldState.tenantP, DbSubscriptions); // // Run the query diff --git a/src/lib/orionld/mongoc/mongocSubscriptionReplace.cpp b/src/lib/orionld/mongoc/mongocSubscriptionReplace.cpp index 64e9e06e64..60b5a965ca 100644 --- a/src/lib/orionld/mongoc/mongocSubscriptionReplace.cpp +++ b/src/lib/orionld/mongoc/mongocSubscriptionReplace.cpp @@ -52,10 +52,7 @@ bool mongocSubscriptionReplace(const char* subscriptionId, KjNode* dbSubscriptio bson_t replacement; bson_t reply; - mongocConnectionGet(); - - if (orionldState.mongoc.subscriptionsP == NULL) - orionldState.mongoc.subscriptionsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "csubs"); + mongocConnectionGet(orionldState.tenantP, DbSubscriptions); bson_init(&selector); bson_init(&replacement); diff --git a/src/lib/orionld/mongoc/mongocSubscriptionsGet.cpp b/src/lib/orionld/mongoc/mongocSubscriptionsGet.cpp index 4fa59224b8..0e118354db 100644 --- a/src/lib/orionld/mongoc/mongocSubscriptionsGet.cpp +++ b/src/lib/orionld/mongoc/mongocSubscriptionsGet.cpp @@ -79,10 +79,7 @@ KjNode* mongocSubscriptionsGet(int64_t* countP) // bson_init(&mongoFilter); - mongocConnectionGet(); - - if (orionldState.mongoc.subscriptionsP == NULL) - orionldState.mongoc.subscriptionsP = mongoc_client_get_collection(orionldState.mongoc.client, orionldState.tenantP->mongoDbName, "csubs"); + mongocConnectionGet(orionldState.tenantP, DbSubscriptions); // count? diff --git a/src/lib/orionld/mongoc/mongocTenantExists.cpp b/src/lib/orionld/mongoc/mongocTenantExists.cpp index 08cb1a345f..5e42cd3694 100644 --- a/src/lib/orionld/mongoc/mongocTenantExists.cpp +++ b/src/lib/orionld/mongoc/mongocTenantExists.cpp @@ -66,13 +66,13 @@ bool mongocTenantExists(const char* tenantName) bson_init(&command); bson_init(&reply); - mongocConnectionGet(); + mongocConnectionGet(NULL, DbNone); bson_append_int32(&command, "listDatabases", 13, 1); bool b = mongoc_client_read_command_with_opts(orionldState.mongoc.client, "admin", &command, NULL, NULL, &reply, &mcError); if (b == false) - LM_RE(false, ("Database Error ()", mcError.message)); + LM_RE(false, ("Database Error (%s)", mcError.message)); char* title; char* detail; diff --git a/src/lib/orionld/mongoc/mongocTenantsGet.cpp b/src/lib/orionld/mongoc/mongocTenantsGet.cpp index 661bf291a8..b33ca20b31 100644 --- a/src/lib/orionld/mongoc/mongocTenantsGet.cpp +++ b/src/lib/orionld/mongoc/mongocTenantsGet.cpp @@ -54,7 +54,7 @@ bool mongocTenantsGet(void) bson_init(&command); bson_init(&reply); - mongocConnectionGet(); + mongocConnectionGet(NULL, DbNone); bson_append_int32(&command, "listDatabases", 13, 1); diff --git a/src/lib/orionld/service/orionldServiceInit.cpp b/src/lib/orionld/service/orionldServiceInit.cpp index afa0292778..a5d05ad803 100644 --- a/src/lib/orionld/service/orionldServiceInit.cpp +++ b/src/lib/orionld/service/orionldServiceInit.cpp @@ -466,14 +466,16 @@ static void restServicePrepare(OrionLdRestService* serviceP, OrionLdRestServiceS serviceP->uriParams |= ORIONLD_URIPARAM_DETAILS; serviceP->uriParams |= ORIONLD_URIPARAM_LOCATION; serviceP->uriParams |= ORIONLD_URIPARAM_URL; + serviceP->uriParams |= ORIONLD_URIPARAM_KIND; serviceP->options |= ORIONLD_SERVICE_OPTION_DONT_ADD_CONTEXT_TO_RESPONSE_PAYLOAD; } else if (serviceP->serviceRoutine == orionldGetContext) { serviceP->options = 0; // Tenant is Ignored - serviceP->options |= ORIONLD_SERVICE_OPTION_DONT_ADD_CONTEXT_TO_RESPONSE_PAYLOAD; + + serviceP->uriParams |= ORIONLD_URIPARAM_DETAILS; } else if (serviceP->serviceRoutine == orionldPostContexts) { diff --git a/src/lib/orionld/serviceRoutines/orionldDeleteContext.cpp b/src/lib/orionld/serviceRoutines/orionldDeleteContext.cpp index 9c674ba4e9..131d503deb 100644 --- a/src/lib/orionld/serviceRoutines/orionldDeleteContext.cpp +++ b/src/lib/orionld/serviceRoutines/orionldDeleteContext.cpp @@ -59,7 +59,10 @@ bool orionldDeleteContext(void) if (orionldState.uriParams.reload == true) { - if (oldContextP->origin != OrionldContextDownloaded) + // + // Only contexts of type Cached (indirect download) can be reloaded + // + if (oldContextP->kind != OrionldContextCached) { orionldError(OrionldBadRequestData, "Wrong type of context", "only cached contexts are subject for reload", 400); return false; @@ -93,6 +96,7 @@ bool orionldDeleteContext(void) if (contextP == NULL) { orionldContextCacheInsert(oldContextP); + // orionldError(OrionldLdContextNotAvailable, "Unable to reload the @context", oldContextP->url, 504); return false; } diff --git a/src/lib/orionld/serviceRoutines/orionldGetContext.cpp b/src/lib/orionld/serviceRoutines/orionldGetContext.cpp index 97f16ae427..268c90e4de 100644 --- a/src/lib/orionld/serviceRoutines/orionldGetContext.cpp +++ b/src/lib/orionld/serviceRoutines/orionldGetContext.cpp @@ -38,6 +38,7 @@ extern "C" +extern KjNode* orionldContextWithDetails(OrionldContext* contextP); // ---------------------------------------------------------------------------- // // orionldGetContext - @@ -54,16 +55,31 @@ bool orionldGetContext(void) return false; } - orionldState.responseTree = kjObject(orionldState.kjsonP, NULL); - if (orionldState.responseTree == NULL) + // + // Contexts of type Cached (indirect download) are not served. + // The broker is not a context server. + // See 5.13.4.4 of the NGSI-LD API Specification + // + if ((contextP->kind == OrionldContextCached) && (orionldState.uriParams.details == false)) { - orionldError(OrionldBadRequestData, "kjObject failed", "out of memory?", 500); + orionldError(OrionldOperationNotSupported, "Not serving cached JSON-LD @context", orionldState.wildcard[0], 422); return false; } - contextP->tree->name = (char*) "@context"; + if (orionldState.uriParams.details == true) + orionldState.responseTree = orionldContextWithDetails(contextP); + else + { + orionldState.responseTree = kjObject(orionldState.kjsonP, NULL); + if (orionldState.responseTree == NULL) + { + orionldError(OrionldBadRequestData, "kjObject failed", "out of memory?", 500); + return false; + } - kjChildAdd(orionldState.responseTree, contextP->tree); + contextP->tree->name = (char*) "@context"; + kjChildAdd(orionldState.responseTree, contextP->tree); + } return true; } diff --git a/src/lib/orionld/serviceRoutines/orionldGetContexts.cpp b/src/lib/orionld/serviceRoutines/orionldGetContexts.cpp index c141dd1d5e..cff5c8df3f 100644 --- a/src/lib/orionld/serviceRoutines/orionldGetContexts.cpp +++ b/src/lib/orionld/serviceRoutines/orionldGetContexts.cpp @@ -83,7 +83,7 @@ bool orionldGetContexts(void) orionldState.noLinkHeader = true; // We don't want the Link header for context requests - orionldState.responseTree = orionldContextCacheGet(contextTree, orionldState.uriParams.details); + orionldState.responseTree = orionldContextCacheGet(contextTree, orionldState.uriParams.details, orionldState.uriParams.kind); return true; } diff --git a/src/lib/orionld/serviceRoutines/orionldGetEntitiesPage.cpp b/src/lib/orionld/serviceRoutines/orionldGetEntitiesPage.cpp index 5675eaaabf..cb249be4dc 100644 --- a/src/lib/orionld/serviceRoutines/orionldGetEntitiesPage.cpp +++ b/src/lib/orionld/serviceRoutines/orionldGetEntitiesPage.cpp @@ -37,6 +37,8 @@ extern "C" #include "orionld/common/orionldState.h" // orionldState, entityMaps #include "orionld/common/orionldError.h" // orionldError #include "orionld/kjTree/kjChildCount.h" // kjChildCount +#include "orionld/apiModel/ntocEntity.h" // ntocEntity +#include "orionld/apiModel/ntosEntity.h" // ntosEntity #include "orionld/distOp/distOpLookupByRegId.h" // distOpLookupByRegId #include "orionld/distOp/distOpListDebug.h" // distOpListDebug #include "orionld/distOp/distOpsSend.h" // distOpsSend2 @@ -66,7 +68,6 @@ static void cleanupSysAttrs(void) { nextAttrP = attrP->next; - LM_T(LmtSR, ("attrP->name: '%s'", attrP->name)); if (strcmp(attrP->name, "createdAt") == 0) kjChildRemove(entityP, attrP); else if (strcmp(attrP->name, "modifiedAt") == 0) kjChildRemove(entityP, attrP); else if (attrP->type == KjObject) @@ -129,6 +130,34 @@ static int queryResponse(DistOp* distOpP, void* callbackParam) + +// ----------------------------------------------------------------------------- +// +// formatFix - +// +static void formatFix(KjNode* entityArray, int skip) +{ + int ix = -1; + for (KjNode* entityP = entityArray->value.firstChildP; entityP != NULL; entityP = entityP->next) + { + ++ix; + if (ix < skip) // Entities from the local DB have already been transformed to the desired format + { + LM_T(LmtFormat, ("Skipping child %d as it comes from local DB", ix)); + continue; + } + + LM_T(LmtFormat, ("Fixing format for child %d as it comes from remote", ix)); + + if (orionldState.out.format == RF_CONCISE) + ntocEntity(entityP, orionldState.uriParams.lang, orionldState.uriParamOptions.sysAttrs); + else if (orionldState.out.format == RF_SIMPLIFIED) + ntosEntity(entityP, orionldState.uriParams.lang); + } +} + + + // ---------------------------------------------------------------------------- // // orionldGetEntitiesPage - @@ -329,11 +358,18 @@ bool orionldGetEntitiesPage(void) if (distOpListItem != NULL) { + int localKids = kjChildCount(entityArray); + + LM_T(LmtFormat, ("Number of children from local: %d (no format fix for those)", localKids)); + distOpItemListDebug(distOpListItem, "To Forward for GET /entities"); distOpsSendAndReceive(distOpListItem, queryResponse, entityArray); + + formatFix(entityArray, localKids); } - orionldState.responseTree = entityArray; + orionldState.responseTree = entityArray; + orionldState.httpStatusCode = 200; // // Time to cleanup ... diff --git a/src/lib/orionld/serviceRoutines/orionldPostContexts.cpp b/src/lib/orionld/serviceRoutines/orionldPostContexts.cpp index 2ef062e1d5..b58f4381d6 100644 --- a/src/lib/orionld/serviceRoutines/orionldPostContexts.cpp +++ b/src/lib/orionld/serviceRoutines/orionldPostContexts.cpp @@ -69,7 +69,13 @@ bool orionldPostContexts(void) url = orionldContextUrlGenerate(&id); - OrionldContext* contextP = orionldContextFromTree(url, OrionldContextUserCreated, id, orionldState.requestTree); + if (orionldState.payloadContextNode == NULL) + { + orionldError(OrionldInvalidRequest, "Invalid @context", "@context field missing", 400); + return false; + } + + OrionldContext* contextP = orionldContextFromTree(url, OrionldContextUserCreated, id, orionldState.payloadContextNode); if (contextP == NULL) { LM_W(("Unable to create context (%s: %s)", orionldState.pd.title, orionldState.pd.detail)); @@ -78,6 +84,7 @@ bool orionldPostContexts(void) contextP->createdAt = orionldState.requestTime; contextP->usedAt = orionldState.requestTime; + contextP->kind = OrionldContextHosted; httpHeaderLocationAdd(contextP->url, NULL, NULL); diff --git a/src/lib/orionld/types/CMakeLists.txt b/src/lib/orionld/types/CMakeLists.txt index b7bf29988f..4b7a4f9e53 100644 --- a/src/lib/orionld/types/CMakeLists.txt +++ b/src/lib/orionld/types/CMakeLists.txt @@ -37,6 +37,7 @@ SET (SOURCES DistOpType.cpp TroeMode.cpp Verb.cpp + OrionldContext.cpp ) # Include directories diff --git a/src/lib/orionld/types/OrionLdRestService.h b/src/lib/orionld/types/OrionLdRestService.h index e63887cb27..53ee8f0613 100644 --- a/src/lib/orionld/types/OrionLdRestService.h +++ b/src/lib/orionld/types/OrionLdRestService.h @@ -156,6 +156,7 @@ typedef struct OrionLdRestServiceSimplifiedVector #define ORIONLD_URIPARAM_ENTITYMAP (UINT64_C(1) << 39) #define ORIONLD_URIPARAM_FORMAT (UINT64_C(1) << 40) #define ORIONLD_URIPARAM_EXPAND_VALUES (UINT64_C(1) << 41) +#define ORIONLD_URIPARAM_KIND (UINT64_C(1) << 42) diff --git a/src/lib/orionld/types/OrionldContext.cpp b/src/lib/orionld/types/OrionldContext.cpp new file mode 100644 index 0000000000..191ad74cf5 --- /dev/null +++ b/src/lib/orionld/types/OrionldContext.cpp @@ -0,0 +1,104 @@ +/* +* +* Copyright 2024 FIWARE Foundation e.V. +* +* This file is part of Orion-LD Context Broker. +* +* Orion-LD Context Broker is free software: you can redistribute it and/or +* modify it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* Orion-LD Context Broker is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +* General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with Orion-LD Context Broker. If not, see http://www.gnu.org/licenses/. +* +* For those usages not covered by this license please contact with +* orionld at fiware dot org +* +* Author: Ken Zangelin +*/ +#include // strcmp + +#include "orionld/types/OrionldContext.h" // OrionldContext + + + +// ----------------------------------------------------------------------------- +// +// orionldOriginFromString - FIXME: move to its own module +// +OrionldContextOrigin orionldOriginFromString(const char* s) +{ + if (strcmp(s, "UnknownOrigin") == 0) return OrionldContextUnknownOrigin; + else if (strcmp(s, "Inline") == 0) return OrionldContextFromInline; + else if (strcmp(s, "Downloaded") == 0) return OrionldContextDownloaded; + else if (strcmp(s, "FileCached") == 0) return OrionldContextFileCached; + else if (strcmp(s, "ForNotifications") == 0) return OrionldContextForNotifications; + else if (strcmp(s, "ForForwarding") == 0) return OrionldContextForForwarding; + else if (strcmp(s, "UserCreated") == 0) return OrionldContextUserCreated; + + return OrionldContextUnknownOrigin; +} + + + +// ----------------------------------------------------------------------------- +// +// orionldOriginToString - +// +const char* orionldOriginToString(OrionldContextOrigin origin) +{ + switch (origin) + { + case OrionldContextUnknownOrigin: return "UnknownOrigin"; + case OrionldContextFromInline: return "FromInline"; + case OrionldContextDownloaded: return "Downloaded"; + case OrionldContextFileCached: return "FileCached"; + case OrionldContextForNotifications: return "ForNotifications"; + case OrionldContextForForwarding: return "ForForwarding"; + case OrionldContextUserCreated: return "UserCreated"; + case OrionldContextBuiltinCoreContext: return "BuiltinCoreContext"; + } + + return "InvalidOrigin"; +} + + + +// ----------------------------------------------------------------------------- +// +// orionldKindFromString - +// +OrionldContextKind orionldKindFromString(const char* kind) +{ + if (strcmp(kind, "Hosted") == 0) return OrionldContextHosted; + else if (strcmp(kind, "Cached") == 0) return OrionldContextCached; + else if (strcmp(kind, "ImplicitlyCreated") == 0) return OrionldContextImplicit; + else if (strcmp(kind, "Unknown") == 0) return OrionldContextUnknownKind; + + return OrionldContextUnknownKind; +} + + + +// ----------------------------------------------------------------------------- +// +// orionldKindToString - +// +const char* orionldKindToString(OrionldContextKind kind) +{ + switch (kind) + { + case OrionldContextUnknownKind: return "Unknown"; + case OrionldContextHosted: return "Hosted"; + case OrionldContextCached: return "Cached"; + case OrionldContextImplicit: return "ImplicitlyCreated"; + } + + return "Invalid"; +} diff --git a/src/lib/orionld/types/OrionldContext.h b/src/lib/orionld/types/OrionldContext.h index 6c84a91500..a98d439ace 100644 --- a/src/lib/orionld/types/OrionldContext.h +++ b/src/lib/orionld/types/OrionldContext.h @@ -84,6 +84,20 @@ typedef enum OrionldContextOrigin +// ----------------------------------------------------------------------------- +// +// OrionldContextKind - +// +typedef enum OrionldContextKind +{ + OrionldContextUnknownKind, + OrionldContextHosted, + OrionldContextCached, + OrionldContextImplicit +} OrionldContextKind; + + + // ----------------------------------------------------------------------------- // // orionldOriginFromString - @@ -92,6 +106,29 @@ extern OrionldContextOrigin orionldOriginFromString(const char* s); +// ----------------------------------------------------------------------------- +// +// orionldOriginToString - +// +extern const char* orionldOriginToString(OrionldContextOrigin origin); + + + +// ----------------------------------------------------------------------------- +// +// orionldKindFromString - +// +extern OrionldContextKind orionldKindFromString(const char* s); + + + +// ----------------------------------------------------------------------------- +// +// orionldKindToString - +// +extern const char* orionldKindToString(OrionldContextKind kind); + + // ---------------------------------------------------------------------------- // @@ -109,10 +146,13 @@ typedef struct OrionldContext bool coreContext; double createdAt; double usedAt; - int lookups; + int compactions; // Number of compactions done with this @context + int expansions; // Number of expansions done with this @context + int lookups; // Number of NGSI-LD requests done using this @context bool keyValues; OrionldContextInfo context; OrionldContextOrigin origin; + OrionldContextKind kind; } OrionldContext; #endif // SRC_LIB_ORIONLD_TYPES_ORIONLDCONTEXT_H_ diff --git a/src/lib/rest/rest.cpp b/src/lib/rest/rest.cpp index f8a3428345..2f4d7457e0 100644 --- a/src/lib/rest/rest.cpp +++ b/src/lib/rest/rest.cpp @@ -391,12 +391,28 @@ static void requestCompleted // - // Release the connection to mongo - after all notifications have been sent (orionldAlterationsTreat takes care of that) - // - if (orionldState.mongoc.contextsP) mongoc_collection_destroy(orionldState.mongoc.contextsP); - if (orionldState.mongoc.entitiesP) mongoc_collection_destroy(orionldState.mongoc.entitiesP); - if (orionldState.mongoc.subscriptionsP) mongoc_collection_destroy(orionldState.mongoc.subscriptionsP); - if (orionldState.mongoc.registrationsP) mongoc_collection_destroy(orionldState.mongoc.registrationsP); + // Release the connections to mongo - after all notifications have been sent (orionldAlterationsTreat takes care of the notifications) + // NOTE, this "construct" with NULLing the mongoc_collection_t pointers before actually calling mongoc_collection_destroy is a + // desperate attempt to fix the issue #1499. + // If still not enough, perhaps a semaphore to protect. + // It's weird though, these collection pointers are THREAD VARIABLES !!! + // No protection should be needed. + // But, desperate times ... + // + mongoc_collection_t* contextsP = orionldState.mongoc.contextsP; + mongoc_collection_t* entitiesP = orionldState.mongoc.entitiesP; + mongoc_collection_t* subscriptionsP = orionldState.mongoc.subscriptionsP; + mongoc_collection_t* registrationsP = orionldState.mongoc.registrationsP; + + orionldState.mongoc.contextsP = NULL; + orionldState.mongoc.entitiesP = NULL; + orionldState.mongoc.subscriptionsP = NULL; + orionldState.mongoc.registrationsP = NULL; + + if (contextsP != NULL) mongoc_collection_destroy(contextsP); + if (entitiesP != NULL) mongoc_collection_destroy(entitiesP); + if (subscriptionsP != NULL) mongoc_collection_destroy(subscriptionsP); + if (registrationsP != NULL) mongoc_collection_destroy(registrationsP); mongocConnectionRelease(); diff --git a/test/functionalTest/cases/0000_ngsild/ngsild_batch_upsert_and_contexts.test b/test/functionalTest/cases/0000_ngsild/ngsild_batch_upsert_and_contexts.test index f1ea731edc..5811c69575 100644 --- a/test/functionalTest/cases/0000_ngsild/ngsild_batch_upsert_and_contexts.test +++ b/test/functionalTest/cases/0000_ngsild/ngsild_batch_upsert_and_contexts.test @@ -726,52 +726,67 @@ Link: /tmp/entities entityMap=$(echo "$_responseHeaders" | grep NGSILD-EntityMap: | awk -F ': ' '{ print $2 }' | tr -d "\r\n") +head -7 /tmp/entities +echo +grep '"id": "' /tmp/entities | sort +echo +echo + + +echo "14. GET /entities?type=T&format=simplified in CB" +echo "================================================" +orionCurl --url '/ngsi-ld/v1/entities?type=T&format=simplified' -H "aerOS: true" > /tmp/entities +head -6 /tmp/entities +echo +grep '"id": "' /tmp/entities | sort +echo +echo + + +echo '15. GET /entities?type=T&options=sysAttrs in CB' +echo "===============================================" +orionCurl --url '/ngsi-ld/v1/entities?type=T&options=sysAttrs' -H "aerOS: true" > /tmp/entities +head -6 /tmp/entities +echo +grep '"id": "' /tmp/entities | sort +\rm -f /tmp/entities +echo +echo + +echo "16. GET /entities?type=T&format=concise in CB" +echo "=============================================" +orionCurl --url '/ngsi-ld/v1/entities?type=T&format=concise' -H "aerOS: true" > /tmp/entities +head -6 /tmp/entities +echo +grep '"id": "' /tmp/entities | sort +\rm -f /tmp/entities echo echo @@ -412,87 +454,70 @@ Location: /ngsi-ld/v1/csourceRegistrations/urn:R2 13. GET /entities?type=T in CB ============================== HTTP/1.1 200 OK -Content-Length: REGEX(.*) +Content-Length: 781 Content-Type: application/json Date: REGEX(.*) Link: