ceph中radosgw的put object代码走读

业务处理入口:

RGWPutObj::execute()

....

op_ret = get_params();----获取相关参数

......

op_ret = get_system_versioning_params(s, &olh_epoch, &version_id);-----object的版本控制

 

后面进行MD5校验功能

分块上传的合法性检查

 

processor = select_processor(*static_cast(s->obj_ctx), &multipart);—获取对应的processer,其中非mutipart采用类RGWPutObjProcessor_Atomic,mutipart采用类RGWPutObjProcessor_Multipart

 

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(s->obj_ctx), &multipart);

 

      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& attrs, time_t delete_at,

                                              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& attrs, time_t delete_at,

                                           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;

 

 }

你可能感兴趣的:(ceph)