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
46struct as_bin_s;
47struct as_file_handle_s;
48struct as_index_s;
49struct as_namespace_s;
50struct as_storage_rd_s;
51struct 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
159typedef 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.
181typedef 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
191typedef struct as_msg_s {
192 uint8_t header_sz; // 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.
207typedef 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
259typedef 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
325typedef 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!
357typedef 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
367typedef 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
398typedef 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
405typedef 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
411typedef 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
424typedef 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
433typedef 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
449typedef enum {
450 AS_CDT_OP_FLAG_RESULT_MASK = 0x0000ffff,
451 AS_CDT_OP_FLAG_INVERTED = 0x00010000
452} as_cdt_op_flags;
453
454typedef 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
460typedef 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
468typedef 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
476typedef 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
488typedef 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
590typedef int (*as_netio_finish_cb) (void* udata, int retcode);
591typedef int (*as_netio_start_cb) (void* udata, int seq);
592
593typedef 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
615void as_proto_swap(as_proto* proto);
616void as_msg_swap_header(as_msg* m);
617void as_msg_swap_field(as_msg_field* mf);
618void as_msg_swap_op(as_msg_op* op);
619
620cl_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
624cl_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);
628int32_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);
630cl_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);
633void as_msg_make_val_response_bufbuilder(const as_val* val,
634 cf_buf_builder** bb_r, uint32_t val_sz, bool);
635
636int 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);
640int as_msg_send_ops_reply(struct as_file_handle_s* fd_h, cf_dyn_buf* db);
641bool as_msg_send_fin(cf_socket* sock, uint32_t result_code);
642size_t as_msg_send_fin_timeout(cf_socket* sock, uint32_t result_code,
643 int32_t timeout);
644
645void as_netio_init();
646int as_netio_send(as_netio* io, bool slow, bool blocking);
647
648static inline bool
649as_proto_is_valid_type(const as_proto* proto)
650{
651 return proto->type != 0 && proto->type < PROTO_TYPE_LAST_PLUS_1;
652}
653
654static inline bool
655as_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
662static inline uint32_t
663as_msg_field_get_value_sz(as_msg_field* f)
664{
665 return f->field_sz - 1;
666}
667
668static inline as_msg_field*
669as_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
674static inline uint8_t*
675as_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
680static inline as_msg_field*
681as_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
696static inline uint8_t*
697as_msg_op_get_value_p(as_msg_op* op)
698{
699 return (uint8_t*)op + sizeof(as_msg_op) + op->name_sz;
700}
701
702static inline uint32_t
703as_msg_op_get_value_sz(const as_msg_op* op)
704{
705 return op->op_sz - (OP_FIXED_SZ + op->name_sz);
706}
707
708static inline as_msg_op*
709as_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
714static inline uint8_t*
715as_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
722static inline as_msg_op*
723as_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