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_AUTH_WRITE 1
48
#define AS_ASYNC_STATE_AUTH_READ_HEADER 2
49
#define AS_ASYNC_STATE_AUTH_READ_BODY 4
50
#define AS_ASYNC_STATE_WRITE 8
51
#define AS_ASYNC_STATE_READ_HEADER 16
52
#define AS_ASYNC_STATE_READ_BODY 32
53
54
#define AS_ASYNC_AUTH_RETURN_CODE 1
55
56
#define AS_EVENT_CONNECTION_COMPLETE 0
57
#define AS_EVENT_CONNECTION_PENDING 1
58
#define AS_EVENT_CONNECTION_ERROR 2
59
60
#define AS_EVENT_QUEUE_INITIAL_CAPACITY 256
61
62
struct
as_event_command
;
63
struct
as_event_executor
;
64
65
typedef
struct
{
66
#if defined(AS_USE_LIBEV)
67
struct
ev_io watcher;
68
int
fd;
69
#elif defined(AS_USE_LIBUV)
70
uv_tcp_t socket;
71
72
// Reuse memory for requests, because only one request is active at a time.
73
union
{
74
uv_connect_t connect;
75
uv_write_t write;
76
} req;
77
#else
78
#endif
79
bool
pipeline
;
80
}
as_event_connection
;
81
82
typedef
struct
{
83
as_event_connection
base
;
84
struct
as_event_command
*
cmd
;
85
}
as_async_connection
;
86
87
typedef
struct
{
88
as_pipe_listener
listener
;
89
void
*
udata
;
90
}
as_queued_pipe_cb
;
91
92
typedef
bool (*
as_event_parse_results_fn
) (
struct
as_event_command
* cmd);
93
typedef
void (*
as_event_executor_complete_fn
) (
struct
as_event_executor
* executor,
as_error
* err);
94
typedef
void (*
as_event_executor_destroy_fn
) (
struct
as_event_executor
* executor);
95
96
typedef
struct
as_event_command
{
97
#if defined(AS_USE_LIBEV)
98
struct
ev_timer timer;
99
#elif defined(AS_USE_LIBUV)
100
uv_timer_t timer;
101
#else
102
#endif
103
as_event_loop
*
event_loop
;
104
as_event_connection
*
conn
;
105
as_cluster
*
cluster
;
106
as_node
*
node
;
107
void
*
udata
;
108
as_event_parse_results_fn
parse_results
;
109
as_pipe_listener
pipe_listener
;
110
cf_ll_element
pipe_link
;
111
112
uint8_t*
buf
;
113
uint32_t
capacity
;
114
uint32_t
len
;
115
uint32_t
pos
;
116
uint32_t
auth_len
;
117
uint32_t
timeout_ms
;
118
119
uint8_t
type
;
120
uint8_t
state
;
121
bool
deserialize
;
122
bool
free_buf
;
123
}
as_event_command
;
124
125
typedef
struct
as_event_executor
{
126
pthread_mutex_t
lock
;
127
struct
as_event_command
**
commands
;
128
as_event_loop
*
event_loop
;
129
as_event_executor_complete_fn
complete_fn
;
130
void
*
udata
;
131
uint32_t
max_concurrent
;
132
uint32_t
max
;
133
uint32_t
count
;
134
bool
valid
;
135
}
as_event_executor
;
136
137
typedef
enum
as_connection_status_e {
138
AS_CONNECTION_FROM_POOL
= 0,
139
AS_CONNECTION_NEW
= 1,
140
AS_CONNECTION_TOO_MANY
= 2
141
}
as_connection_status
;
142
143
/******************************************************************************
144
* GLOBAL VARIABLES
145
*****************************************************************************/
146
147
extern
as_event_loop
*
as_event_loops
;
148
extern
uint32_t
as_event_loop_size
;
149
extern
uint32_t
as_event_loop_current
;
150
151
/******************************************************************************
152
* COMMON FUNCTIONS
153
*****************************************************************************/
154
155
as_status
156
as_event_command_execute
(
as_event_command
* cmd,
as_error
* err);
157
158
void
159
as_event_executor_complete
(
as_event_command
* cmd);
160
161
void
162
as_event_executor_cancel
(
as_event_executor
* executor,
int
queued_count);
163
164
as_connection_status
165
as_event_get_connection
(
as_event_command
* cmd);
166
167
int
168
as_event_create_socket
(
as_event_command
* cmd);
169
170
void
171
as_event_connect_error
(
as_event_command
* cmd,
as_error
* err,
int
fd);
172
173
void
174
as_event_error_callback
(
as_event_command
* cmd,
as_error
* err);
175
176
void
177
as_event_socket_error
(
as_event_command
* cmd,
as_error
* err);
178
179
void
180
as_event_response_error
(
as_event_command
* cmd,
as_error
* err);
181
182
void
183
as_event_timeout
(
as_event_command
* cmd);
184
185
bool
186
as_event_command_parse_result
(
as_event_command
* cmd);
187
188
bool
189
as_event_command_parse_header
(
as_event_command
* cmd);
190
191
bool
192
as_event_command_parse_success_failure
(
as_event_command
* cmd);
193
194
/******************************************************************************
195
* IMPLEMENTATION SPECIFIC FUNCTIONS
196
*****************************************************************************/
197
198
bool
199
as_event_create_loop
(
as_event_loop
*
event_loop
);
200
201
void
202
as_event_register_external_loop
(
as_event_loop
*
event_loop
);
203
204
bool
205
as_event_send
(
as_event_command
* cmd);
206
207
void
208
as_event_command_begin
(
as_event_command
* cmd);
209
210
void
211
as_event_close_connection
(
as_event_connection
*
conn
);
212
213
void
214
as_event_node_destroy
(
as_node
*
node
);
215
216
bool
217
as_event_send_close_loop
(
as_event_loop
*
event_loop
);
218
219
void
220
as_event_close_loop
(
as_event_loop
*
event_loop
);
221
222
static
inline
void
223
as_event_command_free
(
as_event_command
* cmd)
224
{
225
ck_pr_dec_32(&cmd->
cluster
->
async_pending
);
226
as_node_release
(cmd->
node
);
227
228
if
(cmd->
free_buf
) {
229
cf_free(cmd->
buf
);
230
}
231
cf_free(cmd);
232
}
233
234
/******************************************************************************
235
* LIBEV INLINE FUNCTIONS
236
*****************************************************************************/
237
238
#if defined(AS_USE_LIBEV)
239
240
static
inline
int
241
as_event_validate_connection
(
as_event_connection
*
conn
)
242
{
243
return
as_socket_validate
(conn->fd);
244
}
245
246
static
inline
void
247
as_event_stop_timer
(
as_event_command
* cmd)
248
{
249
if
(cmd->
timeout_ms
) {
250
ev_timer_stop(cmd->
event_loop
->
loop
, &cmd->timer);
251
}
252
}
253
254
static
inline
void
255
as_event_stop_watcher
(
as_event_command
* cmd,
as_event_connection
*
conn
)
256
{
257
ev_io_stop(cmd->
event_loop
->
loop
, &conn->watcher);
258
}
259
260
static
inline
void
261
as_event_command_release
(
as_event_command
* cmd)
262
{
263
as_event_command_free
(cmd);
264
}
265
266
/******************************************************************************
267
* LIBUV INLINE FUNCTIONS
268
*****************************************************************************/
269
270
#elif defined(AS_USE_LIBUV)
271
272
static
inline
int
273
as_event_validate_connection
(
as_event_connection
*
conn
)
274
{
275
// Libuv does not have a peek function, so use fd directly.
276
uv_os_fd_t fd;
277
278
if
(uv_fileno((uv_handle_t*)&conn->socket, &fd) == 0) {
279
return
as_socket_validate
(fd);
280
}
281
return
false
;
282
}
283
284
static
inline
void
285
as_event_stop_timer
(
as_event_command
* cmd)
286
{
287
// Timer is stopped in libuv by uv_close which occurs later in as_event_command_release().
288
}
289
290
static
inline
void
291
as_event_stop_watcher
(
as_event_command
* cmd,
as_event_connection
* conn)
292
{
293
// Watcher already stopped by design in libuv.
294
}
295
296
void
297
as_uv_timer_closed(uv_handle_t* handle);
298
299
static
inline
void
300
as_event_command_release
(
as_event_command
* cmd)
301
{
302
if
(cmd->
timeout_ms
) {
303
// libuv requires that cmd can't be freed until timer is closed.
304
uv_close((uv_handle_t*)&cmd->timer, as_uv_timer_closed);
305
}
306
else
{
307
as_event_command_free
(cmd);
308
}
309
}
310
311
/******************************************************************************
312
* EVENT_LIB NOT DEFINED INLINE FUNCTIONS
313
*****************************************************************************/
314
315
#else
316
317
static
inline
int
318
as_event_validate_connection
(
as_event_connection
* conn)
319
{
320
return
-1;
321
}
322
323
static
inline
void
324
as_event_stop_timer
(
as_event_command
* cmd)
325
{
326
}
327
328
static
inline
void
329
as_event_stop_watcher
(
as_event_command
* cmd,
as_event_connection
* conn)
330
{
331
}
332
333
static
inline
void
334
as_event_command_release
(
as_event_command
* cmd)
335
{
336
}
337
338
#endif
339
340
/******************************************************************************
341
* COMMON INLINE FUNCTIONS
342
*****************************************************************************/
343
344
static
inline
void
345
as_event_command_execute_in_loop
(
as_event_command
* cmd)
346
{
347
// Check if command timed out after coming off queue.
348
if
(cmd->
timeout_ms
&& (cf_getms() - *(uint64_t*)cmd) > cmd->
timeout_ms
) {
349
as_error
err;
350
as_error_set_message
(&err,
AEROSPIKE_ERR_TIMEOUT
,
as_error_string
(
AEROSPIKE_ERR_TIMEOUT
));
351
// Tell the libuv version of as_event_command_release() to not try to close the uv_timer_t.
352
cmd->
timeout_ms
= 0;
353
as_event_error_callback
(cmd, &err);
354
return
;
355
}
356
357
// Start processing.
358
as_event_command_begin
(cmd);
359
}
360
361
static
inline
as_event_loop
*
362
as_event_assign
(
as_event_loop
*
event_loop
)
363
{
364
if
(! event_loop) {
365
// Assign event loop using round robin distribution.
366
// Not atomic because doesn't need to be exactly accurate.
367
uint32_t current = as_event_loop_current++;
368
event_loop = &as_event_loops[current % as_event_loop_size];
369
}
370
return
event_loop
;
371
}
372
373
static
inline
void
374
as_event_set_auth_write
(
as_event_command
* cmd)
375
{
376
// The command buffer was already allocated with enough space for max authentication size,
377
// so just use the end of the write buffer for authentication bytes.
378
cmd->
pos
= cmd->
len
;
379
cmd->
auth_len
=
as_authenticate_set
(cmd->
cluster
->
user
, cmd->
cluster
->
password
, &cmd->
buf
[cmd->
pos
]);
380
cmd->
len
= cmd->
pos
+ cmd->
auth_len
;
381
}
382
383
static
inline
void
384
as_event_set_auth_read_header
(
as_event_command
* cmd)
385
{
386
// Authenticate response buffer is at end of write buffer.
387
cmd->
pos
= cmd->
len
- cmd->
auth_len
;
388
cmd->
auth_len
=
sizeof
(as_proto);
389
cmd->
len
= cmd->
pos
+ cmd->
auth_len
;
390
cmd->
state
=
AS_ASYNC_STATE_AUTH_READ_HEADER
;
391
}
392
393
static
inline
void
394
as_event_set_auth_parse_header
(
as_event_command
* cmd)
395
{
396
// Authenticate response buffer is at end of write buffer.
397
cmd->
pos
= cmd->
len
- cmd->
auth_len
;
398
as_proto*
proto
= (as_proto*)&cmd->
buf
[cmd->
pos
];
399
as_proto_swap_from_be
(proto);
400
cmd->
auth_len
= (uint32_t)proto->sz;
401
cmd->
len
= cmd->
pos
+ cmd->
auth_len
;
402
cmd->
state
=
AS_ASYNC_STATE_AUTH_READ_BODY
;
403
}
404
405
static
inline
void
406
as_event_release_connection
(
as_cluster
*
cluster
,
as_event_connection
* conn,
as_queue
* queue)
407
{
408
as_event_close_connection
(conn);
409
ck_pr_dec_32(&cluster->
async_conn_count
);
410
as_queue_decr_total
(queue);
411
}
412
413
static
inline
void
414
as_event_decr_connection
(
as_cluster
*
cluster
,
as_queue
* queue)
415
{
416
ck_pr_dec_32(&cluster->
async_conn_count
);
417
as_queue_decr_total
(queue);
418
}
419
420
static
inline
void
421
as_event_decr_conn
(
as_event_command
* cmd)
422
{
423
as_queue
* queue = cmd->
pipe_listener
!= NULL ?
424
&cmd->
node
->
pipe_conn_qs
[cmd->
event_loop
->
index
] :
425
&cmd->
node
->
async_conn_qs
[cmd->
event_loop
->
index
];
426
427
as_event_decr_connection
(cmd->
cluster
, queue);
428
}
429
430
#ifdef __cplusplus
431
}
// end extern "C"
432
#endif