From 9496732d5a9d03133622a888f0129770862c24ea Mon Sep 17 00:00:00 2001 From: Greg Farnum Date: Fri, 14 Oct 2011 09:01:04 -0700 Subject: [PATCH] rgw: write and use the check_disk_state function This is used to check the actual on-disk state, and encode suggested updates for the index. Then cls_bucket_list sends them back to the OSD. Signed-off-by: Greg Farnum --- src/rgw/rgw_cls_api.h | 4 +++ src/rgw/rgw_rados.cc | 60 +++++++++++++++++++++++++++++++++++++++++-- src/rgw/rgw_rados.h | 19 ++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/rgw/rgw_cls_api.h b/src/rgw/rgw_cls_api.h index 7d729844bdfd3..c078cb80bc78e 100644 --- a/src/rgw/rgw_cls_api.h +++ b/src/rgw/rgw_cls_api.h @@ -6,6 +6,10 @@ #include "include/types.h" #include "include/utime.h" + +#define CEPH_RGW_REMOVE 'r' +#define CEPH_RGW_UPDATE 'u' + enum RGWPendingState { CLS_RGW_STATE_PENDING_MODIFY, CLS_RGW_STATE_COMPLETE, diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 815fcb586f43e..19921c4b605ce 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -2145,25 +2145,81 @@ int RGWRados::cls_bucket_list(rgw_bucket& bucket, string start, uint32_t num, ma struct rgw_bucket_dir& dir = ret.dir; map::iterator miter; + bufferlist updates; for (miter = dir.m.begin(); miter != dir.m.end(); ++miter) { RGWObjEnt e; rgw_bucket_dir_entry& dirent = miter->second; - if (!dirent.exists) - continue; + // fill it in with initial values; we may correct later e.name = dirent.name; e.size = dirent.meta.size; e.mtime = dirent.meta.mtime; e.etag = dirent.meta.etag; e.owner = dirent.meta.owner; e.owner_display_name = dirent.meta.owner_display_name; + + if (!dirent.exists || !dirent.pending_map.empty()) { + /* there are uncommitted ops. We need to check the current state, + * and if the tags are old we need to do cleanup as well. */ + r = check_disk_state(io_ctx, bucket, dirent, e, updates); + if (r < 0) { + if (r == -ENOENT) + continue; + else + return r; + } + } m[e.name] = e; dout(0) << " got " << e.name << dendl; } + if (updates.length()) { + // we don't care if we lose suggested updates, send them off blindly + AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL); + r = io_ctx.aio_exec(oid, c, "rgw", "dir_suggest_changes", in, NULL); + c->release(); + } return m.size(); } +int RGWRados::check_disk_state(librados::IoCtx& io_ctx, + rgw_bucket& bucket, + rgw_bucket_dir_entry& list_state, + RGWObjEnt& object, + bufferlist& suggested_updates) +{ + rgw_obj obj; + std::string oid, key; + obj.init(bucket, list_state.name); + get_obj_bucket_and_oid_key(obj, bucket, oid, key); + int r = io_ctx.stat(oid, &object.size, &object.mtime); + + list_state.pending_map.clear(); // we don't need this and it inflates size + if (r == -ENOENT) { + /* object doesn't exist right now -- hopefully because it's + * marked as !exists and got deleted */ + if (list_state.exists) { + /* FIXME: what should happen now? Work out if there are any + * non-bad ways this could happen (there probably are, but annoying + * to handle!) */ + } + // encode a suggested removal of that key + list_state.epoch = io_ctx.get_last_version(); + suggested_updates.append(CEPH_RGW_REMOVE); + ::encode(list_state, suggested_updates); + } + if (r < 0) + return r; + + // encode suggested updates + list_state.epoch = io_ctx.get_last_version(); + list_state.meta.size = object.size; + list_state.meta.mtime.set_from_double(double(object.mtime)); + suggested_updates.append(CEPH_RGW_UPDATE); + ::encode(list_state, suggested_updates); + return 0; +} + int RGWRados::cls_bucket_head(rgw_bucket& bucket, struct rgw_bucket_dir_header& header) { librados::IoCtx io_ctx; diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 405d3d513c04d..2927229589b23 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -320,6 +320,25 @@ public: private: int process_intent_log(rgw_bucket& bucket, string& oid, time_t epoch, int flags, bool purge); + /** + * Check the actual on-disk state of the object specified + * by list_state, and fill in the time and size of object. + * Then append any changes to suggested_updates for + * the rgw class' dir_suggest_changes function. + * + * Note that this can maul list_state; don't use it afterwards. Also + * it expects object to already be filled in from list_state; it only + * sets the size and mtime. + * + * Returns 0 on success, -ENOENT if the object doesn't exist on disk, + * and -errno on other failures. (-ENOENT is not a failure, and it + * will encode that info as a suggested update.) + */ + int check_disk_state(librados::IoCtx& io_ctx, + rgw_bucket& bucket, + rgw_bucket_dir_entry& list_state, + RGWObjEnt& object, + bufferlist& suggested_updates); }; -- 2.39.5