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