From: Matt Benjamin Date: Mon, 25 Jan 2016 21:14:50 +0000 (-0500) Subject: librgw: header and namespace reorganization X-Git-Tag: v10.1.0~382^2~82 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=baffb146bf3516b83f08214403d56914b670339d;p=ceph.git librgw: header and namespace reorganization Move RGWLibProcess and RGWLibFrontend into new rgw_lib_frontend.h header, which can include rgw_lib.h and rgw_file.h. This allows the already-defined RGWLibProcess to call methods on RGWLibFS objects (e.g., to perform GC, which follows in a separate commit). In addition, move all of the library and file interface into namespace rgw. Signed-off-by: Matt Benjamin --- diff --git a/src/rgw/librgw.cc b/src/rgw/librgw.cc index 40cf4562a115..afddea4f2ba1 100644 --- a/src/rgw/librgw.cc +++ b/src/rgw/librgw.cc @@ -43,6 +43,7 @@ #include "rgw_os_lib.h" #include "rgw_auth_s3.h" #include "rgw_lib.h" +#include "rgw_lib_frontend.h" #include #include @@ -52,510 +53,517 @@ #define dout_subsys ceph_subsys_rgw -using std::string; +bool global_stop = false; -static std::mutex librgw_mtx; +namespace rgw { -bool global_stop = false; + using std::string; -RGWLib librgw; /* XXX initialize? */ + static std::mutex librgw_mtx; -class C_InitTimeout : public Context { -public: - C_InitTimeout() {} - void finish(int r) { - derr << "Initialization timeout, failed to initialize" << dendl; - exit(1); - } -}; + RGWLib librgw; /* XXX initialize? */ -void RGWLibProcess::checkpoint() -{ + class C_InitTimeout : public Context { + public: + C_InitTimeout() {} + void finish(int r) { + derr << "Initialization timeout, failed to initialize" << dendl; + exit(1); + } + }; + + void RGWLibProcess::checkpoint() + { m_tp.drain(&req_wq); -} + } -void RGWLibProcess::run() -{ - /* XXX */ -} + void RGWLibProcess::run() + { + /* XXX */ + } -void RGWLibProcess::handle_request(RGWRequest* r) -{ - /* - * invariant: valid requests are derived from RGWLibRequst - */ - RGWLibRequest* req = static_cast(r); + void RGWLibProcess::handle_request(RGWRequest* r) + { + /* + * invariant: valid requests are derived from RGWLibRequst + */ + RGWLibRequest* req = static_cast(r); - // XXX move RGWLibIO and timing setup into process_request + // XXX move RGWLibIO and timing setup into process_request #if 0 /* XXX */ - utime_t tm = ceph_clock_now(NULL); + utime_t tm = ceph_clock_now(NULL); #endif - RGWLibIO io_ctx; + RGWLibIO io_ctx; - int ret = process_request(req, &io_ctx); - if (ret < 0) { - /* we don't really care about return code */ - dout(20) << "process_request() returned " << ret << dendl; + int ret = process_request(req, &io_ctx); + if (ret < 0) { + /* we don't really care about return code */ + dout(20) << "process_request() returned " << ret << dendl; - } - delete req; -} /* handle_request */ + } + delete req; + } /* handle_request */ -int RGWLibProcess::process_request(RGWLibRequest* req) -{ - // XXX move RGWLibIO and timing setup into process_request + int RGWLibProcess::process_request(RGWLibRequest* req) + { + // XXX move RGWLibIO and timing setup into process_request #if 0 /* XXX */ - utime_t tm = ceph_clock_now(NULL); + utime_t tm = ceph_clock_now(NULL); #endif - RGWLibIO io_ctx; - - int ret = process_request(req, &io_ctx); - if (ret < 0) { - /* we don't really care about return code */ - dout(20) << "process_request() returned " << ret << dendl; - } - return ret; -} /* process_request */ - -static inline void abort_req(struct req_state *s, RGWOp *op, int err_no) -{ - if (!s) - return; - - /* XXX the dump_errno and dump_bucket_from_state behaviors in - * the abort_early (rgw_rest.cc) might be valuable, but aren't - * safe to call presently as they return HTTP data */ + RGWLibIO io_ctx; - perfcounter->inc(l_rgw_failed_req); -} /* abort_req */ + int ret = process_request(req, &io_ctx); + if (ret < 0) { + /* we don't really care about return code */ + dout(20) << "process_request() returned " << ret << dendl; + } + return ret; + } /* process_request */ + + static inline void abort_req(struct req_state *s, RGWOp *op, int err_no) + { + if (!s) + return; + + /* XXX the dump_errno and dump_bucket_from_state behaviors in + * the abort_early (rgw_rest.cc) might be valuable, but aren't + * safe to call presently as they return HTTP data */ + + perfcounter->inc(l_rgw_failed_req); + } /* abort_req */ + + int RGWLibProcess::process_request(RGWLibRequest* req, RGWLibIO* io) + { + int ret = 0; + bool should_log = true; // XXX + + dout(1) << "====== " << __func__ + << " starting new request req=" << hex << req << dec + << " ======" << dendl; + + /* + * invariant: valid requests are derived from RGWOp--well-formed + * requests should have assigned RGWRequest::op in their descendant + * constructor--if not, the compiler can find it, at the cost of + * a runtime check + */ + RGWOp *op = (req->op) ? req->op : dynamic_cast(req); + if (! op) { + dout(1) << "failed to derive cognate RGWOp (invalid op?)" << dendl; + return -EINVAL; + } -int RGWLibProcess::process_request(RGWLibRequest* req, RGWLibIO* io) -{ - int ret = 0; - bool should_log = true; // XXX - - dout(1) << "====== " << __func__ - << " starting new request req=" << hex << req << dec - << " ======" << dendl; - - /* - * invariant: valid requests are derived from RGWOp--well-formed - * requests should have assigned RGWRequest::op in their descendant - * constructor--if not, the compiler can find it, at the cost of - * a runtime check - */ - RGWOp *op = (req->op) ? req->op : dynamic_cast(req); - if (! op) { - dout(1) << "failed to derive cognate RGWOp (invalid op?)" << dendl; - return -EINVAL; - } + io->init(req->cct); - io->init(req->cct); + perfcounter->inc(l_rgw_req); - perfcounter->inc(l_rgw_req); + RGWEnv& rgw_env = io->get_env(); - RGWEnv& rgw_env = io->get_env(); + /* XXX + * until major refactoring of req_state and req_info, we need + * to build their RGWEnv boilerplate from the RGWLibRequest, + * pre-staging any strings (HTTP_HOST) that provoke a crash when + * not found + */ - /* XXX - * until major refactoring of req_state and req_info, we need - * to build their RGWEnv boilerplate from the RGWLibRequest, - * pre-staging any strings (HTTP_HOST) that provoke a crash when - * not found - */ + /* XXX for now, use ""; could be a legit hostname, or, in future, + * perhaps a tenant (Yehuda) */ + rgw_env.set("HTTP_HOST", ""); - /* XXX for now, use ""; could be a legit hostname, or, in future, - * perhaps a tenant (Yehuda) */ - rgw_env.set("HTTP_HOST", ""); + /* XXX and -then- bloat up req_state with string copies from it */ + struct req_state rstate(req->cct, &rgw_env, req->get_user()); + struct req_state *s = &rstate; - /* XXX and -then- bloat up req_state with string copies from it */ - struct req_state rstate(req->cct, &rgw_env, req->get_user()); - struct req_state *s = &rstate; + // XXX fix this + s->cio = io; - // XXX fix this - s->cio = io; + RGWObjectCtx rados_ctx(store, s); // XXX holds std::map - RGWObjectCtx rados_ctx(store, s); // XXX holds std::map + /* XXX and -then- stash req_state pointers everywhere they are needed */ + ret = req->init(rgw_env, &rados_ctx, io, s); + if (ret < 0) { + dout(10) << "failed to initialize request" << dendl; + abort_req(s, op, ret); + goto done; + } - /* XXX and -then- stash req_state pointers everywhere they are needed */ - ret = req->init(rgw_env, &rados_ctx, io, s); - if (ret < 0) { - dout(10) << "failed to initialize request" << dendl; - abort_req(s, op, ret); - goto done; - } + /* req is-a RGWOp, currently initialized separately */ + ret = req->op_init(); + if (ret < 0) { + dout(10) << "failed to initialize RGWOp" << dendl; + abort_req(s, op, ret); + goto done; + } - /* req is-a RGWOp, currently initialized separately */ - ret = req->op_init(); - if (ret < 0) { - dout(10) << "failed to initialize RGWOp" << dendl; - abort_req(s, op, ret); - goto done; - } + /* XXX authorize does less here then in the REST path, e.g., + * the user's info is cached, but still incomplete */ + req->log(s, "authorizing"); + ret = req->authorize(); + if (ret < 0) { + dout(10) << "failed to authorize request" << dendl; + abort_req(s, op, ret); + goto done; + } - /* XXX authorize does less here then in the REST path, e.g., - * the user's info is cached, but still incomplete */ - req->log(s, "authorizing"); - ret = req->authorize(); - if (ret < 0) { - dout(10) << "failed to authorize request" << dendl; - abort_req(s, op, ret); - goto done; - } + req->log(s, "reading op permissions"); + ret = req->read_permissions(op); + if (ret < 0) { + abort_req(s, op, ret); + goto done; + } - req->log(s, "reading op permissions"); - ret = req->read_permissions(op); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + req->log(s, "init op"); + ret = op->init_processing(); + if (ret < 0) { + abort_req(s, op, ret); + goto done; + } - req->log(s, "init op"); - ret = op->init_processing(); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + req->log(s, "verifying op mask"); + ret = op->verify_op_mask(); + if (ret < 0) { + abort_req(s, op, ret); + goto done; + } - req->log(s, "verifying op mask"); - ret = op->verify_op_mask(); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + req->log(s, "verifying op permissions"); + ret = op->verify_permission(); + if (ret < 0) { + if (s->system_request) { + dout(2) << "overriding permissions due to system operation" << dendl; + } else { + abort_req(s, op, ret); + goto done; + } + } - req->log(s, "verifying op permissions"); - ret = op->verify_permission(); - if (ret < 0) { - if (s->system_request) { - dout(2) << "overriding permissions due to system operation" << dendl; - } else { + req->log(s, "verifying op params"); + ret = op->verify_params(); + if (ret < 0) { abort_req(s, op, ret); goto done; } - } - req->log(s, "verifying op params"); - ret = op->verify_params(); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } - - req->log(s, "executing"); - op->pre_exec(); - op->execute(); - op->complete(); + req->log(s, "executing"); + op->pre_exec(); + op->execute(); + op->complete(); -done: - int r = io->complete_request(); - if (r < 0) { - dout(0) << "ERROR: io->complete_request() returned " << r << dendl; - } - if (should_log) { - rgw_log_op(store, s, (op ? op->name() : "unknown"), olog); - } + done: + int r = io->complete_request(); + if (r < 0) { + dout(0) << "ERROR: io->complete_request() returned " << r << dendl; + } + if (should_log) { + rgw_log_op(store, s, (op ? op->name() : "unknown"), olog); + } - int http_ret = s->err.http_ret; + int http_ret = s->err.http_ret; - req->log_format(s, "http status=%d", http_ret); + req->log_format(s, "http status=%d", http_ret); - dout(1) << "====== " << __func__ - << " req done req=" << hex << req << dec << " http_status=" - << http_ret - << " ======" << dendl; + dout(1) << "====== " << __func__ + << " req done req=" << hex << req << dec << " http_status=" + << http_ret + << " ======" << dendl; - return (ret < 0 ? ret : s->err.ret); -} /* process_request */ + return (ret < 0 ? ret : s->err.ret); + } /* process_request */ -int RGWLibProcess::start_request(RGWLibContinuedReq* req) -{ + int RGWLibProcess::start_request(RGWLibContinuedReq* req) + { - dout(1) << "====== " << __func__ - << " starting new continued request req=" << hex << req << dec - << " ======" << dendl; - - /* - * invariant: valid requests are derived from RGWOp--well-formed - * requests should have assigned RGWRequest::op in their descendant - * constructor--if not, the compiler can find it, at the cost of - * a runtime check - */ - RGWOp *op = (req->op) ? req->op : dynamic_cast(req); - if (! op) { - dout(1) << "failed to derive cognate RGWOp (invalid op?)" << dendl; - return -EINVAL; - } + dout(1) << "====== " << __func__ + << " starting new continued request req=" << hex << req << dec + << " ======" << dendl; - struct req_state* s = req->get_state(); + /* + * invariant: valid requests are derived from RGWOp--well-formed + * requests should have assigned RGWRequest::op in their descendant + * constructor--if not, the compiler can find it, at the cost of + * a runtime check + */ + RGWOp *op = (req->op) ? req->op : dynamic_cast(req); + if (! op) { + dout(1) << "failed to derive cognate RGWOp (invalid op?)" << dendl; + return -EINVAL; + } - /* req is-a RGWOp, currently initialized separately */ - int ret = req->op_init(); - if (ret < 0) { - dout(10) << "failed to initialize RGWOp" << dendl; - abort_req(s, op, ret); - goto done; - } + struct req_state* s = req->get_state(); - /* XXX authorize does less here then in the REST path, e.g., - * the user's info is cached, but still incomplete */ - req->log(s, "authorizing"); - ret = req->authorize(); - if (ret < 0) { - dout(10) << "failed to authorize request" << dendl; - abort_req(s, op, ret); - goto done; - } + /* req is-a RGWOp, currently initialized separately */ + int ret = req->op_init(); + if (ret < 0) { + dout(10) << "failed to initialize RGWOp" << dendl; + abort_req(s, op, ret); + goto done; + } - req->log(s, "reading op permissions"); - ret = req->read_permissions(op); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + /* XXX authorize does less here then in the REST path, e.g., + * the user's info is cached, but still incomplete */ + req->log(s, "authorizing"); + ret = req->authorize(); + if (ret < 0) { + dout(10) << "failed to authorize request" << dendl; + abort_req(s, op, ret); + goto done; + } - req->log(s, "init op"); - ret = op->init_processing(); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + req->log(s, "reading op permissions"); + ret = req->read_permissions(op); + if (ret < 0) { + abort_req(s, op, ret); + goto done; + } - req->log(s, "verifying op mask"); - ret = op->verify_op_mask(); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + req->log(s, "init op"); + ret = op->init_processing(); + if (ret < 0) { + abort_req(s, op, ret); + goto done; + } - req->log(s, "verifying op permissions"); - ret = op->verify_permission(); - if (ret < 0) { - if (s->system_request) { - dout(2) << "overriding permissions due to system operation" << dendl; - } else { + req->log(s, "verifying op mask"); + ret = op->verify_op_mask(); + if (ret < 0) { abort_req(s, op, ret); goto done; } - } - req->log(s, "verifying op params"); - ret = op->verify_params(); - if (ret < 0) { - abort_req(s, op, ret); - goto done; - } + req->log(s, "verifying op permissions"); + ret = op->verify_permission(); + if (ret < 0) { + if (s->system_request) { + dout(2) << "overriding permissions due to system operation" << dendl; + } else { + abort_req(s, op, ret); + goto done; + } + } - op->pre_exec(); - req->exec_start(); + req->log(s, "verifying op params"); + ret = op->verify_params(); + if (ret < 0) { + abort_req(s, op, ret); + goto done; + } -done: - return (ret < 0 ? ret : s->err.ret); -} + op->pre_exec(); + req->exec_start(); -int RGWLibProcess::finish_request(RGWLibContinuedReq* req) -{ - RGWOp *op = (req->op) ? req->op : dynamic_cast(req); - if (! op) { - dout(1) << "failed to derive cognate RGWOp (invalid op?)" << dendl; - return -EINVAL; + done: + return (ret < 0 ? ret : s->err.ret); } - int ret = req->exec_finish(); - int op_ret = op->get_ret(); - - dout(1) << "====== " << __func__ - << " finishing continued request req=" << hex << req << dec - << " op status=" << op_ret - << " ======" << dendl; - - return ret; -} - -int RGWLibFrontend::init() -{ - pprocess = new RGWLibProcess(g_ceph_context, &env, - g_conf->rgw_thread_pool_size, conf); - return 0; -} - -int RGWLib::init() -{ - vector args; - return init(args); -} + int RGWLibProcess::finish_request(RGWLibContinuedReq* req) + { + RGWOp *op = (req->op) ? req->op : dynamic_cast(req); + if (! op) { + dout(1) << "failed to derive cognate RGWOp (invalid op?)" << dendl; + return -EINVAL; + } -int RGWLib::init(vector& args) -{ - int r = 0; + int ret = req->exec_finish(); + int op_ret = op->get_ret(); - /* alternative default for module */ - vector def_args; - def_args.push_back("--debug-rgw=1/5"); - def_args.push_back("--keyring=$rgw_data/keyring"); - def_args.push_back("--log-file=/var/log/radosgw/$cluster-$name.log"); + dout(1) << "====== " << __func__ + << " finishing continued request req=" << hex << req << dec + << " op status=" << op_ret + << " ======" << dendl; - global_init(&def_args, args, - CEPH_ENTITY_TYPE_CLIENT, - CODE_ENVIRONMENT_DAEMON, - CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS); + return ret; + } - Mutex mutex("main"); - SafeTimer init_timer(g_ceph_context, mutex); - init_timer.init(); - mutex.Lock(); - init_timer.add_event_after(g_conf->rgw_init_timeout, new C_InitTimeout); - mutex.Unlock(); + int RGWLibFrontend::init() + { + pprocess = new RGWLibProcess(g_ceph_context, &env, + g_conf->rgw_thread_pool_size, conf); + return 0; + } - common_init_finish(g_ceph_context); + int RGWLib::init() + { + vector args; + return init(args); + } - rgw_tools_init(g_ceph_context); + int RGWLib::init(vector& args) + { + int r = 0; - rgw_init_resolver(); + /* alternative default for module */ + vector def_args; + def_args.push_back("--debug-rgw=1/5"); + def_args.push_back("--keyring=$rgw_data/keyring"); + def_args.push_back("--log-file=/var/log/radosgw/$cluster-$name.log"); - store = RGWStoreManager::get_storage(g_ceph_context, - g_conf->rgw_enable_gc_threads, g_conf->rgw_enable_quota_threads); + global_init(&def_args, args, + CEPH_ENTITY_TYPE_CLIENT, + CODE_ENVIRONMENT_DAEMON, + CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS); - if (!store) { + Mutex mutex("main"); + SafeTimer init_timer(g_ceph_context, mutex); + init_timer.init(); mutex.Lock(); - init_timer.cancel_all_events(); - init_timer.shutdown(); + init_timer.add_event_after(g_conf->rgw_init_timeout, new C_InitTimeout); mutex.Unlock(); - derr << "Couldn't init storage provider (RADOS)" << dendl; - return EIO; - } + common_init_finish(g_ceph_context); - r = rgw_perf_start(g_ceph_context); + rgw_tools_init(g_ceph_context); - rgw_rest_init(g_ceph_context, store->region); + rgw_init_resolver(); - mutex.Lock(); - init_timer.cancel_all_events(); - init_timer.shutdown(); - mutex.Unlock(); + store = RGWStoreManager::get_storage(g_ceph_context, + g_conf->rgw_enable_gc_threads, g_conf->rgw_enable_quota_threads); - if (r) - return 1; + if (!store) { + mutex.Lock(); + init_timer.cancel_all_events(); + init_timer.shutdown(); + mutex.Unlock(); - rgw_user_init(store); - rgw_bucket_init(store->meta_mgr); - rgw_log_usage_init(g_ceph_context, store); + derr << "Couldn't init storage provider (RADOS)" << dendl; + return EIO; + } - // XXX ex-RGWRESTMgr_lib, mgr->set_logging(true) + r = rgw_perf_start(g_ceph_context); - if (!g_conf->rgw_ops_log_socket_path.empty()) { - olog = new OpsLogSocket(g_ceph_context, g_conf->rgw_ops_log_data_backlog); - olog->init(g_conf->rgw_ops_log_socket_path); - } + rgw_rest_init(g_ceph_context, store->region); - int port = 80; - RGWProcessEnv env = { store, &rest, olog, port }; + mutex.Lock(); + init_timer.cancel_all_events(); + init_timer.shutdown(); + mutex.Unlock(); - fec = new RGWFrontendConfig("librgw"); - fe = new RGWLibFrontend(env, fec); + if (r) + return 1; - fe->init(); - if (r < 0) { - derr << "ERROR: failed initializing frontend" << dendl; - return -r; - } + rgw_user_init(store); + rgw_bucket_init(store->meta_mgr); + rgw_log_usage_init(g_ceph_context, store); - fe->run(); + // XXX ex-RGWRESTMgr_lib, mgr->set_logging(true) - return 0; -} /* RGWLib::init() */ + if (!g_conf->rgw_ops_log_socket_path.empty()) { + olog = new OpsLogSocket(g_ceph_context, g_conf->rgw_ops_log_data_backlog); + olog->init(g_conf->rgw_ops_log_socket_path); + } -int RGWLib::stop() -{ - derr << "shutting down" << dendl; + int port = 80; + RGWProcessEnv env = { store, &rest, olog, port }; - fe->stop(); + fec = new RGWFrontendConfig("librgw"); + fe = new RGWLibFrontend(env, fec); - fe->join(); + fe->init(); + if (r < 0) { + derr << "ERROR: failed initializing frontend" << dendl; + return -r; + } - delete fe; + fe->run(); - rgw_log_usage_finalize(); + return 0; + } /* RGWLib::init() */ - delete olog; + int RGWLib::stop() + { + derr << "shutting down" << dendl; - RGWStoreManager::close_storage(store); + fe->stop(); - rgw_tools_cleanup(); - rgw_shutdown_resolver(); + fe->join(); - rgw_perf_stop(g_ceph_context); + delete fe; - dout(1) << "final shutdown" << dendl; - g_ceph_context->put(); + rgw_log_usage_finalize(); - ceph::crypto::shutdown(); + delete olog; - return 0; -} /* RGWLib::stop() */ + RGWStoreManager::close_storage(store); -int RGWLibIO::set_uid(RGWRados *store, const rgw_user& uid) -{ - int ret = rgw_get_user_info_by_uid(store, uid, user_info, NULL); - if (ret < 0) { - derr << "ERROR: failed reading user info: uid=" << uid << " ret=" - << ret << dendl; - } - return ret; -} + rgw_tools_cleanup(); + rgw_shutdown_resolver(); -int RGWLibRequest::read_permissions(RGWOp *op) { - int ret = - rgw_build_bucket_policies(librgw.get_store(), get_state()); - if (ret < 0) { - ldout(get_state()->cct, 10) << "read_permissions on " - << get_state()->bucket << ":" - << get_state()->object - << " only_bucket=" << only_bucket() - << " ret=" << ret << dendl; - if (ret == -ENODATA) - ret = -EACCES; - } + rgw_perf_stop(g_ceph_context); - return ret; -} /* RGWLibRequest::read_permissions */ + dout(1) << "final shutdown" << dendl; + g_ceph_context->put(); -int RGWHandler_Lib::authorize() -{ - /* TODO: handle - * 1. subusers - * 2. anonymous access - * 3. system access - * 4. ? - * - * Much or all of this depends on handling the cached authorization - * correctly (e.g., dealing with keystone) at mount time. - */ - s->perm_mask = RGW_PERM_FULL_CONTROL; - - // populate the owner info - s->owner.set_id(s->user->user_id); - s->owner.set_name(s->user->display_name); + ceph::crypto::shutdown(); - return 0; -} /* RGWHandler_Lib::authorize */ + return 0; + } /* RGWLib::stop() */ + + int RGWLibIO::set_uid(RGWRados *store, const rgw_user& uid) + { + int ret = rgw_get_user_info_by_uid(store, uid, user_info, NULL); + if (ret < 0) { + derr << "ERROR: failed reading user info: uid=" << uid << " ret=" + << ret << dendl; + } + return ret; + } + + int RGWLibRequest::read_permissions(RGWOp* op) { + int ret = + rgw_build_bucket_policies(librgw.get_store(), get_state()); + if (ret < 0) { + ldout(get_state()->cct, 10) << "read_permissions on " + << get_state()->bucket << ":" + << get_state()->object + << " only_bucket=" << only_bucket() + << " ret=" << ret << dendl; + if (ret == -ENODATA) + ret = -EACCES; + } + return ret; + } /* RGWLibRequest::read_permissions */ + + int RGWHandler_Lib::authorize() + { + /* TODO: handle + * 1. subusers + * 2. anonymous access + * 3. system access + * 4. ? + * + * Much or all of this depends on handling the cached authorization + * correctly (e.g., dealing with keystone) at mount time. + */ + s->perm_mask = RGW_PERM_FULL_CONTROL; + + // populate the owner info + s->owner.set_id(s->user->user_id); + s->owner.set_name(s->user->display_name); + + return 0; + } /* RGWHandler_Lib::authorize */ /* global RGW library object */ -static RGWLib rgwlib; + static RGWLib rgwlib; + +} /* namespace rgw */ extern "C" { int librgw_init() { + using namespace rgw; + return rgwlib.init(); } int librgw_create(librgw_t* rgw, int argc, char **argv) { + using namespace rgw; + if (! g_ceph_context) { std::lock_guard lg(librgw_mtx); if (! g_ceph_context) { @@ -658,6 +666,8 @@ void librgw_free_bin(librgw_t rgw, char* bin) void librgw_shutdown(librgw_t rgw) { + using namespace rgw; + CephContext* cct = static_cast(rgw); #if 0 rgwlib.stop(); diff --git a/src/rgw/rgw_file.cc b/src/rgw/rgw_file.cc index 5e12d6095497..92419dc8aba9 100644 --- a/src/rgw/rgw_file.cc +++ b/src/rgw/rgw_file.cc @@ -24,346 +24,351 @@ #include "rgw_bucket.h" #include "rgw_file.h" +#include "rgw_lib_frontend.h" #define dout_subsys ceph_subsys_rgw using namespace rgw; -extern RGWLib librgw; +namespace rgw { -const string RGWFileHandle::root_name = "/"; + extern RGWLib librgw; -atomic RGWLibFS::fs_inst; + const string RGWFileHandle::root_name = "/"; -LookupFHResult RGWLibFS::stat_bucket(RGWFileHandle* parent, - const char *path, uint32_t flags) -{ - LookupFHResult fhr{nullptr, 0}; - std::string bucket_name{path}; - RGWStatBucketRequest req(cct, get_user(), bucket_name); + atomic RGWLibFS::fs_inst; - int rc = librgw.get_fe()->execute_req(&req); - if ((rc == 0) && - (req.get_ret() == 0) && - (req.matched())) { - fhr = lookup_fh(parent, path, - RGWFileHandle::FLAG_CREATE| - RGWFileHandle::FLAG_BUCKET); - } - return fhr; -} + LookupFHResult RGWLibFS::stat_bucket(RGWFileHandle* parent, + const char *path, uint32_t flags) + { + LookupFHResult fhr{nullptr, 0}; + std::string bucket_name{path}; + RGWStatBucketRequest req(cct, get_user(), bucket_name); -LookupFHResult RGWLibFS::stat_leaf(RGWFileHandle* parent, - const char *path, - uint32_t flags) -{ - /* find either-of , , only one of - * which should exist; atomicity? */ - LookupFHResult fhr{nullptr, 0}; - std::string object_name{path}; - - for (auto ix : { 0, 1 }) { - switch (ix) { - case 0: - { - RGWStatObjRequest req(cct, get_user(), - parent->bucket_name(), object_name, - RGWStatObjRequest::FLAG_NONE); - int rc = librgw.get_fe()->execute_req(&req); - if ((rc == 0) && - (req.get_ret() == 0)) { - fhr = lookup_fh(parent, path, RGWFileHandle::FLAG_NONE); - goto done; - } + int rc = librgw.get_fe()->execute_req(&req); + if ((rc == 0) && + (req.get_ret() == 0) && + (req.matched())) { + fhr = lookup_fh(parent, path, + RGWFileHandle::FLAG_CREATE| + RGWFileHandle::FLAG_BUCKET); } - break; - case 1: - { - RGWStatLeafRequest req(cct, get_user(), parent, object_name); - int rc = librgw.get_fe()->execute_req(&req); - if ((rc == 0) && - (req.get_ret() == 0)) { - if (req.matched) { - fhr = lookup_fh(parent, path, - RGWFileHandle::FLAG_CREATE| - ((req.is_dir) ? - RGWFileHandle::FLAG_DIRECTORY : - RGWFileHandle::FLAG_NONE)); + return fhr; + } + + LookupFHResult RGWLibFS::stat_leaf(RGWFileHandle* parent, + const char *path, + uint32_t flags) + { + /* find either-of , , only one of + * which should exist; atomicity? */ + LookupFHResult fhr{nullptr, 0}; + std::string object_name{path}; + + for (auto ix : { 0, 1 }) { + switch (ix) { + case 0: + { + RGWStatObjRequest req(cct, get_user(), + parent->bucket_name(), object_name, + RGWStatObjRequest::FLAG_NONE); + int rc = librgw.get_fe()->execute_req(&req); + if ((rc == 0) && + (req.get_ret() == 0)) { + fhr = lookup_fh(parent, path, RGWFileHandle::FLAG_NONE); + goto done; + } + } + break; + case 1: + { + RGWStatLeafRequest req(cct, get_user(), parent, object_name); + int rc = librgw.get_fe()->execute_req(&req); + if ((rc == 0) && + (req.get_ret() == 0)) { + if (req.matched) { + fhr = lookup_fh(parent, path, + RGWFileHandle::FLAG_CREATE| + ((req.is_dir) ? + RGWFileHandle::FLAG_DIRECTORY : + RGWFileHandle::FLAG_NONE)); + } } } - } - break; - default: - /* not reached */ break; + default: + /* not reached */ + break; + } + } + done: + return fhr; + } /* RGWLibFS::stat_leaf */ + + bool RGWFileHandle::reclaim() { + fs->fh_cache.remove(fh.fh_hk.object, this, cohort::lru::FLAG_NONE); + return true; + } /* RGWFileHandle::reclaim */ + + int RGWFileHandle::write(uint64_t off, size_t len, size_t *bytes_written, + void *buffer) + { + using std::get; + lock_guard guard(mtx); + + int rc = 0; + buffer::list bl; + bl.push_back( + buffer::create_static(len, static_cast(buffer))); + + file* f = get(&variant_type); + if (! f) + return -EISDIR; + + if (! f->write_req) { + /* start */ + std::string object_name = full_object_name(); + f->write_req = + new RGWWriteRequest(fs->get_context(), fs->get_user(), this, + bucket_name(), object_name); + rc = librgw.get_fe()->start_req(f->write_req); } - } -done: - return fhr; -} /* RGWLibFS::stat_leaf */ - -bool RGWFileHandle::reclaim() { - fs->fh_cache.remove(fh.fh_hk.object, this, cohort::lru::FLAG_NONE); - return true; -} /* RGWFileHandle::reclaim */ - -int RGWFileHandle::write(uint64_t off, size_t len, size_t *bytes_written, - void *buffer) -{ - using std::get; - lock_guard guard(mtx); - - int rc = 0; - buffer::list bl; - bl.push_back( - buffer::create_static(len, static_cast(buffer))); - file* f = get(&variant_type); - if (! f) - return -EISDIR; + f->write_req->put_data(off, bl); + rc = f->write_req->exec_continue(); - if (! f->write_req) { - /* start */ - std::string object_name = full_object_name(); - f->write_req = - new RGWWriteRequest(fs->get_context(), fs->get_user(), this, - bucket_name(), object_name); - rc = librgw.get_fe()->start_req(f->write_req); - } + size_t min_size = off + len; + if (min_size > get_size()) + set_size(min_size); - f->write_req->put_data(off, bl); - rc = f->write_req->exec_continue(); + *bytes_written = (rc == 0) ? len : 0; + return rc; + } /* RGWFileHandle::write */ - size_t min_size = off + len; - if (min_size > get_size()) - set_size(min_size); + int RGWFileHandle::close() + { + lock_guard guard(mtx); - *bytes_written = (rc == 0) ? len : 0; - return rc; -} /* RGWFileHandle::write */ + int rc = 0; + file* f = get(&variant_type); + if (f && (f->write_req)) { + rc = librgw.get_fe()->finish_req(f->write_req); + if (! rc) { + rc = f->write_req->get_ret(); + } + delete f->write_req; + f->write_req = nullptr; + } -int RGWFileHandle::close() -{ - lock_guard guard(mtx); + flags &= ~FLAG_OPEN; + return rc; + } /* RGWFileHandle::close */ - int rc = 0; - file* f = get(&variant_type); - if (f && (f->write_req)) { - rc = librgw.get_fe()->finish_req(f->write_req); - if (! rc) { - rc = f->write_req->get_ret(); - } - delete f->write_req; - f->write_req = nullptr; + RGWFileHandle::file::~file() + { + delete write_req; } - flags &= ~FLAG_OPEN; - return rc; -} /* RGWFileHandle::close */ - -RGWFileHandle::file::~file() -{ - delete write_req; -} + int RGWWriteRequest::exec_start() { + struct req_state* s = get_state(); -int RGWWriteRequest::exec_start() { - struct req_state* s = get_state(); + // XXX check this + need_calc_md5 = (dlo_manifest == NULL) && (slo_info == NULL); - // XXX check this - need_calc_md5 = (dlo_manifest == NULL) && (slo_info == NULL); + perfcounter->inc(l_rgw_put); + op_ret = -EINVAL; - perfcounter->inc(l_rgw_put); - op_ret = -EINVAL; + // XXX check this + if (s->object.empty()) { + goto done; + } - // XXX check this - if (s->object.empty()) { - goto done; - } + op_ret = get_params(); + if (op_ret < 0) + goto done; - op_ret = get_params(); - if (op_ret < 0) - goto done; + op_ret = get_system_versioning_params(s, &olh_epoch, &version_id); + if (op_ret < 0) { + goto done; + } - op_ret = get_system_versioning_params(s, &olh_epoch, &version_id); - if (op_ret < 0) { - goto done; - } + /* user-supplied MD5 check skipped (not supplied) */ + /* early quota check skipped--we don't have size yet */ + /* skipping user-supplied etag--we might have one in future, but + * like data it and other attrs would arrive after open */ + processor = select_processor(*static_cast(s->obj_ctx), + &multipart); + op_ret = processor->prepare(get_store(), NULL); - /* user-supplied MD5 check skipped (not supplied) */ - /* early quota check skipped--we don't have size yet */ - /* skipping user-supplied etag--we might have one in future, but - * like data it and other attrs would arrive after open */ - processor = select_processor(*static_cast(s->obj_ctx), - &multipart); - op_ret = processor->prepare(get_store(), NULL); + done: + return op_ret; + } /* exec_start */ -done: - return op_ret; -} /* exec_start */ - -int RGWWriteRequest::exec_continue() -{ - struct req_state* s = get_state(); - op_ret = 0; + int RGWWriteRequest::exec_continue() + { + struct req_state* s = get_state(); + op_ret = 0; #if 0 // TODO: check offsets - if (next_off != last_off) - return -EIO; + if (next_off != last_off) + return -EIO; #endif - size_t len = data.length(); - if (! len) - return 0; - - /* XXX won't see multipart */ - bool need_to_wait = (ofs == 0) && multipart; - bufferlist orig_data; + size_t len = data.length(); + if (! len) + return 0; - if (need_to_wait) { - orig_data = data; - } + /* XXX won't see multipart */ + bool need_to_wait = (ofs == 0) && multipart; + bufferlist orig_data; - op_ret = put_data_and_throttle(processor, data, ofs, - (need_calc_md5 ? &hash : NULL), need_to_wait); - if (op_ret < 0) { - if (!need_to_wait || op_ret != -EEXIST) { - ldout(s->cct, 20) << "processor->thottle_data() returned ret=" - << op_ret << dendl; - goto done; + if (need_to_wait) { + orig_data = data; } - ldout(s->cct, 5) << "NOTICE: processor->throttle_data() returned -EEXIST, need to restart write" << dendl; + op_ret = put_data_and_throttle(processor, data, ofs, + (need_calc_md5 ? &hash : NULL), need_to_wait); + if (op_ret < 0) { + if (!need_to_wait || op_ret != -EEXIST) { + ldout(s->cct, 20) << "processor->thottle_data() returned ret=" + << op_ret << dendl; + goto done; + } - /* restore original data */ - data.swap(orig_data); + ldout(s->cct, 5) << "NOTICE: processor->throttle_data() returned -EEXIST, need to restart write" << dendl; - /* restart processing with different oid suffix */ - dispose_processor(processor); - processor = select_processor(*static_cast(s->obj_ctx), - &multipart); + /* restore original data */ + data.swap(orig_data); - string oid_rand; - char buf[33]; - gen_rand_alphanumeric(get_store()->ctx(), buf, sizeof(buf) - 1); - oid_rand.append(buf); + /* restart processing with different oid suffix */ + dispose_processor(processor); + processor = select_processor(*static_cast(s->obj_ctx), + &multipart); - op_ret = processor->prepare(get_store(), &oid_rand); - if (op_ret < 0) { - ldout(s->cct, 0) << "ERROR: processor->prepare() returned " - << op_ret << dendl; - goto done; - } + string oid_rand; + char buf[33]; + gen_rand_alphanumeric(get_store()->ctx(), buf, sizeof(buf) - 1); + oid_rand.append(buf); - op_ret = put_data_and_throttle(processor, data, ofs, NULL, false); + op_ret = processor->prepare(get_store(), &oid_rand); + if (op_ret < 0) { + ldout(s->cct, 0) << "ERROR: processor->prepare() returned " + << op_ret << dendl; + goto done; + } + + op_ret = put_data_and_throttle(processor, data, ofs, NULL, false); + if (op_ret < 0) { + goto done; + } + } + bytes_written += len; + + done: + return op_ret; + } /* exec_continue */ + + int RGWWriteRequest::exec_finish() + { + bufferlist bl, aclbl; + map attrs; + map::iterator iter; + char calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1]; + unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE]; + struct req_state* s = get_state(); + + s->obj_size = ofs; // XXX check ofs + perfcounter->inc(l_rgw_put_b, s->obj_size); + + op_ret = get_store()->check_quota(s->bucket_owner.get_id(), s->bucket, + user_quota, bucket_quota, s->obj_size); if (op_ret < 0) { goto done; } - } - bytes_written += len; - -done: - return op_ret; -} /* exec_continue */ - -int RGWWriteRequest::exec_finish() -{ - bufferlist bl, aclbl; - map attrs; - map::iterator iter; - char calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1]; - unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE]; - struct req_state* s = get_state(); - - s->obj_size = ofs; // XXX check ofs - perfcounter->inc(l_rgw_put_b, s->obj_size); - - op_ret = get_store()->check_quota(s->bucket_owner.get_id(), s->bucket, - user_quota, bucket_quota, s->obj_size); - if (op_ret < 0) { - goto done; - } - if (need_calc_md5) { - processor->complete_hash(&hash); - } - hash.Final(m); + if (need_calc_md5) { + processor->complete_hash(&hash); + } + hash.Final(m); - buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, calc_md5); - etag = calc_md5; + buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, calc_md5); + etag = calc_md5; #if 0 /* XXX only in PostObj currently */ - if (supplied_md5_b64 && strcmp(calc_md5, supplied_md5)) { - op_ret = -ERR_BAD_DIGEST; - goto done; - } + if (supplied_md5_b64 && strcmp(calc_md5, supplied_md5)) { + op_ret = -ERR_BAD_DIGEST; + goto done; + } #endif - policy.encode(aclbl); + policy.encode(aclbl); - attrs[RGW_ATTR_ACL] = aclbl; + attrs[RGW_ATTR_ACL] = aclbl; - /* XXX most of the following cases won't currently arise */ - if (unlikely(!! dlo_manifest)) { - op_ret = encode_dlo_manifest_attr(dlo_manifest, attrs); - if (op_ret < 0) { - ldout(s->cct, 0) << "bad user manifest: " << dlo_manifest << dendl; - goto done; + /* XXX most of the following cases won't currently arise */ + if (unlikely(!! dlo_manifest)) { + op_ret = encode_dlo_manifest_attr(dlo_manifest, attrs); + if (op_ret < 0) { + ldout(s->cct, 0) << "bad user manifest: " << dlo_manifest << dendl; + goto done; + } + complete_etag(hash, &etag); + ldout(s->cct, 10) << __func__ << ": calculated md5 for user manifest: " + << etag << dendl; } - complete_etag(hash, &etag); - ldout(s->cct, 10) << __func__ << ": calculated md5 for user manifest: " - << etag << dendl; - } - if (unlikely(!! slo_info)) { - bufferlist manifest_bl; - ::encode(*slo_info, manifest_bl); - attrs[RGW_ATTR_SLO_MANIFEST] = manifest_bl; + if (unlikely(!! slo_info)) { + bufferlist manifest_bl; + ::encode(*slo_info, manifest_bl); + attrs[RGW_ATTR_SLO_MANIFEST] = manifest_bl; - hash.Update((byte *)slo_info->raw_data, slo_info->raw_data_len); - complete_etag(hash, &etag); - ldout(s->cct, 10) << __func__ << ": calculated md5 for user manifest: " - << etag << dendl; - } + hash.Update((byte *)slo_info->raw_data, slo_info->raw_data_len); + complete_etag(hash, &etag); + ldout(s->cct, 10) << __func__ << ": calculated md5 for user manifest: " + << etag << dendl; + } - if (supplied_etag && etag.compare(supplied_etag) != 0) { - op_ret = -ERR_UNPROCESSABLE_ENTITY; - goto done; - } - bl.append(etag.c_str(), etag.size() + 1); - attrs[RGW_ATTR_ETAG] = bl; - - for (iter = s->generic_attrs.begin(); iter != s->generic_attrs.end(); - ++iter) { - bufferlist& attrbl = attrs[iter->first]; - const string& val = iter->second; - attrbl.append(val.c_str(), val.size() + 1); - } + if (supplied_etag && etag.compare(supplied_etag) != 0) { + op_ret = -ERR_UNPROCESSABLE_ENTITY; + goto done; + } + bl.append(etag.c_str(), etag.size() + 1); + attrs[RGW_ATTR_ETAG] = bl; + + for (iter = s->generic_attrs.begin(); iter != s->generic_attrs.end(); + ++iter) { + bufferlist& attrbl = attrs[iter->first]; + const string& val = iter->second; + attrbl.append(val.c_str(), val.size() + 1); + } - rgw_get_request_metadata(s->cct, s->info, attrs); - encode_delete_at_attr(delete_at, attrs); + rgw_get_request_metadata(s->cct, s->info, attrs); + encode_delete_at_attr(delete_at, attrs); - /* Add a custom metadata to expose the information whether an object - * is an SLO or not. Appending the attribute must be performed AFTER - * processing any input from user in order to prohibit overwriting. */ - if (unlikely(!! slo_info)) { - bufferlist slo_userindicator_bl; - ::encode("True", slo_userindicator_bl); - attrs[RGW_ATTR_SLO_UINDICATOR] = slo_userindicator_bl; - } + /* Add a custom metadata to expose the information whether an object + * is an SLO or not. Appending the attribute must be performed AFTER + * processing any input from user in order to prohibit overwriting. */ + if (unlikely(!! slo_info)) { + bufferlist slo_userindicator_bl; + ::encode("True", slo_userindicator_bl); + attrs[RGW_ATTR_SLO_UINDICATOR] = slo_userindicator_bl; + } - op_ret = processor->complete(etag, &mtime, 0, attrs, delete_at, if_match, - if_nomatch); - if (! op_ret) { - /* update stats */ - rgw_fh->set_mtime({mtime, 0}); - rgw_fh->set_size(bytes_written); - } + op_ret = processor->complete(etag, &mtime, 0, attrs, delete_at, if_match, + if_nomatch); + if (! op_ret) { + /* update stats */ + rgw_fh->set_mtime({mtime, 0}); + rgw_fh->set_size(bytes_written); + } -done: - dispose_processor(processor); - perfcounter->tinc(l_rgw_put_lat, - (ceph_clock_now(s->cct) - s->time)); - return op_ret; -} /* exec_finish */ + done: + dispose_processor(processor); + perfcounter->tinc(l_rgw_put_lat, + (ceph_clock_now(s->cct) - s->time)); + return op_ret; + } /* exec_finish */ + +} /* namespace rgw */ /* librgw */ extern "C" { diff --git a/src/rgw/rgw_lib.h b/src/rgw/rgw_lib.h index ad87b17fb89c..4b704dc0ef8b 100644 --- a/src/rgw/rgw_lib.h +++ b/src/rgw/rgw_lib.h @@ -12,235 +12,184 @@ #include "rgw_process.h" #include "rgw_rest_s3.h" // RGW_Auth_S3 - -class RGWLibFrontendConfig; -class RGWLibFrontend; class OpsLogSocket; -class RGWLib { - RGWFrontendConfig* fec; - RGWLibFrontend* fe; - OpsLogSocket* olog; - RGWREST rest; // XXX needed for RGWProcessEnv - RGWProcessEnv env; - RGWRados* store; - -public: - RGWLib() {} - ~RGWLib() {} +namespace rgw { - RGWRados* get_store() { return store; } + class RGWLibFrontendConfig; + class RGWLibFrontend; - RGWLibFrontend* get_fe() { return fe; } + class RGWLib { + RGWFrontendConfig* fec; + RGWLibFrontend* fe; + OpsLogSocket* olog; + RGWREST rest; // XXX needed for RGWProcessEnv + RGWProcessEnv env; + RGWRados* store; - int init(); - int init(vector& args); - int stop(); -}; + public: + RGWLib() {} + ~RGWLib() {} -extern RGWLib librgw; + RGWRados* get_store() { return store; } -/* request interface */ + RGWLibFrontend* get_fe() { return fe; } -class RGWLibIO : public RGWClientIO -{ - RGWUserInfo user_info; -public: - RGWLibIO() { - get_env().set("HTTP_HOST", ""); - } - RGWLibIO(const RGWUserInfo &_user_info) - : user_info(_user_info) {} - - virtual void init_env(CephContext *cct) {} - - const RGWUserInfo& get_user() { - return user_info; - } - - int set_uid(RGWRados* store, const rgw_user& uid); - - int write_data(const char *buf, int len); - int read_data(char *buf, int len); - int send_status(int status, const char *status_name); - int send_100_continue(); - int complete_header(); - int send_content_length(uint64_t len); - - int complete_request() { /* XXX */ - return 0; + int init(); + int init(vector& args); + int stop(); }; -}; /* RGWLibIO */ - -/* XXX */ -class RGWRESTMgr_Lib : public RGWRESTMgr { -public: - RGWRESTMgr_Lib() {} - virtual ~RGWRESTMgr_Lib() {} -}; /* RGWRESTMgr_Lib */ + extern RGWLib librgw; -/* XXX */ -class RGWHandler_Lib : public RGWHandler { - friend class RGWRESTMgr_Lib; -public: - - virtual int authorize(); - - RGWHandler_Lib() {} - virtual ~RGWHandler_Lib() {} - static int init_from_header(struct req_state *s); -}; /* RGWHandler_Lib */ +/* request interface */ -class RGWLibRequest : public RGWRequest, - public RGWHandler_Lib { -public: - CephContext* cct; - RGWUserInfo* user; + class RGWLibIO : public RGWClientIO + { + RGWUserInfo user_info; + public: + RGWLibIO() { + get_env().set("HTTP_HOST", ""); + } + RGWLibIO(const RGWUserInfo &_user_info) + : user_info(_user_info) {} - /* unambiguiously return req_state */ - inline struct req_state* get_state() { return this->RGWRequest::s; } + virtual void init_env(CephContext *cct) {} - RGWLibRequest(CephContext* _cct, RGWUserInfo* _user) - : RGWRequest(0), cct(_cct), user(_user) - {} + const RGWUserInfo& get_user() { + return user_info; + } - RGWUserInfo* get_user() { return user; } + int set_uid(RGWRados* store, const rgw_user& uid); - /* descendant equivalent of *REST*::init_from_header(...): - * prepare request for execute()--should mean, fixup URI-alikes - * and any other expected stat vars in local req_state, for - * now */ - virtual int header_init() = 0; + int write_data(const char *buf, int len); + int read_data(char *buf, int len); + int send_status(int status, const char *status_name); + int send_100_continue(); + int complete_header(); + int send_content_length(uint64_t len); - /* descendant initializer responsible to call RGWOp::init()--which - * descendants are required to inherit */ - virtual int op_init() = 0; + int complete_request() { /* XXX */ + return 0; + }; - int init(const RGWEnv& rgw_env, RGWObjectCtx* rados_ctx, - RGWLibIO* io, struct req_state* _s) { + }; /* RGWLibIO */ - RGWRequest::init_state(_s); - RGWHandler::init(rados_ctx->store, _s, io); +/* XXX */ + class RGWRESTMgr_Lib : public RGWRESTMgr { + public: + RGWRESTMgr_Lib() {} + virtual ~RGWRESTMgr_Lib() {} + }; /* RGWRESTMgr_Lib */ - /* fixup _s->req */ - _s->req = this; +/* XXX */ + class RGWHandler_Lib : public RGWHandler { + friend class RGWRESTMgr_Lib; + public: - log_init(); + virtual int authorize(); - get_state()->obj_ctx = rados_ctx; - get_state()->req_id = store->unique_id(id); - get_state()->trans_id = store->unique_trans_id(id); + RGWHandler_Lib() {} + virtual ~RGWHandler_Lib() {} + static int init_from_header(struct req_state *s); + }; /* RGWHandler_Lib */ - log_format(_s, "initializing for trans_id = %s", - get_state()->trans_id.c_str()); + class RGWLibRequest : public RGWRequest, + public RGWHandler_Lib { + public: + CephContext* cct; + RGWUserInfo* user; - int ret = header_init(); - if (ret == 0) { - ret = init_from_header(_s); - } - return ret; - } + /* unambiguiously return req_state */ + inline struct req_state* get_state() { return this->RGWRequest::s; } - virtual bool only_bucket() = 0; + RGWLibRequest(CephContext* _cct, RGWUserInfo* _user) + : RGWRequest(0), cct(_cct), user(_user) + {} - virtual int read_permissions(RGWOp *op); + RGWUserInfo* get_user() { return user; } virtual int postauth_init() { return 0; } -}; /* RGWLibRequest */ + /* descendant equivalent of *REST*::init_from_header(...): + * prepare request for execute()--should mean, fixup URI-alikes + * and any other expected stat vars in local req_state, for + * now */ + virtual int header_init() = 0; -class RGWLibContinuedReq : public RGWLibRequest { - RGWLibIO io_ctx; - struct req_state rstate; - RGWObjectCtx rados_ctx; -public: + /* descendant initializer responsible to call RGWOp::init()--which + * descendants are required to inherit */ + virtual int op_init() = 0; -RGWLibContinuedReq(CephContext* _cct, RGWUserInfo* _user) - : RGWLibRequest(_cct, _user), io_ctx(), - rstate(_cct, &io_ctx.get_env(), _user), rados_ctx(librgw.get_store(), - &rstate) - { - io_ctx.init(_cct); + int init(const RGWEnv& rgw_env, RGWObjectCtx* rados_ctx, + RGWLibIO* io, struct req_state* _s) { - RGWRequest::init_state(&rstate); - RGWHandler::init(rados_ctx.store, &rstate, &io_ctx); + RGWRequest::init_state(_s); + RGWHandler::init(rados_ctx->store, _s, io); /* fixup _s->req */ - get_state()->req = this; + _s->req = this; log_init(); - get_state()->obj_ctx = &rados_ctx; + get_state()->obj_ctx = rados_ctx; get_state()->req_id = store->unique_id(id); get_state()->trans_id = store->unique_trans_id(id); - log_format(get_state(), "initializing for trans_id = %s", + log_format(_s, "initializing for trans_id = %s", get_state()->trans_id.c_str()); - } - - inline RGWRados* get_store() { return store; } - virtual int execute() final { abort(); } - virtual int exec_start() = 0; - virtual int exec_continue() = 0; - virtual int exec_finish() = 0; - -}; /* RGWLibContinuedReq */ + int ret = header_init(); + if (ret == 0) { + ret = init_from_header(_s); + } + return ret; + } -class RGWLibProcess : public RGWProcess { - RGWAccessKey access_key; -public: - RGWLibProcess(CephContext* cct, RGWProcessEnv* pe, int num_threads, - RGWFrontendConfig* _conf) : - RGWProcess(cct, pe, num_threads, _conf) {} + virtual bool only_bucket() = 0; - void run(); - void checkpoint(); + virtual int read_permissions(RGWOp *op); - void enqueue_req(RGWLibRequest* req) { + }; /* RGWLibRequest */ - lsubdout(g_ceph_context, rgw, 10) - << __func__ << " enqueue request req=" << hex << req << dec << dendl; + class RGWLibContinuedReq : public RGWLibRequest { + RGWLibIO io_ctx; + struct req_state rstate; + RGWObjectCtx rados_ctx; + public: - req_throttle.get(1); - req_wq.queue(req); - } /* enqueue_req */ + RGWLibContinuedReq(CephContext* _cct, RGWUserInfo* _user) + : RGWLibRequest(_cct, _user), io_ctx(), + rstate(_cct, &io_ctx.get_env(), _user), rados_ctx(librgw.get_store(), + &rstate) + { + io_ctx.init(_cct); - /* "regular" requests */ - void handle_request(RGWRequest* req); // async handler, deletes req - int process_request(RGWLibRequest* req); - int process_request(RGWLibRequest* req, RGWLibIO* io); - void set_access_key(RGWAccessKey& key) { access_key = key; } + RGWRequest::init_state(&rstate); + RGWHandler::init(rados_ctx.store, &rstate, &io_ctx); - /* requests w/continue semantics */ - int start_request(RGWLibContinuedReq* req); - int finish_request(RGWLibContinuedReq* req); -}; /* RGWLibProcess */ + /* fixup _s->req */ + get_state()->req = this; -class RGWLibFrontend : public RGWProcessFrontend { -public: - RGWLibFrontend(RGWProcessEnv& pe, RGWFrontendConfig *_conf) - : RGWProcessFrontend(pe, _conf) {} + log_init(); - int init(); + get_state()->obj_ctx = &rados_ctx; + get_state()->req_id = store->unique_id(id); + get_state()->trans_id = store->unique_trans_id(id); - inline void enqueue_req(RGWLibRequest* req) { - static_cast(pprocess)->enqueue_req(req); // async - } + log_format(get_state(), "initializing for trans_id = %s", + get_state()->trans_id.c_str()); + } - inline int execute_req(RGWLibRequest* req) { - return static_cast(pprocess)->process_request(req); // !async - } + inline RGWRados* get_store() { return store; } - inline int start_req(RGWLibContinuedReq* req) { - return static_cast(pprocess)->start_request(req); - } + virtual int execute() final { abort(); } + virtual int exec_start() = 0; + virtual int exec_continue() = 0; + virtual int exec_finish() = 0; - inline int finish_req(RGWLibContinuedReq* req) { - return static_cast(pprocess)->finish_request(req); - } + }; /* RGWLibContinuedReq */ -}; /* RGWLibFrontend */ +} /* namespace rgw */ #endif /* RGW_LIB_H */ diff --git a/src/rgw/rgw_lib_frontend.h b/src/rgw/rgw_lib_frontend.h new file mode 100644 index 000000000000..51d4f6221183 --- /dev/null +++ b/src/rgw/rgw_lib_frontend.h @@ -0,0 +1,72 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef RGW_LIB_FRONTEND_H +#define RGW_LIB_FRONTEND_H + +#include + +#include "rgw_lib.h" +#include "rgw_file.h" + +namespace rgw { + + class RGWLibProcess : public RGWProcess { + RGWAccessKey access_key; + public: + RGWLibProcess(CephContext* cct, RGWProcessEnv* pe, int num_threads, + RGWFrontendConfig* _conf) : + RGWProcess(cct, pe, num_threads, _conf) {} + + void run(); + void checkpoint(); + + void enqueue_req(RGWLibRequest* req) { + + lsubdout(g_ceph_context, rgw, 10) + << __func__ << " enqueue request req=" + << hex << req << dec << dendl; + + req_throttle.get(1); + req_wq.queue(req); + } /* enqueue_req */ + + /* "regular" requests */ + void handle_request(RGWRequest* req); // async handler, deletes req + int process_request(RGWLibRequest* req); + int process_request(RGWLibRequest* req, RGWLibIO* io); + void set_access_key(RGWAccessKey& key) { access_key = key; } + + /* requests w/continue semantics */ + int start_request(RGWLibContinuedReq* req); + int finish_request(RGWLibContinuedReq* req); + }; /* RGWLibProcess */ + + class RGWLibFrontend : public RGWProcessFrontend { + public: + RGWLibFrontend(RGWProcessEnv& pe, RGWFrontendConfig *_conf) + : RGWProcessFrontend(pe, _conf) {} + + int init(); + + inline void enqueue_req(RGWLibRequest* req) { + static_cast(pprocess)->enqueue_req(req); // async + } + + inline int execute_req(RGWLibRequest* req) { + return static_cast(pprocess)->process_request(req); // !async + } + + inline int start_req(RGWLibContinuedReq* req) { + return static_cast(pprocess)->start_request(req); + } + + inline int finish_req(RGWLibContinuedReq* req) { + return static_cast(pprocess)->finish_request(req); + } + + }; /* RGWLibFrontend */ + +} /* namespace rgw */ + +#endif /* RGW_LIB_FRONTEND_H */ diff --git a/src/rgw/rgw_os_lib.cc b/src/rgw/rgw_os_lib.cc index f34a7cdb41a6..e43bf418a37b 100644 --- a/src/rgw/rgw_os_lib.cc +++ b/src/rgw/rgw_os_lib.cc @@ -6,53 +6,57 @@ #include "rgw_rest_user.h" #include "rgw_os_lib.h" #include "rgw_file.h" +#include "rgw_lib_frontend.h" +namespace rgw { /* static */ -int RGWHandler_Lib::init_from_header(struct req_state *s) -{ - string req; - string first; - - const char *req_name = s->relative_uri.c_str(); - const char *p; - - /* skip request_params parsing, rgw_file should not be - * seeing any */ - if (*req_name == '?') { - p = req_name; - } else { - p = s->info.request_params.c_str(); - } - - s->info.args.set(p); - s->info.args.parse(); - - if (*req_name != '/') - return 0; + int RGWHandler_Lib::init_from_header(struct req_state *s) + { + string req; + string first; + + const char *req_name = s->relative_uri.c_str(); + const char *p; + + /* skip request_params parsing, rgw_file should not be + * seeing any */ + if (*req_name == '?') { + p = req_name; + } else { + p = s->info.request_params.c_str(); + } - req_name++; + s->info.args.set(p); + s->info.args.parse(); - if (!*req_name) - return 0; + if (*req_name != '/') + return 0; + + req_name++; - req = req_name; - int pos = req.find('/'); - if (pos >= 0) { - first = req.substr(0, pos); - } else { - first = req; - } + if (!*req_name) + return 0; - if (s->bucket_name.empty()) { - s->bucket_name = std::move(first); + req = req_name; + int pos = req.find('/'); if (pos >= 0) { - // XXX ugh, another copy - string encoded_obj_str = req.substr(pos+1); - s->object = rgw_obj_key(encoded_obj_str, s->info.args.get("versionId")); + first = req.substr(0, pos); + } else { + first = req; } - } else { - s->object = rgw_obj_key(req_name, s->info.args.get("versionId")); - } - return 0; -} /* init_from_header */ + + if (s->bucket_name.empty()) { + s->bucket_name = std::move(first); + if (pos >= 0) { + // XXX ugh, another copy + string encoded_obj_str = req.substr(pos+1); + s->object = rgw_obj_key(encoded_obj_str, s->info.args.get("versionId")); + } + } else { + s->object = rgw_obj_key(req_name, s->info.args.get("versionId")); + } + return 0; + } /* init_from_header */ + +} /* namespace rgw */