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