int dnet_trans_insert_nolock(struct dnet_net_state *st, struct dnet_trans *a) { struct rb_root *root = &st->trans_root; struct rb_node **n = &root->rb_node, *parent = NULL; struct dnet_trans *t; int cmp; while (*n) { parent = *n; t = rb_entry(parent, struct dnet_trans, trans_entry); cmp = dnet_trans_cmp(t->trans, a->trans); if (cmp < 0) n = &parent->rb_left; else if (cmp > 0) n = &parent->rb_right; else return -EEXIST; } if (a->st && a->st->n) dnet_log(a->st->n, DNET_LOG_NOTICE, "%s: %s: added trans: %llu -> %s/%d", dnet_dump_id(&a->cmd.id), dnet_cmd_string(a->cmd.cmd), (unsigned long long)a->trans, dnet_addr_string(&a->st->addr), a->cmd.backend_id); rb_link_node(&a->trans_entry, parent, n); rb_insert_color(&a->trans_entry, root); return 0; }
/* * Allocates and sends transaction into given @st network state/connection. * Uses @s session only to get wait timeout for transaction, if it is NULL, global node timeout (@dnet_node::wait_ts) is used. * * If something fails, completion handler from @ctl will be invoked with (NULL, NULL, @ctl->priv) arguments */ int dnet_trans_alloc_send_state(struct dnet_session *s, struct dnet_net_state *st, struct dnet_trans_control *ctl) { struct dnet_io_req req; struct dnet_node *n = st->n; struct dnet_cmd *cmd; struct dnet_trans *t; int err; t = dnet_trans_alloc(n, sizeof(struct dnet_cmd) + ctl->size); if (!t) { err = dnet_trans_send_fail(s, dnet_state_addr(st), ctl, -ENOMEM, 1); goto err_out_exit; } t->complete = ctl->complete; t->priv = ctl->priv; if (s) { t->wait_ts = *dnet_session_get_timeout(s); } cmd = (struct dnet_cmd *)(t + 1); dnet_trans_control_fill_cmd(s, ctl, cmd); t->command = cmd->cmd; cmd->trans = t->rcv_trans = t->trans = atomic_inc(&n->trans); memcpy(&t->cmd, cmd, sizeof(struct dnet_cmd)); if (ctl->size && ctl->data) memcpy(cmd + 1, ctl->data, ctl->size); dnet_convert_cmd(cmd); t->st = dnet_state_get(st); memset(&req, 0, sizeof(req)); req.st = st; req.header = cmd; req.hsize = sizeof(struct dnet_cmd) + ctl->size; req.fd = -1; dnet_log(n, DNET_LOG_INFO, "%s: %s: created %s", dnet_dump_id(&cmd->id), dnet_cmd_string(cmd->cmd), dnet_print_trans(t) ); err = dnet_trans_send(t, &req); if (err) goto err_out_put; return 0; err_out_put: dnet_trans_send_fail(s, dnet_state_addr(st), ctl, err, 0); dnet_trans_put(t); err_out_exit: return 0; }
std::string get_cmd_string(int cmd) { return std::string(dnet_cmd_string(cmd)); }
void dnet_trans_destroy(struct dnet_trans *t) { struct dnet_net_state *st = NULL; struct timeval tv; long diff; if (!t) return; dnet_node_set_trace_id(t->cmd.trace_id, t->cmd.flags & DNET_FLAGS_TRACE_BIT); gettimeofday(&tv, NULL); diff = 1000000 * (tv.tv_sec - t->start.tv_sec) + (tv.tv_usec - t->start.tv_usec); if (t->st && t->st->n) { st = t->st; pthread_mutex_lock(&st->trans_lock); list_del_init(&t->trans_list_entry); if (t->trans_entry.rb_parent_color) { dnet_trans_remove_nolock(st, t); } pthread_mutex_unlock(&st->trans_lock); } else if (!list_empty(&t->trans_list_entry)) { assert(0); } if (t->complete) { t->cmd.flags |= DNET_FLAGS_DESTROY; t->complete(t->st ? dnet_state_addr(t->st) : NULL, &t->cmd, t->priv); } if (st && st->n && t->command != 0) { char str[64]; char io_buf[1024] = ""; struct tm tm; if (t->cmd.status != -ETIMEDOUT) { if (st->stall) { dnet_log(st->n, DNET_LOG_INFO, "%s/%d: reseting state stall counter", dnet_state_dump_addr(st), t->cmd.backend_id); } st->stall = 0; } localtime_r((time_t *)&t->start.tv_sec, &tm); strftime(str, sizeof(str), "%F %R:%S", &tm); if ((t->command == DNET_CMD_READ || t->command == DNET_CMD_WRITE) && (t->alloc_size >= sizeof(struct dnet_cmd) + sizeof(struct dnet_io_attr))) { struct dnet_cmd *local_cmd = (struct dnet_cmd *)(t + 1); struct dnet_io_attr *local_io = (struct dnet_io_attr *)(local_cmd + 1); double backend_weight = 0.; dnet_get_backend_weight(st, t->cmd.backend_id, local_io->flags, &backend_weight); snprintf(io_buf, sizeof(io_buf), ", weight: %f, %s", backend_weight, dnet_print_io(local_io)); } dnet_log(st->n, DNET_LOG_INFO, "%s: %s: destruction %s, stall: %d, " "time: %ld, started: %s.%06lu, cached status: %d%s", dnet_dump_id(&t->cmd.id), dnet_cmd_string(t->cmd.cmd), dnet_print_trans(t), t->st->stall, diff, str, t->start.tv_usec, t->cmd.status, io_buf); } dnet_state_put(t->st); dnet_state_put(t->orig); dnet_node_unset_trace_id(); free(t); }
error_info create_error(const dnet_cmd &cmd) { return create_error(cmd.status, cmd.id, "Failed to process %s command", dnet_cmd_string(cmd.cmd)); }