AtomicObjectProcessor prepare&写整体流程

为了便于说明,以代码默认的4M为例

  • prepare
// prepare主要完成对manifest的初始化处理。
AtomicObjectProcessor::prepare
// 获取数据池的名称:head_pool
// alignment : rados对齐方式, 假设64K对齐。max_head_chunk_size : head的最大长度,假设为4M
// 假设 head_max_size = chunk_size = max_head_chunk_size = 4M
// stripe_size = 4M
manifest.set_trivial_rule(head_max_size, stripe_size);
  // RGWObjManifestRule rule(0, 4M, 0, 4M); rules[0] = rule; max_head_size = 4M
manifest_gen.create_begin(store->ctx(), &manifest, bucket_info.placement_rule, &tail_placement_rule, head_obj.bucket, head_obj);
  // manifest 填入数据: placement_rule bucket head_placement_rule obj head_size=0 last_ofs=0 prefix cur_stripe_size=4M cur_part_id=0 
  manifest->get_implicit_location(0, 4M, 0, NULL, &cur_obj);

rgw_raw_obj stripe_obj = manifest_gen.get_cur_obj(store->getRados());
r = writer.set_stripe_obj(stripe_obj);    // RadosWriter writer;

chunk = ChunkProcessor(&writer, 4M);
stripe = StripeProcessor(&chunk, this, 4M);

// 此时manifest的处理如下
manifest.set_trivial_rule(head_max_size, stripe_size);
  RGWObjManifestRule rule(0, 4M, 0, 4M);  // start_part_num=0 start_ofs=4M part_size=0 stripe_max_size=4M
  rules[0] = rule;
  max_head_size = tail_ofs; // 4M

RGWObjManifest::generator::create_begin
  manifest->set_tail_placement  // tail_placement.placement_rule = placement_rule; tail_placement.bucket = _b;
  manifest->set_head(head_placement_rule, _obj, 0); // head_size = 0
  last_ofs = 0;
  生成随机的prefix
  此时head_size为0,cur_stripe_size = rule.stripe_max_size; // 4M
  cur_part_id = rule.start_part_num;  // 0
  RGWObjManifest::get_implicit_location(0, 0, 0, nullptr, &cur_obj)
    cur_obj->set_placement_rule(head_placement_rule);
    *cur_obj = obj;
  manifest->set_tail_instance(_obj.key.instance); // tail_instance
  manifest->update_iterators(); // begin_iter.seek(0); end_iter.seek(obj_size); 此时obj_size=0
  • 循环写对象到rados
fst = copy_source_range_fst;	// 如果是range则该值不为0,否则为0
lst = copy_source_range_lst	// 非copy或是range。非copy并且非range也要lst=0
lst = astate->accounted_size - 1;	// copy但不是range

boost::optional<RGWPutObj_Compress> compressor;	// 压缩,append不支持
std::unique_ptr<DataProcessor> encrypt;	// 加密,如果加密和压缩都需要的情况下,则加密优先。append不支持。
DataProcessor *filter = processor.get();  // 默认既不加密也不压缩
op_ret = get_encrypt_filter(&encrypt, filter);  // RGWPutObj_ObjStore_S3::get_encrypt_filter。filter作为pipe的成员变量
  // 分片上传
  res = get_obj_attrs(store, s, obj, xattrs); // 获取.meta的属性
  res = rgw_s3_prepare_decrypt(s, xattrs, &block_crypt, crypt_http_responses);
  filter->reset(new RGWPutObj_BlockEncrypt(s->cct, cb, std::move(block_crypt)));
  // 整体上传
  res = rgw_s3_prepare_encrypt(s, attrs, nullptr, &block_crypt, crypt_http_responses);
  filter->reset(new RGWPutObj_BlockEncrypt(s->cct, cb, std::move(block_crypt)));
if (encrypt != nullptr) {
  filter = &*encrypt;
} else if (compression_type != "none") {
  plugin = get_compressor_plugin(s, compression_type);
  compressor.emplace(s->cct, plugin, filter);
  filter = &*compressor;
}

// 以下流程不考虑加密和压缩
do {
  bufferlist data;
  if (fst > lst) break;
  
  // 非copy
  len = get_data(data);   // RGWPutObj_ObjStore_S3::get_data  , 从消息中读取数据
  
  // copy
  uint64_t cur_lst = min(fst + s->cct->_conf->rgw_max_chunk_size - 1, lst);  
  op_ret = get_data(fst, cur_lst, data);   // RGWPutObj::get_data , 从本rados读取数据
  len = data.length();
  s->content_length += len;
  fst += len;

  // len如果为0,说明读写完成

  if (need_calc_md5) {
    hash.Update((const unsigned char *)data.c_str(), data.length());
  }
  /* update torrrent */
  torrent.update(data);

  op_ret = filter->process(std::move(data), ofs);   // HeadObjectProcessor::process

  ofs += len;
} while (len > 0);

op_ret = filter->process({}, ofs);  // 把尾部数据写入rados(chunk里面还有的数据)

// 写完成,在complete中需要写first_chunk以及meta
op_ret = processor->complete(s->obj_size, etag, &mtime, real_time(), attrs,
    (delete_at ? *delete_at : real_time()), if_match, if_nomatch,
    (user_data.empty() ? nullptr : &user_data), nullptr, nullptr, s->yield);

ret = rgw::notify::publish(s, obj.key, s->obj_size, mtime, etag, rgw::notify::ObjectCreatedPut, store);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值