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 // (Note: Bit 4 is unused.)
74 #define AS_MSG_INFO2_CREATE_ONLY (1 << 5) // write record only if it doesn't exist
75 // (Note: Bit 6 is unused.)
76 // (Note: Bit 7 is unused.)
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;
147  bool write;
149 
150 /**
151  * @private
152  * Data used in as_command_parse_result().
153  */
154 typedef struct as_command_parse_result_data_s {
158 
159 /**
160  * @private
161  * Parse results callback used in as_command_execute().
162  */
163 typedef as_status (*as_parse_results_fn) (as_error* err, int fd, uint64_t deadline_ms, void* user_data);
164 
165 /******************************************************************************
166  * FUNCTIONS
167  ******************************************************************************/
168 
169 /**
170  * @private
171  * Calculate size of command header plus key fields.
172  */
173 size_t
174 as_command_key_size(as_policy_key policy, const as_key* key, uint16_t* n_fields);
175 
176 /**
177  * @private
178  * Calculate size of string field.
179  */
180 static inline size_t
182 {
183  return strlen(value) + AS_FIELD_HEADER_SIZE;
184 }
185 
186 /**
187  * @private
188  * Calculate size of field structure given field value size.
189  */
190 static inline size_t
192 {
193  return size + AS_FIELD_HEADER_SIZE;
194 }
195 
196 /**
197  * @private
198  * Calculate size of as_val field.
199  */
200 size_t
201 as_command_value_size(as_val* val, as_buffer* buffer);
202 
203 /**
204  * @private
205  * Calculate size of bin name and value combined.
206  */
207 static inline size_t
208 as_command_bin_size(const as_bin* bin, as_buffer* buffer)
209 {
210  return strlen(bin->name) + as_command_value_size((as_val*)bin->valuep, buffer) + 8;
211 }
212 
213 /**
214  * @private
215  * Calculate size of bin name. Return error is bin name greater than 14 characters.
216  */
217 static inline as_status
218 as_command_bin_name_size(as_error* err, const char* name, size_t* size)
219 {
220  size_t s = strlen(name);
221 
222  if (s > AS_BIN_NAME_MAX_LEN) {
223  return as_error_update(err, AEROSPIKE_ERR_PARAM, "Bin name too long: %s", name);
224  }
225  (*size) += s + AS_OPERATION_HEADER_SIZE;
226  return AEROSPIKE_OK;
227 }
228 
229 /**
230  * @private
231  * Calculate size of string operation.
232  */
233 static inline size_t
235 {
236  return strlen(value) + AS_OPERATION_HEADER_SIZE;
237 }
238 
239 /**
240  * @private
241  * Write command header for all commands.
242  */
243 uint8_t*
244 as_command_write_header(uint8_t* cmd, uint8_t read_attr, uint8_t write_attr,
245  as_policy_commit_level commit_level, as_policy_consistency_level consistency,
246  as_policy_exists exists, as_policy_gen gen_policy, uint32_t gen, uint32_t ttl,
247  uint32_t timeout_ms, uint16_t n_fields, uint16_t n_bins);
248 
249 /**
250  * @private
251  * Write command header for read commands only.
252  */
253 static inline uint8_t*
254 as_command_write_header_read(uint8_t* cmd, uint8_t read_attr, as_policy_consistency_level consistency,
255  uint32_t timeout_ms, uint16_t n_fields, uint16_t n_bins)
256 {
257  if (consistency == AS_POLICY_CONSISTENCY_LEVEL_ALL) {
258  read_attr |= AS_MSG_INFO1_CONSISTENCY_ALL;
259  }
260 
261  cmd[8] = 22;
262  cmd[9] = read_attr;
263  memset(&cmd[10], 0, 12);
264  *(uint32_t*)&cmd[22] = cf_swap_to_be32(timeout_ms);
265  *(uint16_t*)&cmd[26] = cf_swap_to_be16(n_fields);
266  *(uint16_t*)&cmd[28] = cf_swap_to_be16(n_bins);
267  return cmd + AS_HEADER_SIZE;
268 }
269 
270 /**
271  * @private
272  * Write field header.
273  */
274 static inline uint8_t*
275 as_command_write_field_header(uint8_t* p, uint8_t id, uint32_t size)
276 {
277  *(uint32_t*)p = cf_swap_to_be32(size+1);
278  p += 4;
279  *p++ = id;
280  return p;
281 }
282 
283 /**
284  * @private
285  * Write string field.
286  */
287 static inline uint8_t*
288 as_command_write_field_string(uint8_t* begin, uint8_t id, const char* val)
289 {
290  uint8_t* p = begin + AS_FIELD_HEADER_SIZE;
291 
292  // Copy string, but do not transfer null byte.
293  while (*val) {
294  *p++ = *val++;
295  }
296  as_command_write_field_header(begin, id, (uint32_t)(p - begin - AS_FIELD_HEADER_SIZE));
297  return p;
298 }
299 
300 /**
301  * @private
302  * Write uint64_t field.
303  */
304 static inline uint8_t*
305 as_command_write_field_uint64(uint8_t* p, uint8_t id, uint64_t val)
306 {
307  p = as_command_write_field_header(p, id, sizeof(uint64_t));
308  *(uint64_t*)p = cf_swap_to_be64(val);
309  return p + sizeof(uint64_t);
310 }
311 
312 /**
313  * @private
314  * Write as_buffer field.
315  */
316 static inline uint8_t*
317 as_command_write_field_buffer(uint8_t* p, uint8_t id, as_buffer* buffer)
318 {
319  p = as_command_write_field_header(p, id, buffer->size);
320  memcpy(p, buffer->data, buffer->size);
321  return p + buffer->size;
322 }
323 
324 /**
325  * @private
326  * Write digest field.
327  */
328 static inline uint8_t*
330 {
332  memcpy(p, val->value, AS_DIGEST_VALUE_SIZE);
333  return p + AS_DIGEST_VALUE_SIZE;
334 }
335 
336 /**
337  * @private
338  * Write key structure.
339  */
340 uint8_t*
341 as_command_write_key(uint8_t* p, as_policy_key policy, const as_key* key);
342 
343 /**
344  * @private
345  * Write bin header and bin name.
346  */
347 static inline uint8_t*
348 as_command_write_bin_name(uint8_t* cmd, const char* name)
349 {
350  uint8_t* p = cmd + AS_OPERATION_HEADER_SIZE;
351 
352  // Copy string, but do not transfer null byte.
353  while (*name) {
354  *p++ = *name++;
355  }
356  uint8_t name_len = p - cmd - AS_OPERATION_HEADER_SIZE;
357  *(uint32_t*)cmd = cf_swap_to_be32((uint32_t)name_len + 4);
358  cmd += 4;
359  *cmd++ = AS_OPERATOR_READ;
360  *cmd++ = 0;
361  *cmd++ = 0;
362  *cmd++ = name_len;
363  return p;
364 }
365 
366 /**
367  * @private
368  * Write bin.
369  */
370 uint8_t*
371 as_command_write_bin(uint8_t* begin, uint8_t operation_type, const as_bin* bin, as_buffer* buffer);
372 
373 /**
374  * @private
375  * Finish writing command.
376  */
377 static inline size_t
378 as_command_write_end(uint8_t* begin, uint8_t* end)
379 {
380  uint64_t len = end - begin;
381  uint64_t proto = (len - 8) | (AS_MESSAGE_VERSION << 56) | (AS_MESSAGE_TYPE << 48);
382  *(uint64_t*)begin = cf_swap_to_be64(proto);
383  return len;
384 }
385 
386 /**
387  * @private
388  * Finish writing compressed command.
389  */
390 static inline size_t
391 as_command_compress_write_end(uint8_t* begin, uint8_t* end, uint64_t uncompressed_sz)
392 {
393  uint64_t len = end - begin;
394  uint64_t proto = (len - 8) | (AS_MESSAGE_VERSION << 56) | (AS_COMPRESSED_MESSAGE_TYPE << 48);
395  *(uint64_t*)begin = cf_swap_to_be64(proto);
396 
397  // TODO: We are not passing this in network byte order because of a mistake
398  // in the past. Should be fixed in unison with server code.
399  ((as_compressed_proto *)begin)->uncompressed_sz = uncompressed_sz;
400 
401  return len;
402 }
403 
404 /**
405  * @private
406  * Calculate max size the compressed command buffer.
407  */
408 size_t
409 as_command_compress_max_size(size_t cmd_sz);
410 
411 /**
412  * @private
413  * Compress command buffer.
414  */
415 as_status
416 as_command_compress(as_error* err, uint8_t* cmd, size_t cmd_sz, uint8_t* compressed_cmd, size_t* compressed_size);
417 
418 /**
419  * @private
420  * Send command to the server.
421  */
422 as_status
423 as_command_execute(as_cluster* cluster, as_error* err, as_command_node* cn, uint8_t* command, size_t command_len,
424  uint32_t timeout_ms, uint32_t retry,
425  as_parse_results_fn parse_results_fn, void* parse_results_data);
426 
427 /**
428  * @private
429  * Parse header of server response.
430  */
431 as_status
432 as_command_parse_header(as_error* err, int fd, uint64_t deadline_ms, void* user_data);
433 
434 /**
435  * @private
436  * Parse server record. Used for reads.
437  */
438 as_status
439 as_command_parse_result(as_error* err, int fd, uint64_t deadline_ms, void* user_data);
440 
441 /**
442  * @private
443  * Parse server success or failure result.
444  */
445 as_status
446 as_command_parse_success_failure(as_error* err, int fd, uint64_t deadline_ms, void* user_data);
447 
448 /**
449  * @private
450  * Parse server success or failure bins.
451  */
452 as_status
453 as_command_parse_success_failure_bins(uint8_t** pp, as_error* err, as_msg* msg, as_val** value);
454 
455 /**
456  * @private
457  * Parse bins received from the server.
458  */
459 uint8_t*
460 as_command_parse_bins(as_record* rec, uint8_t* buf, uint32_t n_bins, bool deserialize);
461 
462 /**
463  * @private
464  * Parse user defined function error.
465  */
466 as_status
467 as_command_parse_udf_failure(uint8_t* p, as_error* err, as_msg* msg, as_status status);
468 
469 /**
470  * @private
471  * Skip over fields section in returned data.
472  */
473 uint8_t*
474 as_command_ignore_fields(uint8_t* p, uint32_t n_fields);
475 
476 /**
477  * @private
478  * Skip over bins in returned data.
479  */
480 uint8_t*
481 as_command_ignore_bins(uint8_t* p, uint32_t n_bins);
482 
483 /**
484  * @private
485  * Parse key fields received from server. Used for reads.
486  */
487 uint8_t*
488 as_command_parse_key(uint8_t* p, uint32_t n_fields, as_key* key);
489 
490 #ifdef __cplusplus
491 } // end extern "C"
492 #endif
#define AS_FIELD_DIGEST
Definition: as_command.h:41
uint64_t uncompressed_sz
Definition: as_proto.h:848
as_policy_key
Definition: as_policy.h:191
static uint8_t * as_command_write_field_uint64(uint8_t *p, uint8_t id, uint64_t val)
Definition: as_command.h:305
as_policy_replica
Definition: as_policy.h:263
as_policy_consistency_level
Definition: as_policy.h:286
static uint8_t * as_command_write_field_header(uint8_t *p, uint8_t id, uint32_t size)
Definition: as_command.h:275
as_bin_value * valuep
Definition: as_bin.h:94
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, uint32_t retry, as_parse_results_fn parse_results_fn, void *parse_results_data)
as_policy_commit_level
Definition: as_policy.h:309
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:218
as_policy_gen
Definition: as_policy.h:163
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:856
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:234
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:191
as_policy_exists
Definition: as_policy.h:227
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:329
static uint8_t * as_command_write_bin_name(uint8_t *cmd, const char *name)
Definition: as_command.h:348
#define AS_FIELD_HEADER_SIZE
Definition: as_command.h:99
as_status as_command_parse_success_failure(as_error *err, int fd, uint64_t deadline_ms, void *user_data)
uint8_t * as_command_write_key(uint8_t *p, as_policy_key policy, const as_key *key)
as_proto proto
Definition: as_proto.h:847
#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_command_parse_result(as_error *err, int fd, uint64_t deadline_ms, void *user_data)
as_status as_command_parse_header(as_error *err, int fd, uint64_t deadline_ms, void *user_data)
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)
#define AS_MSG_INFO1_CONSISTENCY_ALL
Definition: as_command.h:65
static uint8_t * as_command_write_field_buffer(uint8_t *p, uint8_t id, as_buffer *buffer)
Definition: as_command.h:317
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:288
#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:181
as_status(* as_parse_results_fn)(as_error *err, int fd, uint64_t deadline_ms, void *user_data)
Definition: as_command.h:163
static size_t as_command_write_end(uint8_t *begin, uint8_t *end)
Definition: as_command.h:378
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:391
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:254
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:208
as_status as_command_compress(as_error *err, uint8_t *cmd, size_t cmd_sz, uint8_t *compressed_cmd, size_t *compressed_size)