All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_event_internal.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_admin.h>
20 #include <aerospike/as_cluster.h>
21 #include <aerospike/as_listener.h>
22 #include <aerospike/as_queue.h>
23 #include <aerospike/as_proto.h>
24 #include <aerospike/as_socket.h>
25 #include <citrusleaf/cf_ll.h>
26 #include <pthread.h>
27 #include <stdint.h>
28 #include <stdbool.h>
29 #include <unistd.h>
30 
31 #if defined(AS_USE_LIBEV)
32 #include <ev.h>
33 #elif defined(AS_USE_LIBUV)
34 #include <uv.h>
35 #elif defined(AS_USE_LIBEVENT)
36 #include <event2/event.h>
37 #else
38 #endif
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /******************************************************************************
45  * TYPES
46  *****************************************************************************/
47 
48 #define AS_ASYNC_STATE_UNREGISTERED 0
49 #define AS_ASYNC_STATE_TLS_CONNECT 1
50 #define AS_ASYNC_STATE_AUTH_WRITE 2
51 #define AS_ASYNC_STATE_AUTH_READ_HEADER 4
52 #define AS_ASYNC_STATE_AUTH_READ_BODY 8
53 #define AS_ASYNC_STATE_WRITE 16
54 #define AS_ASYNC_STATE_READ_HEADER 32
55 #define AS_ASYNC_STATE_READ_BODY 64
56 
57 #define AS_ASYNC_AUTH_RETURN_CODE 1
58 
59 #define AS_EVENT_CONNECTION_COMPLETE 0
60 #define AS_EVENT_CONNECTION_PENDING 1
61 #define AS_EVENT_CONNECTION_ERROR 2
62 
63 #define AS_EVENT_QUEUE_INITIAL_CAPACITY 256
64 
65 struct as_event_command;
66 struct as_event_executor;
67 
68 typedef struct {
69 #if defined(AS_USE_LIBEV)
70  struct ev_io watcher;
71  as_socket socket;
72  int watching;
73 #elif defined(AS_USE_LIBUV)
74  uv_tcp_t socket;
75  // Reuse memory for requests, because only one request is active at a time.
76  union {
77  uv_connect_t connect;
78  uv_write_t write;
79  } req;
80 #elif defined(AS_USE_LIBEVENT)
81  struct event watcher;
82  as_socket socket;
83  int watching;
84 #else
85 #endif
86  bool pipeline;
88 
89 typedef struct {
93 
94 typedef struct {
96  void* udata;
98 
99 typedef bool (*as_event_parse_results_fn) (struct as_event_command* cmd);
100 typedef void (*as_event_executor_complete_fn) (struct as_event_executor* executor, as_error* err);
101 typedef void (*as_event_executor_destroy_fn) (struct as_event_executor* executor);
102 
103 typedef struct as_event_command {
104 #if defined(AS_USE_LIBEV)
105  struct ev_timer timer;
106 #elif defined(AS_USE_LIBUV)
107  uv_timer_t timer;
108 #elif defined(AS_USE_LIBEVENT)
109  struct event timer;
110 #else
111 #endif
116  void* udata;
119  cf_ll_element pipe_link;
120 
121  uint8_t* buf;
122  uint32_t capacity;
123  uint32_t len;
124  uint32_t pos;
125  uint32_t auth_len;
126  uint32_t timeout_ms;
127 
128  uint8_t type;
129  uint8_t state;
131  bool free_buf;
133 
134 typedef struct as_event_executor {
135  pthread_mutex_t lock;
139  void* udata;
140  uint32_t max_concurrent;
141  uint32_t max;
142  uint32_t count;
143  bool valid;
145 
146 typedef enum as_connection_status_e {
151 
152 /******************************************************************************
153  * COMMON FUNCTIONS
154  *****************************************************************************/
155 
156 as_status
158 
159 void
161 
162 void
163 as_event_executor_cancel(as_event_executor* executor, int queued_count);
164 
167 
168 void
170 
171 void
173 
174 void
176 
177 void
179 
180 bool
182 
183 bool
185 
186 bool
188 
189 void
191 
192 /******************************************************************************
193  * IMPLEMENTATION SPECIFIC FUNCTIONS
194  *****************************************************************************/
195 
196 bool
198 
199 void
201 
202 bool
204 
205 void
207 
208 void
210 
211 void
213 
214 bool
216 
217 /******************************************************************************
218  * LIBEV INLINE FUNCTIONS
219  *****************************************************************************/
220 
221 #if defined(AS_USE_LIBEV)
222 
223 static inline int
225 {
226  return as_socket_validate(&conn->socket);
227 }
228 
229 static inline void
231 {
232  if (conn->socket.ctx) {
233  conn->socket.last_used = cf_get_seconds();
234  }
235 }
236 
237 static inline void
239 {
240  if (cmd->timeout_ms) {
241  ev_timer_stop(cmd->event_loop->loop, &cmd->timer);
242  }
243 }
244 
245 static inline void
247 {
248  ev_io_stop(cmd->event_loop->loop, &conn->watcher);
249 }
250 
251 static inline void
253 {
255 }
256 
257 /******************************************************************************
258  * LIBUV INLINE FUNCTIONS
259  *****************************************************************************/
260 
261 #elif defined(AS_USE_LIBUV)
262 
263 static inline int
265 {
266  // Libuv does not have a peek function, so use fd directly.
267  uv_os_fd_t fd;
268 
269  if (uv_fileno((uv_handle_t*)&conn->socket, &fd) == 0) {
270  return as_socket_validate_fd(fd);
271  }
272  return false;
273 }
274 
275 static inline void
277 {
278 }
279 
280 static inline void
282 {
283  // Timer is stopped in libuv by uv_close which occurs later in as_event_command_release().
284 }
285 
286 static inline void
288 {
289  // Watcher already stopped by design in libuv.
290 }
291 
292 void
293 as_uv_timer_closed(uv_handle_t* handle);
294 
295 static inline void
297 {
298  if (cmd->timeout_ms) {
299  // libuv requires that cmd can't be freed until timer is closed.
300  uv_close((uv_handle_t*)&cmd->timer, as_uv_timer_closed);
301  }
302  else {
304  }
305 }
306 
307 /******************************************************************************
308  * LIBEVENT INLINE FUNCTIONS
309  *****************************************************************************/
310 
311 #elif defined(AS_USE_LIBEVENT)
312 
313 static inline int
315 {
316  return as_socket_validate(&conn->socket);
317 }
318 
319 static inline void
321 {
322  if (conn->socket.ctx) {
323  conn->socket.last_used = cf_get_seconds();
324  }
325 }
326 
327 static inline void
329 {
330  if (cmd->timeout_ms) {
331  evtimer_del(&cmd->timer);
332  }
333 }
334 
335 static inline void
337 {
338  event_del(&conn->watcher);
339 }
340 
341 static inline void
343 {
345 }
346 
347 /******************************************************************************
348  * EVENT_LIB NOT DEFINED INLINE FUNCTIONS
349  *****************************************************************************/
350 
351 #else
352 
353 static inline int
355 {
356  return -1;
357 }
358 
359 static inline void
361 {
362 }
363 
364 static inline void
366 {
367 }
368 
369 static inline void
371 {
372 }
373 
374 static inline void
376 {
377 }
378 
379 #endif
380 
381 /******************************************************************************
382  * COMMON INLINE FUNCTIONS
383  *****************************************************************************/
384 
385 static inline void
387 {
388  // Check if command timed out after coming off queue.
389  if (cmd->timeout_ms && (cf_getms() - *(uint64_t*)cmd) > cmd->timeout_ms) {
390  as_error err;
392  // Tell the libuv version of as_event_command_release() to not try to close the uv_timer_t.
393  cmd->timeout_ms = 0;
394  as_event_error_callback(cmd, &err);
395  return;
396  }
397 
398  // Start processing.
400 }
401 
402 static inline as_event_loop*
404 {
405  // Assign event loop using round robin distribution if not specified.
406  return event_loop ? event_loop : as_event_loop_get();
407 }
408 
409 static inline void
411 {
412  // The command buffer was already allocated with enough space for max authentication size,
413  // so just use the end of the write buffer for authentication bytes.
414  cmd->pos = cmd->len;
415  cmd->auth_len = as_authenticate_set(cmd->cluster->user, cmd->cluster->password, &cmd->buf[cmd->pos]);
416  cmd->len = cmd->pos + cmd->auth_len;
417 }
418 
419 static inline void
421 {
422  // Authenticate response buffer is at end of write buffer.
423  cmd->pos = cmd->len - cmd->auth_len;
424  cmd->auth_len = sizeof(as_proto);
425  cmd->len = cmd->pos + cmd->auth_len;
427 }
428 
429 static inline void
431 {
432  // Authenticate response buffer is at end of write buffer.
433  cmd->pos = cmd->len - cmd->auth_len;
434  as_proto* proto = (as_proto*)&cmd->buf[cmd->pos];
435  as_proto_swap_from_be(proto);
436  cmd->auth_len = (uint32_t)proto->sz;
437  cmd->len = cmd->pos + cmd->auth_len;
439 }
440 
441 static inline void
443 {
445  ck_pr_dec_32(&cluster->async_conn_count);
446  as_queue_decr_total(queue);
447 }
448 
449 static inline void
451 {
452  ck_pr_dec_32(&cluster->async_conn_count);
453  as_queue_decr_total(queue);
454 }
455 
456 static inline void
458 {
459  as_queue* queue = cmd->pipe_listener != NULL ?
460  &cmd->node->pipe_conn_qs[cmd->event_loop->index] :
461  &cmd->node->async_conn_qs[cmd->event_loop->index];
462 
463  as_event_decr_connection(cmd->cluster, queue);
464 }
465 
466 #ifdef __cplusplus
467 } // end extern "C"
468 #endif
as_event_loop * event_loop
as_event_parse_results_fn parse_results
void as_event_timeout(as_event_command *cmd)
bool as_event_command_parse_success_failure(as_event_command *cmd)
as_event_executor_complete_fn complete_fn
bool(* as_event_parse_results_fn)(struct as_event_command *cmd)
#define AS_ASYNC_STATE_AUTH_READ_HEADER
as_pipe_listener listener
as_status
Definition: as_status.h:30
void as_event_command_free(as_event_command *cmd)
static void as_event_set_auth_parse_header(as_event_command *cmd)
void as_proto_swap_from_be(as_proto *m)
static void as_event_set_auth_read_header(as_event_command *cmd)
bool as_event_command_parse_header(as_event_command *cmd)
void as_event_executor_cancel(as_event_executor *executor, int queued_count)
static void as_event_command_release(as_event_command *cmd)
void as_event_node_destroy(as_node *node)
void as_event_socket_error(as_event_command *cmd, as_error *err)
void as_event_executor_complete(as_event_command *cmd)
char * password
Definition: as_cluster.h:122
static void as_event_decr_connection(as_cluster *cluster, as_queue *queue)
as_cluster * cluster
bool as_event_send(as_event_command *cmd)
char * as_error_string(as_status status)
as_queue * async_conn_qs
Definition: as_node.h:174
struct as_event_command ** commands
bool as_event_create_loop(as_event_loop *event_loop)
as_event_loop * event_loop
as_status as_event_command_execute(as_event_command *cmd, as_error *err)
void * loop
Definition: as_event.h:67
static void as_event_set_conn_last_used(as_event_connection *conn)
int as_socket_validate(as_socket *sock)
as_proto proto
Definition: as_proto.h:1087
int as_socket_validate_fd(int fd)
char * user
Definition: as_cluster.h:116
void(* as_event_executor_complete_fn)(struct as_event_executor *executor, as_error *err)
static int as_event_validate_connection(as_event_connection *conn)
#define AS_ASYNC_STATE_AUTH_READ_BODY
static void as_event_stop_watcher(as_event_command *cmd, as_event_connection *conn)
void(* as_pipe_listener)(void *udata, as_event_loop *event_loop)
Definition: as_listener.h:73
void as_event_response_error(as_event_command *cmd, as_error *err)
static void as_event_decr_conn(as_event_command *cmd)
void as_event_command_begin(as_event_command *cmd)
bool as_event_send_close_loop(as_event_loop *event_loop)
void as_event_register_external_loop(as_event_loop *event_loop)
#define as_error_set_message(__err, __code, __msg)
Definition: as_error.h:143
uint32_t as_authenticate_set(const char *user, const char *credential, uint8_t *buffer)
static void as_event_command_execute_in_loop(as_event_command *cmd)
uint32_t index
Definition: as_event.h:75
uint32_t async_conn_count
Definition: as_cluster.h:224
static as_event_loop * as_event_loop_get()
Definition: as_event.h:225
cf_ll_element pipe_link
as_event_connection * conn
static void as_event_set_auth_write(as_event_command *cmd)
static void as_event_stop_timer(as_event_command *cmd)
void as_event_close_connection(as_event_connection *conn)
pthread_mutex_t lock
as_connection_status
as_pipe_listener pipe_listener
static void as_event_release_connection(as_cluster *cluster, as_event_connection *conn, as_queue *queue)
void(* as_event_executor_destroy_fn)(struct as_event_executor *executor)
bool as_event_command_parse_result(as_event_command *cmd)
struct as_event_command * cmd
static as_event_loop * as_event_assign(as_event_loop *event_loop)
as_event_connection base
void as_event_error_callback(as_event_command *cmd, as_error *err)
as_queue * pipe_conn_qs
Definition: as_node.h:180
as_connection_status as_event_get_connection(as_event_command *cmd)
static void as_queue_decr_total(as_queue *queue)
Definition: as_queue.h:170