Beispiel #1
0
static int dnet_check_merge(struct dnet_session *s, struct dnet_meta_container *mc)
{
	struct dnet_node *n = s->node;
	int err;
	struct dnet_meta_container remote_mc;

	dnet_log(n, DNET_LOG_DEBUG, "in dnet_check_merge mc->size = %d\n", mc->size);
	memset(&remote_mc, 0, sizeof(struct dnet_meta_container));

	err = dnet_read_meta(s, &remote_mc, NULL, 0, &mc->id);
	if (err) {
		if (err != -ENOENT) {
			dnet_log_raw(n, DNET_LOG_ERROR, "%s: failed to download object to be merged from storage: %d.\n",
					dnet_dump_id(&mc->id), err);
			goto err_out_exit;
		}

		dnet_log_raw(n, DNET_LOG_INFO, "%s: there is no meta in the storage to merge with, "
				"doing direct merge (plain upload).\n", dnet_dump_id(&mc->id));
		err = dnet_merge_direct(s, mc);
	} else {

		err = dnet_merge_common(s, &remote_mc, mc);
	}

	if (err)
		goto err_out_exit;

err_out_exit:
	if (remote_mc.data)
		free(remote_mc.data);
	return err;
}
Beispiel #2
0
static int dnet_check_find_groups(struct dnet_node *n, struct dnet_meta_container *mc, int **groupsp)
{
	int err, i, num;
	struct dnet_meta *m;
	int *groups;

	m = dnet_meta_search(n, mc, DNET_META_GROUPS);
	if (!m) {
		dnet_log_raw(n, DNET_LOG_ERROR, "%s: failed to find groups metadata.\n", dnet_dump_id(&mc->id));
		err = -ENOENT;
		goto err_out_exit;
	}

	groups = malloc(m->size);
	if (!groups) {
		err = -ENOMEM;
		goto err_out_exit;
	}
	memcpy(groups, m->data, m->size);

	num = m->size / sizeof(int32_t);

	for (i=0; i<num; ++i) {
		dnet_log_raw(n, DNET_LOG_DEBUG, "%s: group: %d\n", dnet_dump_id(&mc->id), groups[i]);
	}

	*groupsp = groups;

	return num;

err_out_exit:
	dnet_dump_meta_container(n, mc);
	return err;
}
Beispiel #3
0
static int leveldb_backend_read(struct leveldb_backend *s, void *state, struct dnet_cmd *cmd, void *iodata, int last)
{
	struct dnet_io_attr *io = iodata;
	struct dnet_ext_list elist;
	char *data;
	size_t data_size;
	int err = -EINVAL;
	char *error_string = NULL;

	dnet_ext_list_init(&elist);

	dnet_convert_io_attr(io);
	if (io->size || io->offset) {
		err = -ERANGE;
		goto err_out_exit;
	}

	data = leveldb_get(s->db, s->roptions, (const char *)io->id, DNET_ID_SIZE, &data_size, &error_string);
	if (error_string || !data) {
		if (!data)
			err = -ENOENT;
		goto err_out_exit;
	}

	/* Extract original data and extension list from &data */
	err = dnet_ext_list_extract((void *)&data, (uint64_t *)&data_size,
			&elist, DNET_EXT_FREE_ON_DESTROY);
	if (err != 0)
		goto err_out_exit;
	dnet_ext_list_to_io(&elist, io);

	io->size = data_size;
	if (data_size && data && last)
		cmd->flags &= ~DNET_FLAGS_NEED_ACK;
	err = dnet_send_read_data(state, cmd, io, data, -1, io->offset, 0);
	if (err < 0)
		goto err_out_exit;

	dnet_backend_log(DNET_LOG_NOTICE, "%s: leveldb: : READ: Ok: size: %llu.\n",
			dnet_dump_id(&cmd->id), (unsigned long long)io->size);

err_out_exit:
	dnet_ext_list_destroy(&elist);
	if (err < 0)
		dnet_backend_log(DNET_LOG_ERROR, "%s: leveldb: READ: error: %s: %d\n",
			dnet_dump_id(&cmd->id), error_string, err);

	free(error_string);
	return err;
}
Beispiel #4
0
static int dnet_send_idc(struct dnet_net_state *orig, 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 = orig->n;
	int size = sizeof(struct dnet_addr_cmd) + orig->idc->id_num * sizeof(struct dnet_raw_id);
	void *buf;
	int err;
	struct timeval start, end;
	long diff;

	gettimeofday(&start, NULL);

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

	dnet_send_idc_fill(orig, buf, size, id, trans, command, reply, direct, more);

	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: %ld\n", dnet_dump_id(id), dnet_state_dump_addr(orig), diff);

	err = dnet_send(send, buf, size);

	free(buf);

err_out_exit:
	return err;
}
Beispiel #5
0
static int dnet_merge_common(struct dnet_session *s, struct dnet_meta_container *remote_meta, struct dnet_meta_container *mc)
{
	struct dnet_node *n = s->node;
	int err = 0;
	struct dnet_meta_update local, remote;
	uint64_t cflags = 0;
	uint64_t ioflags = 0;

	dnet_log(n, DNET_LOG_DEBUG, "in dnet_merge_common mc->size = %d\n", mc->size);
	if (!dnet_get_meta_update(n, mc, &local)) {
		err = -ENOENT;
		dnet_log(n, DNET_LOG_ERROR, "%s: META_UPDATE not found in local meta\n", dnet_dump_id(&mc->id));
		goto err_out_exit;
	}

	if (!dnet_get_meta_update(n, remote_meta, &remote)) {
		err = -ENOENT;
		dnet_log(n, DNET_LOG_ERROR, "%s: META_UPDATE not found in remote meta, perform direct merge\n", dnet_dump_id(&mc->id));
		err = dnet_merge_direct(s, mc);
		goto err_out_exit;
	}

	if ((local.tm.tsec > remote.tm.tsec) || (local.tm.tsec == remote.tm.tsec && local.tm.tnsec > remote.tm.tnsec)) {
		if (local.flags & DNET_IO_FLAGS_REMOVED) {
			err = dnet_remove_object_now(s, &mc->id, cflags, ioflags);
		} else {
			err = dnet_merge_direct(s, mc);
		}
	}

err_out_exit:
	return err;

}
Beispiel #6
0
static int dnet_check_number_of_copies(struct dnet_node *n, struct dnet_meta_container *mc, int *groups, int group_num,
					struct dnet_bulk_array *bulk_array, struct dnet_check_params *params)
{
	struct dnet_id raw;
	int group_id = mc->id.group_id;
	int err = 0, i, error = 0;

	for (i=0; i<group_num; ++i) {
		if (groups[i] == group_id)
			continue;

		dnet_setup_id(&raw, groups[i], mc->id.id);

		err = dnet_bulk_add_id(n, bulk_array, &raw, mc, params);
		if (err)
			dnet_log(n, DNET_LOG_ERROR, "BULK: after adding ID %s err = %d\n", dnet_dump_id(&raw), err);

		if (!err)
			error = 0;
		else if (!error)
			error = err;
	}

	return error;
}
Beispiel #7
0
int dnet_trans_alloc_send(struct dnet_session *s, struct dnet_trans_control *ctl)
{
	struct dnet_node *n = s->node;
	struct dnet_net_state *st;
	struct dnet_addr *addr = NULL;
	int err;

	if (dnet_session_get_cflags(s) & DNET_FLAGS_DIRECT) {
		st = dnet_state_search_by_addr(n, &s->direct_addr);
		addr = &s->direct_addr;
	} else if(dnet_session_get_cflags(s) & DNET_FLAGS_FORWARD) {
		st = dnet_state_search_by_addr(n, &s->forward_addr);
		addr = &s->forward_addr;
	}else {
		st = dnet_state_get_first(n, &ctl->id);
	}

	if (!st) {
		dnet_log(n, DNET_LOG_ERROR, "%s: direct: %d, direct-addr: %s, forward: %d: trans_send: could not find network state for address",
			dnet_dump_id(&ctl->id),
			!!(dnet_session_get_cflags(s) & DNET_FLAGS_DIRECT), dnet_addr_string(&s->direct_addr),
			!!(dnet_session_get_cflags(s) & DNET_FLAGS_FORWARD));

		err = dnet_trans_send_fail(s, addr, ctl, -ENXIO, 1);
	} else {
		err = dnet_trans_alloc_send_state(s, st, ctl);
		dnet_state_put(st);
	}

	return err;
}
Beispiel #8
0
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;
}
Beispiel #9
0
void session::read_file(const key &id, const std::string &file, uint64_t offset, uint64_t size)
{
	transform(id);

	session sess = clone();
	sess.set_exceptions_policy(throw_at_get);

	read_result_entry result = sess.read_data(id, offset, size).get_one();
	dnet_io_attr *io = result.io_attribute();

	int err;

	file_descriptor fd(open(file.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0644));
	if (fd.fd() < 0) {
		err = -errno;
		throw_error(err, id, "Failed to open read completion file: '%s'", file.c_str());
	}

	err = pwrite(fd.fd(), result.file().data(), result.file().size(), offset);
	if (err <= 0) {
		err = -errno;
		throw_error(err, id, "Failed to write data into completion file: '%s'", file.c_str());
	}

	BH_LOG(get_logger(), DNET_LOG_NOTICE, "%s: read completed: file: '%s', offset: %llu, size: %llu, status: %d.",
			dnet_dump_id(&id.id()), file, offset, uint64_t(io->size), int(result.command()->status));
}
Beispiel #10
0
static int smack_backend_lookup_raw(struct smack_backend *s, struct index *idx, void *state, struct dnet_cmd *cmd)
{
	int err, fd;
	char *path;

	err = smack_lookup(s->smack, idx, &path);
	if (err < 0)
		goto err_out_exit;

	fd = open(path, O_RDONLY | O_CLOEXEC);
	if (fd < 0) {
		err = -errno;
		dnet_backend_log(DNET_LOG_ERROR, "%s: SMACK: %s: lookup-open: size: %llu: %s %d.\n",
				dnet_dump_id_str(idx->id), path,
				(unsigned long long)idx->data_size,
				strerror(-err), err);
		goto err_out_free;
	}

	err = dnet_send_file_info(state, cmd, fd, 0, idx->data_size);
	if (err)
		goto err_out_close;

	dnet_backend_log(DNET_LOG_INFO, "%s: SMACK: %s: lookup: size: %llu.\n",
			dnet_dump_id(&cmd->id), path, (unsigned long long)idx->data_size);

err_out_close:
	close(fd);
err_out_free:
	free(path);
err_out_exit:
	return err;
}
Beispiel #11
0
void throw_error(int err, const struct dnet_id &id, const char *format, ...)
{
	va_list args;
	va_start(args, format);
	throw_error_detail(err, dnet_dump_id(&id), format, args);
	va_end(args);
}
Beispiel #12
0
int dnet_remove_local(struct dnet_node *n, struct dnet_id *id)
{
	const size_t cmd_size = sizeof(struct dnet_cmd) + sizeof(struct dnet_io_attr);
	int err;
	char buffer[cmd_size];
	struct dnet_cmd *cmd = (struct dnet_cmd *)buffer;
	struct dnet_io_attr *io = (struct dnet_io_attr *)(cmd + 1);

	memset(buffer, 0, cmd_size);

	cmd->id = *id;
	cmd->size = cmd_size - sizeof(struct dnet_cmd);
	cmd->flags = DNET_FLAGS_NOLOCK;
	cmd->cmd = DNET_CMD_DEL;

	io->flags = DNET_IO_FLAGS_SKIP_SENDING;

	memcpy(io->parent, id->id, DNET_ID_SIZE);
	memcpy(io->id, id->id, DNET_ID_SIZE);

	dnet_convert_io_attr(io);

	err = n->cb->command_handler(n->st, n->cb->command_private, cmd, io);
	dnet_log(n, DNET_LOG_NOTICE, "%s: local remove: err: %d.\n", dnet_dump_id(&cmd->id), err);

	return err;

}
Beispiel #13
0
std::string key::to_string() const
{
	if (m_by_id)
		return dnet_dump_id(&m_id);
	else
		return m_remote;
}
Beispiel #14
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;
}
Beispiel #15
0
error_info create_error(int err, const struct dnet_id &id, const char *format, ...)
{
	va_list args;
	va_start(args, format);
	error_info error = create_info(err, dnet_dump_id(&id), format, args);
	va_end(args);
	return error;
}
Beispiel #16
0
int dnet_stat_local(struct dnet_net_state *st, struct dnet_id *id)
{
	struct dnet_node *n = st->n;
	int size, cmd_size;
	struct dnet_cmd *cmd;
	struct dnet_io_attr *io;
	int err;

	size = 1;
	cmd_size = size + sizeof(struct dnet_cmd) + sizeof(struct dnet_io_attr);

	cmd = malloc(cmd_size);
	if (!cmd) {
		dnet_log(n, DNET_LOG_ERROR, "%s: failed to allocate %d bytes for local stat.\n",
				dnet_dump_id(id), cmd_size);
		err = -ENOMEM;
		goto err_out_exit;
	}

	memset(cmd, 0, cmd_size);

	io = (struct dnet_io_attr *)(cmd + 1);

	memcpy(&cmd->id, id, sizeof(struct dnet_id));
	cmd->size = cmd_size - sizeof(struct dnet_cmd);
	cmd->flags = DNET_FLAGS_NOLOCK;
	cmd->cmd = DNET_CMD_READ;

	io->size = cmd->size - sizeof(struct dnet_io_attr);
	io->offset = 0;
	io->flags = DNET_IO_FLAGS_SKIP_SENDING;

	memcpy(io->parent, id->id, DNET_ID_SIZE);
	memcpy(io->id, id->id, DNET_ID_SIZE);

	dnet_convert_io_attr(io);

	err = n->cb->command_handler(st, n->cb->command_private, cmd, io);
	dnet_log(n, DNET_LOG_INFO, "%s: local stat: io_size: %llu, err: %d.\n", dnet_dump_id(&cmd->id), (unsigned long long)io->size, err);

	free(cmd);

err_out_exit:
	return err;
}
Beispiel #17
0
error_info create_error(int err, const key &id, const char *format, ...)
{
	va_list args;
	va_start(args, format);
	const char *id_str = id.by_id() ? dnet_dump_id(&id.id()) : id.remote().c_str();
	error_info error = create_info(err, id_str, format, args);
	va_end(args);
	return error;
}
Beispiel #18
0
static int stat_complete(struct dnet_net_state *state,
			struct dnet_cmd *cmd,
			void *priv)
{
	float la[3];
	struct dnet_stat *st;
	char str[64];
	struct tm tm;
	struct timeval tv;
	FILE *stream = priv;

	if (is_trans_destroyed(state, cmd))
		return 0;

	if (cmd->size != sizeof(struct dnet_stat))
		return cmd->status;

	if (!stat_mem && !stat_la && !stat_fs)
		return 0;

	gettimeofday(&tv, NULL);
	localtime_r((time_t *)&tv.tv_sec, &tm);
	strftime(str, sizeof(str), "%F %R:%S", &tm);

	fprintf(stream, "%s.%06lu :", str, (unsigned long)tv.tv_usec);

	st = (struct dnet_stat *)(cmd + 1);

	dnet_convert_stat(st);

	la[0] = (float)st->la[0] / 100.0;
	la[1] = (float)st->la[1] / 100.0;
	la[2] = (float)st->la[2] / 100.0;


	fprintf(stream, "%s: %s: ", dnet_dump_id(&cmd->id), dnet_state_dump_addr(state));

	if (stat_la)
		fprintf(stream, "la: %3.2f %3.2f %3.2f ", la[0], la[1], la[2]);

	if (stat_mem)
		fprintf(stream, "mem: total: %8llu kB, free: %8llu kB, cache: %8llu kB, buffers: %8llu, active: %8llu, inactive: %8llu ",
			(unsigned long long)st->vm_total, (unsigned long long)st->vm_free,
			(unsigned long long)st->vm_cached, (unsigned long long)st->vm_buffers,
			(unsigned long long)st->vm_active, (unsigned long long)st->vm_inactive);

	if (stat_fs)
		fprintf(stream, "fs: total: %8llu mB, avail: %8llu/%8llu mB ",
			(unsigned long long)(st->frsize * st->blocks / 1024 / 1024),
			(unsigned long long)(st->bavail * st->bsize / 1024 / 1024),
			(unsigned long long)(st->bfree * st->bsize / 1024 / 1024));

	fprintf(stream, "\n");
	fflush(stream);

	return 0;
}
Beispiel #19
0
int dnet_remove_local(struct dnet_node *n, struct dnet_id *id)
{
	int cmd_size;
	struct dnet_cmd *cmd;
	struct dnet_io_attr *io;
	int err;

	cmd_size = sizeof(struct dnet_cmd) + sizeof(struct dnet_io_attr);

	cmd = malloc(cmd_size);
	if (!cmd) {
		dnet_log(n, DNET_LOG_ERROR, "%s: failed to allocate %d bytes for local remove.\n",
				dnet_dump_id(id), cmd_size);
		err = -ENOMEM;
		goto err_out_exit;
	}

	memset(cmd, 0, cmd_size);

	io = (struct dnet_io_attr *)(cmd + 1);

	cmd->id = *id;
	cmd->size = cmd_size - sizeof(struct dnet_cmd);
	cmd->flags = DNET_FLAGS_NOLOCK;
	cmd->cmd = DNET_CMD_DEL;

	io->flags = DNET_IO_FLAGS_SKIP_SENDING;

	memcpy(io->parent, id->id, DNET_ID_SIZE);
	memcpy(io->id, id->id, DNET_ID_SIZE);

	dnet_convert_io_attr(io);

	err = n->cb->command_handler(n->st, n->cb->command_private, cmd, io);
	dnet_log(n, DNET_LOG_NOTICE, "%s: local remove: err: %d.\n", dnet_dump_id(&cmd->id), err);

	free(cmd);

err_out_exit:
	return err;

}
Beispiel #20
0
void session::write_file(const key &id, const std::string &file, uint64_t local_offset,
				uint64_t offset, uint64_t size)
{
	transform(id);

	session sess = clone();
	sess.set_exceptions_policy(throw_at_wait);

	int err;

	file_descriptor fd(open(file.c_str(), O_RDONLY | O_LARGEFILE | O_CLOEXEC));
	if (fd.fd() < 0) {
		err = -errno;
		throw_error(err, id, "Failed to open read completion file '%s'", file.c_str());
	}

	struct stat stat;
	memset(&stat, 0, sizeof(stat));

	err = fstat(fd.fd(), &stat);
	if (err) {
		err = -errno;
		throw_error(err, id, "Failed to stat to be written file '%s'", file.c_str());
	}

	if (local_offset >= (uint64_t)stat.st_size) {
		BH_LOG(get_logger(), DNET_LOG_NOTICE, "%s: File is already uploaded: '%s'",
				dnet_dump_id(&id.id()), file);
		return;
	}

	if (!size || size + local_offset >= (uint64_t)stat.st_size)
		size = stat.st_size - local_offset;

	dnet_io_control ctl;
	memset(&ctl, 0, sizeof(struct dnet_io_control));

	ctl.data = NULL;
	ctl.fd = fd.fd();
	ctl.local_offset = local_offset;

	memcpy(ctl.io.id, id.id().id, DNET_ID_SIZE);
	memcpy(ctl.io.parent, id.id().id, DNET_ID_SIZE);

	ctl.io.size = size;
	ctl.io.offset = offset;
	ctl.io.timestamp.tsec = stat.st_mtime;
	ctl.io.timestamp.tnsec = 0;
	ctl.id = id.id();

	write_data(ctl).wait();
}
Beispiel #21
0
void dnet_trans_remove_nolock(struct dnet_net_state *st, struct dnet_trans *t)
{
	if (!t->trans_entry.rb_parent_color) {
		dnet_log(st->n, DNET_LOG_ERROR, "%s: trying to remove out-of-trans-tree transaction %llu.",
			dnet_dump_id(&t->cmd.id), (unsigned long long)t->trans);
		return;
	}

	rb_erase(&t->trans_entry, &st->trans_root);
	t->trans_entry.rb_parent_color = 0;

	dnet_trans_remove_timer_nolock(st, t);
}
Beispiel #22
0
static int smack_backend_write(struct smack_backend *s, void *state, struct dnet_cmd *cmd, void *data)
{
	struct dnet_node *n = dnet_get_node_from_state(state);
	int err;
	struct index idx;
	struct dnet_io_attr *io = data;
	struct dnet_file_info *info;
	struct dnet_addr_attr *a;

	dnet_convert_io_attr(io);
	
	data += sizeof(struct dnet_io_attr);

	smack_setup_idx(&idx, io->id);
	idx.data_size = io->size;

	err = smack_write(s->smack, &idx, data);
	if (err < 0)
		goto err_out_exit;
#if 0
	err = smack_backend_lookup_raw(s, &idx, state, cmd);
	if (err)
		goto err_out_exit;
#else
	a = malloc(sizeof(struct dnet_addr_attr) + sizeof(struct dnet_file_info));
	if (!a) {
		err = -ENOMEM;
		goto err_out_exit;
	}
	info = (struct dnet_file_info *)(a + 1);

	dnet_fill_addr_attr(n, a);
	dnet_convert_addr_attr(a);

	memset(info, 0, sizeof(struct dnet_file_info));
	dnet_convert_file_info(info);

	err = dnet_send_reply(state, cmd, a, sizeof(struct dnet_addr_attr) + sizeof(struct dnet_file_info), 0);
#endif
	dnet_backend_log(DNET_LOG_INFO, "%s: SMACK: : WRITE: Ok: offset: %llu, size: %llu.\n",
			dnet_dump_id(&cmd->id), (unsigned long long)io->offset, (unsigned long long)io->size);

err_out_exit:
	return err;
}
Beispiel #23
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;
}
Beispiel #24
0
int process_find_indexes(dnet_net_state *state, dnet_cmd *cmd, dnet_indexes_request *request)
{
	local_session sess(state->n);

	const bool intersection = request->flags & DNET_INDEXES_FLAGS_INTERSECT;
	const bool unite = request->flags & DNET_INDEXES_FLAGS_UNITE;

	dnet_log(state->n, DNET_LOG_DEBUG, "INDEXES_FIND: indexes count: %u, flags: %llu\n",
		 (unsigned) request->entries_count, (unsigned long long) request->flags);

	if (intersection && unite) {
		return -ENOTSUP;
	}

	std::vector<find_indexes_result_entry> result;

	std::map<dnet_raw_id, size_t, dnet_raw_id_less_than<> > result_map;

	dnet_indexes tmp;

	int err = -1;
	dnet_id id = cmd->id;

	size_t data_offset = 0;
	char *data_start = reinterpret_cast<char *>(request->entries);
	for (uint64_t i = 0; i < request->entries_count; ++i) {
		dnet_indexes_request_entry &request_entry = *reinterpret_cast<dnet_indexes_request_entry *>(data_start + data_offset);
		data_offset += sizeof(dnet_indexes_request_entry) + request_entry.size;

		memcpy(id.id, request_entry.id.id, sizeof(id.id));

		int ret = 0;
		data_pointer data = sess.read(id, &ret);

		if (ret) {
			dnet_log(state->n, DNET_LOG_DEBUG, "%s: INDEXES_FIND, err: %d\n",
				 dnet_dump_id(&id), ret);
		}

		if (ret && unite) {
			if (err != -1)
				err = ret;
			continue;
		} else if (ret && intersection) {
			return ret;
		}
		err = 0;

		tmp.indexes.clear();
		indexes_unpack(state->n, &id, data, &tmp, "process_find_indexes");

		if (unite) {
			for (size_t j = 0; j < tmp.indexes.size(); ++j) {
				const index_entry &entry = tmp.indexes[j];

				auto it = result_map.find(entry.index);
				if (it == result_map.end()) {
					it = result_map.insert(std::make_pair(entry.index, result.size())).first;
					result.resize(result.size() + 1);
					result.back().id = entry.index;
				}

				result[it->second].indexes.emplace_back(request_entry.id, entry.data);
			}
		} else if (intersection && i == 0) {
			result.resize(tmp.indexes.size());
			for (size_t j = 0; j < tmp.indexes.size(); ++j) {
				find_indexes_result_entry &entry = result[j];
				entry.id = tmp.indexes[j].index;
				entry.indexes.emplace_back(
					request_entry.id,
					tmp.indexes[j].data);
			}
		} else if (intersection) {
			// Remove all objects from result, which are not presented for this index
			auto it = std::set_intersection(result.begin(), result.end(),
				tmp.indexes.begin(), tmp.indexes.end(),
				result.begin(),
				dnet_raw_id_less_than<skip_data>());
			result.resize(it - result.begin());

			// Remove all objects from this index, which are not presented in result
			std::set_intersection(tmp.indexes.begin(), tmp.indexes.end(),
				result.begin(), result.end(),
				tmp.indexes.begin(),
				dnet_raw_id_less_than<skip_data>());

			// As lists contain othe same objects - it's possible to add index data by one cycle
			auto jt = tmp.indexes.begin();
			for (auto kt = result.begin(); kt != result.end(); ++kt, ++jt) {
				kt->indexes.emplace_back(request_entry.id, jt->data);
			}
		}
	}

//	if (err != 0)
//		return err;

	dnet_log(state->n, DNET_LOG_DEBUG, "%s: INDEXES_FIND: result of find: %zu objects\n",
		dnet_dump_id(&id), result.size());

	msgpack::sbuffer buffer;
	msgpack::pack(&buffer, result);

	cmd->flags &= ~DNET_FLAGS_NEED_ACK;
	dnet_send_reply(state, cmd, buffer.data(), buffer.size(), 0);

	return err;
}
Beispiel #25
0
								       cache, size, time);
			auto top_stats = real_monitor->get_statistics().get_top_stats();
			if (top_stats) {
				top_stats->update_stats(cmd, size);
			}
		}
	} catch (const std::exception &e) {
		dnet_log(n, DNET_LOG_DEBUG, "monitor: failed to update stats: %s", e.what());
	}
}

int dnet_monitor_process_cmd(struct dnet_net_state *orig, struct dnet_cmd *cmd __unused, void *data)
{
	if (cmd->size != sizeof(dnet_monitor_stat_request)) {
		dnet_log(orig->n, DNET_LOG_DEBUG, "monitor: %s: %s: process MONITOR_STAT, invalid size: %llu",
			dnet_state_dump_addr(orig), dnet_dump_id(&cmd->id), static_cast<unsigned long long>(cmd->size));
		return -EINVAL;
	}

	struct dnet_node *n = orig->n;
	struct dnet_monitor_stat_request *req = static_cast<struct dnet_monitor_stat_request *>(data);
	dnet_convert_monitor_stat_request(req);
	static const std::string disabled_reply = ioremap::monitor::compress("{\"monitor_status\":\"disabled\"}");

	dnet_log(orig->n, DNET_LOG_DEBUG, "monitor: %s: %s: process MONITOR_STAT, categories: %lx, monitor: %p",
		dnet_state_dump_addr(orig), dnet_dump_id(&cmd->id), req->categories, n->monitor);

	auto real_monitor = ioremap::monitor::get_monitor(n);
	if (!real_monitor)
		return dnet_send_reply(orig, cmd, disabled_reply.c_str(), disabled_reply.size(), 0);
Beispiel #26
0
int main(int argc, char *argv[])
{
	struct dnet_history_entry *entries;
	ssize_t i, num;
	int err, fd, ch;
	char *file = NULL;
	void *data;
	struct stat st;
	unsigned long long offset, size;
	unsigned int isize = sizeof(struct dnet_history_entry);
	char str[64];
	struct tm tm;

	size = offset = 0;

	while ((ch = getopt(argc, argv, "s:o:f:h")) != -1) {
		switch (ch) {
			case 's':
				size = strtoull(optarg, NULL, 0);
				break;
			case 'o':
				offset = strtoull(optarg, NULL, 0);
				break;
			case 'f':
				file = optarg;
				break;
			case 'h':
				hparser_usage(argv[0]);
		}
	}

	if (!file) {
		fprintf(stderr, "You have to provide history file to parse.\n");
		hparser_usage(argv[0]);
	}

	fd = open(file, O_RDONLY);
	if (fd < 0) {
		err = -errno;
		fprintf(stderr, "Failed to open history file '%s': %s [%d].\n",
				file, strerror(errno), errno);
		goto err_out_exit;
	}

	err = fstat(fd, &st);
	if (err) {
		err = -errno;
		fprintf(stderr, "Failed to stat history file '%s': %s [%d].\n",
				file, strerror(errno), errno);
		goto err_out_close;
	}

	if (!st.st_size || (st.st_size % isize)) {
		fprintf(stderr, "Corrupted history file '%s', its size %llu has to be modulo of %u.\n",
				file, (unsigned long long)st.st_size, isize);
		err = -EINVAL;
		goto err_out_close;
	}

	data = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
	if (data == MAP_FAILED) {
		err = -errno;
		fprintf(stderr, "Failed to map history file '%s': %s [%d]",
				file, strerror(errno), errno);
		goto err_out_close;
	}

	entries = data;
	num = st.st_size / isize;

	printf("%s: objects: %zd, range: %llu-%llu, counting from the most recent (nanoseconds resolution).\n",
			file, num, offset, offset+size);
	for (i=num-1; i>=0; --i) {
		struct dnet_history_entry e = entries[i];

		dnet_convert_history_entry(&e);

		localtime_r((time_t *)&e.tsec, &tm);
		strftime(str, sizeof(str), "%F %R:%S", &tm);

		printf("%s.%09llu: %s: flags: %08x, offset: %8llu, size: %8llu: %c\n",
			str, (unsigned long long)e.tnsec,
			dnet_dump_id(e.id), e.flags,
			(unsigned long long)e.offset, (unsigned long long)e.size,
			hparser_region_match(&e, offset, size) ? '+' : '-');
	}

	munmap(data, st.st_size);
	close(fd);

	return 0;

err_out_close:
	close(fd);
err_out_exit:
	return err;
}
Beispiel #27
0
int dnet_request_bulk_check(struct dnet_node *n, struct dnet_bulk_state *state, struct dnet_check_params *params)
{
	struct dnet_trans_control ctl;
	struct dnet_net_state *st;
	struct dnet_bulk_check_priv *p;
	struct timespec	wait_ts;
	int err;

	p = (struct dnet_bulk_check_priv *)malloc(sizeof(struct dnet_bulk_check_priv));
	if (!p) {
		err = -ENOMEM;
		goto err_out_exit;
	}
	atomic_init(&p->refcnt, 2);
	p->db = params->db;
	dnet_check_temp_db_get(p->db);

	p->w = dnet_wait_alloc(0);
	if (!p->w) {
		err = -ENOMEM;
		goto err_out_free;
	}

	p->group_num = params->group_num;
	p->groups = (int *)malloc(sizeof(int) * params->group_num);
	if (!p->groups) {
		err = -ENOMEM;
		goto err_out_put;
	}
	memcpy(p->groups, params->groups, sizeof(int) * params->group_num);

	memset(&ctl, 0, sizeof(struct dnet_trans_control));

	ctl.cmd = DNET_CMD_LIST;
	ctl.complete = dnet_bulk_check_complete;
	ctl.priv = p;
	ctl.cflags = DNET_FLAGS_NEED_ACK | DNET_FLAGS_NOLOCK | DNET_ATTR_BULK_CHECK;

	ctl.data = state->ids;
	ctl.size = sizeof(struct dnet_bulk_id) * state->num;

	st = dnet_state_search_by_addr(n, &state->addr);
	if (!st) {
		err = -ENOENT;
		goto err_out_put;
	}
	dnet_setup_id(&ctl.id, st->idc->group->group_id, st->idc->ids[0].raw.id);
	dnet_wait_get(p->w);

	dnet_log(n, DNET_LOG_DEBUG, "BULK: sending %u bytes of data to %s (%s)\n",
			ctl.size, dnet_dump_id(&ctl.id), dnet_server_convert_dnet_addr(&state->addr));
	err = dnet_trans_alloc_send_state(st, &ctl);
	dnet_state_put(st);

	wait_ts = n->wait_ts;
	wait_ts.tv_sec *= DNET_BULK_IDS_SIZE;
	err = dnet_wait_event(p->w, p->w->cond != 0, &wait_ts);
	if (err)
		goto err_out_put;

	if (p->w->status) {
		err = p->w->status;
		goto err_out_put;
	}

	dnet_wait_put(p->w);

	if (atomic_dec_and_test(&p->refcnt)) {
		free(p->groups);
		free(p);
	}

	return 0;

err_out_put:
	dnet_wait_put(p->w);

err_out_free:
	if (atomic_dec_and_test(&p->refcnt)) {
		free(p->groups);
		free(p);
	}

err_out_exit:
	dnet_log(n, DNET_LOG_ERROR, "Bulk check exited with status %d\n", err);
	return err;
}
Beispiel #28
0
static int dnet_bulk_add_id(struct dnet_node *n, struct dnet_bulk_array *bulk_array, struct dnet_id *id,
				struct dnet_meta_container *mc, struct dnet_check_params *params)
{
	int err = 0;
	struct dnet_bulk_state tmp;
	struct dnet_bulk_state *state = NULL;
	struct dnet_net_state *st = dnet_state_get_first(n, id);
	struct dnet_bulk_id *bulk_id;
	struct dnet_meta_update mu;

	dnet_log(n, DNET_LOG_DEBUG, "BULK: adding ID %s to array\n", dnet_dump_id(id));
	if (!st)
		return -1;

	memcpy(&tmp.addr, &st->addr, sizeof(struct dnet_addr));
	dnet_state_put(st);

	dnet_log(n, DNET_LOG_DEBUG, "BULK: Searching state in states array\n");
	state = bsearch(&tmp, bulk_array->states, bulk_array->num, sizeof(struct dnet_bulk_state), dnet_compare_bulk_state);
	if (!state)
		return -1;

	if (!dnet_get_meta_update(n, mc, &mu))
		return -ENOENT;

	dnet_log(n, DNET_LOG_DEBUG, "BULK: addr = %s state->num = %d\n", dnet_server_convert_dnet_addr(&state->addr), state->num);
	//pthread_mutex_lock(&state->state_lock);
	if (state->num >= DNET_BULK_IDS_SIZE || state->num < 0)
		goto err_out_unlock;

	bulk_id = &state->ids[state->num];
	memset(bulk_id, 0, sizeof(struct dnet_bulk_id));

	memcpy(&bulk_id->id, &id->id, DNET_ID_SIZE);

	dnet_log(n, DNET_LOG_DEBUG, "BULK: ID: %s, last_update->tsec=%llu, last_update->tnsec=%llu, flags=%02llx\n", 
			dnet_dump_id_str(bulk_id->id.id), (unsigned long long)mu.tm.tsec, (unsigned long long)mu.tm.tnsec,
			(unsigned long long)mu.flags);

	dnet_convert_meta_update(&mu);

	memcpy(&bulk_id->last_update, &mu, sizeof(struct dnet_meta_update));

	state->num++;

	dnet_log(n, DNET_LOG_DEBUG, "BULK: addr = %s state->num = %d\n", dnet_server_convert_dnet_addr(&state->addr), state->num);
	if (state->num == DNET_BULK_IDS_SIZE) {
		err = dnet_request_bulk_check(n, state, params);
		state->num = 0;
		if (err)
			goto err_out_unlock;
	}

	//pthread_mutex_unlock(&state->state_lock);

	return 0;

err_out_unlock:
	//pthread_mutex_unlock(&state->state_lock);
	return -2;
}
Beispiel #29
0
int process_find_indexes(dnet_net_state *state, dnet_cmd *cmd, const dnet_id &request_id, dnet_indexes_request *request, bool more)
{
	local_session sess(state->n);

	const bool intersection = request->flags & DNET_INDEXES_FLAGS_INTERSECT;
	const bool unite = request->flags & DNET_INDEXES_FLAGS_UNITE;

	dnet_log(state->n, DNET_LOG_DEBUG, "INDEXES_FIND: indexes count: %u, flags: %llu, more: %d\n",
		 (unsigned) request->entries_count, (unsigned long long) request->flags, int(more));

	if ((intersection && unite) || !(intersection || unite)) {
		return -EINVAL;
	}

	std::vector<find_indexes_result_entry> result;
	std::vector<data_pointer> data_cache;

	std::map<dnet_raw_id, size_t, dnet_raw_id_less_than<> > result_map;

	dnet_indexes tmp;

	int err = -1;
	dnet_id id = request_id;

	size_t data_offset = 0;
	char *data_start = reinterpret_cast<char *>(request->entries);
	for (uint64_t i = 0; i < request->entries_count; ++i) {
		dnet_indexes_request_entry &request_entry = *reinterpret_cast<dnet_indexes_request_entry *>(data_start + data_offset);
		data_offset += sizeof(dnet_indexes_request_entry) + request_entry.size;

		memcpy(id.id, request_entry.id.id, sizeof(id.id));

		int ret = 0;
		data_pointer data = sess.read(id, &ret);
		data_cache.push_back(data);

		if (ret) {
			dnet_log(state->n, DNET_LOG_DEBUG, "%s: INDEXES_FIND, err: %d\n",
				 dnet_dump_id(&id), ret);
		}

		if (ret && unite) {
			if (err == -1)
				err = ret;
			continue;
		} else if (ret && intersection) {
			return ret;
		}
		err = 0;

		tmp.indexes.clear();
		indexes_unpack(state->n, &id, data, &tmp, "process_find_indexes");

		if (unite) {
			for (size_t j = 0; j < tmp.indexes.size(); ++j) {
				const auto &entry = tmp.indexes[j];

				auto it = result_map.find(entry.index);
				if (it == result_map.end()) {
					it = result_map.insert(std::make_pair(entry.index, result.size())).first;
					result.resize(result.size() + 1);
					result.back().id = entry.index;
				}

				index_entry result_entry = { request_entry.id, entry.data };
				result[it->second].indexes.push_back(result_entry);
			}
		} else if (intersection && i == 0) {
			result.resize(tmp.indexes.size());
			for (size_t j = 0; j < tmp.indexes.size(); ++j) {
				auto &entry = result[j];
				entry.id = tmp.indexes[j].index;
				index_entry result_entry = { request_entry.id, tmp.indexes[j].data };
				entry.indexes.push_back(result_entry);
			}
		} else if (intersection) {
			// Remove all objects from result, which are not presented for this index
			auto it = std::set_intersection(result.begin(), result.end(),
				tmp.indexes.begin(), tmp.indexes.end(),
				result.begin(),
				dnet_raw_id_less_than<skip_data>());
			result.resize(it - result.begin());

			// Remove all objects from this index, which are not presented in result
			std::set_intersection(tmp.indexes.begin(), tmp.indexes.end(),
				result.begin(), result.end(),
				tmp.indexes.begin(),
				dnet_raw_id_less_than<skip_data>());

			// As lists contain othe same objects - it's possible to add index data by one cycle
			auto jt = tmp.indexes.begin();
			for (auto kt = result.begin(); kt != result.end(); ++kt, ++jt) {
				index_entry result_entry = { request_entry.id, jt->data };
				kt->indexes.push_back(result_entry);
			}
		}
	}

	if (err != 0)
		return err;

	dnet_log(state->n, DNET_LOG_DEBUG, "%s: INDEXES_FIND: result of find: %zu objects\n",
		dnet_dump_id(&id), result.size());

	msgpack::sbuffer buffer;
	msgpack::pack(&buffer, result);

	if (!more) {
		/*
		 * Unset NEED_ACK flag if and only if it is the last reply.
		 * We have to send positive reply in such case, also we don't want to send
		 * useless acknowledge packet.
		 */
		cmd->flags &= ~DNET_FLAGS_NEED_ACK;
	}
	dnet_cmd cmd_copy = *cmd;
	dnet_setup_id(&cmd_copy.id, cmd->id.group_id, request_id.id);
	dnet_send_reply(state, &cmd_copy, buffer.data(), buffer.size(), more);

	return err;
}
Beispiel #30
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);
}