mirror of
https://github.com/ceph/ceph
synced 2025-03-11 02:39:05 +00:00
librgw: reimplement RGWLibFS::stat_leaf
Now the code attempts to read an object header (which may be cached), and if this fails, uses RGWStatLeafRequest to find a potential matching file or directory leaf. Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
This commit is contained in:
parent
3ac44f9178
commit
6e70b6deee
@ -40,25 +40,45 @@ LookupFHResult RGWLibFS::stat_leaf(RGWFileHandle* parent,
|
||||
uint32_t flags)
|
||||
{
|
||||
/* find either-of <object_name>, <object_name/>, only one of
|
||||
* which can exist; atomicity? */
|
||||
* which should exist; atomicity? */
|
||||
RGWLibFS* fs = parent->get_fs();
|
||||
LookupFHResult fhr{nullptr, 0};
|
||||
std::string object_name{path};
|
||||
uint32_t cflags = RGWFileHandle::FLAG_NONE;
|
||||
|
||||
for (auto ix : { 0, 1 }) {
|
||||
ignore(ix);
|
||||
RGWStatObjRequest req(cct, fs->get_user(),
|
||||
parent->bucket_name(), object_name,
|
||||
RGWStatObjRequest::FLAG_NONE);
|
||||
int rc = librgw.get_fe()->execute_req(&req);
|
||||
if ((rc == 0) &&
|
||||
(req.get_ret() == 0)) {
|
||||
fhr = fs->lookup_fh(parent, path, cflags);
|
||||
switch (ix) {
|
||||
case 0:
|
||||
{
|
||||
RGWStatObjRequest req(cct, fs->get_user(),
|
||||
parent->bucket_name(), object_name,
|
||||
RGWStatObjRequest::FLAG_NONE);
|
||||
int rc = librgw.get_fe()->execute_req(&req);
|
||||
if ((rc == 0) &&
|
||||
(req.get_ret() == 0)) {
|
||||
fhr = fs->lookup_fh(parent, path, RGWFileHandle::FLAG_NONE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
RGWStatLeafRequest req(cct, fs->get_user(), parent->bucket_name(),
|
||||
object_name);
|
||||
int rc = librgw.get_fe()->execute_req(&req);
|
||||
if ((rc == 0) &&
|
||||
(req.get_ret() == 0)) {
|
||||
if (req.matched) {
|
||||
fhr = fs->lookup_fh(parent, path,
|
||||
(req.path.back() == '/') ?
|
||||
RGWFileHandle::FLAG_DIRECTORY :
|
||||
RGWFileHandle::FLAG_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* not reached */
|
||||
break;
|
||||
}
|
||||
cflags = RGWFileHandle::FLAG_DIRECTORY;
|
||||
object_name += "/";
|
||||
}
|
||||
return fhr;
|
||||
} /* RGWLibFS::stat_leaf */
|
||||
|
@ -124,6 +124,7 @@ namespace rgw {
|
||||
mutable std::atomic<uint64_t> refcnt;
|
||||
std::mutex mtx;
|
||||
RGWLibFS* fs;
|
||||
RGWFHRef bucket;
|
||||
RGWFHRef parent;
|
||||
/* const */ std::string name; /* XXX file or bucket name */
|
||||
/* const */ fh_key fhk;
|
||||
@ -161,13 +162,15 @@ namespace rgw {
|
||||
static constexpr uint32_t FLAG_CREATE = 0x0004;
|
||||
static constexpr uint32_t FLAG_PSEUDO = 0x0008;
|
||||
static constexpr uint32_t FLAG_DIRECTORY = 0x0010;
|
||||
static constexpr uint32_t FLAG_LOCK = 0x0020;
|
||||
static constexpr uint32_t FLAG_BUCKET = 0x0020;
|
||||
static constexpr uint32_t FLAG_LOCK = 0x0040;
|
||||
|
||||
friend class RGWLibFS;
|
||||
|
||||
private:
|
||||
RGWFileHandle(RGWLibFS* _fs, uint32_t fs_inst)
|
||||
: refcnt(1), fs(_fs), parent(nullptr), depth(0), flags(FLAG_ROOT)
|
||||
: refcnt(1), fs(_fs), bucket(nullptr), parent(nullptr), depth(0),
|
||||
flags(FLAG_ROOT)
|
||||
{
|
||||
/* root */
|
||||
fh.fh_type = RGW_FS_TYPE_DIRECTORY;
|
||||
@ -189,10 +192,18 @@ namespace rgw {
|
||||
public:
|
||||
RGWFileHandle(RGWLibFS* fs, uint32_t fs_inst, RGWFileHandle* _parent,
|
||||
const fh_key& _fhk, std::string& _name, uint32_t _flags)
|
||||
: parent(_parent), name(std::move(_name)), fhk(_fhk), flags(_flags) {
|
||||
: bucket(nullptr), parent(_parent), name(std::move(_name)), fhk(_fhk),
|
||||
flags(_flags) {
|
||||
|
||||
fh.fh_type = (parent->is_root() || (flags & FLAG_DIRECTORY))
|
||||
? RGW_FS_TYPE_DIRECTORY : RGW_FS_TYPE_FILE;
|
||||
if (parent->is_root()) {
|
||||
fh.fh_type = RGW_FS_TYPE_DIRECTORY;
|
||||
flags |= FLAG_BUCKET;
|
||||
} else {
|
||||
bucket = (parent->flags & FLAG_BUCKET) ? parent
|
||||
: parent->bucket;
|
||||
fh.fh_type = (flags & FLAG_DIRECTORY) ? RGW_FS_TYPE_DIRECTORY
|
||||
: RGW_FS_TYPE_FILE;
|
||||
}
|
||||
|
||||
depth = parent->depth + 1;
|
||||
|
||||
@ -249,10 +260,7 @@ namespace rgw {
|
||||
const std::string& bucket_name() const {
|
||||
if (is_root())
|
||||
return root_name;
|
||||
if (is_object()) {
|
||||
return parent->object_name();
|
||||
}
|
||||
return name;
|
||||
return bucket->object_name();
|
||||
}
|
||||
|
||||
const std::string& object_name() const { return name; }
|
||||
@ -312,7 +320,7 @@ namespace rgw {
|
||||
|
||||
bool is_open() const { return flags & FLAG_OPEN; }
|
||||
bool is_root() const { return flags & FLAG_ROOT; }
|
||||
bool is_bucket() const { return (fh.fh_type == RGW_FS_TYPE_DIRECTORY); }
|
||||
bool is_bucket() const { return flags & FLAG_BUCKET; }
|
||||
bool is_object() const { return (fh.fh_type == RGW_FS_TYPE_FILE); }
|
||||
bool creating() const { return flags & FLAG_CREATE; }
|
||||
bool pseudo() const { return flags & FLAG_PSEUDO; }
|
||||
@ -516,9 +524,8 @@ namespace rgw {
|
||||
return fhr;
|
||||
}
|
||||
|
||||
LookupFHResult stat_leaf(RGWFileHandle* parent,
|
||||
const char *path,
|
||||
uint32_t flags);
|
||||
LookupFHResult stat_leaf(RGWFileHandle* parent, const char *path,
|
||||
uint32_t flags);
|
||||
|
||||
/* find or create an RGWFileHandle */
|
||||
RGWFileHandle* lookup_handle(struct rgw_fh_hk fh_hk) {
|
||||
@ -557,7 +564,7 @@ namespace rgw {
|
||||
}; /* RGWLibFS */
|
||||
|
||||
static inline std::string make_uri(const std::string& bucket_name,
|
||||
const std::string& object_name) {
|
||||
const std::string& object_name) {
|
||||
std::string uri("/");
|
||||
uri.reserve(bucket_name.length() + object_name.length() + 2);
|
||||
uri += bucket_name;
|
||||
@ -1208,6 +1215,88 @@ public:
|
||||
|
||||
}; /* RGWStatObjRequest */
|
||||
|
||||
class RGWStatLeafRequest : public RGWLibRequest,
|
||||
public RGWListBucket /* RGWOp */
|
||||
{
|
||||
public:
|
||||
const std::string& bucket;
|
||||
std::string path;
|
||||
bool matched;
|
||||
|
||||
RGWStatLeafRequest(CephContext* _cct, RGWUserInfo *_user,
|
||||
const std::string& _bucket, const std::string& _path)
|
||||
: RGWLibRequest(_cct, _user), bucket(_bucket), path(_path),
|
||||
matched(false) {
|
||||
default_max = 2; // logical max {"foo", "foo/"}
|
||||
magic = 79;
|
||||
op = this;
|
||||
}
|
||||
|
||||
virtual bool only_bucket() { return false; }
|
||||
|
||||
virtual int op_init() {
|
||||
// assign store, s, and dialect_handler
|
||||
RGWObjectCtx* rados_ctx
|
||||
= static_cast<RGWObjectCtx*>(get_state()->obj_ctx);
|
||||
// framework promises to call op_init after parent init
|
||||
assert(rados_ctx);
|
||||
RGWOp::init(rados_ctx->store, get_state(), this);
|
||||
op = this; // assign self as op: REQUIRED
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int header_init() {
|
||||
|
||||
struct req_state* s = get_state();
|
||||
s->info.method = "GET";
|
||||
s->op = OP_GET;
|
||||
|
||||
/* XXX derp derp derp */
|
||||
std::string uri = "/" + bucket;
|
||||
s->relative_uri = uri;
|
||||
s->info.request_uri = uri; // XXX
|
||||
s->info.effective_uri = uri;
|
||||
s->info.request_params = "";
|
||||
s->info.domain = ""; /* XXX ? */
|
||||
|
||||
// woo
|
||||
s->user = user;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int get_params() {
|
||||
// XXX S3
|
||||
struct req_state* s = get_state();
|
||||
list_versions = s->info.args.exists("versions");
|
||||
if (!list_versions) {
|
||||
marker = s->info.args.get("marker");
|
||||
} else {
|
||||
marker.name = s->info.args.get("key-marker");
|
||||
marker.instance = s->info.args.get("version-id-marker");
|
||||
}
|
||||
max_keys = default_max; // 2
|
||||
prefix = path;
|
||||
delimiter = "/";
|
||||
#if 0 /* XXX? */
|
||||
encoding_type = s->info.args.get("encoding-type");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void send_response() {
|
||||
for (const auto& iter : objs) {
|
||||
path = iter.key.name;
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void send_versioned_response() {
|
||||
send_response();
|
||||
}
|
||||
}; /* RGWStatLeafRequest */
|
||||
|
||||
} /* namespace rgw */
|
||||
|
||||
#endif /* RGW_FILE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user