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(RGWSI_RADOS
*rados_svc
,
14 const rgw_raw_obj
& obj
,
15 RGWSI_RADOS::Obj
**pobj
)
18 if (obj
.oid
.empty()) {
19 ldout(rados_svc
->ctx(), 0) << "ERROR: obj.oid is empty" << dendl
;
23 rados_obj
= rados_svc
->obj(obj
);
24 int r
= rados_obj
.open();
34 int RGWSI_SysObj_Core::get_rados_obj(RGWSI_Zone
*zone_svc
,
35 const rgw_raw_obj
& obj
,
36 RGWSI_RADOS::Obj
*pobj
)
38 if (obj
.oid
.empty()) {
39 ldout(rados_svc
->ctx(), 0) << "ERROR: obj.oid is empty" << dendl
;
43 *pobj
= rados_svc
->obj(obj
);
52 int RGWSI_SysObj_Core::get_system_obj_state_impl(RGWSysObjectCtxBase
*rctx
,
53 const rgw_raw_obj
& obj
,
54 RGWSysObjState
**state
,
55 RGWObjVersionTracker
*objv_tracker
,
62 RGWSysObjState
*s
= rctx
->get_state(obj
);
63 ldout(cct
, 20) << "get_system_obj_state: rctx=" << (void *)rctx
<< " obj=" << obj
<< " state=" << (void *)s
<< " s->prefetch_data=" << s
->prefetch_data
<< dendl
;
71 int r
= raw_stat(obj
, &s
->size
, &s
->mtime
, &s
->epoch
, &s
->attrset
,
72 (s
->prefetch_data
? &s
->data
: nullptr), objv_tracker
, y
);
76 s
->mtime
= real_time();
84 s
->obj_tag
= s
->attrset
[RGW_ATTR_ID_TAG
];
86 if (s
->obj_tag
.length())
87 ldout(cct
, 20) << "get_system_obj_state: setting s->obj_tag to "
88 << s
->obj_tag
.c_str() << dendl
;
90 ldout(cct
, 20) << "get_system_obj_state: s->obj_tag was set empty" << dendl
;
95 int RGWSI_SysObj_Core::get_system_obj_state(RGWSysObjectCtxBase
*rctx
,
96 const rgw_raw_obj
& obj
,
97 RGWSysObjState
**state
,
98 RGWObjVersionTracker
*objv_tracker
,
104 ret
= get_system_obj_state_impl(rctx
, obj
, state
, objv_tracker
, y
);
105 } while (ret
== -EAGAIN
);
110 int RGWSI_SysObj_Core::raw_stat(const rgw_raw_obj
& obj
, uint64_t *psize
, real_time
*pmtime
, uint64_t *epoch
,
111 map
<string
, bufferlist
> *attrs
, bufferlist
*first_chunk
,
112 RGWObjVersionTracker
*objv_tracker
,
115 RGWSI_RADOS::Obj rados_obj
;
116 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
122 struct timespec mtime_ts
;
124 librados::ObjectReadOperation op
;
126 objv_tracker
->prepare_op_for_read(&op
);
128 op
.getxattrs(attrs
, nullptr);
129 if (psize
|| pmtime
) {
130 op
.stat2(&size
, &mtime_ts
, nullptr);
133 op
.read(0, cct
->_conf
->rgw_max_chunk_size
, first_chunk
, nullptr);
136 r
= rados_obj
.operate(&op
, &outbl
, y
);
139 *epoch
= rados_obj
.get_last_version();
148 *pmtime
= ceph::real_clock::from_timespec(mtime_ts
);
153 int RGWSI_SysObj_Core::stat(RGWSysObjectCtxBase
& obj_ctx
,
154 RGWSI_SysObj_Obj_GetObjState
& _state
,
155 const rgw_raw_obj
& obj
,
156 map
<string
, bufferlist
> *attrs
,
160 RGWObjVersionTracker
*objv_tracker
,
163 RGWSysObjState
*astate
= nullptr;
165 int r
= get_system_obj_state(&obj_ctx
, obj
, &astate
, objv_tracker
, y
);
169 if (!astate
->exists
) {
175 *attrs
= astate
->attrset
;
177 rgw_filter_attrset(astate
->attrset
, RGW_ATTR_PREFIX
, attrs
);
179 if (cct
->_conf
->subsys
.should_gather
<ceph_subsys_rgw
, 20>()) {
180 map
<string
, bufferlist
>::iterator iter
;
181 for (iter
= attrs
->begin(); iter
!= attrs
->end(); ++iter
) {
182 ldout(cct
, 20) << "Read xattr: " << iter
->first
<< dendl
;
188 *obj_size
= astate
->size
;
190 *lastmod
= astate
->mtime
;
195 int RGWSI_SysObj_Core::read(RGWSysObjectCtxBase
& obj_ctx
,
196 RGWSI_SysObj_Obj_GetObjState
& _read_state
,
197 RGWObjVersionTracker
*objv_tracker
,
198 const rgw_raw_obj
& obj
,
199 bufferlist
*bl
, off_t ofs
, off_t end
,
200 map
<string
, bufferlist
> *attrs
,
202 rgw_cache_entry_info
*cache_info
,
203 boost::optional
<obj_version
>,
206 auto& read_state
= static_cast<GetObjState
&>(_read_state
);
209 librados::ObjectReadOperation op
;
217 objv_tracker
->prepare_op_for_read(&op
);
220 ldout(cct
, 20) << "rados->read ofs=" << ofs
<< " len=" << len
<< dendl
;
221 op
.read(ofs
, len
, bl
, nullptr);
223 map
<string
, bufferlist
> unfiltered_attrset
;
227 op
.getxattrs(attrs
, nullptr);
229 op
.getxattrs(&unfiltered_attrset
, nullptr);
233 RGWSI_RADOS::Obj rados_obj
;
234 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
236 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
239 r
= rados_obj
.operate(&op
, nullptr, y
);
241 ldout(cct
, 20) << "rados_obj.operate() r=" << r
<< " bl.length=" << bl
->length() << dendl
;
244 ldout(cct
, 20) << "rados_obj.operate() r=" << r
<< " bl.length=" << bl
->length() << dendl
;
246 uint64_t op_ver
= rados_obj
.get_last_version();
248 if (read_state
.last_ver
> 0 &&
249 read_state
.last_ver
!= op_ver
) {
250 ldout(cct
, 5) << "raced with an object write, abort" << dendl
;
254 if (attrs
&& !raw_attrs
) {
255 rgw_filter_attrset(unfiltered_attrset
, RGW_ATTR_PREFIX
, attrs
);
258 read_state
.last_ver
= op_ver
;
264 * Get an attribute for a system object.
265 * obj: the object to get attr
266 * name: name of the attr to retrieve
267 * dest: bufferlist to store the result in
268 * Returns: 0 on success, -ERR# otherwise.
270 int RGWSI_SysObj_Core::get_attr(const rgw_raw_obj
& obj
,
275 RGWSI_RADOS::Obj rados_obj
;
276 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
278 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
282 librados::ObjectReadOperation op
;
285 op
.getxattr(name
, dest
, &rval
);
287 r
= rados_obj
.operate(&op
, nullptr, y
);
294 int RGWSI_SysObj_Core::set_attrs(const rgw_raw_obj
& obj
,
295 map
<string
, bufferlist
>& attrs
,
296 map
<string
, bufferlist
> *rmattrs
,
297 RGWObjVersionTracker
*objv_tracker
,
300 RGWSI_RADOS::Obj rados_obj
;
301 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
303 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
307 librados::ObjectWriteOperation op
;
310 objv_tracker
->prepare_op_for_write(&op
);
313 map
<string
, bufferlist
>::iterator iter
;
315 for (iter
= rmattrs
->begin(); iter
!= rmattrs
->end(); ++iter
) {
316 const string
& name
= iter
->first
;
317 op
.rmxattr(name
.c_str());
321 for (iter
= attrs
.begin(); iter
!= attrs
.end(); ++iter
) {
322 const string
& name
= iter
->first
;
323 bufferlist
& bl
= iter
->second
;
328 op
.setxattr(name
.c_str(), bl
);
336 r
= rados_obj
.operate(&op
, y
);
343 int RGWSI_SysObj_Core::omap_get_vals(const rgw_raw_obj
& obj
,
344 const string
& marker
,
346 std::map
<string
, bufferlist
> *m
,
350 RGWSI_RADOS::Obj rados_obj
;
351 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
353 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
357 string start_after
= marker
;
361 librados::ObjectReadOperation op
;
363 std::map
<string
, bufferlist
> t
;
365 op
.omap_get_vals2(start_after
, count
, &t
, &more
, &rval
);
367 r
= rados_obj
.operate(&op
, nullptr, y
);
375 start_after
= t
.rbegin()->first
;
376 m
->insert(t
.begin(), t
.end());
377 } while (more
&& count
> 0);
385 int RGWSI_SysObj_Core::omap_get_all(const rgw_raw_obj
& obj
,
386 std::map
<string
, bufferlist
> *m
,
389 RGWSI_RADOS::Obj rados_obj
;
390 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
392 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
396 #define MAX_OMAP_GET_ENTRIES 1024
397 const int count
= MAX_OMAP_GET_ENTRIES
;
402 librados::ObjectReadOperation op
;
404 std::map
<string
, bufferlist
> t
;
406 op
.omap_get_vals2(start_after
, count
, &t
, &more
, &rval
);
408 r
= rados_obj
.operate(&op
, nullptr, y
);
415 start_after
= t
.rbegin()->first
;
416 m
->insert(t
.begin(), t
.end());
421 int RGWSI_SysObj_Core::omap_set(const rgw_raw_obj
& obj
, const std::string
& key
,
422 bufferlist
& bl
, bool must_exist
,
425 RGWSI_RADOS::Obj rados_obj
;
426 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
428 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
432 ldout(cct
, 15) << "omap_set obj=" << obj
<< " key=" << key
<< dendl
;
434 map
<string
, bufferlist
> m
;
436 librados::ObjectWriteOperation op
;
440 r
= rados_obj
.operate(&op
, y
);
444 int RGWSI_SysObj_Core::omap_set(const rgw_raw_obj
& obj
,
445 const std::map
<std::string
, bufferlist
>& m
,
446 bool must_exist
, optional_yield y
)
448 RGWSI_RADOS::Obj rados_obj
;
449 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
451 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
455 librados::ObjectWriteOperation op
;
459 r
= rados_obj
.operate(&op
, y
);
463 int RGWSI_SysObj_Core::omap_del(const rgw_raw_obj
& obj
, const std::string
& key
,
466 RGWSI_RADOS::Obj rados_obj
;
467 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
469 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
476 librados::ObjectWriteOperation op
;
480 r
= rados_obj
.operate(&op
, y
);
484 int RGWSI_SysObj_Core::notify(const rgw_raw_obj
& obj
, bufferlist
& bl
,
485 uint64_t timeout_ms
, bufferlist
*pbl
,
488 RGWSI_RADOS::Obj rados_obj
;
489 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
491 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
495 r
= rados_obj
.notify(bl
, timeout_ms
, pbl
, y
);
499 int RGWSI_SysObj_Core::remove(RGWSysObjectCtxBase
& obj_ctx
,
500 RGWObjVersionTracker
*objv_tracker
,
501 const rgw_raw_obj
& obj
,
504 RGWSI_RADOS::Obj rados_obj
;
505 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
507 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
511 librados::ObjectWriteOperation op
;
514 objv_tracker
->prepare_op_for_write(&op
);
518 r
= rados_obj
.operate(&op
, y
);
525 int RGWSI_SysObj_Core::write(const rgw_raw_obj
& obj
,
527 map
<std::string
, bufferlist
>& attrs
,
529 const bufferlist
& data
,
530 RGWObjVersionTracker
*objv_tracker
,
534 RGWSI_RADOS::Obj rados_obj
;
535 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
537 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
541 librados::ObjectWriteOperation op
;
544 op
.create(true); // exclusive create
547 op
.set_op_flags2(LIBRADOS_OP_FLAG_FAILOK
);
552 objv_tracker
->prepare_op_for_write(&op
);
555 if (real_clock::is_zero(set_mtime
)) {
556 set_mtime
= real_clock::now();
559 struct timespec mtime_ts
= real_clock::to_timespec(set_mtime
);
560 op
.mtime2(&mtime_ts
);
565 for (map
<string
, bufferlist
>::iterator iter
= attrs
.begin(); iter
!= attrs
.end(); ++iter
) {
566 const string
& name
= iter
->first
;
567 bufferlist
& bl
= iter
->second
;
572 op
.setxattr(name
.c_str(), bl
);
575 r
= rados_obj
.operate(&op
, y
);
581 objv_tracker
->apply_write();
592 int RGWSI_SysObj_Core::write_data(const rgw_raw_obj
& obj
,
593 const bufferlist
& bl
,
595 RGWObjVersionTracker
*objv_tracker
,
598 RGWSI_RADOS::Obj rados_obj
;
599 int r
= get_rados_obj(zone_svc
, obj
, &rados_obj
);
601 ldout(cct
, 20) << "get_rados_obj() on obj=" << obj
<< " returned " << r
<< dendl
;
605 librados::ObjectWriteOperation op
;
612 objv_tracker
->prepare_op_for_write(&op
);
615 r
= rados_obj
.operate(&op
, y
);
620 objv_tracker
->apply_write();
625 int RGWSI_SysObj_Core::pool_list_prefixed_objs(const rgw_pool
& pool
, const string
& prefix
,
626 std::function
<void(const string
&)> cb
)
630 auto rados_pool
= rados_svc
->pool(pool
);
632 auto op
= rados_pool
.op();
634 RGWAccessListFilterPrefix
filter(prefix
);
636 int r
= op
.init(string(), &filter
);
643 #define MAX_OBJS_DEFAULT 1000
644 int r
= op
.get_next(MAX_OBJS_DEFAULT
, &oids
, &is_truncated
);
648 for (auto& val
: oids
) {
649 if (val
.size() > prefix
.size()) {
650 cb(val
.substr(prefix
.size()));
653 } while (is_truncated
);
658 int RGWSI_SysObj_Core::pool_list_objects_init(const rgw_pool
& pool
,
659 const string
& marker
,
660 const string
& prefix
,
661 RGWSI_SysObj::Pool::ListCtx
*_ctx
)
663 _ctx
->impl
.emplace
<PoolListImplInfo
>(prefix
);
665 auto& ctx
= static_cast<PoolListImplInfo
&>(*_ctx
->impl
);
667 ctx
.pool
= rados_svc
->pool(pool
);
668 ctx
.op
= ctx
.pool
.op();
670 int r
= ctx
.op
.init(marker
, &ctx
.filter
);
672 ldout(cct
, 10) << "failed to list objects pool_iterate_begin() returned r=" << r
<< dendl
;
678 int RGWSI_SysObj_Core::pool_list_objects_next(RGWSI_SysObj::Pool::ListCtx
& _ctx
,
680 vector
<string
> *oids
,
686 auto& ctx
= static_cast<PoolListImplInfo
&>(*_ctx
.impl
);
687 int r
= ctx
.op
.get_next(max
, oids
, is_truncated
);
690 ldout(cct
, 10) << "failed to list objects pool_iterate returned r=" << r
<< dendl
;
697 int RGWSI_SysObj_Core::pool_list_objects_get_marker(RGWSI_SysObj::Pool::ListCtx
& _ctx
,
704 auto& ctx
= static_cast<PoolListImplInfo
&>(*_ctx
.impl
);
705 return ctx
.op
.get_marker(marker
);