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