\
/* Extensible */ \
f(SET_REDIRECT, __CEPH_OSD_OP(WR, DATA, 39), "set-redirect") \
+ f(SET_CHUNK, __CEPH_OSD_OP(WR, DATA, 40), "set-chunk") \
\
/** attrs **/ \
/* read */ \
*/
void set_redirect(const std::string& tgt_obj, const IoCtx& tgt_ioctx,
uint64_t tgt_version);
+ void set_chunk(uint64_t src_offset, uint64_t src_length, const IoCtx& tgt_ioctx,
+ std::string tgt_oid, uint64_t tgt_offset);
+
friend class IoCtx;
};
tgt_ioctx.io_ctx_impl->oloc, tgt_version);
}
+void librados::ObjectWriteOperation::set_chunk(uint64_t src_offset,
+ uint64_t src_length,
+ const IoCtx& tgt_ioctx,
+ string tgt_oid,
+ uint64_t tgt_offset)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->set_chunk(src_offset, src_length,
+ tgt_ioctx.io_ctx_impl->oloc, object_t(tgt_oid), tgt_offset);
+}
+
void librados::ObjectWriteOperation::tmap_put(const bufferlist &bl)
{
::ObjectOperation *o = &impl->o;
break;
+ case CEPH_OSD_OP_SET_CHUNK:
+ ++ctx->num_write;
+ {
+ if (pool.info.is_tier()) {
+ result = -EINVAL;
+ break;
+ }
+ if (!obs.exists) {
+ result = -ENOENT;
+ break;
+ }
+ if (get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS) {
+ result = -EOPNOTSUPP;
+ break;
+ }
+
+ object_locator_t tgt_oloc;
+ uint64_t src_offset, src_length, tgt_offset;
+ object_t tgt_name;
+ try {
+ ::decode(src_offset, bp);
+ ::decode(src_length, bp);
+ ::decode(tgt_oloc, bp);
+ ::decode(tgt_name, bp);
+ ::decode(tgt_offset, bp);
+ }
+ catch (buffer::error& e) {
+ result = -EINVAL;
+ goto fail;
+ }
+
+ if (!src_length) {
+ result = -EINVAL;
+ goto fail;
+ }
+
+ if (!oi.manifest.is_chunked()) {
+ oi.manifest.clear();
+ }
+
+ pg_t raw_pg;
+ chunk_info_t chunk_info;
+ hobject_t target(tgt_name, tgt_oloc.key, snapid_t(),
+ raw_pg.ps(), raw_pg.pool(),
+ tgt_oloc.nspace);
+ get_osdmap()->object_locator_to_pg(tgt_name, tgt_oloc, raw_pg);
+ chunk_info.flags = chunk_info_t::FLAG_MISSING;
+ chunk_info.oid = target;
+ chunk_info.offset = tgt_offset;
+ chunk_info.length= src_length;
+ oi.manifest.chunk_map[src_offset] = chunk_info;
+
+ oi.set_flag(object_info_t::FLAG_MANIFEST);
+ oi.manifest.type = object_manifest_t::TYPE_CHUNKED;
+ ctx->modify = true;
+
+ dout(10) << "set-chunked oid:" << oi.soid << " user_version: " << oi.user_version
+ << " chunk_info: " << chunk_info << dendl;
+ }
+
+ break;
+
// -- object attrs --
case CEPH_OSD_OP_SETXATTR:
hobject_t oid;
uint32_t flags; // FLAG_*
- chunk_info_t() : length(0), flags(0) { }
+ chunk_info_t() : offset(0), length(0), flags(0) { }
static string get_flag_string(uint64_t flags) {
string r;
::encode(tgt_oloc, osd_op.indata);
}
+ void set_chunk(uint64_t src_offset, uint64_t src_length, object_locator_t tgt_oloc,
+ object_t tgt_oid, uint64_t tgt_offset) {
+ OSDOp& osd_op = add_op(CEPH_OSD_OP_SET_CHUNK);
+ ::encode(src_offset, osd_op.indata);
+ ::encode(src_length, osd_op.indata);
+ ::encode(tgt_oloc, osd_op.indata);
+ ::encode(tgt_oid, osd_op.indata);
+ ::encode(tgt_offset, osd_op.indata);
+ }
+
void set_alloc_hint(uint64_t expected_object_size,
uint64_t expected_write_size,
uint32_t flags) {
" listwatchers <obj-name> list the watchers of this object\n"
" set-alloc-hint <obj-name> <expected-object-size> <expected-write-size>\n"
" set allocation hint for an object\n"
+" set-redirect <object A> --target-pool <caspool> <target object A>\n"
+" set redirect target\n"
+" set-chunk <object A> <offset> <length> --target-pool <caspool> <target object A> <taget-offset>\n"
+" convert an object to chunked object\n"
"\n"
"IMPORT AND EXPORT\n"
" export [filename]\n"
cerr << "error set-redirect " << pool_name << "/" << nargs[1] << " => " << target << "/" << target_obj << ": " << cpp_strerror(ret) << std::endl;
goto out;
}
+ } else if (strcmp(nargs[0], "set-chunk") == 0) {
+ if (!pool_name)
+ usage_exit();
+
+ const char *target = target_pool_name;
+ if (!target)
+ target = pool_name;
+
+ uint64_t offset;
+ uint64_t length;
+ uint64_t tgt_offset;
+ string tgt_oid;
+ if (nargs.size() < 6) {
+ usage_exit();
+ } else {
+ char* endptr = NULL;
+ offset = strtoull(nargs[2], &endptr, 10);
+ if (*endptr) {
+ cerr << "Invalid value for size: '" << nargs[2] << "'" << std::endl;
+ ret = -EINVAL;
+ goto out;
+ }
+ length = strtoull(nargs[3], &endptr, 10);
+ if (*endptr) {
+ cerr << "Invalid value for size: '" << nargs[2] << "'" << std::endl;
+ ret = -EINVAL;
+ goto out;
+ }
+ tgt_oid = string(nargs[4]);
+ tgt_offset = strtoull(nargs[5], &endptr, 10);
+ if (*endptr) {
+ cerr << "Invalid value for size: '" << nargs[2] << "'" << std::endl;
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ IoCtx target_ctx;
+ ret = rados.ioctx_create(target, target_ctx);
+ ObjectWriteOperation op;
+ op.set_chunk(offset, length, target_ctx, tgt_oid, tgt_offset);
+ ret = io_ctx.operate(nargs[1], &op);
+ if (ret < 0) {
+ cerr << "error set-chunk " << pool_name << "/" << nargs[1] << " " << " offset " << offset
+ << " length " << length << " target_pool " << target
+ << "tgt_offset: " << tgt_offset << " : " << cpp_strerror(ret) << std::endl;
+ goto out;
+ }
} else if (strcmp(nargs[0], "export") == 0) {
// export [filename]
if (!pool_name || nargs.size() > 2) {