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