X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fobjclass%2Fclass_api.cc;fp=src%2Fceph%2Fsrc%2Fobjclass%2Fclass_api.cc;h=cb8aa0677f8c215e84374b9da1229f1f30a114e8;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/objclass/class_api.cc b/src/ceph/src/objclass/class_api.cc new file mode 100644 index 0000000..cb8aa06 --- /dev/null +++ b/src/ceph/src/objclass/class_api.cc @@ -0,0 +1,723 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "common/config.h" +#include "common/debug.h" + +#include "objclass/objclass.h" +#include "osd/PrimaryLogPG.h" +#include "osd/osd_types.h" + +#include "osd/ClassHandler.h" + +#include "auth/Crypto.h" +#include "common/armor.h" + +static constexpr int dout_subsys = ceph_subsys_objclass; + +static ClassHandler *ch; + +void cls_initialize(ClassHandler *h) +{ + ch = h; +} + +void cls_finalize() +{ + ch = NULL; +} + + +void *cls_alloc(size_t size) +{ + return malloc(size); +} + +void cls_free(void *p) +{ + free(p); +} + +int cls_register(const char *name, cls_handle_t *handle) +{ + ClassHandler::ClassData *cls = ch->register_class(name); + *handle = (cls_handle_t)cls; + return (cls != NULL); +} + +int cls_unregister(cls_handle_t handle) +{ + ClassHandler::ClassData *cls = (ClassHandler::ClassData *)handle; + ch->unregister_class(cls); + return 1; +} + +int cls_register_method(cls_handle_t hclass, const char *method, + int flags, + cls_method_call_t class_call, cls_method_handle_t *handle) +{ + if (!(flags & (CLS_METHOD_RD | CLS_METHOD_WR))) + return -EINVAL; + ClassHandler::ClassData *cls = (ClassHandler::ClassData *)hclass; + cls_method_handle_t hmethod =(cls_method_handle_t)cls->register_method(method, flags, class_call); + if (handle) + *handle = hmethod; + return (hmethod != NULL); +} + +int cls_register_cxx_method(cls_handle_t hclass, const char *method, + int flags, + cls_method_cxx_call_t class_call, cls_method_handle_t *handle) +{ + ClassHandler::ClassData *cls = (ClassHandler::ClassData *)hclass; + cls_method_handle_t hmethod = (cls_method_handle_t)cls->register_cxx_method(method, flags, class_call); + if (handle) + *handle = hmethod; + return (hmethod != NULL); +} + +int cls_unregister_method(cls_method_handle_t handle) +{ + ClassHandler::ClassMethod *method = (ClassHandler::ClassMethod *)handle; + method->unregister(); + return 1; +} + +int cls_register_cxx_filter(cls_handle_t hclass, + const std::string &filter_name, + cls_cxx_filter_factory_t fn, + cls_filter_handle_t *handle) +{ + ClassHandler::ClassData *cls = (ClassHandler::ClassData *)hclass; + cls_filter_handle_t hfilter = (cls_filter_handle_t)cls->register_cxx_filter(filter_name, fn); + if (handle) { + *handle = hfilter; + } + return (hfilter != NULL); +} + +void cls_unregister_filter(cls_filter_handle_t handle) +{ + ClassHandler::ClassFilter *filter = (ClassHandler::ClassFilter *)handle; + filter->unregister(); +} + +int cls_call(cls_method_context_t hctx, const char *cls, const char *method, + char *indata, int datalen, + char **outdata, int *outdatalen) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + bufferlist idata; + vector nops(1); + OSDOp& op = nops[0]; + int r; + + op.op.op = CEPH_OSD_OP_CALL; + op.op.cls.class_len = strlen(cls); + op.op.cls.method_len = strlen(method); + op.op.cls.indata_len = datalen; + op.indata.append(cls, op.op.cls.class_len); + op.indata.append(method, op.op.cls.method_len); + op.indata.append(indata, datalen); + r = (*pctx)->pg->do_osd_ops(*pctx, nops); + if (r < 0) + return r; + + *outdata = (char *)malloc(op.outdata.length()); + if (!*outdata) + return -ENOMEM; + memcpy(*outdata, op.outdata.c_str(), op.outdata.length()); + *outdatalen = op.outdata.length(); + + return r; +} + +int cls_getxattr(cls_method_context_t hctx, const char *name, + char **outdata, int *outdatalen) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + bufferlist name_data; + vector nops(1); + OSDOp& op = nops[0]; + int r; + + op.op.op = CEPH_OSD_OP_GETXATTR; + op.indata.append(name); + op.op.xattr.name_len = strlen(name); + r = (*pctx)->pg->do_osd_ops(*pctx, nops); + if (r < 0) + return r; + + *outdata = (char *)malloc(op.outdata.length()); + if (!*outdata) + return -ENOMEM; + memcpy(*outdata, op.outdata.c_str(), op.outdata.length()); + *outdatalen = op.outdata.length(); + + return r; +} + +int cls_setxattr(cls_method_context_t hctx, const char *name, + const char *value, int val_len) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + bufferlist name_data; + vector nops(1); + OSDOp& op = nops[0]; + int r; + + op.op.op = CEPH_OSD_OP_SETXATTR; + op.indata.append(name); + op.indata.append(value); + op.op.xattr.name_len = strlen(name); + op.op.xattr.value_len = val_len; + r = (*pctx)->pg->do_osd_ops(*pctx, nops); + + return r; +} + +int cls_read(cls_method_context_t hctx, int ofs, int len, + char **outdata, int *outdatalen) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + ops[0].op.op = CEPH_OSD_OP_SYNC_READ; + ops[0].op.extent.offset = ofs; + ops[0].op.extent.length = len; + int r = (*pctx)->pg->do_osd_ops(*pctx, ops); + if (r < 0) + return r; + + *outdata = (char *)malloc(ops[0].outdata.length()); + if (!*outdata) + return -ENOMEM; + memcpy(*outdata, ops[0].outdata.c_str(), ops[0].outdata.length()); + *outdatalen = ops[0].outdata.length(); + + return *outdatalen; +} + +int cls_get_request_origin(cls_method_context_t hctx, entity_inst_t *origin) +{ + PrimaryLogPG::OpContext **pctx = static_cast(hctx); + *origin = (*pctx)->op->get_req()->get_orig_source_inst(); + return 0; +} + +int cls_cxx_create(cls_method_context_t hctx, bool exclusive) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + ops[0].op.op = CEPH_OSD_OP_CREATE; + ops[0].op.flags = (exclusive ? CEPH_OSD_OP_FLAG_EXCL : 0); + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_remove(cls_method_context_t hctx) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + ops[0].op.op = CEPH_OSD_OP_DELETE; + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_stat(cls_method_context_t hctx, uint64_t *size, time_t *mtime) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + int ret; + ops[0].op.op = CEPH_OSD_OP_STAT; + ret = (*pctx)->pg->do_osd_ops(*pctx, ops); + if (ret < 0) + return ret; + bufferlist::iterator iter = ops[0].outdata.begin(); + utime_t ut; + uint64_t s; + try { + ::decode(s, iter); + ::decode(ut, iter); + } catch (buffer::error& err) { + return -EIO; + } + if (size) + *size = s; + if (mtime) + *mtime = ut.sec(); + return 0; +} + +int cls_cxx_stat2(cls_method_context_t hctx, uint64_t *size, ceph::real_time *mtime) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + int ret; + ops[0].op.op = CEPH_OSD_OP_STAT; + ret = (*pctx)->pg->do_osd_ops(*pctx, ops); + if (ret < 0) + return ret; + bufferlist::iterator iter = ops[0].outdata.begin(); + real_time ut; + uint64_t s; + try { + ::decode(s, iter); + ::decode(ut, iter); + } catch (buffer::error& err) { + return -EIO; + } + if (size) + *size = s; + if (mtime) + *mtime = ut; + return 0; +} + +int cls_cxx_read(cls_method_context_t hctx, int ofs, int len, bufferlist *outbl) +{ + return cls_cxx_read2(hctx, ofs, len, outbl, 0); +} + +int cls_cxx_read2(cls_method_context_t hctx, int ofs, int len, + bufferlist *outbl, uint32_t op_flags) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + int ret; + ops[0].op.op = CEPH_OSD_OP_SYNC_READ; + ops[0].op.extent.offset = ofs; + ops[0].op.extent.length = len; + ops[0].op.flags = op_flags; + ret = (*pctx)->pg->do_osd_ops(*pctx, ops); + if (ret < 0) + return ret; + outbl->claim(ops[0].outdata); + return outbl->length(); +} + +int cls_cxx_write(cls_method_context_t hctx, int ofs, int len, bufferlist *inbl) +{ + return cls_cxx_write2(hctx, ofs, len, inbl, 0); +} + +int cls_cxx_write2(cls_method_context_t hctx, int ofs, int len, + bufferlist *inbl, uint32_t op_flags) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + ops[0].op.op = CEPH_OSD_OP_WRITE; + ops[0].op.extent.offset = ofs; + ops[0].op.extent.length = len; + ops[0].op.flags = op_flags; + ops[0].indata = *inbl; + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_write_full(cls_method_context_t hctx, bufferlist *inbl) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + ops[0].op.op = CEPH_OSD_OP_WRITEFULL; + ops[0].op.extent.offset = 0; + ops[0].op.extent.length = inbl->length(); + ops[0].indata = *inbl; + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_replace(cls_method_context_t hctx, int ofs, int len, bufferlist *inbl) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(2); + ops[0].op.op = CEPH_OSD_OP_TRUNCATE; + ops[0].op.extent.offset = 0; + ops[0].op.extent.length = 0; + ops[1].op.op = CEPH_OSD_OP_WRITE; + ops[1].op.extent.offset = ofs; + ops[1].op.extent.length = len; + ops[1].indata = *inbl; + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_getxattr(cls_method_context_t hctx, const char *name, + bufferlist *outbl) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + bufferlist name_data; + vector nops(1); + OSDOp& op = nops[0]; + int r; + + op.op.op = CEPH_OSD_OP_GETXATTR; + op.indata.append(name); + op.op.xattr.name_len = strlen(name); + r = (*pctx)->pg->do_osd_ops(*pctx, nops); + if (r < 0) + return r; + + outbl->claim(op.outdata); + return outbl->length(); +} + +int cls_cxx_getxattrs(cls_method_context_t hctx, map *attrset) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector nops(1); + OSDOp& op = nops[0]; + int r; + + op.op.op = CEPH_OSD_OP_GETXATTRS; + r = (*pctx)->pg->do_osd_ops(*pctx, nops); + if (r < 0) + return r; + + bufferlist::iterator iter = op.outdata.begin(); + try { + ::decode(*attrset, iter); + } catch (buffer::error& err) { + return -EIO; + } + return 0; +} + +int cls_cxx_setxattr(cls_method_context_t hctx, const char *name, + bufferlist *inbl) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + bufferlist name_data; + vector nops(1); + OSDOp& op = nops[0]; + int r; + + op.op.op = CEPH_OSD_OP_SETXATTR; + op.indata.append(name); + op.indata.append(*inbl); + op.op.xattr.name_len = strlen(name); + op.op.xattr.value_len = inbl->length(); + r = (*pctx)->pg->do_osd_ops(*pctx, nops); + + return r; +} + +int cls_cxx_snap_revert(cls_method_context_t hctx, snapid_t snapid) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + ops[0].op.op = CEPH_OSD_OP_ROLLBACK; + ops[0].op.snap.snapid = snapid; + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_map_get_all_vals(cls_method_context_t hctx, map* vals, + bool *more) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + OSDOp& op = ops[0]; + int ret; + + string start_after; + string filter_prefix; + uint64_t max = (uint64_t)-1; + + ::encode(start_after, op.indata); + ::encode(max, op.indata); + ::encode(filter_prefix, op.indata); + + op.op.op = CEPH_OSD_OP_OMAPGETVALS; + + ret = (*pctx)->pg->do_osd_ops(*pctx, ops); + if (ret < 0) + return ret; + + bufferlist::iterator iter = op.outdata.begin(); + try { + ::decode(*vals, iter); + ::decode(*more, iter); + } catch (buffer::error& err) { + return -EIO; + } + return vals->size(); +} + +int cls_cxx_map_get_keys(cls_method_context_t hctx, const string &start_obj, + uint64_t max_to_get, set *keys, + bool *more) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + OSDOp& op = ops[0]; + int ret; + + ::encode(start_obj, op.indata); + ::encode(max_to_get, op.indata); + + op.op.op = CEPH_OSD_OP_OMAPGETKEYS; + + ret = (*pctx)->pg->do_osd_ops(*pctx, ops); + if (ret < 0) + return ret; + + bufferlist::iterator iter = op.outdata.begin(); + try { + ::decode(*keys, iter); + ::decode(*more, iter); + } catch (buffer::error& err) { + return -EIO; + } + return keys->size(); +} + +int cls_cxx_map_get_vals(cls_method_context_t hctx, const string &start_obj, + const string &filter_prefix, uint64_t max_to_get, + map *vals, bool *more) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + OSDOp& op = ops[0]; + int ret; + + ::encode(start_obj, op.indata); + ::encode(max_to_get, op.indata); + ::encode(filter_prefix, op.indata); + + op.op.op = CEPH_OSD_OP_OMAPGETVALS; + + ret = (*pctx)->pg->do_osd_ops(*pctx, ops); + if (ret < 0) + return ret; + + bufferlist::iterator iter = op.outdata.begin(); + try { + ::decode(*vals, iter); + ::decode(*more, iter); + } catch (buffer::error& err) { + return -EIO; + } + return vals->size(); +} + +int cls_cxx_map_read_header(cls_method_context_t hctx, bufferlist *outbl) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + OSDOp& op = ops[0]; + int ret; + op.op.op = CEPH_OSD_OP_OMAPGETHEADER; + ret = (*pctx)->pg->do_osd_ops(*pctx, ops); + if (ret < 0) + return ret; + + outbl->claim(op.outdata); + + return 0; +} + +int cls_cxx_map_get_val(cls_method_context_t hctx, const string &key, + bufferlist *outbl) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + OSDOp& op = ops[0]; + int ret; + + set k; + k.insert(key); + ::encode(k, op.indata); + + op.op.op = CEPH_OSD_OP_OMAPGETVALSBYKEYS; + ret = (*pctx)->pg->do_osd_ops(*pctx, ops); + if (ret < 0) + return ret; + + bufferlist::iterator iter = op.outdata.begin(); + try { + map m; + + ::decode(m, iter); + map::iterator iter = m.begin(); + if (iter == m.end()) + return -ENOENT; + + *outbl = iter->second; + } catch (buffer::error& e) { + return -EIO; + } + return 0; +} + +int cls_cxx_map_set_val(cls_method_context_t hctx, const string &key, + bufferlist *inbl) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + OSDOp& op = ops[0]; + bufferlist& update_bl = op.indata; + map m; + m[key] = *inbl; + ::encode(m, update_bl); + + op.op.op = CEPH_OSD_OP_OMAPSETVALS; + + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_map_set_vals(cls_method_context_t hctx, + const std::map *map) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + OSDOp& op = ops[0]; + bufferlist& update_bl = op.indata; + ::encode(*map, update_bl); + + op.op.op = CEPH_OSD_OP_OMAPSETVALS; + + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_map_clear(cls_method_context_t hctx) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + OSDOp& op = ops[0]; + + op.op.op = CEPH_OSD_OP_OMAPCLEAR; + + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_map_write_header(cls_method_context_t hctx, bufferlist *inbl) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + OSDOp& op = ops[0]; + op.indata.claim(*inbl); + + op.op.op = CEPH_OSD_OP_OMAPSETHEADER; + + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_map_remove_key(cls_method_context_t hctx, const string &key) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector ops(1); + OSDOp& op = ops[0]; + bufferlist& update_bl = op.indata; + set to_rm; + to_rm.insert(key); + + ::encode(to_rm, update_bl); + + op.op.op = CEPH_OSD_OP_OMAPRMKEYS; + + return (*pctx)->pg->do_osd_ops(*pctx, ops); +} + +int cls_cxx_list_watchers(cls_method_context_t hctx, + obj_list_watch_response_t *watchers) +{ + PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; + vector nops(1); + OSDOp& op = nops[0]; + int r; + + op.op.op = CEPH_OSD_OP_LIST_WATCHERS; + r = (*pctx)->pg->do_osd_ops(*pctx, nops); + if (r < 0) + return r; + + bufferlist::iterator iter = op.outdata.begin(); + try { + ::decode(*watchers, iter); + } catch (buffer::error& err) { + return -EIO; + } + return 0; +} + +int cls_gen_random_bytes(char *buf, int size) +{ + return get_random_bytes(buf, size); +} + +int cls_gen_rand_base64(char *dest, int size) /* size should be the required string size + 1 */ +{ + char buf[size]; + char tmp_dest[size + 4]; /* so that there's space for the extra '=' characters, and some */ + int ret; + + ret = cls_gen_random_bytes(buf, sizeof(buf)); + if (ret < 0) { + lgeneric_derr(ch->cct) << "cannot get random bytes: " << ret << dendl; + return -1; + } + + ret = ceph_armor(tmp_dest, &tmp_dest[sizeof(tmp_dest)], + (const char *)buf, ((const char *)buf) + ((size - 1) * 3 + 4 - 1) / 4); + if (ret < 0) { + lgeneric_derr(ch->cct) << "ceph_armor failed" << dendl; + return -1; + } + tmp_dest[ret] = '\0'; + memcpy(dest, tmp_dest, size); + dest[size-1] = '\0'; + + return 0; +} + +uint64_t cls_current_version(cls_method_context_t hctx) +{ + PrimaryLogPG::OpContext *ctx = *(PrimaryLogPG::OpContext **)hctx; + + return ctx->pg->info.last_user_version; +} + + +int cls_current_subop_num(cls_method_context_t hctx) +{ + PrimaryLogPG::OpContext *ctx = *(PrimaryLogPG::OpContext **)hctx; + + return ctx->current_osd_subop_num; +} + +uint64_t cls_get_features(cls_method_context_t hctx) +{ + PrimaryLogPG::OpContext *ctx = *(PrimaryLogPG::OpContext **)hctx; + return ctx->pg->get_osdmap()->get_up_osd_features(); +} + +uint64_t cls_get_client_features(cls_method_context_t hctx) +{ + PrimaryLogPG::OpContext *ctx = *(PrimaryLogPG::OpContext **)hctx; + return ctx->op->get_req()->get_connection()->get_features(); +} + +void cls_cxx_subop_version(cls_method_context_t hctx, string *s) +{ + if (!s) + return; + + char buf[32]; + uint64_t ver = cls_current_version(hctx); + int subop_num = cls_current_subop_num(hctx); + snprintf(buf, sizeof(buf), "%lld.%d", (long long)ver, subop_num); + + *s = buf; +} + +int cls_log(int level, const char *format, ...) +{ + int size = 256; + va_list ap; + while (1) { + char buf[size]; + va_start(ap, format); + int n = vsnprintf(buf, size, format, ap); + va_end(ap); +#define MAX_SIZE 8196 + if ((n > -1 && n < size) || size > MAX_SIZE) { + ldout(ch->cct, level) << buf << dendl; + return n; + } + size *= 2; + } +}