7 #include <memcached/engine.h>
8 #include <memcached/extension.h>
9 #include <memcached/extension_loggers.h>
10 #include <mock_server.h>
12 #define REALTIME_MAXDELTA 60*60*24*3
13 #define CONN_MAGIC 16369814453946373207ULL
20 struct mock_callbacks *mock_event_handlers[MAX_ENGINE_EVENT_TYPE + 1];
21 time_t process_started;
22 rel_time_t time_travel_offset;
23 rel_time_t current_time;
34 static void mock_get_auth_data(
const void *cookie,
auth_data_t *data) {
37 data->username = c->uname;
38 data->config = c->config;
42 static void mock_store_engine_specific(
const void *cookie,
void *engine_data) {
45 assert(c->magic == CONN_MAGIC);
46 c->engine_data = engine_data;
50 static void *mock_get_engine_specific(
const void *cookie) {
52 assert(c == NULL || c->magic == CONN_MAGIC);
53 return c ? c->engine_data : NULL;
56 static int mock_get_socket_fd(
const void *cookie) {
61 static void mock_set_tap_nack_mode(
const void *cookie,
bool enable) {
66 static void mock_cookie_reserve(
const void *cookie) {
70 static void mock_cookie_release(
const void *cookie) {
74 static const char *mock_get_server_version() {
78 static uint32_t mock_hash(
const void *key,
size_t length,
const uint32_t initval) {
85 static rel_time_t mock_get_current_time(
void) {
87 gettimeofday(&timer, NULL);
88 current_time = (rel_time_t) (timer.tv_sec - process_started + time_travel_offset);
92 static rel_time_t mock_realtime(
const time_t exptime) {
95 if (exptime == 0)
return 0;
97 if (exptime > REALTIME_MAXDELTA) {
104 if (exptime <= process_started)
105 return (rel_time_t)1;
106 return (rel_time_t)(exptime - process_started);
108 return (rel_time_t)(exptime + mock_get_current_time());
112 static void mock_notify_io_complete(
const void *cookie, ENGINE_ERROR_CODE status) {
114 pthread_mutex_lock(&c->mutex);
116 pthread_cond_signal(&c->cond);
117 pthread_mutex_unlock(&c->mutex);
120 static time_t mock_abstime(
const rel_time_t exptime)
122 return process_started + exptime;
125 void mock_time_travel(
int by) {
126 time_travel_offset += by;
129 static int mock_parse_config(
const char *str,
struct config_item items[], FILE *error) {
130 return parse_config(str, items, error);
137 static void *mock_new_independent_stats(
void) {
138 struct mockstats *mockstats = calloc(
sizeof(mockstats),1);
142 static void mock_release_independent_stats(
void *
stats) {
143 struct mockstats *mockstats = stats;
147 static void mock_count_eviction(
const void *cookie,
const void *key,
const int nkey) {
158 if (extension == NULL) {
167 if (ptr == extension) {
172 extensions.daemons = extension;
175 extensions.logger = extension;
182 static void mock_unregister_extension(
extension_type_t type,
void *extension)
190 while (ptr != NULL && ptr != extension) {
195 if (ptr != NULL && prev != NULL) {
199 if (extensions.daemons == ptr) {
200 extensions.daemons = ptr->
next;
205 if (extensions.logger == extension) {
206 if (stderr_logger == extension) {
207 extensions.logger = null_logger;
209 extensions.logger = stderr_logger;
224 return extensions.daemons;
227 return extensions.logger;
239 ENGINE_EVENT_TYPE type,
241 const void *cb_data) {
246 h->cb_data = cb_data;
247 h->next = mock_event_handlers[
type];
248 mock_event_handlers[
type] = h;
251 static void mock_perform_callbacks(ENGINE_EVENT_TYPE type,
256 h->cb(c, type, data, h->cb_data);
265 .realtime = mock_realtime,
266 .get_current_time = mock_get_current_time,
267 .abstime = mock_abstime,
268 .parse_config = mock_parse_config
273 .store_engine_specific = mock_store_engine_specific,
274 .get_engine_specific = mock_get_engine_specific,
275 .get_socket_fd = mock_get_socket_fd,
276 .set_tap_nack_mode = mock_set_tap_nack_mode,
277 .notify_io_complete = mock_notify_io_complete,
278 .reserve = mock_cookie_reserve,
279 .release = mock_cookie_release
284 .release_stats = mock_release_independent_stats,
285 .evicting = mock_count_eviction
290 .unregister_extension = mock_unregister_extension,
291 .get_extension = mock_get_extension
296 .perform_callbacks = mock_perform_callbacks
302 .stat = &server_stat_api,
303 .extension = &extension_api,
304 .callback = &callback_api,
305 .cookie = &server_cookie_api
312 process_started = time(0);
313 null_logger = get_null_logger();
314 stderr_logger = get_stderr_logger();
315 engine = server_engine;
316 extensions.logger = null_logger;
323 rv->magic = CONN_MAGIC;
324 rv->uname = user ? strdup(user) : NULL;
325 rv->config = config ? strdup(config) : NULL;
326 rv->connected =
true;
327 rv->next = connstructs;
330 rv->status = ENGINE_SUCCESS;
332 mock_perform_callbacks(ON_CONNECT, NULL, rv);
334 mock_get_auth_data(rv, &ad);
335 mock_perform_callbacks(ON_AUTH, (
const void*)&ad, rv);
338 assert(pthread_mutex_init(&rv->mutex, NULL) == 0);
339 assert(pthread_cond_init(&rv->cond, NULL) == 0);
344 const void *create_mock_cookie(
void) {
347 rv->magic = CONN_MAGIC;
348 rv->connected =
true;
349 rv->status = ENGINE_SUCCESS;
350 rv->handle_ewouldblock =
true;
351 assert(pthread_mutex_init(&rv->mutex, NULL) == 0);
352 assert(pthread_cond_init(&rv->cond, NULL) == 0);
357 void destroy_mock_cookie(
const void *cookie) {
361 void mock_set_ewouldblock_handling(
const void *cookie,
bool enable) {
363 v->handle_ewouldblock = enable;
366 void lock_mock_cookie(
const void *cookie) {
368 pthread_mutex_lock(&c->mutex);
371 void unlock_mock_cookie(
const void *cookie) {
373 pthread_mutex_unlock(&c->mutex);
376 void waitfor_mock_cookie(
const void *cookie) {
378 pthread_cond_wait(&c->cond, &c->mutex);
382 c->connected =
false;
383 mock_perform_callbacks(ON_DISCONNECT, NULL, c);
388 disconnect_mock_connection(c);
389 disconnect_all_mock_connections(c->next);
390 free((
void*)c->uname);
391 free((
void*)c->config);
398 destroy_mock_event_callbacks_rec(h->next);
403 void destroy_mock_event_callbacks(
void) {
405 for (i = 0; i < MAX_ENGINE_EVENT_TYPE; i++) {
406 destroy_mock_event_callbacks_rec(mock_event_handlers[i]);
407 mock_event_handlers[
i] = NULL;