From eed7f726c5d3074142203db856782ee0a8cd0874 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Mon, 19 Jul 2010 16:20:34 -0700 Subject: [PATCH] rgw: lay groundwork for chunky read/write --- src/rgw/rgw_access.h | 36 ++++++--- src/rgw/rgw_fs.cc | 181 ++++++++++++++++++++++++++++++------------- src/rgw/rgw_fs.h | 18 +++-- src/rgw/rgw_op.cc | 31 +++++++- src/rgw/rgw_op.h | 2 +- src/rgw/rgw_rados.cc | 149 +++++++++++++++++++++++++++-------- src/rgw/rgw_rados.h | 21 ++++- src/rgw/rgw_rest.cc | 9 ++- src/rgw/rgw_rest.h | 9 ++- src/rgw/rgw_user.cc | 38 ++++++--- 10 files changed, 371 insertions(+), 123 deletions(-) diff --git a/src/rgw/rgw_access.h b/src/rgw/rgw_access.h index 210d86f861fea..d486219158093 100644 --- a/src/rgw/rgw_access.h +++ b/src/rgw/rgw_access.h @@ -43,9 +43,19 @@ public: virtual int create_bucket(std::string& id, std::string& bucket, map& attrs, uint64_t auid=0) = 0; /** write an object to the storage device in the appropriate pool with the given stats */ - virtual int put_obj(std::string& id, std::string& bucket, std::string& obj, const char *data, size_t size, - time_t *mtime, + virtual int put_obj_meta(std::string& id, std::string& bucket, std::string& obj, time_t *mtime, map& attrs) = 0; + virtual int put_obj_data(std::string& id, std::string& bucket, std::string& obj, const char *data, + off_t ofs, size_t len, time_t *mtime) = 0; + + int put_obj(std::string& id, std::string& bucket, std::string& obj, const char *data, size_t len, + time_t *mtime, map& attrs) { + int ret = put_obj_meta(id, bucket, obj, NULL, attrs); + if (ret >= 0) + ret = put_obj_data(id, bucket, obj, data, 0, len, mtime); + return ret; + } + /** * Copy an object. * id: unused (well, it's passed to put_obj) @@ -108,15 +118,19 @@ public: * (if get_data==true) length of read data, * (if get_data==false) length of the object */ - virtual int get_obj(std::string& bucket, std::string& obj, - char **data, off_t ofs, off_t end, - map *attrs, - const time_t *mod_ptr, - const time_t *unmod_ptr, - const char *if_match, - const char *if_nomatch, - bool get_data, - struct rgw_err *err) = 0; + virtual int prepare_get_obj(std::string& bucket, std::string& obj, + off_t ofs, off_t *end, + map *attrs, + const time_t *mod_ptr, + const time_t *unmod_ptr, + const char *if_match, + const char *if_nomatch, + bool get_data, + void **handle, + struct rgw_err *err) = 0; + + virtual int get_obj(void *handle, std::string& bucket, std::string& oid, + char **data, off_t ofs, off_t end) = 0; /** * Get the attributes for an object. diff --git a/src/rgw/rgw_fs.cc b/src/rgw/rgw_fs.cc index aa4c9a9f6490a..a8a3106f42718 100644 --- a/src/rgw/rgw_fs.cc +++ b/src/rgw/rgw_fs.cc @@ -172,9 +172,8 @@ int RGWFS::create_bucket(std::string& id, std::string& bucket, map& attrs) +int RGWFS::put_obj_meta(std::string& id, std::string& bucket, std::string& obj, + time_t *mtime, map& attrs) { int len = strlen(DIR_NAME) + 1 + bucket.size() + 1 + obj.size() + 1; char buf[len]; @@ -193,31 +192,58 @@ int RGWFS::put_obj(std::string& id, std::string& bucket, std::string& obj, const if (bl.length()) { r = fsetxattr(fd, name.c_str(), bl.c_str(), bl.length(), 0); - if (r < 0) { - r = -errno; - close(fd); - return r; - } + if (r < 0) + goto done_err; } } - r = write(fd, data, size); - if (r < 0) { - r = -errno; - close(fd); - unlink(buf); - return r; + if (mtime) { + struct stat st; + r = fstat(fd, &st); + if (r < 0) + goto done_err; + *mtime = st.st_mtime; } + r = close(fd); + if (r < 0) + return -errno; + + return 0; +done_err: + r = -errno; + close(fd); + unlink(buf); + return -errno; +} + +int RGWFS::put_obj_data(std::string& id, std::string& bucket, std::string& obj, const char *data, + off_t ofs, size_t size, time_t *mtime) +{ + int len = strlen(DIR_NAME) + 1 + bucket.size() + 1 + obj.size() + 1; + char buf[len]; + snprintf(buf, len, "%s/%s/%s", DIR_NAME, bucket.c_str(), obj.c_str()); + int fd; + + fd = open(buf, O_CREAT | O_WRONLY, 0755); + if (fd < 0) + return -errno; + + int r; + + r = lseek(fd, ofs, SEEK_SET); + if (r < 0) + goto done_err; + + r = write(fd, data, size); + if (r < 0) + goto done_err; + if (mtime) { struct stat st; r = fstat(fd, &st); - if (r < 0) { - r = -errno; - close(fd); - unlink(buf); - return -errno; - } + if (r < 0) + goto done_err; *mtime = st.st_mtime; } @@ -226,6 +252,11 @@ int RGWFS::put_obj(std::string& id, std::string& bucket, std::string& obj, const return -errno; return 0; +done_err: + r = -errno; + close(fd); + unlink(buf); + return r; } int RGWFS::copy_obj(std::string& id, std::string& dest_bucket, std::string& dest_obj, @@ -240,12 +271,21 @@ int RGWFS::copy_obj(std::string& id, std::string& dest_bucket, std::string& dest { int ret; char *data; + void *handle; + off_t ofs = 0, end = -1; map attrset; - ret = get_obj(src_bucket, src_obj, &data, 0, -1, &attrset, - mod_ptr, unmod_ptr, if_match, if_nomatch, true, err); + ret = prepare_get_obj(src_bucket, src_obj, 0, &end, &attrset, mod_ptr, unmod_ptr, + if_match, if_nomatch, true, &handle, err); if (ret < 0) return ret; + + do { + ret = get_obj(handle, src_bucket, src_obj, &data, ofs, end); + if (ret < 0) + return ret; + ofs += ret; + } while (ofs <= end); map::iterator iter; for (iter = attrs.begin(); iter != attrs.end(); ++iter) { @@ -375,14 +415,15 @@ int RGWFS::set_attr(std::string& bucket, std::string& obj, return ret; } -int RGWFS::get_obj(std::string& bucket, std::string& obj, - char **data, off_t ofs, off_t end, +int RGWFS::prepare_get_obj(std::string& bucket, std::string& obj, + off_t ofs, off_t *end, map *attrs, const time_t *mod_ptr, const time_t *unmod_ptr, const char *if_match, const char *if_nomatch, bool get_data, + void **handle, struct rgw_err *err) { int len = strlen(DIR_NAME) + 1 + bucket.size() + 1 + obj.size() + 1; @@ -390,31 +431,43 @@ int RGWFS::get_obj(std::string& bucket, std::string& obj, int fd; struct stat st; int r = -EINVAL; - size_t max_len, pos; + size_t max_len; char *etag = NULL; + off_t size; + + + GetObjState *state = new GetObjState; + if (!state) + return -ENOMEM; snprintf(buf, len, "%s/%s/%s", DIR_NAME, bucket.c_str(), obj.c_str()); fd = open(buf, O_RDONLY, 0755); - if (fd < 0) - return -errno; + if (fd < 0) { + r = -errno; + goto done_err; + } + + state->fd = fd; r = fstat(fd, &st); if (r < 0) return -errno; - if (end < 0) - end = st.st_size - 1; + size = st.st_size; + + if (*end < 0) + *end = size - 1; - max_len = end - ofs + 1; + max_len = *end + 1 - ofs; r = -ECANCELED; if (mod_ptr) { if (st.st_mtime < *mod_ptr) { err->num = "304"; err->code = "PreconditionFailed"; - goto done; + goto done_err; } } @@ -422,13 +475,13 @@ int RGWFS::get_obj(std::string& bucket, std::string& obj, if (st.st_mtime >= *mod_ptr) { err->num = "412"; err->code = "PreconditionFailed"; - goto done; + goto done_err; } } if (if_match || if_nomatch) { r = get_attr(RGW_ATTR_ETAG, fd, &etag); if (r < 0) - goto done; + goto done_err; r = -ECANCELED; if (if_match) { @@ -436,7 +489,7 @@ int RGWFS::get_obj(std::string& bucket, std::string& obj, if (strcmp(if_match, etag)) { err->num = "412"; err->code = "PreconditionFailed"; - goto done; + goto done_err; } } @@ -445,48 +498,72 @@ int RGWFS::get_obj(std::string& bucket, std::string& obj, if (strcmp(if_nomatch, etag) == 0) { err->num = "412"; err->code = "PreconditionFailed"; - goto done; + goto done_err; } } } + free(etag); + if (!get_data) { r = max_len; goto done; } - *data = (char *)malloc(max_len); - if (!*data) { - r = -ENOMEM; - goto done; - } - pos = 0; - while (pos < max_len) { - r = read(fd, (*data) + pos, max_len); + r = 0; +done: + return r; + +done_err: + delete state; + if (fd >= 0) + close(fd); + return r; +} + +int RGWFS::get_obj(void *handle, std::string& bucket, std::string& obj, + char **data, off_t ofs, off_t end) +{ + uint64_t len; + bufferlist bl; + int r = 0; + + GetObjState *state = (GetObjState *)handle; + + if (end <= 0) + len = 0; + else + len = end - ofs + 1; + off_t pos = 0; + + while (pos < (off_t)len) { + r = read(state->fd, (*data) + pos, len - pos); if (r > 0) { pos += r; } else { if (!r) { - cerr << "pos=" << pos << " r=" << r << " max_len=" << max_len << endl; + cerr << "pos=" << pos << " r=" << r << " len=" << len << endl; r = -EIO; /* should not happen as we validated file size earlier */ - goto done; + break; } switch (errno) { case EINTR: break; default: r = -errno; - goto done; + break; } } - } + } - r = max_len; -done: - free(etag); - close(fd); + if (r >= 0) + r = len; + + if (r < 0 || !len || (off_t)(ofs + len - 1) == end) { + close(state->fd); + delete state; + } return r; } - diff --git a/src/rgw/rgw_fs.h b/src/rgw/rgw_fs.h index 702fae24705be..95cedfbc17fe1 100644 --- a/src/rgw/rgw_fs.h +++ b/src/rgw/rgw_fs.h @@ -6,6 +6,9 @@ class RGWFS : public RGWAccess { + struct GetObjState { + int fd; + }; public: int list_buckets_init(std::string& id, RGWAccessHandle *handle); int list_buckets_next(std::string& id, RGWObjEnt& obj, RGWAccessHandle *handle); @@ -14,9 +17,10 @@ public: std::string& marker, std::vector& result, map& common_prefixes); int create_bucket(std::string& id, std::string& bucket, map& attrs, uint64_t auid=0); - int put_obj(std::string& id, std::string& bucket, std::string& obj, const char *data, size_t size, - time_t *mtime, + int put_obj_meta(std::string& id, std::string& bucket, std::string& obj, time_t *mtime, map& attrs); + int put_obj_data(std::string& id, std::string& bucket, std::string& obj, const char *data, + off_t ofs, size_t size, time_t *mtime); int copy_obj(std::string& id, std::string& dest_bucket, std::string& dest_obj, std::string& src_bucket, std::string& src_obj, time_t *mtime, @@ -36,15 +40,19 @@ public: int set_attr(std::string& bucket, std::string& obj, const char *name, bufferlist& bl); - int get_obj(std::string& bucket, std::string& obj, - char **data, off_t ofs, off_t end, - map *attrs, + int prepare_get_obj(std::string& bucket, std::string& obj, + off_t ofs, off_t *end, + map *attrs, const time_t *mod_ptr, const time_t *unmod_ptr, const char *if_match, const char *if_nomatch, bool get_data, + void **handle, struct rgw_err *err); + + int get_obj(void *handle, std::string& bucket, std::string& obj, + char **data, off_t ofs, off_t end); }; #endif diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 68406ce1558ef..fae8c62d0140d 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -123,6 +123,8 @@ int read_acls(struct req_state *s, bool only_bucket) void RGWGetObj::execute() { + void *handle; + if (!verify_permission(s, RGW_PERM_READ)) { ret = -EACCES; goto done; @@ -134,13 +136,34 @@ void RGWGetObj::execute() init_common(); - len = rgwstore->get_obj(s->bucket_str, s->object_str, &data, ofs, end, &attrs, - mod_ptr, unmod_ptr, if_match, if_nomatch, get_data, &err); - if (len < 0) + len = rgwstore->prepare_get_obj(s->bucket_str, s->object_str, ofs, &end, &attrs, mod_ptr, + unmod_ptr, if_match, if_nomatch, get_data, &handle, &err); + + if (len < 0) { ret = len; + goto done; + } + + if (!get_data) + goto done; + + while (ofs <= end) { + len = rgwstore->get_obj(handle, s->bucket_str, s->object_str, &data, ofs, end); + if (len < 0) { + ret = len; + goto done; + } + + ofs += len; + send_response(handle); + free(data); + } + + return; done: - send_response(); + send_response(handle); + free(data); } int RGWGetObj::init_common() diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 36ea6d552a891..8bf432044c745 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -81,7 +81,7 @@ public: void execute(); virtual int get_params() = 0; - virtual int send_response() = 0; + virtual int send_response(void *handle) = 0; }; class RGWListBuckets : public RGWOp { diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index af026959de209..bbcc619774857 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -117,6 +117,11 @@ static int open_pool(string& bucket, rados_pool_t *pool) { return rados->open_pool(bucket.c_str(), pool); } + +static int close_pool(rados_pool_t pool) +{ + return rados->close_pool(pool); +} /** * get listing of the objects in a bucket. * id: ignored. @@ -244,9 +249,8 @@ int RGWRados::create_bucket(std::string& id, std::string& bucket, map& attrs) +int RGWRados::put_obj_meta(std::string& id, std::string& bucket, std::string& oid, + time_t *mtime, map& attrs) { rados_pool_t pool; @@ -266,9 +270,40 @@ int RGWRados::put_obj(std::string& id, std::string& bucket, std::string& oid, co } } + if (mtime) { + r = rados->stat(pool, oid, NULL, mtime); + if (r < 0) + return r; + } + + close_pool(pool); + + return 0; +} + +/** + * Write/overwrite an object to the bucket storage. + * id: ignored + * bucket: the bucket to store the object in + * obj: the object name/key + * data: the object contents/value + * size: the amount of data to write (data must be this long) + * mtime: if non-NULL, writes the given mtime to the bucket storage + * attrs: all the given attrs are written to bucket storage for the given object + * Returns: 0 on success, -ERR# otherwise. + */ +int RGWRados::put_obj_data(std::string& id, std::string& bucket, std::string& oid, const char *data, off_t ofs, size_t len, + time_t *mtime) +{ + rados_pool_t pool; + + int r = open_pool(bucket, &pool); + if (r < 0) + return r; + bufferlist bl; - bl.append(data, size); - r = rados->write_full(pool, oid, bl); + bl.append(data, len); + r = rados->write(pool, oid, ofs, bl, len); if (r < 0) return r; @@ -278,6 +313,8 @@ int RGWRados::put_obj(std::string& id, std::string& bucket, std::string& oid, co return r; } + close_pool(pool); + return 0; } /** @@ -303,27 +340,46 @@ int RGWRados::copy_obj(std::string& id, std::string& dest_bucket, std::string& d map& attrs, /* in/out */ struct rgw_err *err) { - int ret; + int ret, r; char *data; + off_t ofs = 0, end = -1; + map::iterator iter; cerr << "copy " << src_bucket << ":" << src_obj << " => " << dest_bucket << ":" << dest_obj << std::endl; + void *handle; + map attrset; - ret = get_obj(src_bucket, src_obj, &data, 0, -1, &attrset, - mod_ptr, unmod_ptr, if_match, if_nomatch, true, err); + ret = prepare_get_obj(src_bucket, src_obj, ofs, &end, &attrset, + mod_ptr, unmod_ptr, if_match, if_nomatch, true, &handle, err); if (ret < 0) return ret; - map::iterator iter; + do { + ret = get_obj(&handle, src_bucket, src_obj, &data, ofs, end); + if (ret < 0) + return ret; + + r = put_obj_data(id, dest_bucket, dest_obj, data, ofs, ret, NULL); + free(data); + if (r < 0) + goto done_err; + + ofs += ret; + } while (ofs <= end); + for (iter = attrs.begin(); iter != attrs.end(); ++iter) { attrset[iter->first] = iter->second; } attrs = attrset; - ret = put_obj(id, dest_bucket, dest_obj, data, ret, mtime, attrs); + ret = put_obj_meta(id, dest_bucket, dest_obj, mtime, attrs); return ret; +done_err: + /* FIXME: need to free handle */ + return r; } /** @@ -447,40 +503,45 @@ int RGWRados::set_attr(std::string& bucket, std::string& oid, * (if get_data==true) length of read data, * (if get_data==false) length of the object */ -int RGWRados::get_obj(std::string& bucket, std::string& oid, - char **data, off_t ofs, off_t end, +int RGWRados::prepare_get_obj(std::string& bucket, std::string& oid, + off_t ofs, off_t *end, map *attrs, const time_t *mod_ptr, const time_t *unmod_ptr, const char *if_match, const char *if_nomatch, bool get_data, + void **handle, struct rgw_err *err) { int r = -EINVAL; - uint64_t size, len; + uint64_t size; bufferlist etag; time_t mtime; - bufferlist bl; - rados_pool_t pool; map::iterator iter; - r = open_pool(bucket, &pool); + GetObjState *state = new GetObjState; + if (!state) + return -ENOMEM; + + *handle = state; + + r = open_pool(bucket, &state->pool); if (r < 0) - return r; + goto done_err; - r = rados->stat(pool, oid, &size, &mtime); + r = rados->stat(state->pool, oid, &size, &mtime); if (r < 0) - return r; + goto done_err; if (attrs) { - r = rados->getxattrs(pool, oid, *attrs); + r = rados->getxattrs(state->pool, oid, *attrs); for (iter = attrs->begin(); iter != attrs->end(); ++iter) { cerr << "xattr: " << iter->first << std::endl; } if (r < 0) - return r; + goto done_err; } @@ -489,7 +550,7 @@ int RGWRados::get_obj(std::string& bucket, std::string& oid, if (mtime < *mod_ptr) { err->num = "304"; err->code = "PreconditionFailed"; - goto done; + goto done_err; } } @@ -497,13 +558,13 @@ int RGWRados::get_obj(std::string& bucket, std::string& oid, if (mtime >= *mod_ptr) { err->num = "412"; err->code = "PreconditionFailed"; - goto done; + goto done_err; } } if (if_match || if_nomatch) { r = get_attr(bucket, oid, RGW_ATTR_ETAG, etag); if (r < 0) - goto done; + goto done_err; r = -ECANCELED; if (if_match) { @@ -511,7 +572,7 @@ int RGWRados::get_obj(std::string& bucket, std::string& oid, if (strcmp(if_match, etag.c_str())) { err->num = "412"; err->code = "PreconditionFailed"; - goto done; + goto done_err; } } @@ -520,15 +581,33 @@ int RGWRados::get_obj(std::string& bucket, std::string& oid, if (strcmp(if_nomatch, etag.c_str()) == 0) { err->num = "412"; err->code = "PreconditionFailed"; - goto done; + goto done_err; } } } - if (!get_data) { - r = size; - goto done; - } + if (*end < 0) + *end = size - 1; + + if (!get_data) + return size; + + return 0; + +done_err: + delete state; + *handle = NULL; + return r; +} + +int RGWRados::get_obj(void *handle, + std::string& bucket, std::string& oid, + char **data, off_t ofs, off_t end) +{ + uint64_t len; + bufferlist bl; + + GetObjState *state = (GetObjState *)handle; if (end <= 0) len = 0; @@ -536,18 +615,20 @@ int RGWRados::get_obj(std::string& bucket, std::string& oid, len = end - ofs + 1; cout << "rados->read ofs=" << ofs << " len=" << len << std::endl; - r = rados->read(pool, oid, ofs, bl, len); + int r = rados->read(state->pool, oid, ofs, bl, len); cout << "rados->read r=" << r << std::endl; - if (r < 0) - return r; if (r > 0) { *data = (char *)malloc(r); memcpy(*data, bl.c_str(), bl.length()); } -done: + if (r < 0 || !len || (ofs + len - 1 == end)) { + rados->close_pool(state->pool); + delete state; + } return r; + } diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 27552177772b9..3684a91458469 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -9,6 +9,14 @@ class RGWRados : public RGWAccess { /** Open the pool used as root for this gateway */ int open_root_pool(rados_pool_t *pool); + + struct GetObjState { + rados_pool_t pool; + bool sent_data; + + GetObjState() : pool(0), sent_data(false) {} + }; + public: /** Initialize the RADOS instance and prepare to do other ops */ int initialize(int argc, char *argv[]); @@ -31,9 +39,10 @@ public: int create_bucket(std::string& id, std::string& bucket, map& attrs, uint64_t auid=0); /** Write/overwrite an object to the bucket storage. */ - int put_obj(std::string& id, std::string& bucket, std::string& obj, const char *data, size_t size, - time_t *mtime, + int put_obj_meta(std::string& id, std::string& bucket, std::string& obj, time_t *mtime, map& attrs); + int put_obj_data(std::string& id, std::string& bucket, std::string& obj, const char *data, + off_t ofs, size_t len, time_t *mtime); /** Copy an object, with many extra options */ int copy_obj(std::string& id, std::string& dest_bucket, std::string& dest_obj, std::string& src_bucket, std::string& src_obj, @@ -59,15 +68,19 @@ public: const char *name, bufferlist& bl); /** Get data about an object out of RADOS and into memory. */ - int get_obj(std::string& bucket, std::string& obj, - char **data, off_t ofs, off_t end, + int prepare_get_obj(std::string& bucket, std::string& obj, + off_t ofs, off_t *end, map *attrs, const time_t *mod_ptr, const time_t *unmod_ptr, const char *if_match, const char *if_nomatch, bool get_data, + void **handle, struct rgw_err *err); + + int get_obj(void *handle, std::string& bucket, std::string& oid, + char **data, off_t ofs, off_t end); }; #endif diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index ede6bbcfa38a2..f34d1ff6ab68d 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -194,10 +194,13 @@ int RGWGetObj_REST::get_params() return 0; } -int RGWGetObj_REST::send_response() +int RGWGetObj_REST::send_response(void *handle) { const char *content_type = NULL; + if (sent_header) + goto send_data; + if (get_data && !ret) { dump_content_length(s, len); } @@ -222,6 +225,10 @@ int RGWGetObj_REST::send_response() } dump_errno(s, ret, &err); end_header(s, content_type); + + sent_header = true; + +send_data: if (get_data && !ret) { FCGX_PutStr(data, len, s->fcgx->out); } diff --git a/src/rgw/rgw_rest.h b/src/rgw/rgw_rest.h index 6f0b167af3686..20e5f8e9f021b 100644 --- a/src/rgw/rgw_rest.h +++ b/src/rgw/rgw_rest.h @@ -5,11 +5,18 @@ class RGWGetObj_REST : public RGWGetObj { + bool sent_header; public: RGWGetObj_REST() {} ~RGWGetObj_REST() {} + + virtual void init(struct req_state *s) { + RGWGetObj::init(s); + sent_header = false; + } + int get_params(); - int send_response(); + int send_response(void *handle); }; class RGWListBuckets_REST : public RGWListBuckets { diff --git a/src/rgw/rgw_user.cc b/src/rgw/rgw_user.cc index 5152b95fb2b83..07f68f867e54a 100644 --- a/src/rgw/rgw_user.cc +++ b/src/rgw/rgw_user.cc @@ -25,15 +25,24 @@ int rgw_get_user_info(string user_id, RGWUserInfo& info) int ret; char *data; struct rgw_err err; + void *handle; + off_t ofs = 0, end = -1; - ret = rgwstore->get_obj(ui_bucket, user_id, &data, 0, -1, NULL, NULL, NULL, NULL, NULL, true, &err); - if (ret < 0) { + ret = rgwstore->prepare_get_obj(ui_bucket, user_id, ofs, &end, NULL, NULL, NULL, NULL, NULL, true, &handle, &err); + if (ret < 0) return ret; - } - bl.append(data, ret); + do { + ret = rgwstore->get_obj(handle, ui_bucket, user_id, &data, ofs, end); + if (ret < 0) { + return ret; + } + bl.append(data, ret); + free(data); + ofs += ret; + } while (ofs <= end); + bufferlist::iterator iter = bl.begin(); info.decode(iter); - free(data); return 0; } @@ -100,16 +109,25 @@ int rgw_get_uid_by_email(string& email, string& user_id) char *data; struct rgw_err err; RGWUID uid; + void *handle; + off_t ofs = 0, end = -1; - ret = rgwstore->get_obj(ui_email_bucket, email, &data, 0, -1, NULL, NULL, NULL, NULL, NULL, true, &err); - if (ret < 0) { + ret = rgwstore->prepare_get_obj(ui_email_bucket, email, ofs, &end, NULL, NULL, + NULL, NULL, NULL, true, &handle, &err); + if (ret < 0) return ret; - } - bl.append(data, ret); + do { + ret = rgwstore->get_obj(handle, ui_email_bucket, email, &data, ofs, end); + if (ret < 0) + return ret; + ofs += ret; + bl.append(data, ret); + free(data); + } while (ofs <= end); + bufferlist::iterator iter = bl.begin(); uid.decode(iter); user_id = uid.user_id; - free(data); return 0; } -- 2.39.5