| 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 | |