业务处理入口:
RGWPutObj::execute()
....
op_ret = get_params();----获取相关参数
......
op_ret = get_system_versioning_params(s, &olh_epoch, &version_id);-----object的版本控制
后面进行MD5校验功能
分块上传的合法性检查
processor = select_processor(*static_cast
op_ret = processor->prepare(store, NULL);-----读数据之前的准备,不同的类进入不同的相关处理。
下面开始循环读取数据到bufflist中,然后进行处理
do {
bufferlist data;----------------缓存每次读入的数据
len =get_data(data);-----------此处的函数调用可参见这个链接说明s3cmd 消息解析
if (len < 0) {
op_ret = len;
goto done;
}
if (!len)
break;
/* do we need this operation to be synchronous? if we're dealing with an object with immutable
* head, e.g., multipart object we need to make sure we're the first one writing to this object
*/
bool need_to_wait = (ofs == 0) && multipart;
bufferlist orig_data;
if (need_to_wait) {
orig_data = data;
}
op_ret = put_data_and_throttle(processor, data, ofs, (need_calc_md5 ? &hash : NULL), need_to_wait);---------处理数据
if (op_ret < 0) {-----------------------------------------------------------------如果失败,在重新write一次
if (!need_to_wait || op_ret != -EEXIST) {
ldout(s->cct, 20) << "processor->thottle_data() returned ret="
<< op_ret << dendl;
goto done;
}
ldout(s->cct, 5) << "NOTICE: processor->throttle_data() returned -EEXIST, need to restart write" << dendl;
/* restore original data */
data.swap(orig_data);
/* restart processing with different oid suffix */
dispose_processor(processor);
processor = select_processor(*static_cast
string oid_rand;
char buf[33];
gen_rand_alphanumeric(store->ctx(), buf, sizeof(buf) - 1);
oid_rand.append(buf);
op_ret = processor->prepare(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;
}
}
ofs += len;---------------------------累加ofs,记录数据总量
} while (len > 0);
下面是一些合法性的判断
比如鉴权
if (s->aws4_auth_needs_complete) {
/* complete aws4 auth */
op_ret = RGW_Auth_S3::authorize_aws4_auth_complete(store, s);
if (op_ret) {
goto done;
}
s->aws4_auth_needs_complete = false;
/* verify signature */
if (s->aws4_auth->signature != s->aws4_auth->new_signature) {
op_ret = -ERR_SIGNATURE_NO_MATCH;
ldout(s->cct, 20) << "delayed aws4 auth failed" << dendl;
goto done;
}
/* authorization ok */
dout(10) << "v4 auth ok" << dendl;
}
分块存储的合法性判断
op_ret = store->check_quota(s->bucket_owner.get_id(), s->bucket,user_quota, bucket_quota, s->obj_size);
if (op_ret < 0) {
ldout(s->cct, 20) << "second check_quota() returned op_ret=" << op_ret << dendl;
goto done;
}
MD5的一些处理
f (need_calc_md5) {
processor->complete_hash(&hash);
}
hash.Final(m);
buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, calc_md5);
etag = calc_md5;
if (supplied_md5_b64 && strcmp(calc_md5, supplied_md5)) {
op_ret = -ERR_BAD_DIGEST;
goto done;
}
将一些信息存入attribute,其中包括acl,sol info(这里我理解是一种特殊的object类型), etag(md5),一些通用的参数。
op_ret = processor->complete(etag, &mtime, 0, attrs, delete_at, if_match,if_nomatch);----这里是真正的写数据业务
这里分开描述;
对于不支持mutipart的情况,也就是整个文件在S3方面不分块传输,直接发过来整个文件,
上述的complete会进入如下函数int RGWPutObjProcessor_Atomic::do_complete。而对于支持mutipart的情况,上述的complete会进入函数
int RGWPutObjProcessor_Multipart::do_complete(string& etag, time_t *mtime, time_t set_mtime,
map
const char *if_match, const char *if_nomatch)
{
complete_writing_data();
......
}
RGWPutObjProcessor_Multipart类是RGWPutObjProcessor_Atomic的子类,那么两个函数的complete_writing_data()实际上都调用了如下函数:
int RGWPutObjProcessor_Atomic::do_complete(string& etag, time_t *mtime, time_t set_mtime,
map
const char *if_match,
const char *if_nomatch) {
int r = complete_writing_data();-----------------此处进行数据的写入,后面
if (r < 0)
return r;
obj_ctx.set_atomic(head_obj);-------attribute中保存了head_obj的相关信息
RGWRados::Object op_target(store, bucket_info, obj_ctx, head_obj);
/* some object types shouldn't be versioned, e.g., multipart parts */
op_target.set_versioning_disabled(!versioned_object);
RGWRados::Object::Write obj_op(&op_target);
obj_op.meta.data = &first_chunk;
obj_op.meta.manifest = &manifest;
obj_op.meta.ptag = &unique_tag; /* use req_id as operation tag */
obj_op.meta.if_match = if_match;
obj_op.meta.if_nomatch = if_nomatch;
obj_op.meta.mtime = mtime;
obj_op.meta.set_mtime = set_mtime;
obj_op.meta.owner = bucket_info.owner;
obj_op.meta.flags = PUT_OBJ_CREATE;
obj_op.meta.olh_epoch = olh_epoch;
obj_op.meta.delete_at = delete_at;
r = obj_op.write_meta(obj_len, attrs);----------------此处进行attribute参数的写入
if (r < 0) {
return r;
}
canceled = obj_op.meta.canceled;
return 0;
}