Exemplo n.º 1
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;
}
Exemplo n.º 2
0
void dnet_trans_clean_list(struct list_head *head, int error)
{
	struct dnet_trans *t, *tmp;

	list_for_each_entry_safe(t, tmp, head, trans_list_entry) {
		list_del_init(&t->trans_list_entry);

		t->cmd.size = 0;
		t->cmd.flags &= ~DNET_FLAGS_REPLY;
		t->cmd.status = error;

		dnet_node_set_trace_id(t->cmd.trace_id, t->cmd.flags & DNET_FLAGS_TRACE_BIT);
		if (t->complete) {
			t->complete(dnet_state_addr(t->st), &t->cmd, t->priv);
		}

		dnet_trans_put(t);
		dnet_node_unset_trace_id();
	}
Exemplo n.º 3
0
static int dnet_send_idc(struct dnet_net_state *lstate, struct dnet_net_state *send, struct dnet_id *id, uint64_t trans,
		unsigned int command, int reply, int direct, int more)
{
	struct dnet_node *n = lstate->n;
	int size = sizeof(struct dnet_addr_cmd) + sizeof(struct dnet_addr) * n->addr_num + lstate->idc->id_num * sizeof(struct dnet_raw_id);
	void *buf;
	int err;
	struct dnet_addr laddr;
	char server_addr[128], client_addr[128];
	struct timeval start, end;
	long diff;

	gettimeofday(&start, NULL);

	buf = malloc(size);
	if (!buf) {
		err = -ENOMEM;
		goto err_out_exit;
	}
	memset(buf, 0, size);

	dnet_send_idc_fill(lstate, buf, size, id, trans, command, reply, direct, more);
	dnet_socket_local_addr(send->read_s, &laddr);

	gettimeofday(&end, NULL);
	diff = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec;
	dnet_log(n, DNET_LOG_INFO, "%s: sending address %s -> %s, addr_num: %d, time-took: %ld\n",
			dnet_dump_id(id),
			dnet_server_convert_dnet_addr_raw(&laddr, server_addr, sizeof(server_addr)),
			dnet_server_convert_dnet_addr_raw(dnet_state_addr(send), client_addr, sizeof(client_addr)),
			n->addr_num, diff);

	err = dnet_send(send, buf, size);

	free(buf);

err_out_exit:
	return err;
}
Exemplo n.º 4
0
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);
}