예제 #1
0
파일: cache.cpp 프로젝트: weixu8/elliptics
    bool remove(const unsigned char *id) {
        bool removed = false;
        bool remove_from_disk = false;

        boost::mutex::scoped_lock guard(m_lock);
        iset_t::iterator it = m_set.find(id);
        if (it != m_set.end()) {
            remove_from_disk = it->remove_from_disk();
            erase_element(&(*it));
            removed = true;
        }

        guard.unlock();

        if (remove_from_disk) {
            struct dnet_id raw;

            dnet_setup_id(&raw, 0, (unsigned char *)id);
            raw.type = -1;

            dnet_remove_local(m_node, &raw);
        }

        return removed;
    }
예제 #2
0
파일: cache.cpp 프로젝트: weixu8/elliptics
    void life_check(void) {
        while (!m_need_exit) {
            std::deque<struct dnet_id> remove;

            while (!m_need_exit && !m_lifeset.empty()) {
                size_t time = ::time(NULL);

                boost::mutex::scoped_lock guard(m_lock);

                if (m_lifeset.empty())
                    break;

                life_set_t::iterator it = m_lifeset.begin();
                if (it->lifetime() > time)
                    break;

                if (it->remove_from_disk()) {
                    struct dnet_id id;

                    dnet_setup_id(&id, 0, (unsigned char *)it->id().id);
                    id.type = -1;

                    remove.push_back(id);
                }

                erase_element(&(*it));
            }

            for (std::deque<struct dnet_id>::iterator it = remove.begin(); it != remove.end(); ++it) {
                dnet_remove_local(m_node, &(*it));
            }

            sleep(1);
        }
    }
예제 #3
0
파일: check.c 프로젝트: Inkvi/elliptics
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;
}
예제 #4
0
파일: iterate.cpp 프로젝트: 3Hren/elliptics
void iterate_node(Ctx &ctx, const dnet_addr &node) {
	std::cout << "Iterating node: " << dnet_addr_string(&node) << ":" << node.family << std::endl;
	std::vector<dnet_iterator_range> ranges;
	if (ctx.iflags & DNET_IFLAGS_KEY_RANGE)
		ranges.push_back(ctx.key_range);

	dnet_id id;
	memset(&id, 0, sizeof(id));
	bool found = false;
	for (auto it = ctx.routes.begin(), end = ctx.routes.end(); it != end; ++it) {
		if (dnet_addr_equal(&it->addr, &node)) {
			dnet_setup_id(&id, it->group_id, it->id.id);
			found = true;
			break;
		}
	}

	if (!found) {
		std::cerr << "Node was not found in the route list" << std::endl;
		return;
	}

	ctx.session->set_groups(std::vector<int>(1, id.group_id));

	auto res = ctx.session->start_iterator(ioremap::elliptics::key(id),
	                                       ranges, DNET_ITYPE_NETWORK,
	                                       ctx.iflags, ctx.time_begin, ctx.time_end);

	char buffer[2*DNET_ID_SIZE + 1] = {0};
	for (auto it = res.begin(), end = res.end(); it != end; ++it) {
		std::cout << "node: "    << dnet_addr_string(&node) << node.family
		          << ", key: "   << dnet_dump_id_len_raw(it->reply()->key.id, DNET_ID_SIZE, buffer)
		          << ", flags: " << it->reply()->user_flags
		          << ", ts: "    << it->reply()->timestamp.tsec << "/" << it->reply()->timestamp.tnsec
			  << ", keys: "  << it->reply()->iterated_keys << "/" << it->reply()->total_keys
			  << ", status: " << it->reply()->status
		          << ", size: "   << it->reply_data().size()
		          << ", data: "   << it->reply_data().to_string()
		          << std::endl;
	}
}
예제 #5
0
파일: server.c 프로젝트: torkve/elliptics
struct dnet_node *dnet_server_node_create(struct dnet_config *cfg)
{
	struct dnet_node *n;
	struct dnet_raw_id *ids = NULL;
	int id_num = 0;
	int err = -ENOMEM;

	n = dnet_node_create(cfg);
	if (!n) {
		goto err_out_exit;
	}

	if (!n->notify_hash_size) {
		n->notify_hash_size = DNET_DEFAULT_NOTIFY_HASH_SIZE;

	err = dnet_notify_init(n);
	if (err)
		goto err_out_node_destroy;

		dnet_log(n, DNET_LOG_NOTICE, "No notify hash size provided, using default %d.\n",
				n->notify_hash_size);
	}

	err = dnet_cache_init(n);
	if (err)
		goto err_out_notify_exit;

	if (cfg->flags & DNET_CFG_JOIN_NETWORK) {
		int s;

		err = dnet_locks_init(n, cfg->oplock_num);
		if (err)
			goto err_out_cache_cleanup;

		ids = dnet_ids_init(n, cfg->history_env, &id_num, cfg->storage_free);
		if (!ids)
			goto err_out_locks_destroy;

		n->addr.addr_len = sizeof(n->addr.addr);
		err = dnet_socket_create(n, cfg, &n->addr, 1);
		if (err < 0)
			goto err_out_ids_cleanup;

		s = err;
		dnet_setup_id(&n->id, cfg->group_id, ids[0].id);

		n->st = dnet_state_create(n, cfg->group_id, ids, id_num, &n->addr, s, &err, DNET_JOIN, dnet_state_accept_process);
		if (!n->st) {
			close(s);
			goto err_out_state_destroy;
		}

		free(ids);
		ids = NULL;

		err = dnet_srw_init(n, cfg);
		if (err) {
			dnet_log(n, DNET_LOG_ERROR, "srw: initialization failure: %s %d\n", strerror(-err), err);
		}
	}

	dnet_log(n, DNET_LOG_DSA, "New server node has been created at %s, ids: %d.\n",
			dnet_dump_node(n), id_num);

	return n;

err_out_state_destroy:
	dnet_srw_cleanup(n);
	dnet_state_put(n->st);
err_out_ids_cleanup:
	free(ids);
err_out_locks_destroy:
	dnet_locks_destroy(n);
err_out_cache_cleanup:
	dnet_cache_cleanup(n);
err_out_notify_exit:
	dnet_notify_exit(n);
err_out_node_destroy:
	dnet_node_destroy(n);
err_out_exit:
	return NULL;
}
예제 #6
0
파일: notify.c 프로젝트: torkve/elliptics
int main(int argc, char *argv[])
{
	int ch, err, have_remote = 0, i;
	struct dnet_node *n = NULL;
	struct dnet_config cfg, rem;
	int max_id_idx = 1000, id_idx = 0, group_id = 0;
	unsigned char id[max_id_idx][DNET_ID_SIZE];
	char *logfile = "/dev/stderr", *notify_file = "/dev/stdout";
	FILE *log = NULL, *notify;

	memset(&cfg, 0, sizeof(struct dnet_config));

	cfg.sock_type = SOCK_STREAM;
	cfg.proto = IPPROTO_TCP;
	cfg.wait_timeout = 60*60;
	notify_logger.log_mask = DNET_LOG_ERROR | DNET_LOG_INFO;

	memcpy(&rem, &cfg, sizeof(struct dnet_config));

	while ((ch = getopt(argc, argv, "g:m:w:l:I:a:r:h")) != -1) {
		switch (ch) {
			case 'm':
				notify_logger.log_mask = strtoul(optarg, NULL, 0);
				break;
			case 'w':
				cfg.wait_timeout = atoi(optarg);
				break;
			case 'L':
				notify_file = optarg;
				break;
			case 'l':
				logfile = optarg;
				break;
			case 'I':
				if (id_idx < max_id_idx) {
					err = dnet_parse_numeric_id(optarg, id[id_idx]);
					if (err)
						return err;
					id_idx++;
				}
				break;
			case 'g':
				group_id = atoi(optarg);
				break;
			case 'a':
				err = dnet_parse_addr(optarg, &cfg);
				if (err)
					return err;
				break;
			case 'r':
				err = dnet_parse_addr(optarg, &rem);
				if (err)
					return err;
				have_remote = 1;
				break;
			case 'h':
			default:
				notify_usage(argv[0]);
				return -1;
		}
	}

	if (!id_idx) {
		fprintf(stderr, "No ID specified to watch.\n");
		return -EINVAL;
	}

	if (!have_remote) {
		fprintf(stderr, "No remote node specified to route requests.\n");
		return -ENOENT;
	}

	log = fopen(logfile, "a");
	if (!log) {
		err = -errno;
		fprintf(stderr, "Failed to open log file %s: %s.\n", logfile, strerror(errno));
		return err;
	}

	notify_logger.log_private = log;
	notify_logger.log = dnet_common_log;
	cfg.log = &notify_logger;

	notify = fopen(notify_file, "a");
	if (!notify) {
		err = -errno;
		fprintf(stderr, "Failed to open notify file %s: %s.\n", notify_file, strerror(errno));
		return err;
	}

	n = dnet_node_create(&cfg);
	if (!n)
		return -1;

	err = dnet_add_state(n, &rem);
	if (err)
		return err;

	for (i=0; i<id_idx; ++i) {
		struct dnet_id raw;
		dnet_setup_id(&raw, group_id, id[i]);
		err = dnet_request_notification(n, &raw, notify_complete, notify);
	}

	while (1) {
		sleep(1);
	}

	return 0;
}
예제 #7
0
파일: server.c 프로젝트: kod3r/elliptics
struct dnet_node *dnet_server_node_create(struct dnet_config_data *cfg_data, struct dnet_config *cfg, struct dnet_addr *addrs, int addr_num)
{
	struct dnet_node *n;
	struct dnet_raw_id *ids = NULL;
	int id_num = 0;
	int err = -ENOMEM;

	sigset_t previous_sigset;
	sigset_t sigset;
	sigemptyset(&sigset);
	sigaddset(&sigset, SIGINT);
	sigaddset(&sigset, SIGTERM);
	sigaddset(&sigset, SIGALRM);
	sigaddset(&sigset, SIGQUIT);
	pthread_sigmask(SIG_BLOCK, &sigset, &previous_sigset);

	n = dnet_node_create(cfg);
	if (!n)
		goto err_out_exit;

	n->config_data = cfg_data;

	err = dnet_node_check_stack(n);
	if (err)
		goto err_out_node_destroy;

	if (!n->notify_hash_size) {
		n->notify_hash_size = DNET_DEFAULT_NOTIFY_HASH_SIZE;

		err = dnet_notify_init(n);
		if (err)
			goto err_out_node_destroy;

		dnet_log(n, DNET_LOG_NOTICE, "No notify hash size provided, using default %d.\n",
				n->notify_hash_size);
	}

	err = dnet_cache_init(n);
	if (err)
		goto err_out_notify_exit;

	err = dnet_local_addr_add(n, addrs, addr_num);
	if (err)
		goto err_out_cache_cleanup;

	if (cfg->flags & DNET_CFG_JOIN_NETWORK) {
		struct dnet_addr la;
		int s;

		err = dnet_locks_init(n, 1024);
		if (err)
			goto err_out_addr_cleanup;

		ids = dnet_ids_init(n, cfg->history_env, &id_num, cfg->storage_free, cfg_data->cfg_addrs, cfg_data->cfg_remotes);
		if (!ids)
			goto err_out_locks_destroy;

		memset(&la, 0, sizeof(struct dnet_addr));
		la.addr_len = sizeof(la.addr);
		la.family = cfg->family;

		err = dnet_socket_create(n, NULL, cfg->port, &la, 1);
		if (err < 0)
			goto err_out_ids_cleanup;

		s = err;
		dnet_setup_id(&n->id, cfg->group_id, ids[0].id);

		n->st = dnet_state_create(n, cfg->group_id, ids, id_num, &la, s, &err, DNET_JOIN, -1, dnet_state_accept_process);
		if (!n->st) {
			close(s);
			goto err_out_state_destroy;
		}

		free(ids);
		ids = NULL;

		if (!cfg->srw.config) {
			dnet_log(n, DNET_LOG_INFO, "srw: no config\n");
			n->srw = NULL;
		} else {
			err = dnet_srw_init(n, cfg);
			if (err) {
				dnet_log(n, DNET_LOG_ERROR, "srw: initialization failure: %s %d\n", strerror(-err), err);
				goto err_out_state_destroy;
			}
		}
	}

	dnet_log(n, DNET_LOG_DEBUG, "New server node has been created at port %d, ids: %d.\n", cfg->port, id_num);

	pthread_sigmask(SIG_SETMASK, &previous_sigset, NULL);
	return n;

	dnet_srw_cleanup(n);
err_out_state_destroy:
	dnet_state_put(n->st);
err_out_ids_cleanup:
	free(ids);
err_out_locks_destroy:
	dnet_locks_destroy(n);
err_out_addr_cleanup:
	dnet_local_addr_cleanup(n);
err_out_cache_cleanup:
	dnet_cache_cleanup(n);
err_out_notify_exit:
	dnet_notify_exit(n);
err_out_node_destroy:
	dnet_node_destroy(n);
err_out_exit:
	pthread_sigmask(SIG_SETMASK, &previous_sigset, NULL);
	return NULL;
}
예제 #8
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;
}
예제 #9
0
파일: check.c 프로젝트: Inkvi/elliptics
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;
}
예제 #10
0
파일: check.c 프로젝트: Inkvi/elliptics
static int dnet_bulk_check_complete_single(struct dnet_net_state *state, struct dnet_bulk_id *ids,
						int remote_group, struct dnet_bulk_check_priv *p)
{
	struct dnet_session *s = dnet_session_create(state->n);
	struct dnet_meta_container mc;
	struct dnet_meta_container temp_mc;
	struct dnet_meta_update *mu;
	struct dnet_meta *mg;
	struct dnet_id id;
	char *tmpdata = NULL;
	int *groups, group_num = 1;
	int err = -EINVAL, error = 0;
	int i = 0;
	int my_group, lastest_group = -1;
	struct dnet_meta_update lastest_mu, my_mu;
	struct timeval current_ts;
	int removed_in_all = 1, updated = 0;
	int lastest = 0;
	uint64_t cflags = 0;
	uint64_t ioflags = 0;


	my_group = state->n->id.group_id;

	dnet_log(state->n, DNET_LOG_DEBUG, "BULK: checking ID %s\n", dnet_dump_id_str(ids->id.id));
	err = -ENOENT;
	error = 0;

	dnet_setup_id(&mc.id, my_group, ids->id.id);

	err = state->n->cb->meta_read(state->n->cb->command_private, &ids->id, &mc.data);
	if (err <= 0) {
		if (err == 0)
			err = -ENOENT;
		goto err_out_continue;
	}
	mc.size = err;

	/* Set current group meta_update as lastest_mu */
	if (!dnet_get_meta_update(state->n, &mc, &my_mu)) {
		dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: meta_update structure doesn't exist for group %d\n",
				dnet_dump_id_str(ids->id.id), my_group);
		err = -ENOENT;
		goto err_out_kcfree;
	}
	dnet_convert_meta_update(&my_mu);
	memcpy(&lastest_mu, &my_mu, sizeof(struct dnet_meta_update));
	lastest_group = my_group;

	/* Get group list */
	if (p->group_num) {
		/* groups came from dnet_check utility */
		groups = p->groups;
		group_num = p->group_num;
	} else {
		mg = dnet_meta_search(state->n, &mc, DNET_META_GROUPS);
		if (!mg) {
			dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: DNET_META_GROUPS structure doesn't exist\n", dnet_dump_id_str(ids->id.id));
			err = -ENOENT;
			goto err_out_kcfree;
		}
		dnet_convert_meta(mg);
		if (mg->size % sizeof(int)) {
			dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: DNET_META_GROUPS structure is corrupted\n", dnet_dump_id_str(ids->id.id));
			err = -1;
			goto err_out_kcfree;
		}
		group_num = mg->size / sizeof(int);
		groups = (int *)mg->data;
		dnet_convert_meta(mg);
	}

	/* Read temporary meta */
	temp_mc.data = malloc(sizeof(struct dnet_meta_update) * group_num);
	if (!temp_mc.data) {
		err = -ENOMEM;
		dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: could not allocate memory for temp UPDATE_META\n", dnet_dump_id_str(ids->id.id));
		goto err_out_kcfree;
	}
	memset(temp_mc.data, 0, sizeof(struct dnet_meta_update) * group_num);
	temp_mc.size = sizeof(struct dnet_meta_update) * group_num;

	err = dnet_db_read_raw(p->db->b, &ids->id, (void **)&tmpdata);
	if (err <= 0) {
		if (err < 0 && err != -2)
			goto err_out_free;
		/* No data in temp meta was stored. Placing local meta_update at the beginning */
		mu = temp_mc.data;
		mu[0].group_id = my_group;
		mu[0].tm = my_mu.tm;
		mu[0].flags = my_mu.flags;
		
	} else {
		if (err > (int)(sizeof(struct dnet_meta_update) * group_num)) {
			dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: too many data stored in temp meta\n",  dnet_dump_id_str(ids->id.id));
			err = -ENOMEM;
			goto err_out_free;
		}
		memcpy(temp_mc.data, tmpdata, err);
	}

	/* Update temp meta with received group */
	mu = temp_mc.data;
	updated = 0;
	lastest = 0;
	for (i = 0; i < group_num; ++i) {
		if (mu[i].group_id == remote_group) {
			mu[i].tm = ids->last_update.tm;
			mu[i].flags = ids->last_update.flags;
			updated = 1;
		}

		if (mu[i].group_id == 0)
			break;

		if (!(mu[i].flags & DNET_IO_FLAGS_REMOVED))
			removed_in_all = 0;

		if (((mu[i].tm.tsec > mu[lastest].tm.tsec)
				|| ((mu[i].tm.tsec == mu[lastest].tm.tsec) && (mu[i].tm.tnsec > mu[lastest].tm.tnsec)))
			&& i != lastest) {
			lastest = i;
			lastest_group = groups[i];
		}
	
	}
	if (!updated && i == group_num) {
		dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: no space left to save group in temp meta!\n", dnet_dump_id_str(ids->id.id));
		err = -ENOMEM;
		goto err_out_free;
	}
	if (!updated) {
		mu[i].group_id = remote_group;
		mu[i].tm = ids->last_update.tm;
		mu[i].flags = ids->last_update.flags;

		if (((mu[i].tm.tsec > mu[lastest].tm.tsec)
				|| ((mu[i].tm.tsec == mu[lastest].tm.tsec) && (mu[i].tm.tnsec > mu[lastest].tm.tnsec)))
			&& i != lastest) {
			lastest = i;
			lastest_group = groups[i];
		}

		++i;
	}

	/* Not all groups processed yet */
	if (i < group_num) {
		err = 0;
		err = dnet_db_write_raw(p->db->b, &ids->id, temp_mc.data, temp_mc.size);
		if (err) {
			dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: unable to save temp meta, err: %d\n", dnet_dump_id_str(ids->id.id), err);
		}
		goto err_out_free;
	}

	/* Check if removal_delay second has gone since object was marked as REMOVED */
	if (removed_in_all) {
		gettimeofday(&current_ts, NULL);
		if (((uint64_t)current_ts.tv_sec < mu[lastest].tm.tsec) 
			|| ((uint64_t)current_ts.tv_sec - mu[lastest].tm.tsec) < (uint64_t)(state->n->removal_delay * 3600 * 24))
			removed_in_all = 0;
	}

	/* TODO: receive newer files from remote groups
	 *
	 * Yep, we should read it locally and send it to other groups too
	 */
	if ((lastest_group != my_group) && !(mu[lastest].flags & DNET_IO_FLAGS_REMOVED)) {
		dnet_log(state->n, DNET_LOG_DEBUG, "BULK: %s: File on remote group %d is newer, skipping this file\n",
				dnet_dump_id_str(ids->id.id), lastest_group);
		err = 0;
		goto err_out_free;
	}

	for (i = 0; i < group_num; ++i) {
		err = 0;
		if (mu[i].group_id == my_group)
			continue;

		dnet_session_set_groups(s, (int *)&mu[i].group_id, 1);
		dnet_setup_id(&id, mu[i].group_id, ids->id.id);
		id.type = -1;

		if (mu[lastest].flags & DNET_IO_FLAGS_REMOVED) {
			if (removed_in_all) {
				dnet_log(state->n, DNET_LOG_DEBUG, "BULK: dnet_remove_object_now %s in group %d, err=%d\n",
						dnet_dump_id(&id), mu[i].group_id, err);
				err = dnet_remove_object_now(s, &id, cflags, ioflags);
			} else {
				if (!(mu[i].flags & DNET_IO_FLAGS_REMOVED)) {
					err = dnet_remove_object(s, &id, NULL, NULL, cflags, ioflags);
					dnet_log(state->n, DNET_LOG_DEBUG, "BULK: dnet_remove_object %s in group %d err=%d\n",
							dnet_dump_id(&id), mu[i].group_id, err);
				}
			}
			if (err < 0)
				goto err_out_cont2;
		} else {
			if ((mu[i].tm.tsec < mu[lastest].tm.tsec) || ((mu[i].tm.tsec == mu[lastest].tm.tsec) &&
									((mu[i].tm.tnsec < mu[lastest].tm.tnsec)))) {
				err = state->n->cb->send(state, state->n->cb->command_private, &id);

				if (err)
					goto err_out_cont2;

				err = dnet_meta_update_check_status_raw(state->n, &mc);
				if (err)
					goto err_out_cont2;

				memcpy(&mc.id, &id, sizeof(struct dnet_id));
				err = dnet_write_metadata(s, &mc, 1, cflags);
				dnet_log(state->n, DNET_LOG_DEBUG, "BULK: dnet_write_metadata %s in group %d, err=%d\n",
						dnet_dump_id(&id), my_group, err);

				if (err < 0)
					goto err_out_cont2;
			}
		}
err_out_cont2:
		if (err < 0)
			dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: Error during sending transaction to group %d, err=%d\n",
					dnet_dump_id_str(ids->id.id), groups[i], err);
		if (!error && err < 0)
			error = err;
	}

	if (mu[lastest].flags & DNET_IO_FLAGS_REMOVED) {
		if (removed_in_all) {
			err = dnet_merge_remove_local(state->n, &mc.id, 0);
		} else if (!(my_mu.flags & DNET_IO_FLAGS_REMOVED)) {
			err = dnet_merge_remove_local(state->n, &mc.id, 1);
		}
	}

	if (!(mu[lastest].flags & DNET_IO_FLAGS_REMOVED) && !error) {
		err = dnet_meta_update_check_status(state->n, &mc);
		if (err) {
			dnet_log(state->n, DNET_LOG_ERROR, "BULK: %s: couldn't update meta CHECK_STATUS\n", dnet_dump_id_str(ids->id.id));
		}
	}

	if (group_num > 2) {
		err = dnet_db_remove_raw(p->db->b, &ids->id, 1);
		if (!err) {
			dnet_log_raw(state->n, DNET_LOG_ERROR, "BULK: %s: DB: failed to remove temp_meta object, err: %d.\n",
				dnet_dump_id(&mc.id), err);
		}
	}

	if (error > 0)
		error = 0;
err_out_free:
	free(temp_mc.data);
err_out_kcfree:
	free(mc.data);
	if (tmpdata)
		free(tmpdata);
err_out_continue:
	if (error < 0) {
		dnet_log(state->n, DNET_LOG_ERROR, "Failed to check ID %s to %s, err=%d\n", dnet_dump_id_str(ids->id.id),
				dnet_state_dump_addr(state), error);
	}
	if (i == group_num) {
		dnet_counter_inc(state->n, DNET_CNTR_NODE_CHECK_COPY, error);
	}

	return error;
}
예제 #11
0
파일: check.c 프로젝트: Inkvi/elliptics
int dnet_cmd_bulk_check(struct dnet_net_state *orig, struct dnet_cmd *cmd, void *data)
{
	struct dnet_bulk_id *ids = (struct dnet_bulk_id *)data;
	struct dnet_meta_container mc;
	struct dnet_meta_update mu;
	struct dnet_id raw;
	int i;
	int err = 0;
	int num;

	if (!(cmd->size % sizeof(struct dnet_bulk_id))) {
		num = cmd->size / sizeof(struct dnet_bulk_id);

		dnet_log(orig->n, DNET_LOG_DEBUG, "BULK: received %d entries\n", num);

		for (i = 0; i < num; ++i) {

			/* Send empty reply every DNET_BULK_CHECK_PING records to prevent timeout */
			if (i % DNET_BULK_CHECK_PING == 0 && i > 0) {
				dnet_send_reply(orig, cmd, NULL, 0, 1);
			}

			dnet_log(orig->n, DNET_LOG_DEBUG, "BULK: processing ID %s\n", dnet_dump_id_str(ids[i].id.id));
			mc.data = NULL;
			dnet_setup_id(&mc.id, 0, ids[i].id.id);
			err = orig->n->cb->meta_read(orig->n->cb->command_private, &ids[i].id, &mc.data);
			if (mc.data) {
				mc.size = err;
				dnet_log(orig->n, DNET_LOG_DEBUG, "BULK: %d bytes of metadata found, searching for META_UPDATE group_id=%d\n",
						mc.size, orig->n->st->idc->group->group_id);
				if (dnet_get_meta_update(orig->n, &mc, &mu))
				{
					dnet_convert_meta_update(&ids[i].last_update);
					dnet_log(orig->n, DNET_LOG_DEBUG, "BULK: mu.tsec=%lu, mu.tnsec=%lu, mu.flags=%02lx\n",
							(unsigned long)mu.tm.tsec, (unsigned long)mu.tm.tnsec, (unsigned long)mu.flags);
					dnet_log(orig->n, DNET_LOG_DEBUG,
							"BULK: last_update.tsec=%lu, last_update.tnsec=%lu, last_update.flags=%02lx\n",
							(unsigned long)ids[i].last_update.tm.tsec, (unsigned long)ids[i].last_update.tm.tnsec,
							(unsigned long)ids[i].last_update.flags);

					if ((mu.flags & DNET_IO_FLAGS_REMOVED) || (mu.tm.tsec < ids[i].last_update.tm.tsec) || 
						((mu.tm.tnsec < ids[i].last_update.tm.tnsec) && (mu.tm.tsec == ids[i].last_update.tm.tsec))) {
						err = 0;
					} else {
						/* File is not needed to be updated */
						dnet_setup_id(&raw, orig->n->id.group_id, ids[i].id.id);
						err = dnet_stat_local(orig, &raw);
						if (err) {
							/* File was not found in the storage */
							mu.tm.tsec = 1;
							mu.flags = 0;
						} else {
							err = dnet_meta_update_check_status(orig->n, &mc);
							if (err) {
								dnet_log(orig->n, DNET_LOG_ERROR,
										"BULK: %s: couldn't update meta CHECK_STATUS err: %d\n",
										dnet_dump_id_str(ids[i].id.id), err);
							}
						}
					}

					memcpy(&ids[i].last_update, &mu, sizeof(struct dnet_meta_update));
					dnet_convert_meta_update(&ids[i].last_update);
				}
				free(mc.data);
			} else {
				/* Meta is not present - set timestamp to very old one */
				dnet_convert_meta_update(&ids[i].last_update);
				ids[i].last_update.tm.tsec = 1;
				ids[i].last_update.flags = 0;
				dnet_convert_meta_update(&ids[i].last_update);
			}
		}
	} else {
		dnet_log(orig->n, DNET_LOG_ERROR, "BULK: received corrupted data, size = %llu, sizeof(dnet_bulk_id) = %zu\n",
				(unsigned long long)cmd->size, sizeof(struct dnet_bulk_id));
		err = -1;
		goto err_out_exit;
	}

	return dnet_send_reply(orig, cmd, data, sizeof(struct dnet_bulk_id) * num, 0);

err_out_exit:
	return err;
}
예제 #12
0
파일: stat.c 프로젝트: Inkvi/elliptics
int main(int argc, char *argv[])
{
	int ch, err, i, have_remote = 0;
	struct dnet_node *n = NULL;
	struct dnet_session *s = NULL;
	struct dnet_config cfg, rem;
	int max_id_idx = 1000, id_idx = 0;
	int timeout;
	unsigned char id[max_id_idx][DNET_ID_SIZE];
	char *logfile = "/dev/stderr", *statfile = "/dev/stdout";
	FILE *log = NULL, *stat;

	memset(&cfg, 0, sizeof(struct dnet_config));

	cfg.sock_type = SOCK_STREAM;
	cfg.proto = IPPROTO_TCP;
	cfg.wait_timeout = 60*60;
	stat_logger.log_level = DNET_LOG_ERROR;

	timeout = 1;

	memcpy(&rem, &cfg, sizeof(struct dnet_config));

	while ((ch = getopt(argc, argv, "MFAt:m:w:l:I:r:h")) != -1) {
		switch (ch) {
			case 'M':
				stat_mem = 1;
				break;
			case 'F':
				stat_fs = 1;
				break;
			case 'A':
				stat_la = 1;
				break;
			case 't':
				timeout = atoi(optarg);
				break;
			case 'm':
				stat_logger.log_level = strtoul(optarg, NULL, 0);
				break;
			case 'w':
				cfg.wait_timeout = atoi(optarg);
				break;
			case 'L':
				statfile = optarg;
				break;
			case 'l':
				logfile = optarg;
				break;
			case 'I':
				if (id_idx < max_id_idx) {
					err = dnet_parse_numeric_id(optarg, id[id_idx]);
					if (err)
						return err;
					id_idx++;
				}
				break;
			case 'r':
				err = dnet_parse_addr(optarg, &rem);
				if (err)
					return err;
				have_remote = 1;
				break;
			case 'h':
			default:
				stat_usage(argv[0]);
				return -1;
		}
	}

	if (!have_remote) {
		fprintf(stderr, "No remote node specified to route requests.\n");
		return -ENOENT;
	}

	log = fopen(logfile, "a");
	if (!log) {
		err = -errno;
		fprintf(stderr, "Failed to open log file %s: %s.\n", logfile, strerror(errno));
		return err;
	}

	stat_logger.log_private = log;
	stat_logger.log = dnet_common_log;
	cfg.log = &stat_logger;

	stat = fopen(statfile, "a");
	if (!stat) {
		err = -errno;
		fprintf(stderr, "Failed to open stat file %s: %s.\n", statfile, strerror(errno));
		return err;
	}

	n = dnet_node_create(&cfg);
	if (!n)
		return -1;

	s = dnet_session_create(n);
	if (!s)
		return -1;

	err = dnet_add_state(n, &rem);
	if (err)
		return err;

	while (1) {
		struct dnet_id raw;

		if (!id_idx) {
			err = dnet_request_stat(s, NULL, DNET_CMD_STAT, 0, stat_complete, stat);
			if (err < 0)
				return err;
		}

		for (i=0; i<id_idx; ++i) {
			dnet_setup_id(&raw, 0, id[i]);
			err = dnet_request_stat(s, &raw, DNET_CMD_STAT, 0, stat_complete, stat);
			if (err < 0)
				return err;
		}

		sleep(timeout);
	}

	return 0;
}