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