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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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)); }
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; }
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); }
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; }
std::string key::to_string() const { if (m_by_id) return dnet_dump_id(&m_id); else return m_remote; }
/* * 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; }
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; }
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; }
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; }
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; }
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; }
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(); }
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); }
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; }
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; }
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; }
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);
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; }
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_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; }
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; }
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); }