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 uint8_t*
357 as_command_write_bin_name(uint8_t* cmd, const char* name);
358 
359 /**
360  * @private
361  * Write bin.
362  */
363 uint8_t*
364 as_command_write_bin(uint8_t* begin, as_operator op_type, const as_bin* bin, as_buffer* buffer);
365 
366 /**
367  * @private
368  * Finish writing command.
369  */
370 static inline size_t
371 as_command_write_end(uint8_t* begin, uint8_t* end)
372 {
373  uint64_t len = end - begin;
374  uint64_t proto = (len - 8) | (AS_MESSAGE_VERSION << 56) | (AS_MESSAGE_TYPE << 48);
375  *(uint64_t*)begin = cf_swap_to_be64(proto);
376  return len;
377 }
378 
379 /**
380  * @private
381  * Finish writing compressed command.
382  */
383 static inline size_t
384 as_command_compress_write_end(uint8_t* begin, uint8_t* end, uint64_t uncompressed_sz)
385 {
386  uint64_t len = end - begin;
387  uint64_t proto = (len - 8) | (AS_MESSAGE_VERSION << 56) | (AS_COMPRESSED_MESSAGE_TYPE << 48);
388  *(uint64_t*)begin = cf_swap_to_be64(proto);
389 
390  // TODO: We are not passing this in network byte order because of a mistake
391  // in the past. Should be fixed in unison with server code.
392  ((as_compressed_proto *)begin)->uncompressed_sz = uncompressed_sz;
393 
394  return len;
395 }
396 
397 /**
398  * @private
399  * Calculate max size the compressed command buffer.
400  */
401 size_t
402 as_command_compress_max_size(size_t cmd_sz);
403 
404 /**
405  * @private
406  * Compress command buffer.
407  */
408 as_status
409 as_command_compress(as_error* err, uint8_t* cmd, size_t cmd_sz, uint8_t* compressed_cmd, size_t* compressed_size);
410 
411 /**
412  * @private
413  * Send command to the server.
414  */
415 as_status
417  as_cluster* cluster, as_error* err, const as_policy_base* policy, as_command_node* cn,
418  uint8_t* command, size_t command_len, as_parse_results_fn parse_results_fn, void* parse_results_data,
419  bool is_read
420 );
421 
422 /**
423  * @private
424  * Parse header of server response.
425  */
426 as_status
427 as_command_parse_header(as_error* err, as_socket* sock, as_node* node, uint32_t socket_timeout, uint64_t deadline_ms, void* user_data);
428 
429 /**
430  * @private
431  * Parse server record. Used for reads.
432  */
433 as_status
434 as_command_parse_result(as_error* err, as_socket* sock, as_node* node, uint32_t socket_timeout, uint64_t deadline_ms, void* user_data);
435 
436 /**
437  * @private
438  * Parse server success or failure result.
439  */
440 as_status
441 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);
442 
443 /**
444  * @private
445  * Parse server success or failure bins.
446  */
447 as_status
448 as_command_parse_success_failure_bins(uint8_t** pp, as_error* err, as_msg* msg, as_val** value);
449 
450 /**
451  * @private
452  * Parse bins received from the server.
453  */
454 as_status
455 as_command_parse_bins(uint8_t** pp, as_error* err, as_record* rec, uint32_t n_bins, bool deserialize);
456 
457 /**
458  * @private
459  * Parse user defined function error.
460  */
461 as_status
462 as_command_parse_udf_failure(uint8_t* p, as_error* err, as_msg* msg, as_status status);
463 
464 /**
465  * @private
466  * Skip over fields section in returned data.
467  */
468 uint8_t*
469 as_command_ignore_fields(uint8_t* p, uint32_t n_fields);
470 
471 /**
472  * @private
473  * Skip over bins in returned data.
474  */
475 uint8_t*
476 as_command_ignore_bins(uint8_t* p, uint32_t n_bins);
477 
478 /**
479  * @private
480  * Parse key fields received from server. Used for reads.
481  */
482 uint8_t*
483 as_command_parse_key(uint8_t* p, uint32_t n_fields, as_key* key);
484 
485 #ifdef __cplusplus
486 } // end extern "C"
487 #endif