int main(int argc, const char *argv[]) { if(setup_cli(argc, argv) == -1) { usage(argv[0]); return EXIT_FAILURE; } config.syslog = 0; config.loglevel = CRIT; config.bufsize = 16384; struct node_conf conf = {NULL, 0}; struct context ctx; context_init(&ctx); memcpy(&config.node, &conf, sizeof(config.node)); slot_init_updater(&ctx); RUN_CASE(test_slot); RUN_CASE(test_hash); RUN_CASE(test_parser); RUN_CASE(test_cmd); RUN_CASE(test_server); RUN_CASE(test_dict); RUN_CASE(test_socket); RUN_CASE(test_client); RUN_CASE(test_timer); RUN_CASE(test_config); usleep(10000); slot_create_job(SLOT_UPDATER_QUIT); pthread_join(ctx.thread, NULL); report(); return manager.failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }
int main(int argc, const char *argv[]) { if(setup_cli(argc, argv) == -1) { usage(argv[0]); return EXIT_FAILURE; } config.syslog = 0; config.loglevel = CRIT; config.bufsize = 16384; config.thread = 1; struct node_conf conf = {NULL, 0}; build_contexts(); struct context *contexts = get_contexts(); memcpy(&config.node, &conf, sizeof(config.node)); slot_start_manager(&contexts[config.thread]); RUN_CASE(test_slot); RUN_CASE(test_hash); RUN_CASE(test_parser); RUN_CASE(test_cmd); RUN_CASE(test_server); RUN_CASE(test_dict); RUN_CASE(test_socket); RUN_CASE(test_client); RUN_CASE(test_timer); RUN_CASE(test_config); RUN_CASE(test_stats); RUN_CASE(test_mbuf); RUN_CASE(test_slowlog); usleep(10000); slot_create_job(SLOT_UPDATER_QUIT); pthread_join(contexts[config.thread].thread, NULL); for (int i = 0; i <= config.thread; i++) { context_free(&contexts[i]); } destroy_contexts(); report(); return manager.failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }
void server_eof(struct connection *server, const char *reason) { LOG(WARN, "server eof"); struct command *c; while (!STAILQ_EMPTY(&server->info->ready_queue)) { c = STAILQ_FIRST(&server->info->ready_queue); STAILQ_REMOVE_HEAD(&server->info->ready_queue, ready_next); STAILQ_NEXT(c, ready_next) = NULL; if (c->stale) { cmd_free(c); } else { cmd_mark_fail(c, reason); } } // remove unprocessed data struct mbuf *b = TAILQ_LAST(&server->info->data, mhdr); if (b != NULL && b->pos < b->last) { b->pos = b->last; } while (!STAILQ_EMPTY(&server->info->waiting_queue)) { c = STAILQ_FIRST(&server->info->waiting_queue); STAILQ_REMOVE_HEAD(&server->info->waiting_queue, waiting_next); STAILQ_NEXT(c, waiting_next) = NULL; mbuf_range_clear(server->ctx, c->rep_buf); if (c->stale) { cmd_free(c); } else { cmd_mark_fail(c, reason); } } event_deregister(&server->ctx->loop, server); // drop all unsent requests cmd_iov_free(&server->info->iov); conn_free(server); slot_create_job(SLOT_UPDATE); }
int server_read_reply(struct connection *server, struct command *cmd) { int status = cmd_read_rep(cmd, server); if (status != CORVUS_OK) return status; ATOMIC_INC(server->info->completed_commands, 1); if (server->info->readonly_sent) { return CORVUS_READONLY; } if (cmd->asking) return CORVUS_ASKING; if (cmd->stale) { mbuf_range_clear(cmd->ctx, cmd->rep_buf); return CORVUS_OK; } if (cmd->reply_type != REP_ERROR) { cmd_mark_done(cmd); return CORVUS_OK; } struct redirect_info info = {.type = CMD_ERR, .slot = -1}; memset(info.addr, 0, sizeof(info.addr)); if (cmd_parse_redirect(cmd, &info) == CORVUS_ERR) { mbuf_range_clear(cmd->ctx, cmd->rep_buf); cmd_mark_fail(cmd, rep_redirect_err); return CORVUS_OK; } switch (info.type) { case CMD_ERR_MOVED: slot_create_job(SLOT_UPDATE); CHECK_REDIRECTED(cmd, info.addr, rep_redirect_err); return server_redirect(cmd, &info); case CMD_ERR_ASK: CHECK_REDIRECTED(cmd, info.addr, rep_redirect_err); cmd->asking = 1; return server_redirect(cmd, &info); case CMD_ERR_CLUSTERDOWN: slot_create_job(SLOT_UPDATE); CHECK_REDIRECTED(cmd, NULL, NULL); return server_retry(cmd); default: cmd_mark_done(cmd); break; } return CORVUS_OK; } int server_read(struct connection *server) { int status = CORVUS_OK; struct command *cmd; struct conn_info *info = server->info; int64_t now = get_time(); while (!STAILQ_EMPTY(&info->waiting_queue)) { cmd = STAILQ_FIRST(&info->waiting_queue); status = server_read_reply(server, cmd); cmd->rep_time[1] = now; switch (status) { case CORVUS_ASKING: LOG(DEBUG, "recv asking"); mbuf_range_clear(cmd->ctx, cmd->rep_buf); cmd->asking = 0; continue; case CORVUS_READONLY: LOG(DEBUG, "recv readonly"); mbuf_range_clear(cmd->ctx, cmd->rep_buf); server->info->readonly_sent = false; continue; case CORVUS_OK: STAILQ_REMOVE_HEAD(&info->waiting_queue, waiting_next); STAILQ_NEXT(cmd, waiting_next) = NULL; if (cmd->stale) cmd_free(cmd); continue; } break; } info->last_active = -1; return status; }