1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
4 #include "svc_sys_obj_core.h"
8 #include "rgw/rgw_tools.h"
10 #define dout_subsys ceph_subsys_rgw
12 int RGWSI_SysObj_Core_GetObjState::get_rados_obj(const DoutPrefixProvider
*dpp
,
13 RGWSI_RADOS
*rados_svc
,
15 const rgw_raw_obj
& obj
,
16 RGWSI_RADOS::Obj
**pobj
)
19 if (obj
.oid
.empty()) {
20 ldpp_dout(dpp
, 0) << "ERROR: obj.oid is empty" << dendl
;
24 rados_obj
= rados_svc
->obj(obj
);
25 int r
= rados_obj
.open(dpp
);
35 int RGWSI_SysObj_Core::get_rados_obj(const DoutPrefixProvider
*dpp
,
37 const rgw_raw_obj
& obj
,
38 RGWSI_RADOS::Obj
*pobj
)
40 if (obj
.oid
.empty()) {
41 ldpp_dout(dpp
, 0) << "ERROR: obj.oid is empty" << dendl
;
45 *pobj
= rados_svc
->obj(obj
);
46 int r
= pobj
->open(dpp
);
54 int RGWSI_SysObj_Core::get_system_obj_state_impl(RGWSysObjectCtxBase
*rctx
,
55 const rgw_raw_obj
& obj
,
56 RGWSysObjState
**state
,
57 RGWObjVersionTracker
*objv_tracker
,
59 const DoutPrefixProvider
*dpp
)
65 RGWSysObjState
*s
= rctx
->get_state(obj
);
66 ldpp_dout(dpp
, 20) << "get_system_obj_state: rctx=" << (void *)rctx
<< " obj=" << obj
<< " state=" << (void *)s
<< " s->prefetch_data=" << s
->prefetch_data
<< dendl
;
74 int r
= raw_stat(dpp
, obj
, &s
->size
, &s
->mtime
, &s
->epoch
, &s
->attrset
,
75 (s
->prefetch_data
? &s
->data
: nullptr), objv_tracker
, y
);
79 s
->mtime
= real_time();
87 s
->obj_tag
= s
->attrset
[RGW_ATTR_ID_TAG
];
89 if (s
->obj_tag
.length()) {
90 ldpp_dout(dpp
, 20) << "get_system_obj_state: setting s->obj_tag to " << s
->obj_tag
.c_str() << dendl
;
92 ldpp_dout(dpp
, 20) << "get_system_obj_state: s->obj_tag was set empty" << dendl
;
98 int RGWSI_SysObj_Core::get_system_obj_state(RGWSysObjectCtxBase
*rctx
,
99 const rgw_raw_obj
& obj
,
100 RGWSysObjState
**state
,
101 RGWObjVersionTracker
*objv_tracker
,
103 const DoutPrefixProvider
*dpp
)
108 ret
= get_system_obj_state_impl(rctx
, obj
, state
, objv_tracker
, y
, dpp
);
109 } while (ret
== -EAGAIN
);
114 int RGWSI_SysObj_Core::raw_stat(const DoutPrefixProvider
*dpp
, const rgw_raw_obj
& obj
, uint64_t *psize
, real_time
*pmtime
, uint64_t *epoch
,
115 map
<string
, bufferlist
> *attrs
, bufferlist
*first_chunk
,
116 RGWObjVersionTracker
*objv_tracker
,
119 RGWSI_RADOS::Obj rados_obj
;
120 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
126 struct timespec mtime_ts
;
128 librados::ObjectReadOperation op
;
130 objv_tracker
->prepare_op_for_read(&op
);
132 op
.getxattrs(attrs
, nullptr);
133 if (psize
|| pmtime
) {
134 op
.stat2(&size
, &mtime_ts
, nullptr);
137 op
.read(0, cct
->_conf
->rgw_max_chunk_size
, first_chunk
, nullptr);
140 r
= rados_obj
.operate(dpp
, &op
, &outbl
, y
);
143 *epoch
= rados_obj
.get_last_version();
152 *pmtime
= ceph::real_clock::from_timespec(mtime_ts
);
157 int RGWSI_SysObj_Core::stat(RGWSysObjectCtxBase
& obj_ctx
,
158 RGWSI_SysObj_Obj_GetObjState
& _state
,
159 const rgw_raw_obj
& obj
,
160 map
<string
, bufferlist
> *attrs
,
164 RGWObjVersionTracker
*objv_tracker
,
166 const DoutPrefixProvider
*dpp
)
168 RGWSysObjState
*astate
= nullptr;
170 int r
= get_system_obj_state(&obj_ctx
, obj
, &astate
, objv_tracker
, y
, dpp
);
174 if (!astate
->exists
) {
180 *attrs
= astate
->attrset
;
182 rgw_filter_attrset(astate
->attrset
, RGW_ATTR_PREFIX
, attrs
);
184 if (cct
->_conf
->subsys
.should_gather
<ceph_subsys_rgw
, 20>()) {
185 map
<string
, bufferlist
>::iterator iter
;
186 for (iter
= attrs
->begin(); iter
!= attrs
->end(); ++iter
) {
187 ldpp_dout(dpp
, 20) << "Read xattr: " << iter
->first
<< dendl
;
193 *obj_size
= astate
->size
;
195 *lastmod
= astate
->mtime
;
200 int RGWSI_SysObj_Core::read(const DoutPrefixProvider
*dpp
,
201 RGWSysObjectCtxBase
& obj_ctx
,
202 RGWSI_SysObj_Obj_GetObjState
& _read_state
,
203 RGWObjVersionTracker
*objv_tracker
,
204 const rgw_raw_obj
& obj
,
205 bufferlist
*bl
, off_t ofs
, off_t end
,
206 map
<string
, bufferlist
> *attrs
,
208 rgw_cache_entry_info
*cache_info
,
209 boost::optional
<obj_version
>,
212 auto& read_state
= static_cast<GetObjState
&>(_read_state
);
215 librados::ObjectReadOperation op
;
223 objv_tracker
->prepare_op_for_read(&op
);
226 ldpp_dout(dpp
, 20) << "rados->read ofs=" << ofs
<< " len=" << len
<< dendl
;
227 op
.read(ofs
, len
, bl
, nullptr);
229 map
<string
, bufferlist
> unfiltered_attrset
;
233 op
.getxattrs(attrs
, nullptr);
235 op
.getxattrs(&unfiltered_attrset
, nullptr);
239 RGWSI_RADOS::Obj rados_obj
;
240 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
242 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
245 r
= rados_obj
.operate(dpp
, &op
, nullptr, y
);
247 ldpp_dout(dpp
, 20) << "rados_obj.operate() r=" << r
<< " bl.length=" << bl
->length() << dendl
;
250 ldpp_dout(dpp
, 20) << "rados_obj.operate() r=" << r
<< " bl.length=" << bl
->length() << dendl
;
252 uint64_t op_ver
= rados_obj
.get_last_version();
254 if (read_state
.last_ver
> 0 &&
255 read_state
.last_ver
!= op_ver
) {
256 ldpp_dout(dpp
, 5) << "raced with an object write, abort" << dendl
;
260 if (attrs
&& !raw_attrs
) {
261 rgw_filter_attrset(unfiltered_attrset
, RGW_ATTR_PREFIX
, attrs
);
264 read_state
.last_ver
= op_ver
;
270 * Get an attribute for a system object.
271 * obj: the object to get attr
272 * name: name of the attr to retrieve
273 * dest: bufferlist to store the result in
274 * Returns: 0 on success, -ERR# otherwise.
276 int RGWSI_SysObj_Core::get_attr(const DoutPrefixProvider
*dpp
,
277 const rgw_raw_obj
& obj
,
282 RGWSI_RADOS::Obj rados_obj
;
283 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
285 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
289 librados::ObjectReadOperation op
;
292 op
.getxattr(name
, dest
, &rval
);
294 r
= rados_obj
.operate(dpp
, &op
, nullptr, y
);
301 int RGWSI_SysObj_Core::set_attrs(const DoutPrefixProvider
*dpp
,
302 const rgw_raw_obj
& obj
,
303 map
<string
, bufferlist
>& attrs
,
304 map
<string
, bufferlist
> *rmattrs
,
305 RGWObjVersionTracker
*objv_tracker
,
308 RGWSI_RADOS::Obj rados_obj
;
309 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
311 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
315 librados::ObjectWriteOperation op
;
318 objv_tracker
->prepare_op_for_write(&op
);
321 map
<string
, bufferlist
>::iterator iter
;
323 for (iter
= rmattrs
->begin(); iter
!= rmattrs
->end(); ++iter
) {
324 const string
& name
= iter
->first
;
325 op
.rmxattr(name
.c_str());
329 for (iter
= attrs
.begin(); iter
!= attrs
.end(); ++iter
) {
330 const string
& name
= iter
->first
;
331 bufferlist
& bl
= iter
->second
;
336 op
.setxattr(name
.c_str(), bl
);
344 r
= rados_obj
.operate(dpp
, &op
, y
);
349 objv_tracker
->apply_write();
354 int RGWSI_SysObj_Core::omap_get_vals(const DoutPrefixProvider
*dpp
,
355 const rgw_raw_obj
& obj
,
356 const string
& marker
,
358 std::map
<string
, bufferlist
> *m
,
362 RGWSI_RADOS::Obj rados_obj
;
363 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
365 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
369 string start_after
= marker
;
373 librados::ObjectReadOperation op
;
375 std::map
<string
, bufferlist
> t
;
377 op
.omap_get_vals2(start_after
, count
, &t
, &more
, &rval
);
379 r
= rados_obj
.operate(dpp
, &op
, nullptr, y
);
387 start_after
= t
.rbegin()->first
;
388 m
->insert(t
.begin(), t
.end());
389 } while (more
&& count
> 0);
397 int RGWSI_SysObj_Core::omap_get_all(const DoutPrefixProvider
*dpp
,
398 const rgw_raw_obj
& obj
,
399 std::map
<string
, bufferlist
> *m
,
402 RGWSI_RADOS::Obj rados_obj
;
403 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
405 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
409 #define MAX_OMAP_GET_ENTRIES 1024
410 const int count
= MAX_OMAP_GET_ENTRIES
;
415 librados::ObjectReadOperation op
;
417 std::map
<string
, bufferlist
> t
;
419 op
.omap_get_vals2(start_after
, count
, &t
, &more
, &rval
);
421 r
= rados_obj
.operate(dpp
, &op
, nullptr, y
);
428 start_after
= t
.rbegin()->first
;
429 m
->insert(t
.begin(), t
.end());
434 int RGWSI_SysObj_Core::omap_set(const DoutPrefixProvider
*dpp
, const rgw_raw_obj
& obj
, const std::string
& key
,
435 bufferlist
& bl
, bool must_exist
,
438 RGWSI_RADOS::Obj rados_obj
;
439 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
441 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
445 ldpp_dout(dpp
, 15) << "omap_set obj=" << obj
<< " key=" << key
<< dendl
;
447 map
<string
, bufferlist
> m
;
449 librados::ObjectWriteOperation op
;
453 r
= rados_obj
.operate(dpp
, &op
, y
);
457 int RGWSI_SysObj_Core::omap_set(const DoutPrefixProvider
*dpp
, const rgw_raw_obj
& obj
,
458 const std::map
<std::string
, bufferlist
>& m
,
459 bool must_exist
, optional_yield y
)
461 RGWSI_RADOS::Obj rados_obj
;
462 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
464 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
468 librados::ObjectWriteOperation op
;
472 r
= rados_obj
.operate(dpp
, &op
, y
);
476 int RGWSI_SysObj_Core::omap_del(const DoutPrefixProvider
*dpp
, const rgw_raw_obj
& obj
, const std::string
& key
,
479 RGWSI_RADOS::Obj rados_obj
;
480 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
482 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
489 librados::ObjectWriteOperation op
;
493 r
= rados_obj
.operate(dpp
, &op
, y
);
497 int RGWSI_SysObj_Core::notify(const DoutPrefixProvider
*dpp
, const rgw_raw_obj
& obj
, bufferlist
& bl
,
498 uint64_t timeout_ms
, bufferlist
*pbl
,
501 RGWSI_RADOS::Obj rados_obj
;
502 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
504 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
508 r
= rados_obj
.notify(dpp
, bl
, timeout_ms
, pbl
, y
);
512 int RGWSI_SysObj_Core::remove(const DoutPrefixProvider
*dpp
,
513 RGWSysObjectCtxBase
& obj_ctx
,
514 RGWObjVersionTracker
*objv_tracker
,
515 const rgw_raw_obj
& obj
,
518 RGWSI_RADOS::Obj rados_obj
;
519 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
521 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
525 librados::ObjectWriteOperation op
;
528 objv_tracker
->prepare_op_for_write(&op
);
532 r
= rados_obj
.operate(dpp
, &op
, y
);
539 int RGWSI_SysObj_Core::write(const DoutPrefixProvider
*dpp
,
540 const rgw_raw_obj
& obj
,
542 map
<std::string
, bufferlist
>& attrs
,
544 const bufferlist
& data
,
545 RGWObjVersionTracker
*objv_tracker
,
549 RGWSI_RADOS::Obj rados_obj
;
550 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
552 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
556 librados::ObjectWriteOperation op
;
559 op
.create(true); // exclusive create
562 op
.set_op_flags2(LIBRADOS_OP_FLAG_FAILOK
);
567 objv_tracker
->prepare_op_for_write(&op
);
570 if (real_clock::is_zero(set_mtime
)) {
571 set_mtime
= real_clock::now();
574 struct timespec mtime_ts
= real_clock::to_timespec(set_mtime
);
575 op
.mtime2(&mtime_ts
);
580 for (map
<string
, bufferlist
>::iterator iter
= attrs
.begin(); iter
!= attrs
.end(); ++iter
) {
581 const string
& name
= iter
->first
;
582 bufferlist
& bl
= iter
->second
;
587 op
.setxattr(name
.c_str(), bl
);
590 r
= rados_obj
.operate(dpp
, &op
, y
);
596 objv_tracker
->apply_write();
607 int RGWSI_SysObj_Core::write_data(const DoutPrefixProvider
*dpp
,
608 const rgw_raw_obj
& obj
,
609 const bufferlist
& bl
,
611 RGWObjVersionTracker
*objv_tracker
,
614 RGWSI_RADOS::Obj rados_obj
;
615 int r
= get_rados_obj(dpp
, zone_svc
, obj
, &rados_obj
);
617 ldpp_dout(dpp
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
621 librados::ObjectWriteOperation op
;
628 objv_tracker
->prepare_op_for_write(&op
);
631 r
= rados_obj
.operate(dpp
, &op
, y
);
636 objv_tracker
->apply_write();
641 int RGWSI_SysObj_Core::pool_list_prefixed_objs(const DoutPrefixProvider
*dpp
,
642 const rgw_pool
& pool
, const string
& prefix
,
643 std::function
<void(const string
&)> cb
)
647 auto rados_pool
= rados_svc
->pool(pool
);
649 auto op
= rados_pool
.op();
651 RGWAccessListFilterPrefix
filter(prefix
);
653 int r
= op
.init(dpp
, string(), &filter
);
660 #define MAX_OBJS_DEFAULT 1000
661 int r
= op
.get_next(MAX_OBJS_DEFAULT
, &oids
, &is_truncated
);
665 for (auto& val
: oids
) {
666 if (val
.size() > prefix
.size()) {
667 cb(val
.substr(prefix
.size()));
670 } while (is_truncated
);
675 int RGWSI_SysObj_Core::pool_list_objects_init(const DoutPrefixProvider
*dpp
,
676 const rgw_pool
& pool
,
677 const string
& marker
,
678 const string
& prefix
,
679 RGWSI_SysObj::Pool::ListCtx
*_ctx
)
681 _ctx
->impl
.emplace
<PoolListImplInfo
>(prefix
);
683 auto& ctx
= static_cast<PoolListImplInfo
&>(*_ctx
->impl
);
685 ctx
.pool
= rados_svc
->pool(pool
);
686 ctx
.op
= ctx
.pool
.op();
688 int r
= ctx
.op
.init(dpp
, marker
, &ctx
.filter
);
690 ldpp_dout(dpp
, 10) << "failed to list objects pool_iterate_begin() returned r=" << r
<< dendl
;
696 int RGWSI_SysObj_Core::pool_list_objects_next(RGWSI_SysObj::Pool::ListCtx
& _ctx
,
698 vector
<string
> *oids
,
704 auto& ctx
= static_cast<PoolListImplInfo
&>(*_ctx
.impl
);
705 int r
= ctx
.op
.get_next(max
, oids
, is_truncated
);
708 ldout(cct
, 10) << "failed to list objects pool_iterate returned r=" << r
<< dendl
;
715 int RGWSI_SysObj_Core::pool_list_objects_get_marker(RGWSI_SysObj::Pool::ListCtx
& _ctx
,
722 auto& ctx
= static_cast<PoolListImplInfo
&>(*_ctx
.impl
);
723 return ctx
.op
.get_marker(marker
);