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 #define AS_MSG_INFO3_LINEARIZE_READ (1 << 6) // linearize read when in CP mode.
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  bool linearize_read, as_policy_exists exists, as_policy_gen gen_policy, uint32_t gen,
248  uint32_t ttl, 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  bool linearize_read, uint32_t timeout_ms, uint16_t n_fields, uint16_t n_bins)
257 {
258  uint8_t info_attr = 0;
259 
260  if (linearize_read) {
261  info_attr |= AS_MSG_INFO3_LINEARIZE_READ;
262  }
263 
264  if (consistency == AS_POLICY_CONSISTENCY_LEVEL_ALL) {
265  read_attr |= AS_MSG_INFO1_CONSISTENCY_ALL;
266  }
267 
268  cmd[8] = 22;
269  cmd[9] = read_attr;
270  cmd[10] = 0;
271  cmd[11] = info_attr;
272  memset(&cmd[12], 0, 10);
273  *(uint32_t*)&cmd[22] = cf_swap_to_be32(timeout_ms);
274  *(uint16_t*)&cmd[26] = cf_swap_to_be16(n_fields);
275  *(uint16_t*)&cmd[28] = cf_swap_to_be16(n_bins);
276  return cmd + AS_HEADER_SIZE;
277 }
278 
279 /**
280  * @private
281  * Write field header.
282  */
283 static inline uint8_t*
284 as_command_write_field_header(uint8_t* p, uint8_t id, uint32_t size)
285 {
286  *(uint32_t*)p = cf_swap_to_be32(size+1);
287  p += 4;
288  *p++ = id;
289  return p;
290 }
291 
292 /**
293  * @private
294  * Write string field.
295  */
296 static inline uint8_t*
297 as_command_write_field_string(uint8_t* begin, uint8_t id, const char* val)
298 {
299  uint8_t* p = begin + AS_FIELD_HEADER_SIZE;
300 
301  // Copy string, but do not transfer null byte.
302  while (*val) {
303  *p++ = *val++;
304  }
305  as_command_write_field_header(begin, id, (uint32_t)(p - begin - AS_FIELD_HEADER_SIZE));
306  return p;
307 }
308 
309 /**
310  * @private
311  * Write uint64_t field.
312  */
313 static inline uint8_t*
314 as_command_write_field_uint64(uint8_t* p, uint8_t id, uint64_t val)
315 {
316  p = as_command_write_field_header(p, id, sizeof(uint64_t));
317  *(uint64_t*)p = cf_swap_to_be64(val);
318  return p + sizeof(uint64_t);
319 }
320 
321 /**
322  * @private
323  * Write as_buffer field.
324  */
325 static inline uint8_t*
326 as_command_write_field_buffer(uint8_t* p, uint8_t id, as_buffer* buffer)
327 {
328  p = as_command_write_field_header(p, id, buffer->size);
329  memcpy(p, buffer->data, buffer->size);
330  return p + buffer->size;
331 }
332 
333 /**
334  * @private
335  * Write digest field.
336  */
337 static inline uint8_t*
339 {
341  memcpy(p, val->value, AS_DIGEST_VALUE_SIZE);
342  return p + AS_DIGEST_VALUE_SIZE;
343 }
344 
345 /**
346  * @private
347  * Write key structure.
348  */
349 uint8_t*
350 as_command_write_key(uint8_t* p, as_policy_key policy, const as_key* key);
351 
352 /**
353  * @private
354  * Write bin header and bin name.
355  */
356 static inline uint8_t*
357 as_command_write_bin_name(uint8_t* cmd, const char* name)
358 {
359  uint8_t* p = cmd + AS_OPERATION_HEADER_SIZE;
360 
361  // Copy string, but do not transfer null byte.
362  while (*name) {
363  *p++ = *name++;
364  }
365  uint8_t name_len = p - cmd - AS_OPERATION_HEADER_SIZE;
366  *(uint32_t*)cmd = cf_swap_to_be32((uint32_t)name_len + 4);
367  cmd += 4;
368  *cmd++ = AS_OPERATOR_READ;
369  *cmd++ = 0;
370  *cmd++ = 0;
371  *cmd++ = name_len;
372  return p;
373 }
374 
375 /**
376  * @private
377  * Write bin.
378  */
379 uint8_t*
380 as_command_write_bin(uint8_t* begin, uint8_t operation_type, const as_bin* bin, as_buffer* buffer);
381 
382 /**
383  * @private
384  * Finish writing command.
385  */
386 static inline size_t
387 as_command_write_end(uint8_t* begin, uint8_t* end)
388 {
389  uint64_t len = end - begin;
390  uint64_t proto = (len - 8) | (AS_MESSAGE_VERSION << 56) | (AS_MESSAGE_TYPE << 48);
391  *(uint64_t*)begin = cf_swap_to_be64(proto);
392  return len;
393 }
394 
395 /**
396  * @private
397  * Finish writing compressed command.
398  */
399 static inline size_t
400 as_command_compress_write_end(uint8_t* begin, uint8_t* end, uint64_t uncompressed_sz)
401 {
402  uint64_t len = end - begin;
403  uint64_t proto = (len - 8) | (AS_MESSAGE_VERSION << 56) | (AS_COMPRESSED_MESSAGE_TYPE << 48);
404  *(uint64_t*)begin = cf_swap_to_be64(proto);
405 
406  // TODO: We are not passing this in network byte order because of a mistake
407  // in the past. Should be fixed in unison with server code.
408  ((as_compressed_proto *)begin)->uncompressed_sz = uncompressed_sz;
409 
410  return len;
411 }
412 
413 /**
414  * @private
415  * Calculate max size the compressed command buffer.
416  */
417 size_t
418 as_command_compress_max_size(size_t cmd_sz);
419 
420 /**
421  * @private
422  * Compress command buffer.
423  */
424 as_status
425 as_command_compress(as_error* err, uint8_t* cmd, size_t cmd_sz, uint8_t* compressed_cmd, size_t* compressed_size);
426 
427 /**
428  * @private
429  * Send command to the server.
430  */
431 as_status
433  as_cluster* cluster, as_error* err, const as_policy_base* policy, as_command_node* cn,
434  uint8_t* command, size_t command_len, as_parse_results_fn parse_results_fn, void* parse_results_data,
435  bool is_read
436 );
437 
438 /**
439  * @private
440  * Parse header of server response.
441  */
442 as_status
443 as_command_parse_header(as_error* err, as_socket* sock, as_node* node, uint32_t socket_timeout, uint64_t deadline_ms, void* user_data);
444 
445 /**
446  * @private
447  * Parse server record. Used for reads.
448  */
449 as_status
450 as_command_parse_result(as_error* err, as_socket* sock, as_node* node, uint32_t socket_timeout, uint64_t deadline_ms, void* user_data);
451 
452 /**
453  * @private
454  * Parse server success or failure result.
455  */
456 as_status
457 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);
458 
459 /**
460  * @private
461  * Parse server success or failure bins.
462  */
463 as_status
464 as_command_parse_success_failure_bins(uint8_t** pp, as_error* err, as_msg* msg, as_val** value);
465 
466 /**
467  * @private
468  * Parse bins received from the server.
469  */
470 as_status
471 as_command_parse_bins(uint8_t** pp, as_error* err, as_record* rec, uint32_t n_bins, bool deserialize);
472 
473 /**
474  * @private
475  * Parse user defined function error.
476  */
477 as_status
478 as_command_parse_udf_failure(uint8_t* p, as_error* err, as_msg* msg, as_status status);
479 
480 /**
481  * @private
482  * Skip over fields section in returned data.
483  */
484 uint8_t*
485 as_command_ignore_fields(uint8_t* p, uint32_t n_fields);
486 
487 /**
488  * @private
489  * Skip over bins in returned data.
490  */
491 uint8_t*
492 as_command_ignore_bins(uint8_t* p, uint32_t n_bins);
493 
494 /**
495  * @private
496  * Parse key fields received from server. Used for reads.
497  */
498 uint8_t*
499 as_command_parse_key(uint8_t* p, uint32_t n_fields, as_key* key);
500 
501 #ifdef __cplusplus
502 } // end extern "C"
503 #endif