All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_command.h
Go to the documentation of this file.
1 /*
2  * Copyright 2008-2017 Aerospike, Inc.
3  *
4  * Portions may be licensed to Aerospike, Inc. under one or more contributor
5  * license agreements.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8  * use this file except in compliance with the License. You may obtain a copy of
9  * the License at http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations under
15  * the License.
16  */
17 #pragma once
18 
19 #include <aerospike/as_bin.h>
20 #include <aerospike/as_buffer.h>
22 #include <aerospike/as_cluster.h>
23 #include <aerospike/as_key.h>
25 #include <aerospike/as_proto.h>
26 #include <aerospike/as_record.h>
27 #include <citrusleaf/cf_byte_order.h>
28 #include <citrusleaf/cf_digest.h>
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /******************************************************************************
35  * MACROS
36  *****************************************************************************/
37 
38 // Field IDs
39 #define AS_FIELD_NAMESPACE 0
40 #define AS_FIELD_SETNAME 1
41 #define AS_FIELD_KEY 2
42 #define AS_FIELD_DIGEST 4
43 #define AS_FIELD_DIGEST_ARRAY 6
44 #define AS_FIELD_TASK_ID 7
45 #define AS_FIELD_SCAN_OPTIONS 8
46 #define AS_FIELD_SCAN_TIMEOUT 9
47 #define AS_FIELD_INDEX_RANGE 22
48 #define AS_FIELD_INDEX_FILTER 23
49 #define AS_FIELD_INDEX_LIMIT 24
50 #define AS_FIELD_INDEX_ORDER 25
51 #define AS_FIELD_INDEX_TYPE 26
52 #define AS_FIELD_UDF_PACKAGE_NAME 30
53 #define AS_FIELD_UDF_FUNCTION 31
54 #define AS_FIELD_UDF_ARGLIST 32
55 #define AS_FIELD_UDF_OP 33
56 #define AS_FIELD_QUERY_BINS 40
57 #define AS_FIELD_BATCH_INDEX 41
58 #define AS_FIELD_BATCH_INDEX_WITH_SET 42
59 #define AS_FIELD_PREDEXP 43
60 
61 // Message info1 bits
62 #define AS_MSG_INFO1_READ (1 << 0) // contains a read operation
63 #define AS_MSG_INFO1_GET_ALL (1 << 1) // get all bins, period
64 // (Note: Bit 2 is unused.)
65 #define AS_MSG_INFO1_BATCH_INDEX (1 << 3) // batch read
66 #define AS_MSG_INFO1_XDR (1 << 4) // operation is being performed by XDR
67 #define AS_MSG_INFO1_GET_NOBINDATA (1 << 5) // do not get information about bins and its data
68 #define AS_MSG_INFO1_CONSISTENCY_ALL (1 << 6) // read consistency level - bit 0
69 // (Note: Bit 7 is unused.)
70 
71 // Message info2 bits
72 #define AS_MSG_INFO2_WRITE (1 << 0) // contains a write semantic
73 #define AS_MSG_INFO2_DELETE (1 << 1) // delete record
74 #define AS_MSG_INFO2_GENERATION (1 << 2) // pay attention to the generation
75 #define AS_MSG_INFO2_GENERATION_GT (1 << 3) // apply write if new generation >= old, good for restore
76 #define AS_MSG_INFO2_DURABLE_DELETE (1 << 4) // transaction resulting in record deletion leaves tombstone (Enterprise only).
77 #define AS_MSG_INFO2_CREATE_ONLY (1 << 5) // write record only if it doesn't exist
78 // (Note: Bit 6 is unused.)
79 #define AS_MSG_INFO2_RESPOND_ALL_OPS (1 << 7) // return a result for every operation.
80 
81 // Message info3 bits
82 #define AS_MSG_INFO3_LAST (1 << 0) // this is the last of a multi-part message
83 #define AS_MSG_INFO3_COMMIT_MASTER (1 << 1) // write commit level - bit 0
84 // (Note: Bit 2 is unused.)
85 #define AS_MSG_INFO3_UPDATE_ONLY (1 << 3) // update existing record only, do not create new record
86 #define AS_MSG_INFO3_CREATE_OR_REPLACE (1 << 4) // completely replace existing record, or create new record
87 #define AS_MSG_INFO3_REPLACE_ONLY (1 << 5) // completely replace existing record, do not create new record
88 // (Note: Bit 6 is unused.)
89 // (Note: Bit 7 is unused.)
90 
91 // Transaction message
92 #define AS_MESSAGE_VERSION 2L
93 #define AS_MESSAGE_TYPE 3L
94 #define AS_COMPRESSED_MESSAGE_TYPE 4L
95 
96 // Info message
97 #define AS_INFO_MESSAGE_VERSION 2L
98 #define AS_INFO_MESSAGE_TYPE 1L
99 
100 // Misc
101 #define AS_HEADER_SIZE 30
102 #define AS_FIELD_HEADER_SIZE 5
103 #define AS_OPERATION_HEADER_SIZE 8
104 
105 #define AS_STACK_BUF_SIZE (1024 * 16)
106 
107 /**
108  * @private
109  * Macros use these stand-ins for cf_malloc() / cf_free(), so that
110  * instrumentation properly substitutes them.
111  */
112 
113 static inline void*
114 local_malloc(size_t size)
115 {
116  return cf_malloc(size);
117 }
118 
119 static inline void
120 local_free(void* memory)
121 {
122  return cf_free(memory);
123 }
124 
125 /**
126  * @private
127  * Allocate command buffer on stack or heap depending on given size.
128  */
129 #define as_command_init(_sz) (_sz > AS_STACK_BUF_SIZE) ? (uint8_t*)local_malloc(_sz) : (uint8_t*)alloca(_sz)
130 
131 /**
132  * @private
133  * Free command buffer.
134  */
135 #define as_command_free(_buf, _sz) if (_sz > AS_STACK_BUF_SIZE) {local_free(_buf);}
136 
137 /******************************************************************************
138  * TYPES
139  *****************************************************************************/
140 
141 /**
142  * @private
143  * Node map data used in as_command_execute().
144  */
145 typedef struct as_command_node_s {
147  const char* ns;
148  const uint8_t* digest;
151 
152 /**
153  * @private
154  * Data used in as_command_parse_result().
155  */
156 typedef struct as_command_parse_result_data_s {
160 
161 /**
162  * @private
163  * Parse results callback used in as_command_execute().
164  */
165 typedef as_status (*as_parse_results_fn) (as_error* err, as_socket* sock, as_node* node, uint32_t max_idle, uint64_t deadline_ms, void* user_data);
166 
167 /******************************************************************************
168  * FUNCTIONS
169  ******************************************************************************/
170 
171 /**
172  * @private
173  * Calculate size of command header plus key fields.
174  */
175 size_t
176 as_command_key_size(as_policy_key policy, const as_key* key, uint16_t* n_fields);
177 
178 /**
179  * @private
180  * Calculate size of string field.
181  */
182 static inline size_t
184 {
185  return strlen(value) + AS_FIELD_HEADER_SIZE;
186 }
187 
188 /**
189  * @private
190  * Calculate size of field structure given field value size.
191  */
192 static inline size_t
194 {
195  return size + AS_FIELD_HEADER_SIZE;
196 }
197 
198 /**
199  * @private
200  * Calculate size of as_val field.
201  */
202 size_t
203 as_command_value_size(as_val* val, as_buffer* buffer);
204 
205 /**
206  * @private
207  * Calculate size of bin name and value combined.
208  */
209 static inline size_t
210 as_command_bin_size(const as_bin* bin, as_buffer* buffer)
211 {
212  return strlen(bin->name) + as_command_value_size((as_val*)bin->valuep, buffer) + 8;
213 }
214 
215 /**
216  * @private
217  * Calculate size of bin name. Return error is bin name greater than 14 characters.
218  */
219 static inline as_status
220 as_command_bin_name_size(as_error* err, const char* name, size_t* size)
221 {
222  size_t s = strlen(name);
223 
224  if (s > AS_BIN_NAME_MAX_LEN) {
225  return as_error_update(err, AEROSPIKE_ERR_PARAM, "Bin name too long: %s", name);
226  }
227  (*size) += s + AS_OPERATION_HEADER_SIZE;
228  return AEROSPIKE_OK;
229 }
230 
231 /**
232  * @private
233  * Calculate size of string operation.
234  */
235 static inline size_t
237 {
238  return strlen(value) + AS_OPERATION_HEADER_SIZE;
239 }
240 
241 /**
242  * @private
243  * Write command header for all commands.
244  */
245 uint8_t*
246 as_command_write_header(uint8_t* cmd, uint8_t read_attr, uint8_t write_attr,
247  as_policy_commit_level commit_level, as_policy_consistency_level consistency,
248  as_policy_exists exists, as_policy_gen gen_policy, uint32_t gen, uint32_t ttl,
249  uint32_t timeout_ms, uint16_t n_fields, uint16_t n_bins, bool durable_delete);
250 
251 /**
252  * @private
253  * Write command header for read commands only.
254  */
255 static inline uint8_t*
256 as_command_write_header_read(uint8_t* cmd, uint8_t read_attr, as_policy_consistency_level consistency,
257  uint32_t timeout_ms, uint16_t n_fields, uint16_t n_bins)
258 {
259  if (consistency == AS_POLICY_CONSISTENCY_LEVEL_ALL) {
260  read_attr |= AS_MSG_INFO1_CONSISTENCY_ALL;
261  }
262 
263  cmd[8] = 22;
264  cmd[9] = read_attr;
265  memset(&cmd[10], 0, 12);
266  *(uint32_t*)&cmd[22] = cf_swap_to_be32(timeout_ms);
267  *(uint16_t*)&cmd[26] = cf_swap_to_be16(n_fields);
268  *(uint16_t*)&cmd[28] = cf_swap_to_be16(n_bins);
269  return cmd + AS_HEADER_SIZE;
270 }
271 
272 /**
273  * @private
274  * Write field header.
275  */
276 static inline uint8_t*
277 as_command_write_field_header(uint8_t* p, uint8_t id, uint32_t size)
278 {
279  *(uint32_t*)p = cf_swap_to_be32(size+1);
280  p += 4;
281  *p++ = id;
282  return p;
283 }
284 
285 /**
286  * @private
287  * Write string field.
288  */
289 static inline uint8_t*
290 as_command_write_field_string(uint8_t* begin, uint8_t id, const char* val)
291 {
292  uint8_t* p = begin + AS_FIELD_HEADER_SIZE;
293 
294  // Copy string, but do not transfer null byte.
295  while (*val) {
296  *p++ = *val++;
297  }
298  as_command_write_field_header(begin, id, (uint32_t)(p - begin - AS_FIELD_HEADER_SIZE));
299  return p;
300 }
301 
302 /**
303  * @private
304  * Write uint64_t field.
305  */
306 static inline uint8_t*
307 as_command_write_field_uint64(uint8_t* p, uint8_t id, uint64_t val)
308 {
309  p = as_command_write_field_header(p, id, sizeof(uint64_t));
310  *(uint64_t*)p = cf_swap_to_be64(val);
311  return p + sizeof(uint64_t);
312 }
313 
314 /**
315  * @private
316  * Write as_buffer field.
317  */
318 static inline uint8_t*
319 as_command_write_field_buffer(uint8_t* p, uint8_t id, as_buffer* buffer)
320 {
321  p = as_command_write_field_header(p, id, buffer->size);
322  memcpy(p, buffer->data, buffer->size);
323  return p + buffer->size;
324 }
325 
326 /**
327  * @private
328  * Write digest field.
329  */
330 static inline uint8_t*
332 {
334  memcpy(p, val->value, AS_DIGEST_VALUE_SIZE);
335  return p + AS_DIGEST_VALUE_SIZE;
336 }
337 
338 /**
339  * @private
340  * Write key structure.
341  */
342 uint8_t*
343 as_command_write_key(uint8_t* p, as_policy_key policy, const as_key* key);
344 
345 /**
346  * @private
347  * Write bin header and bin name.
348  */
349 static inline uint8_t*
350 as_command_write_bin_name(uint8_t* cmd, const char* name)
351 {
352  uint8_t* p = cmd + AS_OPERATION_HEADER_SIZE;
353 
354  // Copy string, but do not transfer null byte.
355  while (*name) {
356  *p++ = *name++;
357  }
358  uint8_t name_len = p - cmd - AS_OPERATION_HEADER_SIZE;
359  *(uint32_t*)cmd = cf_swap_to_be32((uint32_t)name_len + 4);
360  cmd += 4;
361  *cmd++ = AS_OPERATOR_READ;
362  *cmd++ = 0;
363  *cmd++ = 0;
364  *cmd++ = name_len;
365  return p;
366 }
367 
368 /**
369  * @private
370  * Write bin.
371  */
372 uint8_t*
373 as_command_write_bin(uint8_t* begin, uint8_t operation_type, const as_bin* bin, as_buffer* buffer);
374 
375 /**
376  * @private
377  * Finish writing command.
378  */
379 static inline size_t
380 as_command_write_end(uint8_t* begin, uint8_t* end)
381 {
382  uint64_t len = end - begin;
383  uint64_t proto = (len - 8) | (AS_MESSAGE_VERSION << 56) | (AS_MESSAGE_TYPE << 48);
384  *(uint64_t*)begin = cf_swap_to_be64(proto);
385  return len;
386 }
387 
388 /**
389  * @private
390  * Finish writing compressed command.
391  */
392 static inline size_t
393 as_command_compress_write_end(uint8_t* begin, uint8_t* end, uint64_t uncompressed_sz)
394 {
395  uint64_t len = end - begin;
396  uint64_t proto = (len - 8) | (AS_MESSAGE_VERSION << 56) | (AS_COMPRESSED_MESSAGE_TYPE << 48);
397  *(uint64_t*)begin = cf_swap_to_be64(proto);
398 
399  // TODO: We are not passing this in network byte order because of a mistake
400  // in the past. Should be fixed in unison with server code.
401  ((as_compressed_proto *)begin)->uncompressed_sz = uncompressed_sz;
402 
403  return len;
404 }
405 
406 /**
407  * @private
408  * Calculate max size the compressed command buffer.
409  */
410 size_t
411 as_command_compress_max_size(size_t cmd_sz);
412 
413 /**
414  * @private
415  * Compress command buffer.
416  */
417 as_status
418 as_command_compress(as_error* err, uint8_t* cmd, size_t cmd_sz, uint8_t* compressed_cmd, size_t* compressed_size);
419 
420 /**
421  * @private
422  * Send command to the server.
423  */
424 as_status
426  as_cluster* cluster, as_error* err, as_command_policy* policy, as_command_node* cn,
427  uint8_t* command, size_t command_len, as_parse_results_fn parse_results_fn, void* parse_results_data
428 );
429 
430 /**
431  * @private
432  * Parse header of server response.
433  */
434 as_status
435 as_command_parse_header(as_error* err, as_socket* sock, as_node* node, uint32_t max_idle, uint64_t deadline_ms, void* user_data);
436 
437 /**
438  * @private
439  * Parse server record. Used for reads.
440  */
441 as_status
442 as_command_parse_result(as_error* err, as_socket* sock, as_node* node, uint32_t max_idle, uint64_t deadline_ms, void* user_data);
443 
444 /**
445  * @private
446  * Parse server success or failure result.
447  */
448 as_status
449 as_command_parse_success_failure(as_error* err, as_socket* sock, as_node* node, uint32_t max_idle, uint64_t deadline_ms, void* user_data);
450 
451 /**
452  * @private
453  * Parse server success or failure bins.
454  */
455 as_status
456 as_command_parse_success_failure_bins(uint8_t** pp, as_error* err, as_msg* msg, as_val** value);
457 
458 /**
459  * @private
460  * Parse bins received from the server.
461  */
462 as_status
463 as_command_parse_bins(uint8_t** pp, as_error* err, as_record* rec, uint32_t n_bins, bool deserialize);
464 
465 /**
466  * @private
467  * Parse user defined function error.
468  */
469 as_status
470 as_command_parse_udf_failure(uint8_t* p, as_error* err, as_msg* msg, as_status status);
471 
472 /**
473  * @private
474  * Skip over fields section in returned data.
475  */
476 uint8_t*
477 as_command_ignore_fields(uint8_t* p, uint32_t n_fields);
478 
479 /**
480  * @private
481  * Skip over bins in returned data.
482  */
483 uint8_t*
484 as_command_ignore_bins(uint8_t* p, uint32_t n_bins);
485 
486 /**
487  * @private
488  * Parse key fields received from server. Used for reads.
489  */
490 uint8_t*
491 as_command_parse_key(uint8_t* p, uint32_t n_fields, as_key* key);
492 
493 #ifdef __cplusplus
494 } // end extern "C"
495 #endif
#define AS_FIELD_DIGEST
Definition: as_command.h:42
uint64_t uncompressed_sz
Definition: as_proto.h:49
as_policy_key
Definition: as_policy.h:198
static uint8_t * as_command_write_field_uint64(uint8_t *p, uint8_t id, uint64_t val)
Definition: as_command.h:307
as_policy_replica
Definition: as_policy.h:270
as_policy_consistency_level
Definition: as_policy.h:301
static uint8_t * as_command_write_field_header(uint8_t *p, uint8_t id, uint32_t size)
Definition: as_command.h:277
as_status as_command_parse_header(as_error *err, as_socket *sock, as_node *node, uint32_t max_idle, uint64_t deadline_ms, void *user_data)
as_status as_command_parse_result(as_error *err, as_socket *sock, as_node *node, uint32_t max_idle, uint64_t deadline_ms, void *user_data)
as_bin_value * valuep
Definition: as_bin.h:94
as_policy_commit_level
Definition: as_policy.h:324
as_status
Definition: as_status.h:30
static as_status as_command_bin_name_size(as_error *err, const char *name, size_t *size)
Definition: as_command.h:220
as_policy_gen
Definition: as_policy.h:170
as_policy_replica replica
Definition: as_command.h:149
#define AS_BIN_NAME_MAX_LEN
Definition: as_bin.h:43
#define AS_OPERATION_HEADER_SIZE
Definition: as_command.h:103
uint16_t n_fields
Definition: as_proto.h:57
static void local_free(void *memory)
Definition: as_command.h:120
static size_t as_command_string_operation_size(const char *value)
Definition: as_command.h:236
as_bin_name name
Definition: as_bin.h:82
#define AS_MESSAGE_VERSION
Definition: as_command.h:92
as_digest_value value
Definition: as_key.h:99
size_t as_command_value_size(as_val *val, as_buffer *buffer)
static size_t as_command_field_size(size_t size)
Definition: as_command.h:193
as_policy_exists
Definition: as_policy.h:234
Definition: as_bin.h:77
Definition: as_val.h:57
static uint8_t * as_command_write_field_digest(uint8_t *p, const as_digest *val)
Definition: as_command.h:331
static uint8_t * as_command_write_bin_name(uint8_t *cmd, const char *name)
Definition: as_command.h:350
#define AS_FIELD_HEADER_SIZE
Definition: as_command.h:102
as_status as_command_parse_bins(uint8_t **pp, as_error *err, as_record *rec, uint32_t n_bins, bool deserialize)
uint8_t * as_command_write_key(uint8_t *p, as_policy_key policy, const as_key *key)
as_proto proto
Definition: as_proto.h:48
#define AS_MESSAGE_TYPE
Definition: as_command.h:93
static void * local_malloc(size_t size)
Definition: as_command.h:114
uint8_t * as_command_ignore_bins(uint8_t *p, uint32_t n_bins)
as_status as_command_parse_udf_failure(uint8_t *p, as_error *err, as_msg *msg, as_status status)
#define AS_DIGEST_VALUE_SIZE
Definition: as_key.h:41
as_node * node
Definition: as_command.h:146
#define AS_MSG_INFO1_CONSISTENCY_ALL
Definition: as_command.h:68
static uint8_t * as_command_write_field_buffer(uint8_t *p, uint8_t id, as_buffer *buffer)
Definition: as_command.h:319
uint8_t * as_command_ignore_fields(uint8_t *p, uint32_t n_fields)
static uint8_t * as_command_write_field_string(uint8_t *begin, uint8_t id, const char *val)
Definition: as_command.h:290
#define AS_HEADER_SIZE
Definition: as_command.h:101
uint8_t * as_command_parse_key(uint8_t *p, uint32_t n_fields, as_key *key)
const uint8_t * digest
Definition: as_command.h:148
const char * ns
Definition: as_command.h:147
as_status as_command_parse_success_failure(as_error *err, as_socket *sock, as_node *node, uint32_t max_idle, uint64_t deadline_ms, void *user_data)
static size_t as_command_string_field_size(const char *value)
Definition: as_command.h:183
as_status(* as_parse_results_fn)(as_error *err, as_socket *sock, as_node *node, uint32_t max_idle, uint64_t deadline_ms, void *user_data)
Definition: as_command.h:165
static size_t as_command_write_end(uint8_t *begin, uint8_t *end)
Definition: as_command.h:380
size_t as_command_compress_max_size(size_t cmd_sz)
static size_t as_command_compress_write_end(uint8_t *begin, uint8_t *end, uint64_t uncompressed_sz)
Definition: as_command.h:393
as_status as_command_execute(as_cluster *cluster, as_error *err, as_command_policy *policy, as_command_node *cn, uint8_t *command, size_t command_len, as_parse_results_fn parse_results_fn, void *parse_results_data)
as_status as_command_parse_success_failure_bins(uint8_t **pp, as_error *err, as_msg *msg, as_val **value)
uint8_t * as_command_write_bin(uint8_t *begin, uint8_t operation_type, const as_bin *bin, as_buffer *buffer)
Definition: as_key.h:199
size_t as_command_key_size(as_policy_key policy, const as_key *key, uint16_t *n_fields)
static uint8_t * as_command_write_header_read(uint8_t *cmd, uint8_t read_attr, as_policy_consistency_level consistency, uint32_t timeout_ms, uint16_t n_fields, uint16_t n_bins)
Definition: as_command.h:256
#define as_error_update(__err, __code, __fmt,...)
Definition: as_error.h:135
#define AS_COMPRESSED_MESSAGE_TYPE
Definition: as_command.h:94
static size_t as_command_bin_size(const as_bin *bin, as_buffer *buffer)
Definition: as_command.h:210
as_status as_command_compress(as_error *err, uint8_t *cmd, size_t cmd_sz, uint8_t *compressed_cmd, size_t *compressed_size)
uint8_t * as_command_write_header(uint8_t *cmd, uint8_t read_attr, uint8_t write_attr, as_policy_commit_level commit_level, as_policy_consistency_level consistency, as_policy_exists exists, as_policy_gen gen_policy, uint32_t gen, uint32_t ttl, uint32_t timeout_ms, uint16_t n_fields, uint16_t n_bins, bool durable_delete)