static inline int Server_copy_active_handlers(Server *srv, Server *copy_from) { int i = 0; for(i = 0; i < darray_end(copy_from->handlers); i++) { Handler *from = darray_get(copy_from->handlers, i); int j = 0; for(j = 0; j < darray_end(srv->handlers); j++) { Handler *to = darray_get(srv->handlers, j); if(same_handler(from, to)) { debug("Swapping %p original for %p replacement", to, from); RouteUpdater update = {.original = to, .replacement = from}; tst_traverse(srv->hosts->routes, update_host_routes, &update); darray_set(srv->handlers, j, from); // swap them around so that the darrays stay full darray_set(copy_from->handlers, i, to); to->running = 0; break; } } } return 0; }
static int setup_master(void) { rstatus_t status; uint32_t j; vr_listen **vlisten; vr_worker *worker; for (j = 0; j < darray_n(&workers); j ++) { worker = darray_get(&workers, j); status = aeCreateFileEvent(master.vel.el, worker->socketpairs[0], AE_READABLE, thread_event_process, worker); if (status == AE_ERR) { log_error("Unrecoverable error creating master ipfd file event."); return VR_ERROR; } } for (j = 0; j < darray_n(&master.listens); j ++) { vlisten = darray_get(&master.listens,j); status = aeCreateFileEvent(master.vel.el, (*vlisten)->sd, AE_READABLE, client_accept, *vlisten); if (status == AE_ERR) { log_error("Unrecoverable error creating master ipfd file event."); return VR_ERROR; } } return VR_OK; }
static void dispatch_data_thread_deinit(dispatch_data_thread *ddt) { if (ddt->el) { aeDeleteEventLoop(ddt->el); ddt->el = NULL; } if (ddt->datas) { dmtqueue_destroy(ddt->datas); ddt->datas = NULL; } if (ddt->abgs) { int i, j, k; /* Deinit connection context for each server */ for (i = 0; i < darray_n(ddt->abgs); i ++) { abtest_group *abg = darray_get(ddt->abgs, i); for (j = 0; j < darray_n(&abg->abtest_servers); j ++) { abtest_server *abs = darray_get(&abg->abtest_servers, j); while (darray_n(abs->conn_contexts) > 0) { conn_context *cc = darray_pop(abs->conn_contexts); dispatch_conn_context_deinit(cc); } } } abtest_groups_destroy(ddt->abgs); ddt->abgs = NULL; } }
char *test_get() { mu_assert(darray_get(array, 0)==val1, "Wrong first value"); mu_assert(darray_get(array, 1)==val2, "Wrong second value"); return NULL; }
static int dispatch_thread_send_data(dispatch_data_thread *ddt) { int count_per_time = 1000; data_unit *du; while ((du = dmtqueue_pop(ddt->datas)) != NULL) { redisAsyncContext *actx; int j; size_t *argvlen = malloc(du->argc*sizeof(size_t)); reply_unit *ru = malloc(sizeof(reply_unit)); ru->du = du; ru->total_count = darray_n(ddt->abgs); ru->received_count = 0; ru->replys = malloc(ru->total_count*sizeof(redisReply *)); for (j = 0; j < du->argc; j ++) { argvlen[j] = sdslen(du->argv[j]); } for (j = 0; j < darray_n(ddt->abgs); j ++) { struct callback_data *cbd; int *keyindex, numkeys; abtest_server *abs; cbd = malloc(sizeof(struct callback_data)); cbd->ddt = ddt; cbd->ru = ru; cbd->idx = j; abtest_group *abg = darray_get(ddt->abgs, j); keyindex = get_keys_from_data_producer(du->dp, du->argv, du->argc, &numkeys); if (numkeys == 0) { unsigned int idx; idx = (unsigned int)rand()%darray_n(&abg->abtest_servers); abs = darray_get(&abg->abtest_servers,idx); } else { sds key = du->argv[keyindex[0]]; abs = abg->get_backend_server(abg,key,sdslen(key)); } free(keyindex); conn_context *cc = darray_get(abs->conn_contexts, du->hashvalue%darray_n(abs->conn_contexts)); actx = cc->actx; redisAsyncCommandArgv(actx, reply_callback, cbd, du->argc, du->argv, argvlen); } free(argvlen); ddt->count_wait_for_reply ++; if (count_per_time-- <= 0) break; } return VRT_OK; }
int master_init(vr_conf *conf) { rstatus_t status; uint32_t j; sds *host, listen_str; vr_listen **vlisten; int threads_num; int filelimit; master.cbsul = NULL; pthread_mutex_init(&master.cbsullock, NULL); conf_server_get(CONFIG_SOPN_THREADS,&threads_num); filelimit = threads_num*2+CONFIG_MIN_RESERVED_FDS; vr_eventloop_init(&master.vel,filelimit); master.vel.thread.fun_run = master_thread_run; darray_init(&master.listens,darray_n(&cserver->binds),sizeof(vr_listen*)); for (j = 0; j < darray_n(&cserver->binds); j ++) { host = darray_get(&cserver->binds,j); listen_str = sdsdup(*host); listen_str = sdscatfmt(listen_str, ":%i", cserver->port); vlisten = darray_push(&master.listens); *vlisten = vr_listen_create(listen_str); if (*vlisten == NULL) { darray_pop(&master.listens); log_error("Create listen %s failed", listen_str); sdsfree(listen_str); return VR_ERROR; } sdsfree(listen_str); } for (j = 0; j < darray_n(&master.listens); j ++) { vlisten = darray_get(&master.listens, j); status = vr_listen_begin(*vlisten); if (status != VR_OK) { log_error("Begin listen to %s failed", (*vlisten)->name); return VR_ERROR; } } master.cbsul = dlistCreate(); if (master.cbsul == NULL) { log_error("Create list failed: out of memory"); return VR_ENOMEM; } setup_master(); return VR_OK; }
static int simple_set_session( ssl_context *ssl ) { time_t t = THE_CURRENT_TIME_IS; int i = 0; ssl_session *cur = NULL; int make_new = 1; check(setup_ssl_session_cache() == 0, "Failed to initialize SSL session cache."); for(i = 0; i < darray_end(SSL_SESSION_CACHE); i++) { cur = darray_get(SSL_SESSION_CACHE, i); if( ssl->timeout != 0 && t - cur->start > ssl->timeout ) { make_new = 0; break; /* expired, reuse this slot */ } if( memcmp( ssl->session->id, cur->id, cur->length ) == 0 ) { make_new = 0; break; /* client reconnected */ } } if(make_new) { cur = (ssl_session *) darray_new(SSL_SESSION_CACHE); check_mem(cur); darray_push(SSL_SESSION_CACHE, cur); } *cur = *ssl->session; return 0; error: return 1; }
static int handler_process_control_request(Connection *conn, tns_value_t *data) { tns_value_t *args = darray_get(data->value.list, 1); check(args->type==tns_tag_dict, "Invalid control response: not a dict."); hnode_t *n = hash_lookup(args->value.dict, &KEEP_ALIVE); if(n != NULL) { Register_ping(IOBuf_fd(conn->iob)); } n = hash_lookup(args->value.dict, &CREDITS); if(n != NULL) { tns_value_t *credits = (tns_value_t *)hnode_get(n); conn->sendCredits += credits->value.number; taskwakeup(&conn->uploadRendez); } n = hash_lookup(args->value.dict, &CANCEL); if(n != NULL && !conn->closing) { Register_disconnect(IOBuf_fd(conn->iob)); taskwakeup(&conn->uploadRendez); } tns_value_destroy(data); return 0; error: return -1; }
static inline void handler_process_extended_request(int fd, Connection *conn, bstring payload) { char *x; tns_value_t *data = NULL; darray_t *l = NULL; data = tns_parse(bdata(payload),blength(payload),&x); check((x-bdata(payload))==blength(payload), "Invalid extended response: extra data after tnetstring."); check(data->type==tns_tag_list, "Invalid extended response: not a list."); l = data->value.list; check(darray_end(l)==2, "Invalid extended response: odd number of elements in list."); tns_value_t *key=darray_get(l,0); check(key->type==tns_tag_string, "Invalid extended response: key is not a string"); check(key->value.string != NULL,, "Invalid extended response: key is NULL"); if(!bstrcmp(key->value.string, &XREQ_CTL)) { check (0 == handler_process_control_request(conn, data), "Control request processing returned non-zero: %s", bdata(key->value.string)); } else { check (0 == dispatch_extended_request(conn, key->value.string, data), "Extended request dispatch returned non-zero: %s",bdata(key->value.string)); } return; error: tns_value_destroy(data); Register_disconnect(fd); // return ignored return; }
void Server_queue_cleanup() { if(darray_end(SERVER_QUEUE) < SERVER_ACTIVE) { // skip it, not enough to care about return; } // pop the last one off to make sure it's never deleted Server *cur_srv = darray_pop(SERVER_QUEUE); uint32_t too_old = time(NULL) - SERVER_TTL; int i = 0; // TODO: kind of a dumb way to do this since it reorders the list // go through all but the max we want to keep for(i = 0; i < darray_end(SERVER_QUEUE) - SERVER_ACTIVE; i++) { Server *srv = darray_get(SERVER_QUEUE, i); if(srv->created_on < too_old) { Server *replace = darray_pop(SERVER_QUEUE); darray_set(SERVER_QUEUE, i, replace); srv->listen_fd = -1; // don't close it Server_destroy(srv); } } // put the sacred server back on the end darray_push(SERVER_QUEUE, cur_srv); return; }
/* return value * 1: need sleep a while because of there are too many data cached * 0: can normally continue * -1: error occur */ int data_dispatch(data_unit *du) { int thread_idx; dispatch_data_thread *ddt; long long length; int *keyindex, numkeys; keyindex = get_keys_from_data_producer(du->dp, du->argv, du->argc, &numkeys); if (numkeys == 0) { du->hashvalue = (unsigned int)rand(); } else { sds key = du->argv[keyindex[0]]; du->hashvalue = (unsigned int)hash_crc32a(key, sdslen(key)); } free(keyindex); thread_idx = du->hashvalue%dispatch_data_threads_count; ddt = darray_get(dispatch_data_threads, thread_idx); length = dmtqueue_push(ddt->datas, du); if (length <= 0) { test_log_error("Data unit push to dispatch thread %d failed", ddt->id); return -1; } else if (length > 2000) { return 1; } return 0; }
int Server_stop_handlers(Server *srv) { int i = 0; for(i = 0; i < darray_end(srv->handlers); i++) { Handler *handler = darray_get(srv->handlers, i); check(handler != NULL, "Invalid handler, can't be NULL."); if(handler->running) { log_info("STOPPING HANDLER %s", bdata(handler->send_spec)); if(handler->task != NULL) { tasksignal(handler->task, SIGINT); handler->running = 0; taskdelay(1); } } if(handler->recv_socket) zmq_close(handler->recv_socket); if(handler->send_socket) zmq_close(handler->send_socket); handler->recv_socket = NULL; handler->send_socket = NULL; } return 0; error: return -1; }
static int simple_get_session( ssl_context *ssl ) { time_t t = THE_CURRENT_TIME_IS; int i = 0; check(setup_ssl_session_cache() == 0, "Failed to initialize SSL session cache."); if( ssl->resume == 0 ) return 1; ssl_session *cur = NULL; for(i = 0; i < darray_end(SSL_SESSION_CACHE); i++) { cur = darray_get(SSL_SESSION_CACHE, i); if( ssl->timeout != 0 && t - cur->start > ssl->timeout ) { continue; } if( ssl->session->ciphersuite != cur->ciphersuite || ssl->session->length != cur->length ) { continue; } if( memcmp( ssl->session->id, cur->id, cur->length ) != 0 ) { continue; } // TODO: odd, why 48? this is from polarssl memcpy( ssl->session->master, cur->master, 48 ); return 0; } error: // fallthrough return 1; }
void dispatch_conn_exist(client *c, int tid) { struct connswapunit *su = csui_new(); char buf[1]; vr_worker *worker; if (su == NULL) { freeClient(c); /* given that malloc failed this may also fail, but let's try */ log_error("Failed to allocate memory for connection swap object\n"); return ; } su->num = tid; su->data = c; unlinkClientFromEventloop(c); cbsul_push(su); worker = darray_get(&workers, (uint32_t)c->curidx); /* Back to master */ buf[0] = 'b'; if (vr_write(worker->socketpairs[1], buf, 1) != 1) { log_error("Notice the worker failed."); } }
int DB_valid_schema(tns_value_t *res, int row, int ncols, ...) { va_list argp; va_start(argp, ncols); int i = 0; check(tns_get_type(res) == tns_tag_list, "Invalid result set, must be a list."); int rows = darray_end(res->value.list); check(rows != -1, "Result isn't in a table format."); check(row < rows, "Row is past end of result set: %d > %d", row, rows); // get the row they ask for tns_value_t *row_data = darray_get(res->value.list, row); // make sure it's got the right number of columns check(tns_get_type(row_data) == tns_tag_list, "Invalid row %d, must be a list.", row); int cols = darray_end(row_data->value.list); check(cols == ncols, "Expected %d columns, but result set has %d.", cols, ncols); for(i = 0; i < ncols; i++) { tns_type_tag expecting = va_arg(argp, tns_type_tag); tns_value_t *cell = DB_get(res, row, i); check(tns_get_type(cell) == expecting, "Row %d, Column %d has wrong type.", row, i); } va_end(argp); return 1; error: va_end(argp); return 0; }
tns_value_t *Register_info() { int i = 0; Registration *reg; tns_value_t *rows = tns_new_list(); int nscanned = 0; time_t now = THE_CURRENT_TIME_IS; for(i = 0, nscanned = 0; i < darray_max(REGISTRATIONS) && nscanned < NUM_REG_FD; i++) { reg = darray_get(REGISTRATIONS, i); if(Register_valid(reg)) { nscanned++; // stop scaning after we found all of them tns_value_t *data = tns_new_list(); tns_add_to_list(data, tns_new_integer(reg->id == UINT32_MAX ? -1 : (long)reg->id)); tns_add_to_list(data, tns_new_integer(i)); // fd tns_add_to_list(data, tns_new_integer(reg->data->type)); tns_add_to_list(data, tns_new_integer(ZERO_OR_DELTA(now, reg->last_ping))); tns_add_to_list(data, tns_new_integer(ZERO_OR_DELTA(now, reg->last_read))); tns_add_to_list(data, tns_new_integer(ZERO_OR_DELTA(now, reg->last_write))); tns_add_to_list(data, tns_new_integer(reg->bytes_read)); tns_add_to_list(data, tns_new_integer(reg->bytes_written)); tns_add_to_list(rows, data); } } return tns_standard_table(®ISTER_HEADERS, rows); }
int Server_start_handlers(Server *srv, Server *copy_from) { int i = 0; int rc = 0; if(copy_from != NULL) { rc = Server_copy_active_handlers(srv, copy_from); check(rc != -1, "Failed to copy old handlers to new server config."); } for(i = 0; i < darray_end(srv->handlers); i++) { Handler *handler = darray_get(srv->handlers, i); check(handler != NULL, "Invalid handler, can't be NULL."); if(!handler->running) { log_info("LOADING Handler %s", bdata(handler->send_spec)); rc = taskcreate(Handler_task, handler, HANDLER_STACK); check(rc != -1, "Failed to start handler task."); handler->running = 1; } } return 0; error: return -1; }
void * darray_pop(DArray *array) { void *value; value = darray_get(array, array->last); darray_set(array, array->last, NULL); array->last--; return value; }
/** * Gets the tns_value_t at this result's row/col point, * or NULL (which will be tns_get_type == tns_tag_invalid) * if that row isn't possible. */ tns_value_t *DB_get(tns_value_t *res, int row, int col) { check(tns_get_type(res) == tns_tag_list, "Result should be a list."); check(row < darray_end(res->value.list), "Row %d past end of result set length: %d", row, darray_end(res->value.list)); tns_value_t *r = darray_get(res->value.list, row); check(tns_get_type(r) == tns_tag_list, "Row %d should be a list.", row); check(col < darray_end(r->value.list), "Column %d past end of result set length: %d", col, darray_end(r->value.list)); return darray_get(r->value.list, col); error: return NULL; }
int Register_cleanout() { int i = 0; int nkilled = 0; int nscanned = 0; time_t now = THE_CURRENT_TIME_IS; int min_ping = Setting_get_int("limits.min_ping", DEFAULT_MIN_PING); int min_write_rate = Setting_get_int("limits.min_write_rate", DEFAULT_MIN_READ_RATE); int min_read_rate = Setting_get_int("limits.min_read_rate", DEFAULT_MIN_WRITE_RATE); int kill_limit = Setting_get_int("limits.kill_limit", DEFAULT_KILL_LIMIT); for(i = 0, nscanned = 0; i < darray_max(REGISTRATIONS) && nscanned < NUM_REG_FD; i++) { Registration *reg = darray_get(REGISTRATIONS, i); if(Register_valid(reg)) { nscanned++; // avoid scanning the whole array if we've found them all int last_ping = ZERO_OR_DELTA(now, reg->last_ping); off_t read_rate = reg->bytes_read / (ZERO_OR_DELTA(now, reg->last_read) + 1); off_t write_rate = reg->bytes_written / (ZERO_OR_DELTA(now, reg->last_write) + 1); int should_kill = 0; debug("Checking fd=%d:conn_id=%d against last_ping: %d, read_rate: %d, write_rate: %d", i, reg->id, last_ping, read_rate, write_rate); // these are weighted so they are not if-else statements if(min_ping != 0 && last_ping > min_ping) { debug("Connection fd=%d:conn_id=%d over limits.min_ping time: %d < %d", i, reg->id, min_ping, last_ping); should_kill++; } if(min_read_rate != 0 && read_rate < min_read_rate) { debug("Connection fd=%d:conn_id=%d read rate lower than allowed: %d < %d", i, reg->id, read_rate, min_read_rate); should_kill++; } if(min_write_rate != 0 && write_rate < min_write_rate) { debug("Connection fd=%d:conn_id=%d write rate lower than allowed: %d < %d", i, reg->id, write_rate, min_write_rate); should_kill++; } if(should_kill > kill_limit) { nkilled++; Register_disconnect(i); } } } if(nkilled) { log_warn("Killed %d connections according to min_ping: %d, min_write_rate: %d, min_read_rate: %d", nkilled, min_ping, min_write_rate, min_read_rate); } return nkilled; }
void putItem(struct tile *t, int x, int y){ union item *i = darray_get(t->itm, 0); switch(i->type){ case I_ORB: putChar(x, y, ORB_C, CORB); default: putChar(x, y, i->g.disp, i->g.col); } }
int hashmap_traverse(Hashmap *map, Hashmap_traverse_cb traverse_cb) { int i = 0; int j = 0; int rc = 0; for (i = 0; i < darray_count(map->buckets); i += 1) { DArray *bucket = darray_get(map->buckets, i); if (bucket) { for (j = 0; j < darray_count(bucket); j += 1) { HashmapNode *node = darray_get(bucket, j); rc = traverse_cb(node); if (rc != 0) return rc; } } } return 0; }
DArray * darray_radix_sort(DArray *array) { DArray *buckets, *bucket; int *val, i, j, cur, mask, sortval, sorted; buckets = darray_init(); mask = 1; do { sorted = 1; // reset the buckets for (i = 0; i < 10; i++) { darray_set(buckets, i, darray_init()); } // sort the values into buckets for (i = 0; i <= (array->last); i++) { val = (int*)darray_get(array, i); sortval = (*val / mask) % 10; if (sortval > 0) { sorted = 0; } darray_push((PDArray)darray_get(buckets, sortval), val); } // rebuild array cur = 0; for (i = 0; i < 10; i++) { bucket = (PDArray)darray_get(buckets, i); for (j = 0; j <= (bucket->last); j++) { darray_set(array, cur++, darray_get(bucket, j)); } } mask *= 10; } while (!sorted); return array; }
static inline void Server_destroy_handlers(Server *srv) { int i = 0; for(i = 0; i < darray_end(srv->handlers); i++) { Handler *handler = darray_get(srv->handlers, i); Handler_destroy(handler); } darray_destroy(srv->handlers); }
int vrt_wait_dispatch_data(void) { unsigned int i; /* wait for the produce threads finish */ for(i = 0; i < darray_n(dispatch_data_threads); i ++){ dispatch_data_thread *ddt = darray_get(dispatch_data_threads, i); pthread_join(ddt->thread_id, NULL); } return VRT_OK; }
Connection *Register_fd_exists(int fd) { check(fd < MAX_REGISTERED_FDS, "FD given to register is greater than max."); check(fd >= 0, "Invalid FD given for exists check"); Registration *reg = darray_get(REGISTRATIONS, fd); return reg != NULL ? reg->data : NULL; error: return NULL; }
static inline int hashmap_get_node(Hashmap *map, uint32_t hash, DArray *bucket, void *key) { int i = 0; for (i = 0; i < darray_end(bucket); i += 1) { debug("TRY: %d", i); HashmapNode *node = darray_get(bucket, i); if (node->hash == hash && map->compare(node->key, key) == 0) { return i; } } return -1; }
int Register_fd_for_id(uint32_t id) { RMElement *el = RadixMap_find(REG_ID_TO_FD, id); check_debug(el != NULL, "Id %d not registered.", id); Registration *reg = darray_get(REGISTRATIONS, el->data.value); check_debug(Register_valid(reg), "Nothing registered under id %d.", id); return reg->fd; error: return -1; }
void hashmap_destroy(Hashmap *map) { int i = 0; int j = 0; if (map) { if (map->buckets) { for (i = 0; i < darray_count(map->buckets); i += 1) { DArray *bucket = darray_get(map->buckets, i); if (bucket) { for (j = 0; j < darray_count(bucket); j += 1) { free(darray_get(bucket, j)); } darray_destroy(bucket); } } darray_destroy(map->buckets); } free(map); } }
void darray_free(DArray *array) { int i = array->last; while (i >= 0) { void * ptr = darray_get(array, i); if (ptr != NULL) { free(ptr); } i--; } free(array); }