RGWRados::get_obj_state_impl()
1 函数详解
这个函数有着比较重要的作用,涉及rgw对象向rados对象的转换以及其他元数据的获取。
int RGWRados::get_obj_state_impl(RGWObjectCtx *rctx, const RGWBucketInfo& bucket_info, const rgw_obj& obj,RGWObjState **state, bool follow_olh, bool assume_noent)
{if (obj.empty()) {return -EINVAL;}bool need_follow_olh = follow_olh && obj.key.instance.empty();RGWObjState *s = rctx->obj.get_state(obj);ldout(cct, 20) << "get_obj_state: rctx=" << (void *)rctx << " obj=" << obj << " state=" << (void *)s << " s->prefetch_data=" << s->prefetch_data << dendl;*state = s;if (s->has_attrs) {if (s->is_olh && need_follow_olh) {return get_olh_target_state(*rctx, bucket_info, obj, s, state);}return 0;}
以上为获取obj状态,get_state函数最终调用的是RGWObjectCtxImpl::get_state(),在内存中RGWObjectCtxImpl<rgw_obj, RGWObjState>数据结构会用一个名为objs_state的map记录所有rgw_obj和其对应的状态,如果get_state没有找到则会在map中添加该rgw_obj对应的RGWObjState并返回。
s->obj = obj;rgw_raw_obj raw_obj;obj_to_raw(bucket_info.placement_rule, obj, &raw_obj);
这一步则是将rgw对象转化为rados对象:
obj_to_raw函数只调用了两个函数get_obj_bucket_and_oid_loc()和get_obj_data_pool(),先看get_obj_bucket_and_oid_loc(),这个函数的作用就是生成rados对象的名称,这里不过多赘述,只说结论,最终生成的rados对象名称为:
bucket_id + “" + "” + namespace + “_” + key + “.” + upload_id + “.” + meta
而get_obj_data_pool()函数就很直观了,就是确定这个rados对象存在哪个存储池中,这个函数最终调用的是rgw_get_obj_data_pool(),由于在RGWInitMultipart::execute()中已经将meta对象设置为extra data,因此需要存储在data_extra_pool之中,也就是non-ec池:
int r = -ENOENT;if (!assume_noent) {r = RGWRados::raw_obj_stat(raw_obj, &s->size, &s->mtime, &s->epoch, &s->attrset, (s->prefetch_data ? &s->data : NULL), NULL);}
这里如果!assume_noent为真则认为该对象存在,会去读取这个对象记录在attrset中的属性,如果新上传的对象则不会进入读取和处理属性的逻辑。以下代码均为获取和处理属性的逻辑,这里不过多赘述:
if (r == -ENOENT) {s->exists = false;s->has_attrs = true;tombstone_entry entry;if (obj_tombstone_cache && obj_tombstone_cache->find(obj, entry)) {s->mtime = entry.mtime;s->zone_short_id = entry.zone_short_id;s->pg_ver = entry.pg_ver;ldout(cct, 20) << __func__ << "(): found obj in tombstone cache: obj=" << obj<< " mtime=" << s->mtime << " pgv=" << s->pg_ver << dendl;} else {s->mtime = real_time();}return 0;}if (r < 0)return r;s->exists = true;s->has_attrs = true;s->accounted_size = s->size;auto iter = s->attrset.find(RGW_ATTR_ETAG);if (iter != s->attrset.end()) {/* get rid of extra null character at the end of the etag, as we used to store it like that */bufferlist& bletag = iter->second;if (bletag.length() > 0 && bletag[bletag.length() - 1] == '\0') {bufferlist newbl;bletag.splice(0, bletag.length() - 1, &newbl);bletag.claim(newbl);}}iter = s->attrset.find(RGW_ATTR_COMPRESSION);const bool compressed = (iter != s->attrset.end());if (compressed) {// use uncompressed size for accounted_sizetry {RGWCompressionInfo info;auto p = iter->second.begin();decode(info, p);s->accounted_size = info.orig_size; } catch (buffer::error&) {dout(0) << "ERROR: could not decode compression info for object: " << obj << dendl;return -EIO;}}iter = s->attrset.find(RGW_ATTR_SHADOW_OBJ);if (iter != s->attrset.end()) {bufferlist bl = iter->second;bufferlist::iterator it = bl.begin();it.copy(bl.length(), s->shadow_obj);s->shadow_obj[bl.length()] = '\0';}s->obj_tag = s->attrset[RGW_ATTR_ID_TAG];auto ttiter = s->attrset.find(RGW_ATTR_TAIL_TAG);if (ttiter != s->attrset.end()) {s->tail_tag = s->attrset[RGW_ATTR_TAIL_TAG];}bufferlist manifest_bl = s->attrset[RGW_ATTR_MANIFEST];if (manifest_bl.length()) {bufferlist::iterator miter = manifest_bl.begin();try {decode(s->manifest, miter);s->has_manifest = true;s->manifest.set_head(bucket_info.placement_rule, obj, s->size); /* patch manifest to reflect the head we just read, some manifests might bebroken due to old bugs */s->size = s->manifest.get_obj_size();if (!compressed)s->accounted_size = s->size;} catch (buffer::error& err) {ldout(cct, 0) << "ERROR: couldn't decode manifest" << dendl;return -EIO;}ldout(cct, 10) << "manifest: total_size = " << s->manifest.get_obj_size() << dendl;if (cct->_conf->subsys.should_gather<ceph_subsys_rgw, 20>() && \s->manifest.has_explicit_objs()) {RGWObjManifest::obj_iterator mi;for (mi = s->manifest.obj_begin(); mi != s->manifest.obj_end(); ++mi) {ldout(cct, 20) << "manifest: ofs=" << mi.get_ofs() << " loc=" << mi.get_location().get_raw_obj(this) << dendl;}}if (!s->obj_tag.length()) {/** Uh oh, something's wrong, object with manifest should have tag. Let's* create one out of the manifest, would be unique*/generate_fake_tag(this, s->attrset, s->manifest, manifest_bl, s->obj_tag);s->fake_tag = true;}}map<string, bufferlist>::iterator aiter = s->attrset.find(RGW_ATTR_PG_VER);if (aiter != s->attrset.end()) {bufferlist& pg_ver_bl = aiter->second;if (pg_ver_bl.length()) {bufferlist::iterator pgbl = pg_ver_bl.begin();try {decode(s->pg_ver, pgbl);} catch (buffer::error& err) {ldout(cct, 0) << "ERROR: couldn't decode pg ver attr for object " << s->obj << ", non-critical error, ignoring" << dendl;}}}aiter = s->attrset.find(RGW_ATTR_SOURCE_ZONE);if (aiter != s->attrset.end()) {bufferlist& zone_short_id_bl = aiter->second;if (zone_short_id_bl.length()) {bufferlist::iterator zbl = zone_short_id_bl.begin();try {decode(s->zone_short_id, zbl);} catch (buffer::error& err) {ldout(cct, 0) << "ERROR: couldn't decode zone short id attr for object " << s->obj << ", non-critical error, ignoring" << dendl;}}}if (s->obj_tag.length())ldout(cct, 20) << "get_obj_state: setting s->obj_tag to " << s->obj_tag.c_str() << dendl;elseldout(cct, 20) << "get_obj_state: s->obj_tag was set empty" << dendl;/* an object might not be olh yet, but could have olh id tag, so we should set it anyway if* it exist, and not only if is_olh() returns true*/iter = s->attrset.find(RGW_ATTR_OLH_ID_TAG);if (iter != s->attrset.end()) {s->olh_tag = iter->second;}if (is_olh(s->attrset)) {s->is_olh = true;ldout(cct, 20) << __func__ << ": setting s->olh_tag to " << string(s->olh_tag.c_str(), s->olh_tag.length()) << dendl;if (need_follow_olh) {return get_olh_target_state(*rctx, bucket_info, obj, s, state);} else if (obj.key.have_null_instance() && !s->has_manifest) {// read null version, and the head object only have olh infos->exists = false;return -ENOENT;}}return 0;
}