RGW中OP请求处理函数的入口都是process_request,process_request会根据传入的RGWRados参数获取RGWOp,然后当请求合法性通过后去调用rgw_process_authenticated函数执行OP的具体动作。
请求的处理
Collapse source
int
process_request(RGWRados*
const
store,
RGWREST*
const
rest,
RGWRequest*
const
req,
const
std::string& frontend_prefix,
const
rgw_auth_registry_t& auth_registry,
RGWRestfulIO*
const
client_io,
OpsLogSocket*
const
olog)
{
...
RGWOp* op = NULL;
int
init_error = 0;
bool
should_log =
false
;
RGWRESTMgr *mgr;
RGWHandler_REST *handler = rest->get_handler(store, s,
auth_registry,
frontend_prefix,
client_io, &mgr, &init_error);
...
op = handler->get_op(store);
//解析出具体的OP
...
ret = rgw_process_authenticated(handler, op, req, s);
//验证OP
if
(ret < 0) {
abort_early(s, op, ret, handler);
goto
done;
}
|
rgw_process_authenticated函数内部执行OP具体动作时候,分为三个阶段pre_exec,execute和complete
OP执行
Collapse source
int
rgw_process_authenticated(RGWHandler_REST *
const
handler,
RGWOp *& op,
RGWRequest *
const
req,
req_state *
const
s,
const
bool
skip_retarget)
{
...
req->
log
(s,
"init op"
);
ret = op->init_processing();
if
(ret < 0) {
return
ret;
}
req->
log
(s,
"verifying op mask"
);
ret = op->verify_op_mask();
if
(ret < 0) {
return
ret;
}
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
if
(s->auth.identity->is_admin_of(s->user->user_id)) {
dout(2) <<
"overriding permissions due to admin operation"
<< dendl;
}
else
{
return
ret;
}
}
req->
log
(s,
"verifying op params"
);
ret = op->verify_params();
if
(ret < 0) {
return
ret;
}
req->
log
(s,
"pre-executing"
);
op->pre_exec();
req->
log
(s,
"executing"
);
op->execute();
req->
log
(s,
"completing"
);
op->complete();
...
}
|
所有的RGW 操作都是继承于基类RGWOp,然后具体的OP重写自己的的execute方法。
对象上传分为整体上传和分段上传。对于选择整体上传和分段上传的选择在于用户单次操作上传文件大小,若大于5GB对象就需要使用分段上传API,否则使用整体上传的API。这个就是用来兼容S3标准(对象操作)
对于整体上传就会对应到RGWPutObjProcessor_Atomic处理类,分段上传会对应RGWPutObjProcessor_Multipart处理类。这两个类会对上传的对象做加密操作,压缩,数据处理等。是整个上传对象操作的核心处理类。关于对上传对象压缩处理见ceph 官方文档介绍。
对于对象文件上传OP的类为RGWPutObj,其定义的execute函数为整个文件上传的入口,整个函数调用及嵌套关系如下所示:
RGWPutObj::execute
- RGWPutObj_Compress::prepare
- RGWPutObjProcessor_Atomic::prepare
- put_data_and_throttle
- RGWPutObj_Compress::handle_data
- RGWPutObjProcessor_Atomic::handle_data
- RGWPutObjProcessor_Atomic::write_data
- RGWPutObjProcessor_Aio::handle_obj_data
- RGWRados::aio_put_obj_data
- librados aio API
- RGWRados::aio_put_obj_data
- RGWPutObjProcessor_Aio::handle_obj_data
- RGWPutObjProcessor_Atomic::write_data
- RGWPutObjProcessor_Atomic::handle_data
- RGWPutObjProcessor_Aio::throttle_data
- RGWPutObj_Compress::handle_data
- RGWPutObjProcessor::complete
- RGWPutObjProcessor_Atomic::complete
- RGWPutObjProcessor_Atomic::complete
RGWPutObj::execute
Collapse source
void
RGWPutObj::execute()
{
RGWPutObjProcessor *processor = NULL;
// filter用于对数据进行处理,比如加密和压缩
RGWPutObjDataProcessor *filter = nullptr;
std::unique_ptr<RGWPutObjDataProcessor> encrypt;
// 用于存储用户提供的md5、计算的md5 相关的数组
char
supplied_md5_bin[CEPH_CRYPTO_MD5_DIGESTSIZE + 1];
char
supplied_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
char
calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
unsigned
char
m[CEPH_CRYPTO_MD5_DIGESTSIZE];
MD5 hash;
bufferlist bl, aclbl, bs;
int
len;
map<string, string>::iterator iter;
bool
multipart;
// copy source range 相关
off_t fst;
off_t lst;
// 根据zone配置选择object的压缩类型,可为none或具体的压缩插件名字
const
auto& compression_type = store->get_zone_params().get_compression_type(
s->bucket_info.placement_rule);
CompressorRef plugin;
boost::optional<RGWPutObj_Compress> compressor;
bool
need_calc_md5 = (dlo_manifest == NULL) && (slo_info == NULL);
perfcounter->inc(l_rgw_put);
op_ret = -EINVAL;
//---------------------------------------------------------
// 解析并检查请求参数是否完整、正确
//---------------------------------------------------------
// 判断用户请求object name、bucket name等是否正确
if
(s->object.empty()) {
goto
done;
}
if
(!s->bucket_exists) {
op_ret = -ERR_NO_SUCH_BUCKET;
return
;
}
// 解析并判断http请求的相关参数,包括copy obj的情况、包含tagging的情况、包含version的情况,以及基本的objname和bucketname解析
op_ret = get_params();
if
(op_ret < 0) {
ldout(s->cct, 20) <<
"get_params() returned ret="
<< op_ret << dendl;
goto
done;
}
op_ret = get_system_versioning_params(s, &olh_epoch, &version_id);
//版本号
if
(op_ret < 0) {
ldout(s->cct, 20) <<
"get_system_versioning_params() returned ret="
<< op_ret << dendl;
goto
done;
|