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 #else
36 #endif
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 /******************************************************************************
43  * TYPES
44  *****************************************************************************/
45 
46 #define AS_ASYNC_STATE_UNREGISTERED 0
47 #define AS_ASYNC_STATE_TLS_CONNECT 1
48 #define AS_ASYNC_STATE_AUTH_WRITE 2
49 #define AS_ASYNC_STATE_AUTH_READ_HEADER 4
50 #define AS_ASYNC_STATE_AUTH_READ_BODY 8
51 #define AS_ASYNC_STATE_WRITE 16
52 #define AS_ASYNC_STATE_READ_HEADER 32
53 #define AS_ASYNC_STATE_READ_BODY 64
54 
55 #define AS_ASYNC_AUTH_RETURN_CODE 1
56 
57 #define AS_EVENT_CONNECTION_COMPLETE 0
58 #define AS_EVENT_CONNECTION_PENDING 1
59 #define AS_EVENT_CONNECTION_ERROR 2
60 
61 #define AS_EVENT_QUEUE_INITIAL_CAPACITY 256
62 
63 struct as_event_command;
64 struct as_event_executor;
65 
66 typedef struct {
67 #if defined(AS_USE_LIBEV)
68  struct ev_io watcher;
69  as_socket socket;
70  int watching;
71 #elif defined(AS_USE_LIBUV)
72  uv_tcp_t socket;
73  // Reuse memory for requests, because only one request is active at a time.
74  union {
75  uv_connect_t connect;
76  uv_write_t write;
77  } req;
78 #else
79 #endif
80  bool pipeline;
82 
83 typedef struct {
87 
88 typedef struct {
90  void* udata;
92 
93 typedef bool (*as_event_parse_results_fn) (struct as_event_command* cmd);
94 typedef void (*as_event_executor_complete_fn) (struct as_event_executor* executor, as_error* err);
95 typedef void (*as_event_executor_destroy_fn) (struct as_event_executor* executor);
96 
97 typedef struct as_event_command {
98 #if defined(AS_USE_LIBEV)
99  struct ev_timer timer;
100 #elif defined(AS_USE_LIBUV)
101  uv_timer_t timer;
102 #else
103 #endif
108  void* udata;
111  cf_ll_element pipe_link;
112 
113  uint8_t* buf;
114  uint32_t capacity;
115  uint32_t len;
116  uint32_t pos;
117  uint32_t auth_len;
118  uint32_t timeout_ms;
119 
120  uint8_t type;
121  uint8_t state;
123  bool free_buf;
125 
126 typedef struct as_event_executor {
127  pthread_mutex_t lock;
131  void* udata;
132  uint32_t max_concurrent;
133  uint32_t max;
134  uint32_t count;
135  bool valid;
137 
138 typedef enum as_connection_status_e {
143 
144 /******************************************************************************
145  * COMMON FUNCTIONS
146  *****************************************************************************/
147 
148 as_status
150 
151 void
153 
154 void
155 as_event_executor_cancel(as_event_executor* executor, int queued_count);
156 
159 
160 void
162 
163 void
165 
166 void
168 
169 void
171 
172 bool
174 
175 bool
177 
178 bool
180 
181 void
183 
184 /******************************************************************************
185  * IMPLEMENTATION SPECIFIC FUNCTIONS
186  *****************************************************************************/
187 
188 bool
190 
191 void
193 
194 bool
196 
197 void
199 
200 void
202 
203 void
205 
206 bool
208 
209 /******************************************************************************
210  * LIBEV INLINE FUNCTIONS
211  *****************************************************************************/
212 
213 #if defined(AS_USE_LIBEV)
214 
215 static inline int
217 {
218  return as_socket_validate(&conn->socket);
219 }
220 
221 static inline void
223 {
224  if (cmd->timeout_ms) {
225  ev_timer_stop(cmd->event_loop->loop, &cmd->timer);
226  }
227 }
228 
229 static inline void
231 {
232  ev_io_stop(cmd->event_loop->loop, &conn->watcher);
233 }
234 
235 static inline void
237 {
239 }
240 
241 /******************************************************************************
242  * LIBUV INLINE FUNCTIONS
243  *****************************************************************************/
244 
245 #elif defined(AS_USE_LIBUV)
246 
247 static inline int
249 {
250  // Libuv does not have a peek function, so use fd directly.
251  uv_os_fd_t fd;
252 
253  if (uv_fileno((uv_handle_t*)&conn->socket, &fd) == 0) {
254  return as_socket_validate_fd(fd);
255  }
256  return false;
257 }
258 
259 static inline void
261 {
262  // Timer is stopped in libuv by uv_close which occurs later in as_event_command_release().
263 }
264 
265 static inline void
267 {
268  // Watcher already stopped by design in libuv.
269 }
270 
271 void
272 as_uv_timer_closed(uv_handle_t* handle);
273 
274 static inline void
276 {
277  if (cmd->timeout_ms) {
278  // libuv requires that cmd can't be freed until timer is closed.
279  uv_close((uv_handle_t*)&cmd->timer, as_uv_timer_closed);
280  }
281  else {
283  }
284 }
285 
286 /******************************************************************************
287  * EVENT_LIB NOT DEFINED INLINE FUNCTIONS
288  *****************************************************************************/
289 
290 #else
291 
292 static inline int
294 {
295  return -1;
296 }
297 
298 static inline void
300 {
301 }
302 
303 static inline void
305 {
306 }
307 
308 static inline void
310 {
311 }
312 
313 #endif
314 
315 /******************************************************************************
316  * COMMON INLINE FUNCTIONS
317  *****************************************************************************/
318 
319 static inline void
321 {
322  // Check if command timed out after coming off queue.
323  if (cmd->timeout_ms && (cf_getms() - *(uint64_t*)cmd) > cmd->timeout_ms) {
324  as_error err;
326  // Tell the libuv version of as_event_command_release() to not try to close the uv_timer_t.
327  cmd->timeout_ms = 0;
328  as_event_error_callback(cmd, &err);
329  return;
330  }
331 
332  // Start processing.
334 }
335 
336 static inline as_event_loop*
338 {
339  // Assign event loop using round robin distribution if not specified.
340  return event_loop ? event_loop : as_event_loop_get();
341 }
342 
343 static inline void
345 {
346  // The command buffer was already allocated with enough space for max authentication size,
347  // so just use the end of the write buffer for authentication bytes.
348  cmd->pos = cmd->len;
349  cmd->auth_len = as_authenticate_set(cmd->cluster->user, cmd->cluster->password, &cmd->buf[cmd->pos]);
350  cmd->len = cmd->pos + cmd->auth_len;
351 }
352 
353 static inline void
355 {
356  // Authenticate response buffer is at end of write buffer.
357  cmd->pos = cmd->len - cmd->auth_len;
358  cmd->auth_len = sizeof(as_proto);
359  cmd->len = cmd->pos + cmd->auth_len;
361 }
362 
363 static inline void
365 {
366  // Authenticate response buffer is at end of write buffer.
367  cmd->pos = cmd->len - cmd->auth_len;
368  as_proto* proto = (as_proto*)&cmd->buf[cmd->pos];
369  as_proto_swap_from_be(proto);
370  cmd->auth_len = (uint32_t)proto->sz;
371  cmd->len = cmd->pos + cmd->auth_len;
373 }
374 
375 static inline void
377 {
379  ck_pr_dec_32(&cluster->async_conn_count);
380  as_queue_decr_total(queue);
381 }
382 
383 static inline void
385 {
386  ck_pr_dec_32(&cluster->async_conn_count);
387  as_queue_decr_total(queue);
388 }
389 
390 static inline void
392 {
393  as_queue* queue = cmd->pipe_listener != NULL ?
394  &cmd->node->pipe_conn_qs[cmd->event_loop->index] :
395  &cmd->node->async_conn_qs[cmd->event_loop->index];
396 
397  as_event_decr_connection(cmd->cluster, queue);
398 }
399 
400 #ifdef __cplusplus
401 } // end extern "C"
402 #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:60
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:68
uint32_t async_conn_count
Definition: as_cluster.h:224
static as_event_loop * as_event_loop_get()
Definition: as_event.h:218
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