• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #pragma once
2 #ifndef EJDB2_INTERNAL_H
3 #define EJDB2_INTERNAL_H
4 
5 /**************************************************************************************************
6  * EJDB2
7  *
8  * MIT License
9  *
10  * Copyright (c) 2012-2022 Softmotions Ltd <info@softmotions.com>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  *  copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in all
20  * copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  * SOFTWARE.
29  *************************************************************************************************/
30 
31 #include "ejdb2.h"
32 #include "jql.h"
33 #ifdef JB_HTTP
34 #include "jbr.h"
35 #endif
36 #include "jql_internal.h"
37 
38 #include <iowow/iwkv.h>
39 #include <iowow/iwxstr.h>
40 #include <iowow/iwexfile.h>
41 #include <iowow/iwutils.h>
42 #include <iowow/iwhmap.h>
43 #include <iowow/iwjson_internal.h>
44 
45 #include <pthread.h>
46 #include <unistd.h>
47 #include <assert.h>
48 #include <setjmp.h>
49 
50 #include "ejdb2cfg.h"
51 
52 #define METADB_ID           1
53 #define NUMRECSDB_ID        2    // DB for number of records per index/collection
54 #define KEY_PREFIX_COLLMETA "c." // Full key format: c.<coldbid>
55 #define KEY_PREFIX_IDXMETA  "i." // Full key format: i.<coldbid>.<idxdbid>
56 
57 #define ENSURE_OPEN(db_)                  \
58   if (!(db_) || !((db_)->open)) {         \
59     iwlog_error2("Database is not open");  \
60     return IW_ERROR_INVALID_STATE;        \
61   }
62 
63 #define API_RLOCK(db_, rci_) \
64   ENSURE_OPEN(db_);  \
65   rci_ = pthread_rwlock_rdlock(&(db_)->rwl); \
66   if (rci_) return iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_)
67 
68 #define API_WLOCK(db_, rci_) \
69   ENSURE_OPEN(db_);  \
70   rci_ = pthread_rwlock_wrlock(&(db_)->rwl); \
71   if (rci_) return iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_)
72 
73 #define API_WLOCK2(db_, rci_) \
74   rci_ = pthread_rwlock_wrlock(&(db_)->rwl); \
75   if (rci_) return iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_)
76 
77 #define API_UNLOCK(db_, rci_, rc_)  \
78   rci_ = pthread_rwlock_unlock(&(db_)->rwl); \
79   if (rci_) IWRC(iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_), rc_)
80 
81 #define API_COLL_UNLOCK(jbc_, rci_, rc_)                                     \
82   do {                                                                    \
83     rci_ = pthread_rwlock_unlock(&(jbc_)->rwl);                            \
84     if (rci_) IWRC(iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_), rc_);  \
85     API_UNLOCK((jbc_)->db, rci_, rc_);                                   \
86   } while (0)
87 
88 struct _JBIDX;
89 typedef struct _JBIDX*JBIDX;
90 
91 /** Database collection */
92 typedef struct _JBCOLL {
93   uint32_t    dbid;         /**< IWKV collection database ID */
94   const char *name;         /**< Collection name */
95   IWDB    cdb;              /**< IWKV collection database */
96   EJDB    db;               /**< Main database reference */
97   JBL     meta;             /**< Collection meta object */
98   JBIDX   idx;              /**< First index in chain */
99   int64_t rnum;             /**< Number of records stored in collection */
100   pthread_rwlock_t rwl;
101   int64_t id_seq;
102 } *JBCOLL;
103 
104 /** Database collection index */
105 struct _JBIDX {
106   struct _JBIDX *next;      /**< Next index in chain */
107   int64_t  rnum;            /**< Number of records stored in index */
108   JBCOLL   jbc;             /**< Owner document collection */
109   JBL_PTR  ptr;             /**< Indexed JSON path poiner 0*/
110   IWDB     idb;             /**< KV database for this index */
111   uint32_t dbid;            /**< IWKV collection database ID */
112   ejdb_idx_mode_t mode;     /**< Index mode/type mask */
113   iwdb_flags_t    idbf;     /**< Index database flags */
114 };
115 
116 /** Pair: collection name, document id */
117 struct _JBDOCREF {
118   int64_t     id;
119   const char *coll;
120 };
121 
122 struct _EJDB {
123   IWKV iwkv;
124   IWDB metadb;
125   IWDB nrecdb;
126 #ifdef JB_HTTP
127   JBR jbr;
128 #endif
129   IWHMAP *mcolls;
130   iwkv_openflags    oflags;
131   pthread_rwlock_t  rwl;      /**< Main RWL */
132   struct _EJDB_OPTS opts;
133   volatile bool     open;
134 };
135 
136 struct _JBPHCTX {
137   int64_t  id;
138   JBCOLL   jbc;
139   JBL      jbl;
140   IWKV_val oldval;
141 };
142 
143 struct _JBEXEC;
144 
145 typedef iwrc (*JB_SCAN_CONSUMER)(
146   struct _JBEXEC *ctx, IWKV_cursor cur, int64_t id,
147   int64_t *step, bool *matched, iwrc err);
148 
149 /**
150  * @brief Index scan sorter consumer context
151  */
152 struct _JBSSC {
153   iwrc      rc;               /**< RC code used for in `_jb_do_sorting` */
154   uint32_t *refs;             /**< Document references array */
155   uint32_t  refs_asz;         /**< Document references array allocated size */
156   uint32_t  refs_num;         /**< Document references array elements count */
157   uint32_t  docs_asz;         /**< Documents array allocated size */
158   uint8_t  *docs;             /**< Documents byte array */
159   uint32_t  docs_npos;        /**< Next document offset */
160   jmp_buf   fatal_jmp;
161   IWFS_EXT  sof;              /**< Sort overflow file */
162   bool      sof_active;
163 };
164 
165 struct _JBMIDX {
166   JBIDX       idx;                    /**< Index matched this filter */
167   JQP_FILTER *filter;                 /**< Query filter */
168   JQP_EXPR   *nexpr;                  /**< Filter node expression */
169   JQP_EXPR   *expr1;                  /**< Start index expression (optional) */
170   JQP_EXPR   *expr2;                  /**< End index expression (optional) */
171   IWKV_cursor_op cursor_init;         /**< Initial index cursor position (optional) */
172   IWKV_cursor_op cursor_step;         /**< Next index cursor step */
173   bool orderby_support;               /**< Index supported first order-by clause */
174 };
175 
176 typedef struct _JBEXEC {
177   EJDB_EXEC *ux;           /**< User defined context */
178   JBCOLL     jbc;          /**< Collection */
179 
180   int64_t istep;
181   iwrc (*scanner)(struct _JBEXEC *ctx, JB_SCAN_CONSUMER consumer);
182   uint8_t *jblbuf;            /**< Buffer used to keep currently processed document */
183   size_t   jblbufsz;          /**< Size of jblbuf allocated memory */
184   bool     sorting;           /**< Resultset sorting needed */
185   IWKV_cursor_op cursor_init; /**< Initial index cursor position (optional) */
186   IWKV_cursor_op cursor_step; /**< Next index cursor step */
187   struct _JBMIDX midx;        /**< Index matching context */
188   struct _JBSSC  ssc;         /**< Result set sorting context */
189 
190   // JQL joned nodes cache
191   IWHMAP *proj_joined_nodes_cache;
192   IWPOOL *proj_joined_nodes_pool;
193 } JBEXEC;
194 
195 
196 typedef uint8_t jb_coll_acquire_t;
197 #define JB_COLL_ACQUIRE_WRITE    ((jb_coll_acquire_t) 0x01U)
198 #define JB_COLL_ACQUIRE_EXISTING ((jb_coll_acquire_t) 0x02U)
199 
200 // Index selector empiric constants
201 #define JB_IDX_EMPIRIC_MAX_INOP_ARRAY_SIZE  500
202 #define JB_IDX_EMPIRIC_MIN_INOP_ARRAY_SIZE  10
203 #define JB_IDX_EMPIRIC_MAX_INOP_ARRAY_RATIO 200
204 
205 void jbi_jbl_fill_ikey(JBIDX idx, JBL jbv, IWKV_val *ikey, char numbuf[static IWNUMBUF_SIZE]);
206 void jbi_jqval_fill_ikey(JBIDX idx, const JQVAL *jqval, IWKV_val *ikey, char numbuf[static IWNUMBUF_SIZE]);
207 void jbi_node_fill_ikey(JBIDX idx, JBL_NODE node, IWKV_val *ikey, char numbuf[static IWNUMBUF_SIZE]);
208 
209 iwrc jbi_consumer(struct _JBEXEC *ctx, IWKV_cursor cur, int64_t id, int64_t *step, bool *matched, iwrc err);
210 iwrc jbi_sorter_consumer(struct _JBEXEC *ctx, IWKV_cursor cur, int64_t id, int64_t *step, bool *matched, iwrc err);
211 iwrc jbi_full_scanner(struct _JBEXEC *ctx, JB_SCAN_CONSUMER consumer);
212 iwrc jbi_selection(JBEXEC *ctx);
213 iwrc jbi_pk_scanner(struct _JBEXEC *ctx, JB_SCAN_CONSUMER consumer);
214 iwrc jbi_uniq_scanner(struct _JBEXEC *ctx, JB_SCAN_CONSUMER consumer);
215 iwrc jbi_dup_scanner(struct _JBEXEC *ctx, JB_SCAN_CONSUMER consumer);
216 bool jbi_node_expr_matched(JQP_AUX *aux, JBIDX idx, IWKV_cursor cur, JQP_EXPR *expr, iwrc *rcp);
217 
218 iwrc jb_get(EJDB db, const char *coll, int64_t id, jb_coll_acquire_t acm, JBL *jblp);
219 iwrc jb_put(JBCOLL jbc, JBL jbl, int64_t id);
220 iwrc jb_del(JBCOLL jbc, JBL jbl, int64_t id);
221 iwrc jb_cursor_set(JBCOLL jbc, IWKV_cursor cur, int64_t id, JBL jbl);
222 iwrc jb_cursor_del(JBCOLL jbc, IWKV_cursor cur, int64_t id, JBL jbl);
223 
224 iwrc jb_collection_join_resolver(int64_t id, const char *coll, JBL *out, JBEXEC *ctx);
225 int jb_proj_node_cache_cmp(const void *v1, const void *v2);
226 void jb_proj_node_kvfree(void *key, void *val);
227 uint32_t jb_proj_node_hash(const void *key);
228 
229 #endif
230