1 | /* |
2 | * proto.h |
3 | * |
4 | * Copyright (C) 2008-2018 Aerospike, Inc. |
5 | * |
6 | * Portions may be licensed to Aerospike, Inc. under one or more contributor |
7 | * license agreements. |
8 | * |
9 | * This program is free software: you can redistribute it and/or modify it under |
10 | * the terms of the GNU Affero General Public License as published by the Free |
11 | * Software Foundation, either version 3 of the License, or (at your option) any |
12 | * later version. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, but WITHOUT |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
16 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
17 | * details. |
18 | * |
19 | * You should have received a copy of the GNU Affero General Public License |
20 | * along with this program. If not, see http://www.gnu.org/licenses/ |
21 | */ |
22 | |
23 | #pragma once |
24 | |
25 | //========================================================== |
26 | // Includes. |
27 | // |
28 | |
29 | #include <stdbool.h> |
30 | #include <stddef.h> |
31 | #include <stdint.h> |
32 | #include <string.h> |
33 | |
34 | #include "aerospike/as_val.h" |
35 | #include "citrusleaf/cf_digest.h" |
36 | #include "citrusleaf/cf_vector.h" |
37 | |
38 | #include "dynbuf.h" |
39 | #include "socket.h" |
40 | |
41 | |
42 | //========================================================== |
43 | // Forward declarations. |
44 | // |
45 | |
46 | struct as_bin_s; |
47 | struct as_file_handle_s; |
48 | struct as_index_s; |
49 | struct as_namespace_s; |
50 | struct as_storage_rd_s; |
51 | struct as_transaction_s; |
52 | |
53 | |
54 | //========================================================== |
55 | // Typedefs & constants. |
56 | // |
57 | |
58 | //------------------------------------------------ |
59 | // Result codes used in client protocol. Must |
60 | // match those in as_status.h in the client. Must |
61 | // be <= 255, to fit in one byte. |
62 | // |
63 | |
64 | // Generic. |
65 | #define AS_OK 0 |
66 | #define AS_ERR_UNKNOWN 1 |
67 | #define AS_ERR_NOT_FOUND 2 |
68 | #define AS_ERR_GENERATION 3 |
69 | #define AS_ERR_PARAMETER 4 |
70 | #define AS_ERR_RECORD_EXISTS 5 |
71 | #define AS_ERR_BIN_EXISTS 6 |
72 | #define AS_ERR_CLUSTER_KEY_MISMATCH 7 |
73 | #define AS_ERR_OUT_OF_SPACE 8 |
74 | #define AS_ERR_TIMEOUT 9 |
75 | #define AS_ERR_ALWAYS_FORBIDDEN 10 |
76 | #define AS_ERR_UNAVAILABLE 11 |
77 | #define AS_ERR_INCOMPATIBLE_TYPE 12 |
78 | #define AS_ERR_RECORD_TOO_BIG 13 |
79 | #define AS_ERR_KEY_BUSY 14 |
80 | #define AS_ERR_SCAN_ABORT 15 |
81 | #define AS_ERR_UNSUPPORTED_FEATURE 16 |
82 | #define AS_ERR_BIN_NOT_FOUND 17 |
83 | #define AS_ERR_DEVICE_OVERLOAD 18 |
84 | #define AS_ERR_KEY_MISMATCH 19 |
85 | #define AS_ERR_NAMESPACE 20 |
86 | #define AS_ERR_BIN_NAME 21 |
87 | #define AS_ERR_FORBIDDEN 22 |
88 | #define AS_ERR_ELEMENT_NOT_FOUND 23 |
89 | #define AS_ERR_ELEMENT_EXISTS 24 |
90 | #define AS_ERR_ENTERPRISE_ONLY 25 |
91 | #define AS_ERR_OP_NOT_APPLICABLE 26 |
92 | #define AS_ERR_FILTERED_OUT 27 |
93 | |
94 | // Security. (Defined here to ensure no overlap with other result codes.) |
95 | #define AS_SEC_OK_LAST 50 // the last message |
96 | // Security message errors. |
97 | #define AS_SEC_ERR_NOT_SUPPORTED 51 // security features not supported |
98 | #define AS_SEC_ERR_NOT_ENABLED 52 // security features not enabled |
99 | #define AS_SEC_ERR_SCHEME 53 // security scheme not supported |
100 | #define AS_SEC_ERR_COMMAND 54 // unrecognized command |
101 | #define AS_SEC_ERR_FIELD 55 // can't parse field |
102 | #define AS_SEC_ERR_STATE 56 // e.g. unexpected command |
103 | // Security procedure errors. |
104 | #define AS_SEC_ERR_USER 60 // no/unknown user |
105 | #define AS_SEC_ERR_USER_EXISTS 61 // user already exists |
106 | #define AS_SEC_ERR_PASSWORD 62 // no/bad password |
107 | #define AS_SEC_ERR_EXPIRED_PASSWORD 63 // expired password |
108 | #define AS_SEC_ERR_FORBIDDEN_PASSWORD 64 // e.g. recently used password |
109 | #define AS_SEC_ERR_CREDENTIAL 65 // no/bad credential |
110 | #define AS_SEC_ERR_EXPIRED_SESSION 66 // expired session token |
111 | // ... room for more ... |
112 | #define AS_SEC_ERR_ROLE 70 // no/unknown role(s) |
113 | #define AS_SEC_ERR_ROLE_EXISTS 71 // role already exists |
114 | #define AS_SEC_ERR_PRIVILEGE 72 // no/unknown privilege(s) |
115 | #define AS_SEC_ERR_WHITELIST 73 // bad whitelist |
116 | // Permission errors. |
117 | #define AS_SEC_ERR_NOT_AUTHENTICATED 80 // socket not authenticated |
118 | #define AS_SEC_ERR_ROLE_VIOLATION 81 // role (privilege) violation |
119 | #define AS_SEC_ERR_NOT_WHITELISTED 82 // client IP-addr not on whitelist |
120 | // LDAP-related errors. |
121 | #define AS_SEC_ERR_LDAP_NOT_ENABLED 90 // LDAP features not enabled |
122 | #define AS_SEC_ERR_LDAP_SETUP 91 // LDAP setup error |
123 | #define AS_SEC_ERR_LDAP_TLS_SETUP 92 // LDAP TLS setup error |
124 | #define AS_SEC_ERR_LDAP_AUTHENTICATION 93 // error authenticating LDAP user |
125 | #define AS_SEC_ERR_LDAP_QUERY 94 // error querying LDAP server |
126 | |
127 | // UDF. |
128 | #define AS_ERR_UDF_EXECUTION 100 |
129 | |
130 | // Batch. |
131 | #define AS_ERR_BATCH_DISABLED 150 |
132 | #define AS_ERR_BATCH_MAX_REQUESTS 151 |
133 | #define AS_ERR_BATCH_QUEUES_FULL 152 |
134 | |
135 | // Geo. |
136 | #define AS_ERR_GEO_INVALID_GEOJSON 160 |
137 | |
138 | // Secondary Index. |
139 | #define AS_ERR_SINDEX_FOUND 200 |
140 | #define AS_ERR_SINDEX_NOT_FOUND 201 |
141 | #define AS_ERR_SINDEX_OOM 202 |
142 | #define AS_ERR_SINDEX_NOT_READABLE 203 |
143 | #define AS_ERR_SINDEX_GENERIC 204 |
144 | #define AS_ERR_SINDEX_NAME 205 |
145 | #define AS_ERR_SINDEX_MAX_COUNT 206 |
146 | |
147 | // Query. |
148 | #define AS_ERR_QUERY_USER_ABORT 210 |
149 | #define AS_ERR_QUERY_QUEUE_FULL 211 |
150 | #define AS_ERR_QUERY_TIMEOUT 212 |
151 | #define AS_ERR_QUERY_CB 213 |
152 | #define AS_ERR_QUERY_NET_IO 214 |
153 | #define AS_ERR_QUERY_DUPLICATE 215 |
154 | |
155 | //------------------------------------------------ |
156 | // as_proto. |
157 | // |
158 | |
159 | typedef struct as_proto_s { |
160 | uint8_t version; |
161 | uint8_t type; |
162 | uint64_t sz: 48; // body size |
163 | uint8_t body[0]; |
164 | } __attribute__ ((__packed__)) as_proto; |
165 | |
166 | // Current version of as_proto header - not version of (body) message type. |
167 | #define PROTO_VERSION 2 |
168 | |
169 | // as_proto (body) message types. |
170 | #define PROTO_TYPE_INFO 1 |
171 | #define PROTO_TYPE_SECURITY 2 |
172 | #define PROTO_TYPE_AS_MSG 3 |
173 | #define PROTO_TYPE_AS_MSG_COMPRESSED 4 |
174 | #define PROTO_TYPE_INTERNAL_XDR 5 |
175 | #define PROTO_TYPE_LAST_PLUS_1 6 |
176 | |
177 | // Limit for sanity-checking. |
178 | #define PROTO_SIZE_MAX (128 * 1024 * 1024) |
179 | |
180 | // Wrapper for compressed message. |
181 | typedef struct as_comp_proto_s { |
182 | as_proto proto; |
183 | uint64_t orig_sz; |
184 | uint8_t data[0]; // compressed message (includes its own header) |
185 | } as_comp_proto; |
186 | |
187 | //------------------------------------------------ |
188 | // as_msg. |
189 | // |
190 | |
191 | typedef struct as_msg_s { |
192 | uint8_t ; // size of this header - 22 |
193 | uint8_t info1; |
194 | uint8_t info2; |
195 | uint8_t info3; |
196 | uint8_t unused; |
197 | uint8_t result_code; |
198 | uint32_t generation; |
199 | uint32_t record_ttl; |
200 | uint32_t transaction_ttl; |
201 | uint16_t n_fields; |
202 | uint16_t n_ops; |
203 | uint8_t data[0]; // first fields, then ops |
204 | } __attribute__((__packed__)) as_msg; |
205 | |
206 | // cl_msg - convenient wrapper for message with as_msg body. |
207 | typedef struct cl_msg_s { |
208 | as_proto proto; |
209 | as_msg msg; |
210 | } __attribute__((__packed__)) cl_msg; |
211 | |
212 | // Bits in info1. |
213 | #define AS_MSG_INFO1_READ (1 << 0) // contains a read operation |
214 | #define AS_MSG_INFO1_GET_ALL (1 << 1) // get all bins |
215 | // Bit 2 is unused. |
216 | #define AS_MSG_INFO1_BATCH (1 << 3) // batch protocol |
217 | #define AS_MSG_INFO1_XDR (1 << 4) // operation is via XDR |
218 | #define AS_MSG_INFO1_GET_NO_BINS (1 << 5) // get record metadata only - no bin metadata or data |
219 | #define AS_MSG_INFO1_CONSISTENCY_LEVEL_ALL (1 << 6) // duplicate resolve reads |
220 | // Bit 7 is unused. |
221 | |
222 | // Bits in info2. |
223 | #define AS_MSG_INFO2_WRITE (1 << 0) // contains a write semantic |
224 | #define AS_MSG_INFO2_DELETE (1 << 1) // delete record |
225 | #define AS_MSG_INFO2_GENERATION (1 << 2) // pay attention to the generation |
226 | #define AS_MSG_INFO2_GENERATION_GT (1 << 3) // apply write if new generation > old, good for restore |
227 | #define AS_MSG_INFO2_DURABLE_DELETE (1 << 4) // op resulting in record deletion leaves tombstone (enterprise only) |
228 | #define AS_MSG_INFO2_CREATE_ONLY (1 << 5) // write record only if it doesn't exist |
229 | // Bit 6 is unused. |
230 | #define AS_MSG_INFO2_RESPOND_ALL_OPS (1 << 7) // all bin ops (read, write, or modify) require a response, in request order |
231 | |
232 | // Bits in info3. |
233 | #define AS_MSG_INFO3_LAST (1 << 0) // this is the last of a multi-part message |
234 | #define AS_MSG_INFO3_COMMIT_LEVEL_MASTER (1 << 1) // "fire and forget" replica writes |
235 | // Bit 2 is unused. |
236 | #define AS_MSG_INFO3_UPDATE_ONLY (1 << 3) // update existing record only, do not create new record |
237 | #define AS_MSG_INFO3_CREATE_OR_REPLACE (1 << 4) // completely replace existing record, or create new record |
238 | #define AS_MSG_INFO3_REPLACE_ONLY (1 << 5) // completely replace existing record, do not create new record |
239 | #define AS_MSG_INFO3_SC_READ_TYPE (1 << 6) // (enterprise only) |
240 | #define AS_MSG_INFO3_SC_READ_RELAX (1 << 7) // (enterprise only) |
241 | |
242 | // Interpret SC_READ bits in info3. |
243 | // |
244 | // RELAX TYPE |
245 | // strict |
246 | // ------ |
247 | // 0 0 sequential (default) |
248 | // 0 1 linearize |
249 | // |
250 | // relaxed |
251 | // ------- |
252 | // 1 0 allow prole |
253 | // 1 1 allow unavailable |
254 | |
255 | //------------------------------------------------ |
256 | // as_msg_field. |
257 | // |
258 | |
259 | typedef struct as_msg_field_s { |
260 | uint32_t field_sz; // includes type |
261 | uint8_t type; |
262 | uint8_t data[0]; |
263 | } __attribute__((__packed__)) as_msg_field; |
264 | |
265 | // Generic. |
266 | #define AS_MSG_FIELD_TYPE_NAMESPACE 0 |
267 | #define AS_MSG_FIELD_TYPE_SET 1 |
268 | #define AS_MSG_FIELD_TYPE_KEY 2 |
269 | // 3 is unused. |
270 | #define AS_MSG_FIELD_TYPE_DIGEST_RIPE 4 |
271 | // 5 is unused. |
272 | #define AS_MSG_FIELD_TYPE_DIGEST_RIPE_ARRAY 6 // old batch - deprecated |
273 | #define AS_MSG_FIELD_TYPE_TRID 7 |
274 | #define AS_MSG_FIELD_TYPE_SCAN_OPTIONS 8 |
275 | #define AS_MSG_FIELD_TYPE_SOCKET_TIMEOUT 9 |
276 | #define AS_MSG_FIELD_TYPE_RECS_PER_SEC 10 |
277 | |
278 | // Secondary index. |
279 | #define AS_MSG_FIELD_TYPE_INDEX_NAME 21 |
280 | #define AS_MSG_FIELD_TYPE_INDEX_RANGE 22 |
281 | #define AS_MSG_FIELD_TYPE_INDEX_TYPE 26 |
282 | |
283 | // UDF. |
284 | #define AS_MSG_FIELD_TYPE_UDF_FILENAME 30 |
285 | #define AS_MSG_FIELD_TYPE_UDF_FUNCTION 31 |
286 | #define AS_MSG_FIELD_TYPE_UDF_ARGLIST 32 |
287 | #define AS_MSG_FIELD_TYPE_UDF_OP 33 |
288 | |
289 | // More generic. |
290 | #define AS_MSG_FIELD_TYPE_QUERY_BINLIST 40 |
291 | #define AS_MSG_FIELD_TYPE_BATCH 41 |
292 | #define AS_MSG_FIELD_TYPE_BATCH_WITH_SET 42 |
293 | #define AS_MSG_FIELD_TYPE_PREDEXP 43 |
294 | |
295 | // Bits in as_transaction.msg_fields indicate which fields are present. |
296 | #define AS_MSG_FIELD_BIT_NAMESPACE (1 << 0) |
297 | #define AS_MSG_FIELD_BIT_SET (1 << 1) |
298 | #define AS_MSG_FIELD_BIT_KEY (1 << 2) |
299 | #define AS_MSG_FIELD_BIT_DIGEST_RIPE (1 << 3) |
300 | #define AS_MSG_FIELD_BIT_DIGEST_RIPE_ARRAY (1 << 4) // old batch - deprecated |
301 | #define AS_MSG_FIELD_BIT_TRID (1 << 5) |
302 | #define AS_MSG_FIELD_BIT_SCAN_OPTIONS (1 << 6) |
303 | #define AS_MSG_FIELD_BIT_SOCKET_TIMEOUT (1 << 7) |
304 | #define AS_MSG_FIELD_BIT_RECS_PER_SEC (1 << 8) |
305 | #define AS_MSG_FIELD_BIT_INDEX_NAME (1 << 9) |
306 | #define AS_MSG_FIELD_BIT_INDEX_RANGE (1 << 10) |
307 | #define AS_MSG_FIELD_BIT_INDEX_TYPE (1 << 11) |
308 | #define AS_MSG_FIELD_BIT_UDF_FILENAME (1 << 12) |
309 | #define AS_MSG_FIELD_BIT_UDF_FUNCTION (1 << 13) |
310 | #define AS_MSG_FIELD_BIT_UDF_ARGLIST (1 << 14) |
311 | #define AS_MSG_FIELD_BIT_UDF_OP (1 << 15) |
312 | #define AS_MSG_FIELD_BIT_QUERY_BINLIST (1 << 16) |
313 | #define AS_MSG_FIELD_BIT_BATCH (1 << 17) |
314 | #define AS_MSG_FIELD_BIT_BATCH_WITH_SET (1 << 18) |
315 | #define AS_MSG_FIELD_BIT_PREDEXP (1 << 19) |
316 | |
317 | // Special message field values. |
318 | #define AS_MSG_FIELD_SCAN_FAIL_ON_CLUSTER_CHANGE (0x08) |
319 | #define AS_MSG_FIELD_SCAN_PRIORITY(v) ((v & 0xF0) >> 4) |
320 | |
321 | //------------------------------------------------ |
322 | // as_msg_op. |
323 | // |
324 | |
325 | typedef struct as_msg_op_s { |
326 | uint32_t op_sz; // includes everything past this |
327 | uint8_t op; |
328 | uint8_t particle_type; |
329 | uint8_t version; // now unused |
330 | uint8_t name_sz; |
331 | uint8_t name[0]; |
332 | // Note - op value follows name. |
333 | } __attribute__((__packed__)) as_msg_op; |
334 | |
335 | #define OP_FIXED_SZ (offsetof(as_msg_op, name) - offsetof(as_msg_op, op)) |
336 | |
337 | #define AS_MSG_OP_READ 1 |
338 | #define AS_MSG_OP_WRITE 2 |
339 | #define AS_MSG_OP_CDT_READ 3 // CDT top-level op |
340 | #define AS_MSG_OP_CDT_MODIFY 4 // CDT top-level op |
341 | #define AS_MSG_OP_INCR 5 // arithmetic add - only for integers |
342 | // 6 is unused. |
343 | // 7 is unused. |
344 | // 8 is unused. |
345 | #define AS_MSG_OP_APPEND 9 // append to strings and blobs |
346 | #define AS_MSG_OP_PREPEND 10 // prepend to strings and blobs |
347 | #define AS_MSG_OP_TOUCH 11 // will increment the generation |
348 | #define AS_MSG_OP_BITS_READ 12 // blob bits top-level op |
349 | #define AS_MSG_OP_BITS_MODIFY 13 // blob bits top-level op |
350 | #define AS_MSG_OP_DELETE_ALL 14 // used without bin name |
351 | |
352 | //------------------------------------------------ |
353 | // UDF ops. |
354 | // |
355 | |
356 | // These values correspond to client protocol values - do not change them! |
357 | typedef enum { |
358 | AS_UDF_OP_KVS = 0, |
359 | AS_UDF_OP_AGGREGATE = 1, |
360 | AS_UDF_OP_BACKGROUND = 2 |
361 | } as_udf_op; |
362 | |
363 | //------------------------------------------------ |
364 | // Blob bitwise ops. |
365 | // |
366 | |
367 | typedef enum { |
368 | AS_BITS_MODIFY_OP_START = 0, |
369 | |
370 | AS_BITS_OP_RESIZE = AS_BITS_MODIFY_OP_START, |
371 | AS_BITS_OP_INSERT = 1, |
372 | AS_BITS_OP_REMOVE = 2, |
373 | |
374 | AS_BITS_OP_SET = 3, |
375 | AS_BITS_OP_OR = 4, |
376 | AS_BITS_OP_XOR = 5, |
377 | AS_BITS_OP_AND = 6, |
378 | AS_BITS_OP_NOT = 7, |
379 | AS_BITS_OP_LSHIFT = 8, |
380 | AS_BITS_OP_RSHIFT = 9, |
381 | AS_BITS_OP_ADD = 10, |
382 | AS_BITS_OP_SUBTRACT = 11, |
383 | AS_BITS_OP_SET_INT = 12, |
384 | |
385 | AS_BITS_MODIFY_OP_END, |
386 | |
387 | AS_BITS_READ_OP_START = 50, |
388 | |
389 | AS_BITS_OP_GET = AS_BITS_READ_OP_START, |
390 | AS_BITS_OP_COUNT = 51, |
391 | AS_BITS_OP_LSCAN = 52, |
392 | AS_BITS_OP_RSCAN = 53, |
393 | AS_BITS_OP_GET_INT = 54, |
394 | |
395 | AS_BITS_READ_OP_END |
396 | } as_bits_op_type; |
397 | |
398 | typedef enum { |
399 | AS_BITS_FLAG_CREATE_ONLY = 1 << 0, |
400 | AS_BITS_FLAG_UPDATE_ONLY = 1 << 1, |
401 | AS_BITS_FLAG_NO_FAIL = 1 << 2, |
402 | AS_BITS_FLAG_PARTIAL = 1 << 3 |
403 | } as_bits_flags; |
404 | |
405 | typedef enum { |
406 | AS_BITS_INT_SUBFLAG_SIGNED = 1 << 0, |
407 | AS_BITS_INT_SUBFLAG_SATURATE = 1 << 1, |
408 | AS_BITS_INT_SUBFLAG_WRAP = 1 << 2 |
409 | } as_bits_int_flags; |
410 | |
411 | typedef enum { |
412 | AS_BITS_SUBFLAG_RESIZE_FROM_FRONT = 1 << 0, |
413 | AS_BITS_SUBFLAG_RESIZE_GROW_ONLY = 1 << 1, |
414 | AS_BITS_SUBFLAG_RESIZE_SHRINK_ONLY = 1 << 2 |
415 | } as_bits_resize_subflags; |
416 | |
417 | //------------------------------------------------ |
418 | // CDT ops. |
419 | // |
420 | |
421 | // So we know it can't be (first byte of) msgpack list/map. |
422 | #define CDT_MAGIC 0xC0 |
423 | |
424 | typedef enum { |
425 | AS_CDT_PARAM_NONE = 0, |
426 | AS_CDT_PARAM_INDEX = 1, |
427 | AS_CDT_PARAM_COUNT = 2, |
428 | AS_CDT_PARAM_PAYLOAD = 3, |
429 | AS_CDT_PARAM_FLAGS = 4, |
430 | AS_CDT_PARAM_STORAGE = 5 |
431 | } as_cdt_paramtype; |
432 | |
433 | typedef enum { |
434 | RESULT_TYPE_NONE = 0, |
435 | RESULT_TYPE_INDEX = 1, |
436 | RESULT_TYPE_REVINDEX = 2, |
437 | RESULT_TYPE_RANK = 3, |
438 | RESULT_TYPE_REVRANK = 4, |
439 | RESULT_TYPE_COUNT = 5, |
440 | RESULT_TYPE_KEY = 6, |
441 | RESULT_TYPE_VALUE = 7, |
442 | RESULT_TYPE_MAP = 8, |
443 | RESULT_TYPE_INDEX_RANGE = 9, |
444 | RESULT_TYPE_REVINDEX_RANGE = 10, |
445 | RESULT_TYPE_RANK_RANGE = 11, |
446 | RESULT_TYPE_REVRANK_RANGE = 12 |
447 | } result_type_t; |
448 | |
449 | typedef enum { |
450 | AS_CDT_OP_FLAG_RESULT_MASK = 0x0000ffff, |
451 | AS_CDT_OP_FLAG_INVERTED = 0x00010000 |
452 | } as_cdt_op_flags; |
453 | |
454 | typedef enum { |
455 | AS_CDT_SORT_ASCENDING = 0, |
456 | AS_CDT_SORT_DESCENDING = 1, |
457 | AS_CDT_SORT_DROP_DUPLICATES = 2 |
458 | } as_cdt_sort_flags; |
459 | |
460 | typedef enum { |
461 | AS_CDT_LIST_MODIFY_DEFAULT = 0x00, |
462 | AS_CDT_LIST_ADD_UNIQUE = 0x01, |
463 | AS_CDT_LIST_INSERT_BOUNDED = 0x02, |
464 | AS_CDT_LIST_NO_FAIL = 0x04, |
465 | AS_CDT_LIST_DO_PARTIAL = 0x08 |
466 | } as_cdt_list_modify_flags; |
467 | |
468 | typedef enum { |
469 | AS_CDT_MAP_MODIFY_DEFAULT = 0x00, |
470 | AS_CDT_MAP_NO_OVERWRITE = 0x01, |
471 | AS_CDT_MAP_NO_CREATE = 0x02, |
472 | AS_CDT_MAP_NO_FAIL = 0x04, |
473 | AS_CDT_MAP_DO_PARTIAL = 0x08 |
474 | } as_cdt_map_modify_flags; |
475 | |
476 | typedef enum { |
477 | AS_CDT_CTX_INDEX = 0, |
478 | AS_CDT_CTX_RANK = 1, |
479 | AS_CDT_CTX_KEY = 2, |
480 | AS_CDT_CTX_VALUE = 3, |
481 | AS_CDT_MAX_CTX |
482 | } as_cdt_subcontext; |
483 | |
484 | #define AS_CDT_CTX_LIST 0x10 |
485 | #define AS_CDT_CTX_MAP 0x20 |
486 | #define AS_CDT_CTX_MASK 0x0f |
487 | |
488 | typedef enum { |
489 | // List operations. |
490 | |
491 | // Create and flags. |
492 | AS_CDT_OP_LIST_SET_TYPE = 0, |
493 | |
494 | // Modify. |
495 | AS_CDT_OP_LIST_APPEND = 1, |
496 | AS_CDT_OP_LIST_APPEND_ITEMS = 2, |
497 | AS_CDT_OP_LIST_INSERT = 3, |
498 | AS_CDT_OP_LIST_INSERT_ITEMS = 4, |
499 | AS_CDT_OP_LIST_POP = 5, |
500 | AS_CDT_OP_LIST_POP_RANGE = 6, |
501 | AS_CDT_OP_LIST_REMOVE = 7, |
502 | AS_CDT_OP_LIST_REMOVE_RANGE = 8, |
503 | AS_CDT_OP_LIST_SET = 9, |
504 | AS_CDT_OP_LIST_TRIM = 10, |
505 | AS_CDT_OP_LIST_CLEAR = 11, |
506 | AS_CDT_OP_LIST_INCREMENT = 12, |
507 | AS_CDT_OP_LIST_SORT = 13, |
508 | |
509 | // Read. |
510 | AS_CDT_OP_LIST_SIZE = 16, |
511 | AS_CDT_OP_LIST_GET = 17, |
512 | AS_CDT_OP_LIST_GET_RANGE = 18, |
513 | AS_CDT_OP_LIST_GET_BY_INDEX = 19, |
514 | AS_CDT_OP_LIST_GET_BY_VALUE = 20, |
515 | AS_CDT_OP_LIST_GET_BY_RANK = 21, |
516 | AS_CDT_OP_LIST_GET_ALL_BY_VALUE = 22, |
517 | AS_CDT_OP_LIST_GET_ALL_BY_VALUE_LIST = 23, |
518 | AS_CDT_OP_LIST_GET_BY_INDEX_RANGE = 24, |
519 | AS_CDT_OP_LIST_GET_BY_VALUE_INTERVAL = 25, |
520 | AS_CDT_OP_LIST_GET_BY_RANK_RANGE = 26, |
521 | AS_CDT_OP_LIST_GET_BY_VALUE_REL_RANK_RANGE = 27, |
522 | |
523 | // More modify - remove by. |
524 | AS_CDT_OP_LIST_REMOVE_BY_INDEX = 32, |
525 | AS_CDT_OP_LIST_REMOVE_BY_VALUE = 33, |
526 | AS_CDT_OP_LIST_REMOVE_BY_RANK = 34, |
527 | AS_CDT_OP_LIST_REMOVE_ALL_BY_VALUE = 35, |
528 | AS_CDT_OP_LIST_REMOVE_ALL_BY_VALUE_LIST = 36, |
529 | AS_CDT_OP_LIST_REMOVE_BY_INDEX_RANGE = 37, |
530 | AS_CDT_OP_LIST_REMOVE_BY_VALUE_INTERVAL = 38, |
531 | AS_CDT_OP_LIST_REMOVE_BY_RANK_RANGE = 39, |
532 | AS_CDT_OP_LIST_REMOVE_BY_VALUE_REL_RANK_RANGE = 40, |
533 | |
534 | // Map operations. |
535 | |
536 | // Create and flags. |
537 | AS_CDT_OP_MAP_SET_TYPE = 64, |
538 | |
539 | // Modify. |
540 | AS_CDT_OP_MAP_ADD = 65, |
541 | AS_CDT_OP_MAP_ADD_ITEMS = 66, |
542 | AS_CDT_OP_MAP_PUT = 67, |
543 | AS_CDT_OP_MAP_PUT_ITEMS = 68, |
544 | AS_CDT_OP_MAP_REPLACE = 69, |
545 | AS_CDT_OP_MAP_REPLACE_ITEMS = 70, |
546 | // 71 is unused. |
547 | // 72 is unused. |
548 | AS_CDT_OP_MAP_INCREMENT = 73, |
549 | AS_CDT_OP_MAP_DECREMENT = 74, |
550 | AS_CDT_OP_MAP_CLEAR = 75, |
551 | AS_CDT_OP_MAP_REMOVE_BY_KEY = 76, |
552 | AS_CDT_OP_MAP_REMOVE_BY_INDEX = 77, |
553 | AS_CDT_OP_MAP_REMOVE_BY_VALUE = 78, |
554 | AS_CDT_OP_MAP_REMOVE_BY_RANK = 79, |
555 | // 80 is unused. |
556 | AS_CDT_OP_MAP_REMOVE_BY_KEY_LIST = 81, |
557 | AS_CDT_OP_MAP_REMOVE_ALL_BY_VALUE = 82, |
558 | AS_CDT_OP_MAP_REMOVE_BY_VALUE_LIST = 83, |
559 | AS_CDT_OP_MAP_REMOVE_BY_KEY_INTERVAL = 84, |
560 | AS_CDT_OP_MAP_REMOVE_BY_INDEX_RANGE = 85, |
561 | AS_CDT_OP_MAP_REMOVE_BY_VALUE_INTERVAL = 86, |
562 | AS_CDT_OP_MAP_REMOVE_BY_RANK_RANGE = 87, |
563 | AS_CDT_OP_MAP_REMOVE_BY_KEY_REL_INDEX_RANGE = 88, |
564 | AS_CDT_OP_MAP_REMOVE_BY_VALUE_REL_RANK_RANGE = 89, |
565 | |
566 | // Read. |
567 | AS_CDT_OP_MAP_SIZE = 96, |
568 | AS_CDT_OP_MAP_GET_BY_KEY = 97, |
569 | AS_CDT_OP_MAP_GET_BY_INDEX = 98, |
570 | AS_CDT_OP_MAP_GET_BY_VALUE = 99, |
571 | AS_CDT_OP_MAP_GET_BY_RANK = 100, |
572 | // 101 is unused. |
573 | AS_CDT_OP_MAP_GET_ALL_BY_VALUE = 102, |
574 | AS_CDT_OP_MAP_GET_BY_KEY_INTERVAL = 103, |
575 | AS_CDT_OP_MAP_GET_BY_INDEX_RANGE = 104, |
576 | AS_CDT_OP_MAP_GET_BY_VALUE_INTERVAL = 105, |
577 | AS_CDT_OP_MAP_GET_BY_RANK_RANGE = 106, |
578 | AS_CDT_OP_MAP_GET_BY_KEY_LIST = 107, |
579 | AS_CDT_OP_MAP_GET_BY_VALUE_LIST = 108, |
580 | AS_CDT_OP_MAP_GET_BY_KEY_REL_INDEX_RANGE = 109, |
581 | AS_CDT_OP_MAP_GET_BY_VALUE_REL_RANK_RANGE = 110, |
582 | |
583 | AS_CDT_OP_CONTEXT_EVAL = 0xFF |
584 | } as_cdt_optype; |
585 | |
586 | //------------------------------------------------ |
587 | // Query responses. |
588 | // |
589 | |
590 | typedef int (*as_netio_finish_cb) (void* udata, int retcode); |
591 | typedef int (*as_netio_start_cb) (void* udata, int seq); |
592 | |
593 | typedef struct as_netio_s { |
594 | as_netio_finish_cb finish_cb; |
595 | as_netio_start_cb start_cb; |
596 | void* data; |
597 | struct as_file_handle_s* fd_h; |
598 | cf_buf_builder* bb_r; |
599 | uint32_t offset; |
600 | uint32_t seq; |
601 | bool slow; |
602 | uint64_t start_time; |
603 | } as_netio; |
604 | |
605 | #define AS_NETIO_OK 0 |
606 | #define AS_NETIO_CONTINUE 1 |
607 | #define AS_NETIO_ERR 2 |
608 | #define AS_NETIO_IO_ERR 3 |
609 | |
610 | |
611 | //========================================================== |
612 | // Public API. |
613 | // |
614 | |
615 | void as_proto_swap(as_proto* proto); |
616 | void (as_msg* m); |
617 | void as_msg_swap_field(as_msg_field* mf); |
618 | void as_msg_swap_op(as_msg_op* op); |
619 | |
620 | cl_msg* as_msg_create_internal(const char* ns_name, uint8_t info1, |
621 | uint8_t info2, uint8_t info3, uint16_t n_ops, uint8_t* ops, |
622 | size_t ops_sz); |
623 | |
624 | cl_msg* as_msg_make_response_msg(uint32_t result_code, uint32_t generation, |
625 | uint32_t void_time, as_msg_op** ops, struct as_bin_s** bins, |
626 | uint16_t bin_count, struct as_namespace_s* ns, cl_msg* msgp_in, |
627 | size_t* msg_sz_in, uint64_t trid); |
628 | int32_t as_msg_make_response_bufbuilder(cf_buf_builder** bb_r, |
629 | struct as_storage_rd_s* rd, bool no_bin_data, cf_vector* select_bins); |
630 | cl_msg* as_msg_make_val_response(bool success, const as_val* val, |
631 | uint32_t result_code, uint32_t generation, uint32_t void_time, |
632 | uint64_t trid, size_t* p_msg_sz); |
633 | void as_msg_make_val_response_bufbuilder(const as_val* val, |
634 | cf_buf_builder** bb_r, uint32_t val_sz, bool); |
635 | |
636 | int as_msg_send_reply(struct as_file_handle_s* fd_h, uint32_t result_code, |
637 | uint32_t generation, uint32_t void_time, as_msg_op** ops, |
638 | struct as_bin_s** bins, uint16_t bin_count, struct as_namespace_s* ns, |
639 | uint64_t trid); |
640 | int as_msg_send_ops_reply(struct as_file_handle_s* fd_h, cf_dyn_buf* db); |
641 | bool as_msg_send_fin(cf_socket* sock, uint32_t result_code); |
642 | size_t as_msg_send_fin_timeout(cf_socket* sock, uint32_t result_code, |
643 | int32_t timeout); |
644 | |
645 | void as_netio_init(); |
646 | int as_netio_send(as_netio* io, bool slow, bool blocking); |
647 | |
648 | static inline bool |
649 | as_proto_is_valid_type(const as_proto* proto) |
650 | { |
651 | return proto->type != 0 && proto->type < PROTO_TYPE_LAST_PLUS_1; |
652 | } |
653 | |
654 | static inline bool |
655 | as_proto_wrapped_is_valid(const as_proto* proto, size_t size) |
656 | { |
657 | return proto->version == PROTO_VERSION && |
658 | proto->type == PROTO_TYPE_AS_MSG && // currently only wrap as_msg |
659 | sizeof(as_proto) + proto->sz == size; |
660 | } |
661 | |
662 | static inline uint32_t |
663 | as_msg_field_get_value_sz(as_msg_field* f) |
664 | { |
665 | return f->field_sz - 1; |
666 | } |
667 | |
668 | static inline as_msg_field* |
669 | as_msg_field_get_next(as_msg_field* f) |
670 | { |
671 | return (as_msg_field*)(((uint8_t*)f) + sizeof(f->field_sz) + f->field_sz); |
672 | } |
673 | |
674 | static inline uint8_t* |
675 | as_msg_field_skip(as_msg_field* f) |
676 | { |
677 | return f->field_sz == 0 ? NULL : (uint8_t*)as_msg_field_get_next(f); |
678 | } |
679 | |
680 | static inline as_msg_field* |
681 | as_msg_field_get(const as_msg* msg, uint8_t type) |
682 | { |
683 | as_msg_field* f = (as_msg_field*)msg->data; |
684 | |
685 | for (uint16_t n = 0; n < msg->n_fields; n++) { |
686 | if (f->type == type) { |
687 | return f; |
688 | } |
689 | |
690 | f = as_msg_field_get_next(f); |
691 | } |
692 | |
693 | return NULL; |
694 | } |
695 | |
696 | static inline uint8_t* |
697 | as_msg_op_get_value_p(as_msg_op* op) |
698 | { |
699 | return (uint8_t*)op + sizeof(as_msg_op) + op->name_sz; |
700 | } |
701 | |
702 | static inline uint32_t |
703 | as_msg_op_get_value_sz(const as_msg_op* op) |
704 | { |
705 | return op->op_sz - (OP_FIXED_SZ + op->name_sz); |
706 | } |
707 | |
708 | static inline as_msg_op* |
709 | as_msg_op_get_next(as_msg_op* op) |
710 | { |
711 | return (as_msg_op*)(((uint8_t*)op) + sizeof(op->op_sz) + op->op_sz); |
712 | } |
713 | |
714 | static inline uint8_t* |
715 | as_msg_op_skip(as_msg_op* op) |
716 | { |
717 | // At least 4 bytes always follow op_sz. |
718 | return OP_FIXED_SZ + (uint32_t)op->name_sz > op->op_sz ? |
719 | NULL : (uint8_t*)as_msg_op_get_next(op); |
720 | } |
721 | |
722 | static inline as_msg_op* |
723 | as_msg_op_iterate(const as_msg* msg, as_msg_op* current, int* n) |
724 | { |
725 | // Skip over the fields the first time. |
726 | if (! current) { |
727 | if (msg->n_ops == 0) { |
728 | return 0; // short cut |
729 | } |
730 | |
731 | as_msg_field* f = (as_msg_field*)msg->data; |
732 | |
733 | for (uint16_t i = 0; i < msg->n_fields; i++) { |
734 | f = as_msg_field_get_next(f); |
735 | } |
736 | |
737 | current = (as_msg_op*)f; |
738 | *n = 0; |
739 | |
740 | return current; |
741 | } |
742 | |
743 | (*n)++; |
744 | |
745 | if (*n >= msg->n_ops) { |
746 | return 0; |
747 | } |
748 | |
749 | return as_msg_op_get_next(current); |
750 | } |
751 | |
752 | #define OP_IS_MODIFY(op) ( \ |
753 | (op) == AS_MSG_OP_INCR || \ |
754 | (op) == AS_MSG_OP_APPEND || \ |
755 | (op) == AS_MSG_OP_PREPEND \ |
756 | ) |
757 | |
758 | #define IS_CDT_LIST_OP(op) ((op) < AS_CDT_OP_MAP_SET_TYPE) |
759 | |