s3cmd put --multipart-chunk-size-mb=5 source/testfile s3://test-bucket/test
每生成一个 stripe 对象(StripeGenerator::create_begin、StripeGenerator::create_next),就会把这个 stripe 对象绑定到 RadosWriter 上,process 链的调用顺序是 HeadObjectProcessor::process
-> StripeProcessor::process
-> ChunkProcessor::process
-> RadosWriter::process
详细函数过程:
REST 请求的处理
process_request
init 用户,认证,权限,桶等参数
init 操作类型相关的初始化
检查权限
检查参数
返回头上加上操作的 bucket
execute
complete
返回 io 的完成状态
记录日志
RGWPutObj(向对象上传数据)
-
获取 request 中的版本
-
生成校验 md5 码
-
检查配额
-
为桶的 event_type 类型的 topic 预留用于 notification 的空间
-
获取 dest_placement(name、storage class)(get_multipart_info)
-
生成 processor
-
包装加密 processor
-
包装压缩 processor
-
处理每个文件
- 获取数据
- 计算 hash
- 更新 torrent
- 处理机处理
- 设置对象大小
- 检查 aws4 验证与配额
- 执行压缩
- 检查 md5 校验
- 设置 attr
- acl
- user manifest
- slo manifest
- etag
- 上传 request 中的 attr
- delete at
- tags
- 是否是 slo
- legal hold
- 生存时间 object retention
- 完成 processor
- 获取数据
-
生成 torrent
-
通知各 OSD 提交 (publish_commit)
AtomicObjectProcessor:
prepare
- manifest 中记录 tail_ofs、stripe_max_size
- 配置 bucket 与其 placement rule
- manifest::gen 创建一个文件头 manifest (create_begin)
- 绑定 0 号 obj 为当前 obj
- 设置前缀 .xxxx_
- 在前缀上加上 stripe 的位置
- 设置对象大小
- 设置object 的 key 在 tail_instance 上
- 设置begin end 位置为 0
- gen 生成一个 stripe_obj
- 打开相应 pool,set 这个 key(writer.set_stripe_obj(stripe_obj))
MultipartObjectProcessor
prepare
-
设置前缀 obj_key.upload_id
-
设置 stripe max size 与 part_num
-
manifest::gen 创建一个文件头 manifest (create_begin)
-
gen 生成一个 stripe_obj
-
stripe obj 转 obj
-
设置其与前一版本的链接 index_hash_source
-
打开相应 pool,set 这个 key(writer.set_stripe_obj(stripe_obj))
-
设置 obj 的大小(set_head_chunk_size)
complete
- flush 没写完的数据
- 获取实际写的大小,并更新统计到下一个 stripe 对象的位置
- 设置 obj 禁用 versioning
- 写元数据,把 prepare 时生成的 attrs 写进去 (_do_write_meta)
- 生成这个 part 的信息 info,并序列化
- 在 sys_obj 对象中存上 key 为 part.n,value 为序列化的 info 的映射
- 清除临时 stripe 对象
AppendObjectProcessor
prepare
-
检查对象是不是最后一个对象,只最后一个对象可追加
-
设置 part_num 加1
-
获取 etag
-
获取 storage class
-
获取前缀
-
设置 stripe 大小与 part_num
-
manifest::gen 创建一个文件头 manifest (create_begin)
-
gen 生成一个 stripe_obj
-
打开相应 pool,set 这个 key(writer.set_stripe_obj(stripe_obj))
-
设置 obj 的大小(set_head_chunk_size)
HeadObjectProcessor::process
-
加密、压缩处理等
-
处理第一个 part(process_first_chunk)
- atomic:无操作
- append:直接写数据
- multipart:直接写数据,如果对象存在了,就生成新对象名(只是改前缀中的随机项),再重写
-
StripeProcessor.process
- 每当一个 stripe 满了,就创建下一个 stripe (manifest_gen.create_next)
- cur_stripe ++
- 更新 obj 大小
- 新 obj 名称为 cur_part_id + _ + cur_stripe
- 更新 begin、end 的位置
- gen 生成一个 stripe_obj
- 打开相应 pool,set 这个 key(writer.set_stripe_obj(stripe_obj))
- 生成这个 writer 的新 ChunkProcessor
- 每当一个 stripe 满了,就创建下一个 stripe (manifest_gen.create_next)
-
ChunkProcessor.process
- 积攒数据,每攒到一个 chunk 大小,就调用 writer 去写
- 当没有数据时,当作是 flush 操作,也调用 writer 去写
-
RadosWriter.process
- 生成写操作
- 加入 pending 队列
- 将结果存在 written 中
write_exclusive
-
组装创建文件、写文件的操作 ObjectWriteOperation.create/write_full
-
等待可写,将动作加入 pending 队列,并执行异步 operate(aio->get)
-
耗尽 pending 写队列 aio->drain()
-
将写后返回的对象加入 written 中
multipart 上传
RGWInitMultipart::execute
- 获取请求中的参数
- reserve 空间用于 notification
- 生成upload_id 2~xxxx (2 指 v2 版本)
- 生成 write 的操作
- 将 upload_info (name和storage_class) 绑定到元数据中
- 执行写元数据
- 通知各节点提交
RGWCompleteMultipart::execute
删除原有的各part的object,并修改原 obj 的元数据。
最后删除原有的 .meta 文件