static ngx_int_t __on_write_master1_complete( uint8_t method, ngx_bool_t has_tb, ngx_http_request_t *r, ngx_http_hustdb_ha_write_ctx_t * ctx) { __update_error(method, r->headers_out.status, ctx); ctx->base.peer = ctx->base.peer->next; ngx_bool_t alive = ngx_http_peer_is_alive(ctx->base.peer->peer); ngx_http_hustdb_ha_main_conf_t * mcf = hustdb_ha_get_module_main_conf(r); if (mcf->debug_sync) { alive = false; } if (alive) // master2 { ctx->state = STATE_WRITE_MASTER2; return ngx_http_run_subrequest(r, &ctx->base.base, ctx->base.peer->peer); } // master2 dead ++ctx->error_count; ctx->error_peer = ctx->base.peer; if (ctx->error_count > 1) // both master1 & master2 fail { return hustdb_ha_send_response(NGX_HTTP_NOT_FOUND, NULL, NULL, r); } return __write_sync_data(method, has_tb, r, ctx); }
static ngx_int_t __write_sync_data( uint8_t method, ngx_bool_t has_tb, ngx_http_request_t *r, ngx_http_hustdb_ha_write_ctx_t * ctx) { do { time_t now = time(NULL); uint32_t ttl = (0 == ctx->ttl) ? 0 : (uint32_t) (now + ctx->ttl); ngx_buf_t * value = NULL; ngx_buf_t * head = __encode_head(method, ctx->proto, has_tb, ctx->base.version, ctx->base.key, ctx->base.tb, ttl, r->pool); if (r->request_body) { if (!ngx_http_insert_head_to_body(head, r)) { break; } value = ngx_http_get_request_body(r); } else { value = head; } if (!value) { break; } ngx_http_hustdb_ha_main_conf_t * mcf = hustdb_ha_get_module_main_conf(r); ngx_str_t * server = &ctx->error_peer->peer->server; if (!hustdb_ha_write_log(&mcf->zlog_mdc, server, value, r->pool)) { break; } static ngx_str_t SYNC_KEY = ngx_string("Sync"); if (!ngx_http_add_field_to_headers_out(&SYNC_KEY, server, r)) { break; } return hustdb_ha_send_response(NGX_HTTP_OK, ctx->base.version, NULL, r); } while (0); return hustdb_ha_send_response(NGX_HTTP_NOT_FOUND, NULL, NULL, r); }
ngx_int_t hustdb_ha_sync_status_handler(ngx_str_t * backend_uri, ngx_http_request_t *r) { ngx_http_hustdb_ha_main_conf_t * mcf = hustdb_ha_get_module_main_conf(r); if (!mcf) { return NGX_ERROR; } ngx_int_t rc = hustdb_ha_fetch_sync_data(&mcf->sync_status_uri, &mcf->sync_status_args, &mcf->sync_user, &mcf->sync_passwd, mcf->sync_peer, r); if (NGX_ERROR == rc) { return ngx_http_send_response_imp(NGX_HTTP_NOT_FOUND, NULL, r); } return NGX_DONE; }
static ngx_bool_t __set_write_context(const char * key, ngx_bool_t has_tb, ngx_http_request_t *r, write_ctx_t * ctx) { if (key) { ctx->key = key; } else { ctx->key = ngx_http_get_param_val(&r->args, "key", r->pool); if (!ctx->key) { return false; } } ctx->proto = HUSTDB_PROTO_BINARY; char * proto = ngx_http_get_param_val(&r->args, "proto", r->pool); if (proto) { int tmp = atoi(proto); if (HUSTDB_PROTO_JSON == tmp) { ctx->proto = HUSTDB_PROTO_JSON; } else if (HUSTDB_PROTO_BINARY == tmp) { ctx->proto = HUSTDB_PROTO_BINARY; } else { return false; } } ctx->tb = ngx_http_get_param_val(&r->args, "tb", r->pool); if (has_tb && !ctx->tb) { return false; } ctx->ttl = 0; char * val = ngx_http_get_param_val(&r->args, "ttl", r->pool); if (val) { ctx->ttl = atoi(val); } ngx_http_hustdb_ha_main_conf_t * mcf = hustdb_ha_get_module_main_conf(r); if (!mcf) { return false; } ctx->peer = hustdb_ha_get_writelist(ctx->key); if (!ctx->peer) { return false; } ctx->error_count = 0; ctx->error_peer = NULL; ctx->state = STATE_WRITE_MASTER1; ngx_bool_t alive = ngx_http_peer_is_alive(ctx->peer->peer); if (!alive) // master1 { ++ctx->error_count; ctx->error_peer = ctx->peer; ctx->peer = ctx->peer->next; ctx->state = STATE_WRITE_MASTER2; alive = ngx_http_peer_is_alive(ctx->peer->peer); if (!alive) // master2 { return false; } } return true; }
static ngx_bool_t __parse_args( ngx_bool_t has_tb, ngx_bool_t hash_by_tb, ngx_http_request_t *r, write_ctx_t * ctx) { ctx->tb = ngx_http_get_param_val(&r->args, "tb", r->pool); if (has_tb && !ctx->tb) { return false; } ctx->ttl = 0; char * val = ngx_http_get_param_val(&r->args, "ttl", r->pool); if (val) { ctx->ttl = atoi(val); } ctx->score = 0; val = ngx_http_get_param_val(&r->args, "score", r->pool); if (val) { char * endptr; ctx->score = strtoull(val, &endptr, 10); } ctx->opt = 0; val = ngx_http_get_param_val(&r->args, "opt", r->pool); if (val) { ctx->opt = atoi(val); } ngx_http_hustdb_ha_main_conf_t * mcf = hustdb_ha_get_module_main_conf(r); if (!mcf) { return false; } ctx->peer = hustdb_ha_get_writelist(hash_by_tb ? ctx->tb : ctx->key); if (!ctx->peer) { return false; } ctx->error_count = 0; ctx->error_peer = NULL; ctx->state = STATE_WRITE_MASTER1; ngx_bool_t alive = ngx_http_peer_is_alive(ctx->peer->peer); if (!alive) // master1 { ++ctx->error_count; ctx->error_peer = ctx->peer; ctx->peer = ctx->peer->next; ctx->state = STATE_WRITE_MASTER2; alive = ngx_http_peer_is_alive(ctx->peer->peer); if (!alive) // master2 { return false; } } return true; }