static int smack_backend_read(struct smack_backend *s, void *state, struct dnet_cmd *cmd, void *iodata) { struct dnet_io_attr *io = iodata; char *data; struct index idx; int err; dnet_convert_io_attr(io); smack_setup_idx(&idx, io->id); idx.data_size = io->size; err = smack_read(s->smack, &idx, &data); if (err < 0) goto err_out_exit; io->size = idx.data_size; err = dnet_send_read_data(state, cmd, io, data, -1, io->offset, 0); if (err) goto err_out_free; err_out_free: free(data); err_out_exit: return err; }
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; }
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; }
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; }
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; }
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; }
static int leveldb_backend_write(struct leveldb_backend *s, void *state, struct dnet_cmd *cmd, void *data) { struct dnet_ext_list elist; int err = -EINVAL; char *error_string = NULL; struct dnet_io_attr *io = data; void *read_data = NULL; dnet_ext_list_init(&elist); dnet_convert_io_attr(io); data += sizeof(struct dnet_io_attr); /* Combine data with empty extension list header */ err = dnet_ext_list_combine(&data, &io->size, &elist); if (err != 0) goto err_out_exit; /* * key should be locked by elliptics here, so it is safe to run read-modify-write cycle * if one performs write without lock we do not really care that one write may overwrite another one */ if (io->offset || (io->flags & DNET_IO_FLAGS_APPEND)) { size_t data_size; size_t offset = io->offset; read_data = leveldb_get(s->db, s->roptions, (const char *)io->id, DNET_ID_SIZE, &data_size, &error_string); if (error_string || !read_data) { free(error_string); error_string = NULL; goto plain_write; } if (io->flags & DNET_IO_FLAGS_APPEND) { io->offset = 0; offset = data_size; } /* * XXX: Account for extended header */ if (io->offset > data_size) { err = -ERANGE; goto err_out_exit; } if (offset + io->size > data_size) { read_data = realloc(read_data, data_size + io->size); if (!read_data) { err = -ENOMEM; goto err_out_exit; } } memcpy(read_data + offset, data, io->size); data = read_data; if (offset + io->size > data_size) io->size = offset + io->size; else io->size = data_size; } plain_write: leveldb_put(s->db, s->woptions, (const char *)cmd->id.id, DNET_ID_SIZE, data, io->size, &error_string); if (error_string) goto err_out_free; if (io->flags & DNET_IO_FLAGS_WRITE_NO_FILE_INFO) { cmd->flags |= DNET_FLAGS_NEED_ACK; err = 0; goto err_out_exit; } err = dnet_send_file_info_ts_without_fd(state, cmd, 0, io->size, &elist.timestamp); if (err < 0) goto err_out_free; dnet_backend_log(DNET_LOG_NOTICE, "%s: leveldb: : WRITE: Ok: offset: %llu, size: %llu, ioflags: %x.\n", dnet_dump_id(&cmd->id), (unsigned long long)io->offset, (unsigned long long)io->size, io->flags); err_out_free: free(data); err_out_exit: dnet_ext_list_destroy(&elist); if (err < 0) dnet_backend_log(DNET_LOG_ERROR, "%s: leveldb: : WRITE: error: %s: %d.\n", dnet_dump_id(&cmd->id), error_string, err); free(read_data); free(error_string); return err; }