@@ -2471,7 +2471,108 @@ bool RadosObject::is_sync_completed(const DoutPrefixProvider* dpp,
24712471
24722472 const rgw_bi_log_entry& earliest_marker = entries.front ();
24732473 return earliest_marker.timestamp > obj_mtime;
2474- }
2474+ } /* is_sync_completed */
2475+
2476+ int RadosObject::list_parts (const DoutPrefixProvider* dpp, CephContext* cct,
2477+ int max_parts, int marker, int * next_marker,
2478+ bool * truncated, list_parts_each_t each_func,
2479+ optional_yield y)
2480+ {
2481+ int ret{0 };
2482+
2483+ /* require an object with a manifest, so call to get_obj_state() must precede this */
2484+ if (! manifest) {
2485+ return -EINVAL;
2486+ }
2487+
2488+ RGWObjManifest::obj_iterator end = manifest->obj_end (dpp);
2489+ if (end.get_cur_part_id () == 0 ) { // not multipart
2490+ ldpp_dout (dpp, 20 ) << __func__ << " object does not have a multipart manifest"
2491+ << dendl;
2492+ return 0 ;
2493+ }
2494+
2495+ auto end_part_id = end.get_cur_part_id ();
2496+ auto parts_count = (end_part_id == 1 ) ? 1 : end_part_id - 1 ;
2497+ if (marker > (parts_count - 1 )) {
2498+ return 0 ;
2499+ }
2500+
2501+ RGWObjManifest::obj_iterator part_iter = manifest->obj_begin (dpp);
2502+
2503+ if (marker != 0 ) {
2504+ ldpp_dout_fmt (dpp, 20 ,
2505+ " {} seeking to part #{} in the object manifest" ,
2506+ __func__, marker);
2507+
2508+ part_iter = manifest->obj_find_part (dpp, marker + 1 );
2509+
2510+ if (part_iter == end) {
2511+ ldpp_dout_fmt (dpp, 5 ,
2512+ " {} failed to find part #{} in the object manifest" ,
2513+ __func__, marker + 1 );
2514+ return 0 ;
2515+ }
2516+ }
2517+
2518+ RGWObjectCtx& obj_ctx = get_ctx ();
2519+ RGWBucketInfo& bucket_info = get_bucket ()->get_info ();
2520+
2521+ Object::Part obj_part{};
2522+ for (; part_iter != manifest->obj_end (dpp); ++part_iter) {
2523+
2524+ /* we're only interested in the first object in each logical part */
2525+ auto cur_part_id = part_iter.get_cur_part_id ();
2526+ if (cur_part_id == obj_part.part_number ) {
2527+ continue ;
2528+ }
2529+
2530+ if (max_parts < 1 ) {
2531+ *truncated = true ;
2532+ break ;
2533+ }
2534+
2535+ /* get_part_obj_state alters the passed manifest** to point to a part
2536+ * manifest, which we don't want to leak out here */
2537+ RGWObjManifest* obj_m = manifest;
2538+ RGWObjState* astate;
2539+ bool part_prefetch = false ;
2540+ ret = RGWRados::get_part_obj_state (dpp, y, store->getRados (), bucket_info, &obj_ctx,
2541+ obj_m, cur_part_id, &parts_count,
2542+ part_prefetch, &astate, &obj_m);
2543+
2544+ if (ret < 0 ) {
2545+ ldpp_dout_fmt (dpp, 4 ,
2546+ " {} get_part_obj_state() failed ret={}" ,
2547+ __func__, ret);
2548+ break ;
2549+ }
2550+
2551+ obj_part.part_number = part_iter.get_cur_part_id ();
2552+ obj_part.part_size = astate->accounted_size ;
2553+
2554+ if (auto iter = astate->attrset .find (RGW_ATTR_CKSUM);
2555+ iter != astate->attrset .end ()) {
2556+ try {
2557+ rgw::cksum::Cksum part_cksum;
2558+ auto ck_iter = iter->second .cbegin ();
2559+ part_cksum.decode (ck_iter);
2560+ obj_part.cksum = std::move (part_cksum);
2561+ } catch (buffer::error& err) {
2562+ ldpp_dout_fmt (dpp, 4 ,
2563+ " WARN: {} could not decode stored cksum, "
2564+ " caught buffer::error" ,
2565+ __func__);
2566+ }
2567+ }
2568+
2569+ each_func (obj_part);
2570+ *next_marker = ++marker;
2571+ --max_parts;
2572+ } /* each part */
2573+
2574+ return ret;
2575+ } /* RadosObject::list_parts */
24752576
24762577int RadosObject::load_obj_state (const DoutPrefixProvider* dpp, optional_yield y, bool follow_olh)
24772578{
0 commit comments