Repository navigation
Expand file tree
/
Copy pathcorDbEntityRetrieve.c
More file actions
118 lines (92 loc) · 3.8 KB
/
Copy pathcorDbEntityRetrieve.c
File metadata and controls
118 lines (92 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//
// FILE corDbEntityRetrieve.c
//
// AUTHOR Ken Zangelin
//
// Copyright 2026 Seamware
// SPDX-License-Identifier: Apache-2.0
//
#include <string.h> // strcmp
#include "corTree/CorNode.h" // CorNode
#include "corTree/corTreeClone.h" // corTreeClone
#include "corTree/corTreeLookup.h" // corTreeLookup
#include "corRest/CorRestState.h" // corRest
#include "db/DbDriver.h" // DB_OK, DB_NOT_FOUND, Tenant
#include "corDB/corDbSysTimes.h" // corDbTreeIn, corDbTreeOut
#include "corDB/corDbIndex.h" // corDbIndexLookup
#include "corDB/corDbStore.h" // corDbEntities
#include "corDB/corDbEntityRetrieve.h" // Own interface
// -----------------------------------------------------------------------------
//
// entityRetrieve - under the store's read lock
//
static int entityRetrieve(Tenant* tenantP, const char* entityId, CorNode** entityPP, int64_t* createdAtP)
{
COR_DB_READ(tenantP);
CorNode* entities = corDbEntities(tenantP);
//
// O(1) via the id index. The walk below is the fallback for a store built
// before the index existed - it cannot happen in a running broker, but a NULL
// index must not mean "entity not found".
//
{
CorNode* hitP = corDbIndexLookup(corDbStoreOf(tenantP), entityId);
if (hitP != NULL)
{
*entityPP = corDbEntityCopy(corRest.kallocP, hitP, createdAtP);
return DB_OK;
}
if (corDbStoreOf(tenantP)->idToPrevEntity != NULL)
return DB_NOT_FOUND; // indexed, and it is not there
}
for (CorNode* eP = entities->value.head; eP != NULL; eP = eP->next)
{
CorNode* idP = corTreeLookup(eP, "id");
if (idP != NULL && idP->type == CorString && strcmp(idP->value.s, entityId) == 0)
{
// Clone into the request arena (freed at request end), matching mongoc's
// retrieve. A NULL (malloc) clone would leak — no caller frees the result;
// they all consume it within the request (render / merge / replace-copy).
*entityPP = corDbEntityCopy(corRest.kallocP, eP, createdAtP);
return DB_OK;
}
}
return DB_NOT_FOUND;
}
// -----------------------------------------------------------------------------
//
// corDbEntityRetrieve - the copy under the store's lock, its inherited times put back after it
//
int corDbEntityRetrieve(Tenant* tenantP, const char* entityId, CorNode** entityPP)
{
int64_t createdAt = 0;
int r = entityRetrieve(tenantP, entityId, entityPP, &createdAt);
if (r == DB_OK)
corDbEntityCopyFinish(corRest.kallocP, *entityPP, createdAt);
return r;
}
// -----------------------------------------------------------------------------
//
// corDbEntityTypes - the entity's "type" alone (DbDriver.entityTypes), cloned under the store's read lock:
// no copy of its attributes. The entity's type is stored as it is given (only an attribute's lives in the
// node - corDbSysTimes.c), so the clone is what corDbEntityRetrieve's tree has
//
int corDbEntityTypes(Tenant* tenantP, const char* entityId, CorNode** typePP)
{
COR_DB_READ(tenantP);
CorNode* hitP = corDbIndexLookup(corDbStoreOf(tenantP), entityId);
if ((hitP == NULL) && (corDbStoreOf(tenantP)->idToPrevEntity == NULL)) // no index: the walk
{
for (CorNode* eP = corDbEntities(tenantP)->value.head; (eP != NULL) && (hitP == NULL); eP = eP->next)
{
CorNode* idP = corTreeLookup(eP, "id");
if ((idP != NULL) && (idP->type == CorString) && (strcmp(idP->value.s, entityId) == 0))
hitP = eP;
}
}
if (hitP == NULL)
return DB_NOT_FOUND;
CorNode* typeP = corTreeLookup(hitP, "type");
*typePP = (typeP != NULL) ? corTreeClone(corRest.kallocP, typeP) : NULL;
return DB_OK;
}