From 99be4f14b2fa50a4a1b113801eec4ad2616d4599 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 5 Jun 2009 21:33:32 -0700 Subject: [PATCH] objclass: add support for c++ methods --- src/common/ClassHandler.cc | 37 +++++++++++++++----- src/common/ClassHandler.h | 9 +++-- src/objclass/class_api.cc | 71 +++++++++++++++++++++++++++++++------- src/objclass/objclass.h | 13 ++++++- 4 files changed, 106 insertions(+), 24 deletions(-) diff --git a/src/common/ClassHandler.cc b/src/common/ClassHandler.cc index e3596cb1908b5..555cabfb7bae8 100644 --- a/src/common/ClassHandler.cc +++ b/src/common/ClassHandler.cc @@ -286,9 +286,10 @@ void ClassHandler::ClassData::_add_dependent(ClassData& dependent) dependents.push_back(&dependent); } -ClassHandler::ClassMethod *ClassHandler::ClassData::register_method(const char *mname, cls_method_call_t func) +ClassHandler::ClassMethod *ClassHandler::ClassData::register_method(const char *mname, + cls_method_call_t func) { - /* no need for locking, called under the class_init mutex */ + /* no need for locking, called under the class_init mutex */ ClassMethod& method = methods_map[mname]; method.func = func; method.name = mname; @@ -297,6 +298,18 @@ ClassHandler::ClassMethod *ClassHandler::ClassData::register_method(const char * return &method; } +ClassHandler::ClassMethod *ClassHandler::ClassData::register_cxx_method(const char *mname, + cls_method_cxx_call_t func) +{ + /* no need for locking, called under the class_init mutex */ + ClassMethod& method = methods_map[mname]; + method.cxx_func = func; + method.name = mname; + method.cls = this; + + return &method; +} + ClassHandler::ClassMethod *ClassHandler::ClassData::get_method(const char *mname) { Mutex::Locker lock(*mutex); @@ -353,12 +366,20 @@ void ClassHandler::ClassMethod::unregister() int ClassHandler::ClassMethod::exec(cls_method_context_t ctx, bufferlist& indata, bufferlist& outdata) { - char *out = NULL; - int olen; int ret; - ret = func(ctx, indata.c_str(), indata.length(), &out, &olen); - if (out) - outdata.append(out, olen); - + if (cxx_func) { + // C++ call version + ret = cxx_func(ctx, &indata, &outdata); + } else { + // C version + char *out = NULL; + int olen = 0; + ret = func(ctx, indata.c_str(), indata.length(), &out, &olen); + if (out) { + // assume *out was allocated via cls_alloc (which calls malloc!) + buffer::ptr bp = buffer::claim_malloc(olen, out); + outdata.push_back(bp); + } + } return ret; } diff --git a/src/common/ClassHandler.h b/src/common/ClassHandler.h index 38d892612c533..a8fc0257fb3ad 100644 --- a/src/common/ClassHandler.h +++ b/src/common/ClassHandler.h @@ -26,9 +26,12 @@ public: struct ClassHandler::ClassData *cls; string name; cls_method_call_t func; - int exec(cls_method_context_t ctx, bufferlist& indata, bufferlist& outdata); + cls_method_cxx_call_t cxx_func; + int exec(cls_method_context_t ctx, bufferlist& indata, bufferlist& outdata); void unregister(); + + ClassMethod() : cls(0), func(0), cxx_func(0) {} }; struct ClassData { @@ -63,8 +66,8 @@ public: ClassData() : mutex(NULL), status(CLASS_UNKNOWN), version(), timeout(0), handle(NULL), registered(false) {} ~ClassData() { if (mutex) delete mutex; } - ClassMethod *register_method(const char *mname, - cls_method_call_t func); + ClassMethod *register_method(const char *mname, cls_method_call_t func); + ClassMethod *register_cxx_method(const char *mname, cls_method_cxx_call_t func); ClassMethod *get_method(const char *mname); void unregister_method(ClassMethod *method); diff --git a/src/objclass/class_api.cc b/src/objclass/class_api.cc index 2285fd3d09fc2..3f0e5ea75f8d1 100644 --- a/src/objclass/class_api.cc +++ b/src/objclass/class_api.cc @@ -57,12 +57,22 @@ int cls_register_method(cls_handle_t hclass, const char *method, cls_method_handle_t hmethod; cd = (ClassHandler::ClassData *)hclass; - hmethod = (cls_method_handle_t)cd->register_method(method, class_call); - if (handle) *handle = hmethod; + return (hmethod != NULL); +} + +int cls_register_cxx_method(cls_handle_t hclass, const char *method, + cls_method_cxx_call_t class_call, cls_method_handle_t *handle) +{ + ClassHandler::ClassData *cd; + cls_method_handle_t hmethod; + cd = (ClassHandler::ClassData *)hclass; + hmethod = (cls_method_handle_t)cd->register_cxx_method(method, class_call); + if (handle) + *handle = hmethod; return (hmethod != NULL); } @@ -97,6 +107,7 @@ int cls_rdcall(cls_method_handle_t hctx, const char *cls, const char *method, *outdata = odata.c_str(); *outdatalen = odata.length(); +#warning use after free! return r; } @@ -105,21 +116,57 @@ int cls_read(cls_method_handle_t hctx, int ofs, int len, char **outdata, int *outdatalen) { ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx; - bufferlist odata; - bufferlist idata; - vector nops(1); - ceph_osd_op& op = nops[0]; - int r; - - op.offset = ofs; - op.length = len; - op.op = CEPH_OSD_OP_READ; + vector ops(1); + ops[0].op = CEPH_OSD_OP_READ; + ops[0].offset = ofs; + ops[0].length = len; + bufferlist idata, odata; bufferlist::iterator iter = idata.begin(); - r = (*pctx)->pg->do_osd_ops(*pctx, nops, iter, odata); + int r = (*pctx)->pg->do_osd_ops(*pctx, ops, iter, odata); *outdata = odata.c_str(); *outdatalen = odata.length(); +#warning use after free! return r; } +int cls_cxx_read(cls_method_handle_t hctx, int ofs, int len, bufferlist *outbl) +{ + ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx; + vector ops(1); + ops[0].op = CEPH_OSD_OP_READ; + ops[0].offset = ofs; + ops[0].length = len; + bufferlist idata; + bufferlist::iterator iter = idata.begin(); + return (*pctx)->pg->do_osd_ops(*pctx, ops, iter, *outbl); +} + +int cls_cxx_write(cls_method_handle_t hctx, int ofs, int len, bufferlist *inbl) +{ + ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx; + vector ops(1); + ops[0].op = CEPH_OSD_OP_WRITE; + ops[0].offset = ofs; + ops[0].length = len; + bufferlist outbl; + bufferlist::iterator iter = inbl->begin(); + return (*pctx)->pg->do_osd_ops(*pctx, ops, iter, outbl); +} + +int cls_cxx_replace(cls_method_handle_t hctx, int ofs, int len, bufferlist *inbl) +{ + ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx; + vector ops(2); + ops[0].op = CEPH_OSD_OP_TRUNCATE; + ops[0].offset = 0; + ops[0].length = 0; + ops[1].op = CEPH_OSD_OP_WRITE; + ops[1].offset = ofs; + ops[1].length = len; + bufferlist outbl; + bufferlist::iterator iter = inbl->begin(); + return (*pctx)->pg->do_osd_ops(*pctx, ops, iter, outbl); +} + diff --git a/src/objclass/objclass.h b/src/objclass/objclass.h index 938cf17b87cae..20c6520368d1a 100644 --- a/src/objclass/objclass.h +++ b/src/objclass/objclass.h @@ -17,7 +17,6 @@ typedef void *cls_method_context_t; typedef int (*cls_method_call_t)(cls_method_context_t ctx, char *indata, int datalen, char **outdata, int *outdatalen); - typedef struct { const char *name; const char *ver; @@ -61,6 +60,18 @@ extern void class_fini(void); #ifdef __cplusplus } + +typedef int (*cls_method_cxx_call_t)(cls_method_context_t ctx, + class buffer::list *inbl, class buffer::list *outbl); + +extern int cls_register_cxx_method(cls_handle_t hclass, const char *method, + cls_method_cxx_call_t class_call, cls_method_handle_t *handle); + +extern int cls_cxx_read(cls_method_handle_t hctx, int ofs, int len, bufferlist *bl); +extern int cls_cxx_write(cls_method_handle_t hctx, int ofs, int len, bufferlist *bl); +extern int cls_cxx_replace(cls_method_handle_t hctx, int ofs, int len, bufferlist *bl); + + #endif #endif -- 2.39.5