Main Page
Modules
Data Structures
Files
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
Groups
Pages
aerospike
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
;
81
}
as_event_connection
;
82
83
typedef
struct
{
84
as_event_connection
base
;
85
struct
as_event_command
*
cmd
;
86
}
as_async_connection
;
87
88
typedef
struct
{
89
as_pipe_listener
listener
;
90
void
*
udata
;
91
}
as_queued_pipe_cb
;
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
104
as_event_loop
*
event_loop
;
105
as_event_connection
*
conn
;
106
as_cluster
*
cluster
;
107
as_node
*
node
;
108
void
*
udata
;
109
as_event_parse_results_fn
parse_results
;
110
as_pipe_listener
pipe_listener
;
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
;
122
bool
deserialize
;
123
bool
free_buf
;
124
}
as_event_command
;
125
126
typedef
struct
as_event_executor
{
127
pthread_mutex_t
lock
;
128
struct
as_event_command
**
commands
;
129
as_event_loop
*
event_loop
;
130
as_event_executor_complete_fn
complete_fn
;
131
void
*
udata
;
132
uint32_t
max_concurrent
;
133
uint32_t
max
;
134
uint32_t
count
;
135
bool
valid
;
136
}
as_event_executor
;
137
138
typedef
enum
as_connection_status_e {
139
AS_CONNECTION_FROM_POOL
= 0,
140
AS_CONNECTION_NEW
= 1,
141
AS_CONNECTION_TOO_MANY
= 2
142
}
as_connection_status
;
143
144
/******************************************************************************
145
* COMMON FUNCTIONS
146
*****************************************************************************/
147
148
as_status
149
as_event_command_execute
(
as_event_command
* cmd,
as_error
* err);
150
151
void
152
as_event_executor_complete
(
as_event_command
* cmd);
153
154
void
155
as_event_executor_cancel
(
as_event_executor
* executor,
int
queued_count);
156
157
as_connection_status
158
as_event_get_connection
(
as_event_command
* cmd);
159
160
int
161
as_event_create_socket
(
as_event_command
* cmd,
int
family);
162
163
void
164
as_event_fd_error
(
as_event_command
* cmd,
as_error
* err,
int
fd);
165
166
void
167
as_event_connect_error
(
as_event_command
* cmd,
as_error
* err,
as_socket
* sock);
168
169
void
170
as_event_error_callback
(
as_event_command
* cmd,
as_error
* err);
171
172
void
173
as_event_socket_error
(
as_event_command
* cmd,
as_error
* err);
174
175
void
176
as_event_response_error
(
as_event_command
* cmd,
as_error
* err);
177
178
void
179
as_event_timeout
(
as_event_command
* cmd);
180
181
bool
182
as_event_command_parse_result
(
as_event_command
* cmd);
183
184
bool
185
as_event_command_parse_header
(
as_event_command
* cmd);
186
187
bool
188
as_event_command_parse_success_failure
(
as_event_command
* cmd);
189
190
void
191
as_event_command_free
(
as_event_command
* cmd);
192
193
/******************************************************************************
194
* IMPLEMENTATION SPECIFIC FUNCTIONS
195
*****************************************************************************/
196
197
bool
198
as_event_create_loop
(
as_event_loop
*
event_loop
);
199
200
void
201
as_event_register_external_loop
(
as_event_loop
*
event_loop
);
202
203
bool
204
as_event_send
(
as_event_command
* cmd);
205
206
void
207
as_event_command_begin
(
as_event_command
* cmd);
208
209
void
210
as_event_close_connection
(
as_event_connection
*
conn
);
211
212
void
213
as_event_node_destroy
(
as_node
*
node
);
214
215
bool
216
as_event_send_close_loop
(
as_event_loop
*
event_loop
);
217
218
/******************************************************************************
219
* LIBEV INLINE FUNCTIONS
220
*****************************************************************************/
221
222
#if defined(AS_USE_LIBEV)
223
224
static
inline
int
225
as_event_validate_connection
(
as_event_connection
*
conn
)
226
{
227
return
as_socket_validate
(&conn->socket);
228
}
229
230
static
inline
void
231
as_event_stop_timer
(
as_event_command
* cmd)
232
{
233
if
(cmd->
timeout_ms
) {
234
ev_timer_stop(cmd->
event_loop
->
loop
, &cmd->timer);
235
}
236
}
237
238
static
inline
void
239
as_event_stop_watcher
(
as_event_command
* cmd,
as_event_connection
*
conn
)
240
{
241
ev_io_stop(cmd->
event_loop
->
loop
, &conn->watcher);
242
}
243
244
static
inline
void
245
as_event_command_release
(
as_event_command
* cmd)
246
{
247
as_event_command_free
(cmd);
248
}
249
250
/******************************************************************************
251
* LIBUV INLINE FUNCTIONS
252
*****************************************************************************/
253
254
#elif defined(AS_USE_LIBUV)
255
256
static
inline
int
257
as_event_validate_connection
(
as_event_connection
*
conn
)
258
{
259
// Libuv does not have a peek function, so use fd directly.
260
uv_os_fd_t fd;
261
262
if
(uv_fileno((uv_handle_t*)&conn->socket, &fd) == 0) {
263
return
as_socket_validate_fd
(fd);
264
}
265
return
false
;
266
}
267
268
static
inline
void
269
as_event_stop_timer
(
as_event_command
* cmd)
270
{
271
// Timer is stopped in libuv by uv_close which occurs later in as_event_command_release().
272
}
273
274
static
inline
void
275
as_event_stop_watcher
(
as_event_command
* cmd,
as_event_connection
* conn)
276
{
277
// Watcher already stopped by design in libuv.
278
}
279
280
void
281
as_uv_timer_closed(uv_handle_t* handle);
282
283
static
inline
void
284
as_event_command_release
(
as_event_command
* cmd)
285
{
286
if
(cmd->
timeout_ms
) {
287
// libuv requires that cmd can't be freed until timer is closed.
288
uv_close((uv_handle_t*)&cmd->timer, as_uv_timer_closed);
289
}
290
else
{
291
as_event_command_free
(cmd);
292
}
293
}
294
295
/******************************************************************************
296
* EVENT_LIB NOT DEFINED INLINE FUNCTIONS
297
*****************************************************************************/
298
299
#else
300
301
static
inline
int
302
as_event_validate_connection
(
as_event_connection
* conn)
303
{
304
return
-1;
305
}
306
307
static
inline
void
308
as_event_stop_timer
(
as_event_command
* cmd)
309
{
310
}
311
312
static
inline
void
313
as_event_stop_watcher
(
as_event_command
* cmd,
as_event_connection
* conn)
314
{
315
}
316
317
static
inline
void
318
as_event_command_release
(
as_event_command
* cmd)
319
{
320
}
321
322
#endif
323
324
/******************************************************************************
325
* COMMON INLINE FUNCTIONS
326
*****************************************************************************/
327
328
static
inline
void
329
as_event_command_execute_in_loop
(
as_event_command
* cmd)
330
{
331
// Check if command timed out after coming off queue.
332
if
(cmd->
timeout_ms
&& (cf_getms() - *(uint64_t*)cmd) > cmd->
timeout_ms
) {
333
as_error
err;
334
as_error_set_message
(&err,
AEROSPIKE_ERR_TIMEOUT
,
as_error_string
(
AEROSPIKE_ERR_TIMEOUT
));
335
// Tell the libuv version of as_event_command_release() to not try to close the uv_timer_t.
336
cmd->
timeout_ms
= 0;
337
as_event_error_callback
(cmd, &err);
338
return
;
339
}
340
341
// Start processing.
342
as_event_command_begin
(cmd);
343
}
344
345
static
inline
as_event_loop
*
346
as_event_assign
(
as_event_loop
*
event_loop
)
347
{
348
// Assign event loop using round robin distribution if not specified.
349
return
event_loop ? event_loop :
as_event_loop_get
();
350
}
351
352
static
inline
void
353
as_event_set_auth_write
(
as_event_command
* cmd)
354
{
355
// The command buffer was already allocated with enough space for max authentication size,
356
// so just use the end of the write buffer for authentication bytes.
357
cmd->
pos
= cmd->
len
;
358
cmd->
auth_len
=
as_authenticate_set
(cmd->
cluster
->
user
, cmd->
cluster
->
password
, &cmd->
buf
[cmd->
pos
]);
359
cmd->
len
= cmd->
pos
+ cmd->
auth_len
;
360
}
361
362
static
inline
void
363
as_event_set_auth_read_header
(
as_event_command
* cmd)
364
{
365
// Authenticate response buffer is at end of write buffer.
366
cmd->
pos
= cmd->
len
- cmd->
auth_len
;
367
cmd->
auth_len
=
sizeof
(as_proto);
368
cmd->
len
= cmd->
pos
+ cmd->
auth_len
;
369
cmd->
state
=
AS_ASYNC_STATE_AUTH_READ_HEADER
;
370
}
371
372
static
inline
void
373
as_event_set_auth_parse_header
(
as_event_command
* cmd)
374
{
375
// Authenticate response buffer is at end of write buffer.
376
cmd->
pos
= cmd->
len
- cmd->
auth_len
;
377
as_proto*
proto
= (as_proto*)&cmd->
buf
[cmd->
pos
];
378
as_proto_swap_from_be
(proto);
379
cmd->
auth_len
= (uint32_t)proto->sz;
380
cmd->
len
= cmd->
pos
+ cmd->
auth_len
;
381
cmd->
state
=
AS_ASYNC_STATE_AUTH_READ_BODY
;
382
}
383
384
static
inline
void
385
as_event_release_connection
(
as_cluster
*
cluster
,
as_event_connection
* conn,
as_queue
* queue)
386
{
387
as_event_close_connection
(conn);
388
ck_pr_dec_32(&cluster->
async_conn_count
);
389
as_queue_decr_total
(queue);
390
}
391
392
static
inline
void
393
as_event_decr_connection
(
as_cluster
*
cluster
,
as_queue
* queue)
394
{
395
ck_pr_dec_32(&cluster->
async_conn_count
);
396
as_queue_decr_total
(queue);
397
}
398
399
static
inline
void
400
as_event_decr_conn
(
as_event_command
* cmd)
401
{
402
as_queue
* queue = cmd->
pipe_listener
!= NULL ?
403
&cmd->
node
->
pipe_conn_qs
[cmd->
event_loop
->
index
] :
404
&cmd->
node
->
async_conn_qs
[cmd->
event_loop
->
index
];
405
406
as_event_decr_connection
(cmd->
cluster
, queue);
407
}
408
409
#ifdef __cplusplus
410
}
// end extern "C"
411
#endif