--- /dev/null
+rgw_main: contains the web server interface and checks user access keys.
+rgw_user: defines the RGWUserBuckets class and contains global functions
+to get/store user info, get the anon user, and get UIDs from email.
+rgw_user: defines the RGWUID class with some basic bookkeeping operations
+rgw_common: houses data types and functions
+rgw_access: abstract class providing interface for storage mechanisms
+rgw_acl.h: Many different classes, some decoding XML, some encoding XML, some doing checks for owner and permissions.
+rgw_fs: rgw_access based on the local fs.
+rgw_rados: rgw_access based on an actual RADOS cluster.
+rgw_admin: Administer the cluster -- create users, look at the state, etc.
+rgw_op: Define the different operations as objects for easy tracking.
+rgw_REST: extend the classes in rgw_op for a REST interface
+
+user IDs are strings, as with S3.
+
+buckets:
+ui_email_bucket: hold objects named by email and containing encoded RGWUIDs
+ui_bucket: holds objects named by user_id and containing encoded RGWUserInfos
+root_bucket: holds objects corresponding to the other buckets, with ACLs in their attrs.
\ No newline at end of file
#include "rgw_common.h"
-
+/**
+ * Abstract class defining the interface for storage devices used by RGW.
+ */
class RGWAccess {
public:
+ /** do all necessary setup of the storage device */
virtual int initialize(int argc, char *argv[]) { return 0; }
+ /** prepare a listing of all buckets. */
virtual int list_buckets_init(std::string& id, RGWAccessHandle *handle) = 0;
+ /** get the next bucket in the provided listing context. */
virtual int list_buckets_next(std::string& id, RGWObjEnt& obj, RGWAccessHandle *handle) = 0;
+ /**
+ * get listing of the objects in a bucket.
+ * id: ignored in current implementations
+ * bucket: bucket to list contents of
+ * max: maximum number of results to return
+ * prefix: only return results that match this prefix
+ * delim: do not include results that match this string.
+ * Any skipped results will have the matching portion of their name
+ * inserted in common_prefixes with a "true" mark.
+ * marker: if filled in, begin the listing with this object.
+ * result: the objects are put in here.
+ * common_prefixes: if delim is filled in, any matching prefixes are placed
+ * here.
+ */
virtual int list_objects(std::string& id, std::string& bucket, int max, std::string& prefix, std::string& delim,
std::string& marker, std::vector<RGWObjEnt>& result, map<string, bool>& common_prefixes) = 0;
+ /** Create a new bucket*/
virtual int create_bucket(std::string& id, std::string& bucket, map<nstring, bufferlist>& attrs) = 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,
map<nstring, bufferlist>& attrs) = 0;
-
+ /**
+ * Copy an object.
+ * id: unused (well, it's passed to put_obj)
+ * dest_bucket: the bucket to copy into
+ * dest_obj: the object to copy into
+ * src_bucket: the bucket to copy from
+ * src_obj: the object to copy from
+ * mod_ptr, unmod_ptr, if_match, if_nomatch: as used in get_obj
+ * attrs: these are placed on the new object IN ADDITION to
+ * (or overwriting) any attrs copied from the original object
+ * err: stores any errors resulting from the get of the original object
+ * Returns: 0 on success, -ERR# otherwise.
+ */
virtual 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,
const char *if_nomatch,
map<nstring, bufferlist>& attrs,
struct rgw_err *err) = 0;
+ /**
+ * Delete a bucket.
+ * id: unused in implementations
+ * bucket: the name of the bucket to delete
+ * Returns 0 on success, -ERR# otherwise.
+ */
virtual int delete_bucket(std::string& id, std::string& bucket) = 0;
+
+ /**
+ * Delete an object.
+ * id: unused in current implementations
+ * bucket: name of the bucket storing the object
+ * obj: name of the object to delete
+ * Returns: 0 on success, -ERR# otherwise.
+ */
virtual int delete_obj(std::string& id, std::string& bucket, std::string& obj) = 0;
+/**
+ * Get data about an object out of RADOS and into memory.
+ * bucket: name of the bucket the object is in.
+ * obj: name/key of the object to read
+ * data: if get_data==true, this pointer will be set
+ * to an address containing the object's data/value
+ * ofs: the offset of the object to read from
+ * end: the point in the object to stop reading
+ * attrs: if non-NULL, the pointed-to map will contain
+ * all the attrs of the object when this function returns
+ * mod_ptr: if non-NULL, compares the object's mtime to *mod_ptr,
+ * and if mtime is smaller it fails.
+ * unmod_ptr: if non-NULL, compares the object's mtime to *unmod_ptr,
+ * and if mtime is >= it fails.
+ * if_match/nomatch: if non-NULL, compares the object's etag attr
+ * to the string and, if it doesn't/does match, fails out.
+ * get_data: if true, the object's data/value will be read out, otherwise not
+ * err: Many errors will result in this structure being filled
+ * with extra informatin on the error.
+ * Returns: -ERR# on failure, otherwise
+ * (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<nstring, bufferlist> *attrs,
bool get_data,
struct rgw_err *err) = 0;
+ /**
+ * Get the attributes for an object.
+ * bucket: name of the bucket holding the object.
+ * obj: name of the object
+ * name: name of the attr to retrieve
+ * dest: bufferlist to store the result in
+ * Returns: 0 on success, -ERR# otherwise.
+ */
virtual int get_attr(std::string& bucket, std::string& obj,
const char *name, bufferlist& dest) = 0;
+ /**
+ * Set an attr on an object.
+ * bucket: name of the bucket holding the object
+ * obj: name of the object to set the attr on
+ * name: the attr to set
+ * bl: the contents of the attr
+ * Returns: 0 on success, -ERR# otherwise.
+ */
virtual int set_attr(std::string& bucket, std::string& obj,
const char *name, bufferlist& bl) = 0;
+ /**
+ * Given the name of the storage provider, initialize it
+ * with the given arguments.
+ */
static RGWAccess *init_storage_provider(const char *type, int argc, char *argv[]);
static RGWAccess *store;
};
};
};
+/**
+ * Represents a block of XML.
+ * Give the class an XML blob, and it will parse the blob into
+ * an attr_name->value map.
+ * This really ought to be an abstract class or something; it
+ * shouldn't be the startpoint for any parsing. Look at RGWXMLParser for that.
+ */
class XMLObj
{
int refcount;
};
WRITE_CLASS_ENCODER(RGWAccessControlPolicy)
+/**
+ * Interfaces with the webserver's XML handling code
+ * to parse it in a way that makes sense for the rgw.
+ */
class RGWXMLParser : public XMLObj
{
XML_Parser p;
#define RGW_ATTR_ACL RGW_ATTR_PREFIX "acl"
#define RGW_ATTR_ETAG RGW_ATTR_PREFIX "etag"
-#define RGW_ATTR_BUCKETS RGW_ATTR_PREFIX "buckets"
+#define RGW_ATTR_BUCKETS RGW_ATTR_PREFIX "buckets"
#define RGW_ATTR_META_PREFIX RGW_ATTR_PREFIX "x-amz-meta-"
#define RGW_ATTR_CONTENT_TYPE RGW_ATTR_PREFIX "content_type"
typedef void *RGWAccessHandle;
+/** Store error returns for output at a different point in the program */
struct rgw_err {
const char *num;
const char *code;
rgw_err() : num(NULL), code(NULL), message(NULL) {}
};
+/* Helper class used for XMLArgs parsing */
class NameVal
{
string str;
string& get_val() { return val; }
};
+/** Stores the XML arguments associated with the HTTP request in req_state*/
class XMLArgs
{
string str, empty_str;
public:
XMLArgs() {}
XMLArgs(string s) : str(s) {}
+ /** Set the arguments; as received */
void set(string s) { val_map.clear(); sub_resource.clear(); str = s; }
+ /** parse the received arguments */
int parse();
+ /** Get the value for a specific argument parameter */
string& get(string& name);
string& get(const char *name);
+ /** see if a parameter is contained in this XMLArgs */
bool exists(const char *name) {
map<string, string>::iterator iter = val_map.find(name);
return (iter != val_map.end());
};
WRITE_CLASS_ENCODER(RGWUserInfo)
-
+/** Store all the state necessary to complete and respond to an HTTP request*/
struct req_state {
struct fcgx_state *fcgx;
http_op op;
req_state() : acl(NULL) {}
};
+/** Store basic data on an object */
struct RGWObjEnt {
std::string name;
size_t size;
}
}
+/** */
extern int parse_time(const char *time_str, time_t *time);
+/** Check if a user has a permission on that ACL */
extern bool verify_permission(RGWAccessControlPolicy *policy, string& uid, int perm);
+/** Check if the req_state's user has the necessary permissions
+ * to do the requested action */
extern bool verify_permission(struct req_state *s, int perm);
+/** Convert an input URL into a sane object name
+ * by converting %-escaped strings into characters, etc*/
extern bool url_decode(string& src_str, string& dest_str);
FCGX_FPrintF(stream, format, __VA_ARGS__); \
} while (0)
+/*
+ * ?get the canonical amazon-style header for something?
+ */
static void get_canon_amz_hdr(struct req_state *s, string& dest)
{
dest = "";
}
}
+/*
+ * ?get the canonical representation of the object's location
+ */
static void get_canon_resource(struct req_state *s, string& dest)
{
if (s->host_bucket) {
}
}
+/*
+ * get the header authentication information required to
+ * compute a request's signature
+ */
static void get_auth_header(struct req_state *s, string& dest, bool qsr)
{
dest = "";
dest.append(canon_resource);
}
+/*
+ * calculate the sha1 value of a given msg and key
+ */
static void calc_hmac_sha1(const char *key, int key_len,
const char *msg, int msg_len,
char *dest, int *len) /* dest should be large enough to hold result */
cerr << "hmac=" << hex_str << std::endl;
}
+/*
+ * verify that a signed request comes from the keyholder
+ * by checking the signature against our locally-computed version
+ */
static bool verify_signature(struct req_state *s)
{
bool qsr = false;
static sighandler_t sighandler;
+/*
+ * ?print out the C++ errors to log in case it fails
+ */
static void godown(int signum)
{
BackTrace bt(0);
signal(SIGSEGV, sighandler);
}
+/*
+ * start up the RADOS connection and then handle HTTP messages as they come in
+ */
int main(int argc, char *argv[])
{
struct req_state s;
return r;
}
+/**
+ * Get the HTTP request metadata out of the req_state as a
+ * map(<attr_name, attr_contents>, where attr_name is RGW_ATTR_PREFIX.HTTP_NAME)
+ * s: The request state
+ * attrs: will be filled up with attrs mapped as <attr_name, attr_contents>
+ *
+ */
void get_request_metadata(struct req_state *s, map<nstring, bufferlist>& attrs)
{
map<string, string>::iterator iter;
}
}
+/**
+ * Get the AccessControlPolicy for an object off of disk.
+ * policy: must point to a valid RGWACL, and will be filled upon return.
+ * bucket: name of the bucket containing the object.
+ * object: name of the object to get the ACL for.
+ * Returns: 0 on success, -ERR# otherwise.
+ */
int read_acls(RGWAccessControlPolicy *policy, string& bucket, string& object)
{
bufferlist bl;
return ret;
}
+/**
+ * Get the AccessControlPolicy for a bucket or object off of disk.
+ * s: The req_state to draw information from.
+ * only_bucket: If true, reads the bucket ACL rather than the object ACL.
+ * Returns: 0 on success, -ERR# otherwise.
+ */
int read_acls(struct req_state *s, bool only_bucket)
{
int ret = 0;
+/**
+ * All operations via the rados gateway are carried out by
+ * small classes known as RGWOps. This class contains a req_state
+ * and each possible command is a subclass of this with a defined
+ * execute() method that does whatever the subclass name implies.
+ * These subclasses must be further subclassed (by interface type)
+ * to provide additional virtual methods such as send_response or get_params.
+ */
#ifndef __RGW_OP_H
#define __RGW_OP_H
struct req_state;
+/** Get the HTTP request metadata */
extern void get_request_metadata(struct req_state *s, map<nstring, bufferlist>& attrs);
+/**
+ * Get the ACL for an object off of disk. If you hold the req_state, use next
+ * method.
+ */
extern int read_acls(RGWAccessControlPolicy *policy, string& bucket, string& object);
+/** Get the ACL needed for a request off of disk.*/
extern int read_acls(struct req_state *s, bool only_bucket = false);
-
+/**
+ * Provide the base class for all ops.
+ */
class RGWOp {
protected:
struct req_state *s;
static string root_bucket(ROOT_BUCKET);
static rados_pool_t root_pool;
+/**
+ * Initialize the RADOS instance and prepare to do other ops
+ * Returns 0 on success, -ERR# on failure.
+ */
int RGWRados::initialize(int argc, char *argv[])
{
rados = new Rados();
return ret;
}
+/**
+ * Open the pool used as root for this gateway
+ * Returns: 0 on success, -ERR# otherwise.
+ */
int RGWRados::open_root_pool(rados_pool_t *pool)
{
int r = rados->open_pool(root_bucket.c_str(), pool);
RGWRadosListState() : pos(0) {}
};
+/**
+ * set up a bucket listing.
+ * id is ignored
+ * handle is filled in.
+ * Returns 0 on success, -ERR# otherwise.
+ */
int RGWRados::list_buckets_init(std::string& id, RGWAccessHandle *handle)
{
RGWRadosListState *state = new RGWRadosListState();
return 0;
}
+/**
+ * get the next bucket in the listing.
+ * id is ignored
+ * obj is filled in,
+ * handle is updated.
+ * returns 0 on success, -ERR# otherwise.
+ */
int RGWRados::list_buckets_next(std::string& id, RGWObjEnt& obj, RGWAccessHandle *handle)
{
RGWRadosListState *state = (RGWRadosListState *)*handle;
{
return rados->open_pool(bucket.c_str(), pool);
}
-
+/**
+ * get listing of the objects in a bucket.
+ * id: ignored.
+ * bucket: bucket to list contents of
+ * max: maximum number of results to return
+ * prefix: only return results that match this prefix
+ * delim: do not include results that match this string.
+ * Any skipped results will have the matching portion of their name
+ * inserted in common_prefixes with a "true" mark.
+ * marker: if filled in, begin the listing with this object.
+ * result: the objects are put in here.
+ * common_prefixes: if delim is filled in, any matching prefixes are placed
+ * here.
+ */
int RGWRados::list_objects(string& id, string& bucket, int max, string& prefix, string& delim,
string& marker, vector<RGWObjEnt>& result, map<string, bool>& common_prefixes)
{
return count;
}
-
+/**
+ * create a bucket with name bucket and the given list of attrs
+ * returns 0 on success, -ERR# otherwise.
+ */
int RGWRados::create_bucket(std::string& id, std::string& bucket, map<nstring, bufferlist>& attrs)
{
object_t bucket_oid(bucket.c_str());
return ret;
}
+/**
+ * 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(std::string& id, std::string& bucket, std::string& obj, const char *data, size_t size,
time_t *mtime,
map<nstring, bufferlist>& attrs)
return 0;
}
-
+/**
+ * Copy an object.
+ * id: unused (well, it's passed to put_obj)
+ * dest_bucket: the bucket to copy into
+ * dest_obj: the object to copy into
+ * src_bucket: the bucket to copy from
+ * src_obj: the object to copy from
+ * mod_ptr, unmod_ptr, if_match, if_nomatch: as used in get_obj
+ * attrs: these are placed on the new object IN ADDITION to
+ * (or overwriting) any attrs copied from the original object
+ * err: stores any errors resulting from the get of the original object
+ * Returns: 0 on success, -ERR# otherwise.
+ */
int RGWRados::copy_obj(std::string& id, std::string& dest_bucket, std::string& dest_obj,
std::string& src_bucket, std::string& src_obj,
time_t *mtime,
return ret;
}
-
+/**
+ * Delete a bucket.
+ * id: unused
+ * bucket: the name of the bucket to delete
+ * Returns 0 on success, -ERR# otherwise.
+ */
int RGWRados::delete_bucket(std::string& id, std::string& bucket)
{
rados_pool_t pool;
return 0;
}
-
+/**
+ * Delete an object.
+ * id: unused
+ * bucket: name of the bucket storing the object
+ * obj: name of the object to delete
+ * Returns: 0 on success, -ERR# otherwise.
+ */
int RGWRados::delete_obj(std::string& id, std::string& bucket, std::string& obj)
{
rados_pool_t pool;
return 0;
}
+/**
+ * Get the attributes for an object.
+ * bucket: name of the bucket holding the object.
+ * obj: name of the object
+ * name: name of the attr to retrieve
+ * dest: bufferlist to store the result in
+ * Returns: 0 on success, -ERR# otherwise.
+ */
int RGWRados::get_attr(std::string& bucket, std::string& obj,
const char *name, bufferlist& dest)
{
return 0;
}
+/**
+ * Set an attr on an object.
+ * bucket: name of the bucket holding the object
+ * obj: name of the object to set the attr on
+ * name: the attr to set
+ * bl: the contents of the attr
+ * Returns: 0 on success, -ERR# otherwise.
+ */
int RGWRados::set_attr(std::string& bucket, std::string& obj,
const char *name, bufferlist& bl)
{
return 0;
}
+/**
+ * Get data about an object out of RADOS and into memory.
+ * bucket: name of the bucket the object is in.
+ * obj: name/key of the object to read
+ * data: if get_data==true, this pointer will be set
+ * to an address containing the object's data/value
+ * ofs: the offset of the object to read from
+ * end: the point in the object to stop reading
+ * attrs: if non-NULL, the pointed-to map will contain
+ * all the attrs of the object when this function returns
+ * mod_ptr: if non-NULL, compares the object's mtime to *mod_ptr,
+ * and if mtime is smaller it fails.
+ * unmod_ptr: if non-NULL, compares the object's mtime to *unmod_ptr,
+ * and if mtime is >= it fails.
+ * if_match/nomatch: if non-NULL, compares the object's etag attr
+ * to the string and, if it doesn't/does match, fails out.
+ * get_data: if true, the object's data/value will be read out, otherwise not
+ * err: Many errors will result in this structure being filled
+ * with extra informatin on the error.
+ * Returns: -ERR# on failure, otherwise
+ * (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& obj,
char **data, off_t ofs, off_t end,
map<nstring, bufferlist> *attrs,
class RGWRados : public RGWAccess
{
+ /** Open the pool used as root for this gateway */
int open_root_pool(rados_pool_t *pool);
public:
+ /** Initialize the RADOS instance and prepare to do other ops */
int initialize(int argc, char *argv[]);
+ /** set up a bucket listing. id is ignored, handle is filled in. */
int list_buckets_init(std::string& id, RGWAccessHandle *handle);
+ /**
+ * get the next bucket in the listing. id is ignored, obj is filled in,
+ * handle is updated.
+ */
int list_buckets_next(std::string& id, RGWObjEnt& obj, RGWAccessHandle *handle);
+ /** get listing of the objects in a bucket */
int list_objects(std::string& id, std::string& bucket, int max, std::string& prefix, std::string& delim,
std::string& marker, std::vector<RGWObjEnt>& result, map<string, bool>& common_prefixes);
+ /**
+ * create a bucket with name bucket and the given list of attrs
+ * returns 0 on success, -ERR# otherwise.
+ */
int create_bucket(std::string& id, std::string& bucket, map<nstring, bufferlist>& attrs);
+
+ /** 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,
map<nstring, bufferlist>& attrs);
+ /** 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,
time_t *mtime,
const char *if_nomatch,
map<nstring, bufferlist>& attrs,
struct rgw_err *err);
+ /** delete a bucket*/
int delete_bucket(std::string& id, std::string& bucket);
+
+ /** Delete an object.*/
int delete_obj(std::string& id, std::string& bucket, std::string& obj);
+ /** Get the attributes for an object.*/
int get_attr(std::string& bucket, std::string& obj,
const char *name, bufferlist& dest);
+
+ /** Set an attr on an object. */
int set_attr(std::string& bucket, std::string& obj,
const char *name, bufferlist& bl);
- int get_obj(std::string& bucket, std::string& obj,
+ /** 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,
map<nstring, bufferlist> *attrs,
const time_t *mod_ptr,
static string ui_bucket = USER_INFO_BUCKET_NAME;
static string ui_email_bucket = USER_INFO_EMAIL_BUCKET_NAME;
+/**
+ * Get the info for a user out of storage.
+ * Returns: 0 on success, -ERR# on failure
+ */
int rgw_get_user_info(string user_id, RGWUserInfo& info)
{
bufferlist bl;
return 0;
}
+/**
+ * Get the anonymous (ie, unauthenticated) user info.
+ */
void rgw_get_anon_user(RGWUserInfo& info)
{
info.user_id = RGW_USER_ANON_ID;
info.secret_key.clear();
}
+/**
+ * Save the given user information to storage.
+ * Returns: 0 on success, -ERR# on failure.
+ */
int rgw_store_user_info(RGWUserInfo& info)
{
bufferlist bl;
return ret;
}
+/**
+ * Given an email, finds the user_id associated with it.
+ * returns: 0 on success, -ERR# on failure (including nonexistence)
+ */
int rgw_get_uid_by_email(string& email, string& user_id)
{
bufferlist bl;
return 0;
}
+/**
+ * Get all the buckets owned by a user and fill up an RGWUserBuckets with them.
+ * Returns: 0 on success, -ERR# on failure.
+ */
int rgw_get_user_buckets(string user_id, RGWUserBuckets& buckets)
{
bufferlist bl;
return 0;
}
+/**
+ * Store the set of buckets associated with a user.
+ * This completely overwrites any previously-stored list, so be careful!
+ * Returns 0 on success, -ERR# otherwise.
+ */
int rgw_put_user_buckets(string user_id, RGWUserBuckets& buckets)
{
bufferlist bl;
#define USER_INFO_BUCKET_NAME ".users"
#define USER_INFO_EMAIL_BUCKET_NAME ".users.email"
-
#define RGW_USER_ANON_ID "anonymous"
+/**
+ * A string wrapper that includes encode/decode functions
+ * for easily accessing a UID in all forms
+ */
struct RGWUID
{
string user_id;
};
WRITE_CLASS_ENCODER(RGWUID)
+/**
+ * Get the info for a user out of storage.
+ * Returns: 0 on success, -ERR# on failure
+ */
extern int rgw_get_user_info(string user_id, RGWUserInfo& info);
+/**
+ * Get the anonymous (ie, unauthenticated) user info.
+ */
extern void rgw_get_anon_user(RGWUserInfo& info);
+/**
+ * Save the given user information to storage.
+ * Returns: 0 on success, -ERR# on failure.
+ */
extern int rgw_store_user_info(RGWUserInfo& info);
+/**
+ * Given an email, finds the user_id associated with it.
+ * returns: 0 on success, -ERR# on failure (including nonexistence)
+ */
extern int rgw_get_uid_by_email(string& email, string& user_id);
+/**
+ * Store a list of the user's buckets, with associated functinos.
+ */
class RGWUserBuckets
{
map<string, RGWObjEnt> buckets;
void decode(bufferlist::iterator& bl) {
::decode(buckets, bl);
}
-
+ /**
+ * Check if the user owns a bucket by the given name.
+ */
bool owns(string& name) {
map<string, RGWObjEnt>::iterator iter;
iter = buckets.find(name);
return (iter != buckets.end());
}
+ /**
+ * Add a (created) bucket to the user's bucket list.
+ */
void add(RGWObjEnt& bucket) {
buckets[bucket.name] = bucket;
}
+ /**
+ * Remove a bucket from the user's list by name.
+ */
void remove(string& name) {
map<string, RGWObjEnt>::iterator iter;
iter = buckets.find(name);
}
}
+ /**
+ * Get the user's buckets as a map.
+ */
map<string, RGWObjEnt>& get_buckets() { return buckets; }
};
WRITE_CLASS_ENCODER(RGWUserBuckets)
+/**
+ * Get all the buckets owned by a user and fill up an RGWUserBuckets with them.
+ * Returns: 0 on success, -ERR# on failure.
+ */
extern int rgw_get_user_buckets(string user_id, RGWUserBuckets& buckets);
+/**
+ * Store the set of buckets associated with a user.
+ * This completely overwrites any previously-stored list, so be careful!
+ * Returns 0 on success, -ERR# otherwise.
+ */
extern int rgw_put_user_buckets(string user_id, RGWUserBuckets& buckets);
#endif