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; }
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); } }
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; }
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; } }
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; }
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 = ¬ify_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; }
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; }
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; }
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; }
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(¤t_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; }
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; }
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; }