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
void
161
as_event_error_callback
(
as_event_command
* cmd,
as_error
* err);
162
163
void
164
as_event_socket_error
(
as_event_command
* cmd,
as_error
* err);
165
166
void
167
as_event_response_error
(
as_event_command
* cmd,
as_error
* err);
168
169
void
170
as_event_timeout
(
as_event_command
* cmd);
171
172
bool
173
as_event_command_parse_result
(
as_event_command
* cmd);
174
175
bool
176
as_event_command_parse_header
(
as_event_command
* cmd);
177
178
bool
179
as_event_command_parse_success_failure
(
as_event_command
* cmd);
180
181
void
182
as_event_command_free
(
as_event_command
* cmd);
183
184
/******************************************************************************
185
* IMPLEMENTATION SPECIFIC FUNCTIONS
186
*****************************************************************************/
187
188
bool
189
as_event_create_loop
(
as_event_loop
*
event_loop
);
190
191
void
192
as_event_register_external_loop
(
as_event_loop
*
event_loop
);
193
194
bool
195
as_event_send
(
as_event_command
* cmd);
196
197
void
198
as_event_command_begin
(
as_event_command
* cmd);
199
200
void
201
as_event_close_connection
(
as_event_connection
*
conn
);
202
203
void
204
as_event_node_destroy
(
as_node
*
node
);
205
206
bool
207
as_event_send_close_loop
(
as_event_loop
*
event_loop
);
208
209
/******************************************************************************
210
* LIBEV INLINE FUNCTIONS
211
*****************************************************************************/
212
213
#if defined(AS_USE_LIBEV)
214
215
static
inline
int
216
as_event_validate_connection
(
as_event_connection
*
conn
)
217
{
218
return
as_socket_validate
(&conn->socket);
219
}
220
221
static
inline
void
222
as_event_stop_timer
(
as_event_command
* cmd)
223
{
224
if
(cmd->
timeout_ms
) {
225
ev_timer_stop(cmd->
event_loop
->
loop
, &cmd->timer);
226
}
227
}
228
229
static
inline
void
230
as_event_stop_watcher
(
as_event_command
* cmd,
as_event_connection
*
conn
)
231
{
232
ev_io_stop(cmd->
event_loop
->
loop
, &conn->watcher);
233
}
234
235
static
inline
void
236
as_event_command_release
(
as_event_command
* cmd)
237
{
238
as_event_command_free
(cmd);
239
}
240
241
/******************************************************************************
242
* LIBUV INLINE FUNCTIONS
243
*****************************************************************************/
244
245
#elif defined(AS_USE_LIBUV)
246
247
static
inline
int
248
as_event_validate_connection
(
as_event_connection
*
conn
)
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
260
as_event_stop_timer
(
as_event_command
* cmd)
261
{
262
// Timer is stopped in libuv by uv_close which occurs later in as_event_command_release().
263
}
264
265
static
inline
void
266
as_event_stop_watcher
(
as_event_command
* cmd,
as_event_connection
* conn)
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
275
as_event_command_release
(
as_event_command
* cmd)
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
{
282
as_event_command_free
(cmd);
283
}
284
}
285
286
/******************************************************************************
287
* EVENT_LIB NOT DEFINED INLINE FUNCTIONS
288
*****************************************************************************/
289
290
#else
291
292
static
inline
int
293
as_event_validate_connection
(
as_event_connection
* conn)
294
{
295
return
-1;
296
}
297
298
static
inline
void
299
as_event_stop_timer
(
as_event_command
* cmd)
300
{
301
}
302
303
static
inline
void
304
as_event_stop_watcher
(
as_event_command
* cmd,
as_event_connection
* conn)
305
{
306
}
307
308
static
inline
void
309
as_event_command_release
(
as_event_command
* cmd)
310
{
311
}
312
313
#endif
314
315
/******************************************************************************
316
* COMMON INLINE FUNCTIONS
317
*****************************************************************************/
318
319
static
inline
void
320
as_event_command_execute_in_loop
(
as_event_command
* cmd)
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;
325
as_error_set_message
(&err,
AEROSPIKE_ERR_TIMEOUT
,
as_error_string
(
AEROSPIKE_ERR_TIMEOUT
));
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.
333
as_event_command_begin
(cmd);
334
}
335
336
static
inline
as_event_loop
*
337
as_event_assign
(
as_event_loop
*
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
344
as_event_set_auth_write
(
as_event_command
* cmd)
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
354
as_event_set_auth_read_header
(
as_event_command
* cmd)
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
;
360
cmd->
state
=
AS_ASYNC_STATE_AUTH_READ_HEADER
;
361
}
362
363
static
inline
void
364
as_event_set_auth_parse_header
(
as_event_command
* cmd)
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
;
372
cmd->
state
=
AS_ASYNC_STATE_AUTH_READ_BODY
;
373
}
374
375
static
inline
void
376
as_event_release_connection
(
as_cluster
*
cluster
,
as_event_connection
* conn,
as_queue
* queue)
377
{
378
as_event_close_connection
(conn);
379
ck_pr_dec_32(&cluster->
async_conn_count
);
380
as_queue_decr_total
(queue);
381
}
382
383
static
inline
void
384
as_event_decr_connection
(
as_cluster
*
cluster
,
as_queue
* queue)
385
{
386
ck_pr_dec_32(&cluster->
async_conn_count
);
387
as_queue_decr_total
(queue);
388
}
389
390
static
inline
void
391
as_event_decr_conn
(
as_event_command
* cmd)
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