From b4c564c7d9b22fed810d020c386b8f72ed5c18eb Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 8 Apr 2010 21:49:17 -0700 Subject: [PATCH] librados: clean up object listing api --- src/TODO | 1 + src/include/librados.h | 16 +++--- src/include/librados.hpp | 5 +- src/librados.cc | 105 +++++++++++++++++++-------------------- src/osdc/Objecter.cc | 3 +- src/osdc/Objecter.h | 6 +-- src/rados.cc | 4 +- src/rgw/rgw_rados.cc | 7 +-- src/testrados.c | 24 +++------ src/testradospp.cc | 4 +- 10 files changed, 84 insertions(+), 91 deletions(-) diff --git a/src/TODO b/src/TODO index acae8e02713b2..44cd2f5251f1a 100644 --- a/src/TODO +++ b/src/TODO @@ -49,6 +49,7 @@ v0.20 - mds: many clustered mds fixes - auth: many auth_x cleanups, fixes, improvements - kclient: many bug fixes +- librados: some cleanup, c++ api now usable v0.21 diff --git a/src/include/librados.h b/src/include/librados.h index cf008c932b09d..cdd039abd5978 100644 --- a/src/include/librados.h +++ b/src/include/librados.h @@ -13,10 +13,9 @@ extern "C" { int rados_initialize(int argc, const char **argv); /* arguments are optional */ void rados_deinitialize(); -typedef void *rados_list_ctx_t; - /* pools */ typedef void *rados_pool_t; +typedef void *rados_list_ctx_t; typedef __u64 rados_snap_t; struct rados_pool_stat_t { @@ -40,18 +39,17 @@ int rados_close_pool(rados_pool_t pool); void rados_set_snap(rados_pool_t pool, rados_snap_t snap); - /* After creating a new rados_list_ctx_t, call this to initialize it*/ -void rados_pool_init_ctx(rados_list_ctx_t *ctx); - /* Once you've finished with a rados_list_ctx_t, call before you dump it*/ -void rados_pool_close_ctx(rados_list_ctx_t *ctx); - /* Given a rados_list_ctx_t and its pool, get the next object in sequence*/ -int rados_pool_list_next(rados_pool_t pool, const char **entry, rados_list_ctx_t *ctx); - int rados_create_pool(const char *name); int rados_create_pool_with_auid(const char *name, __u64 auid); int rados_delete_pool(const rados_pool_t pool); int rados_change_pool_auid(const rados_pool_t pool, __u64 auid); +/* objects */ +int rados_list_objects_open(rados_pool_t pool, rados_list_ctx_t *ctx); +int rados_list_objects_next(rados_list_ctx_t ctx, const char **entry); +void rados_list_objects_close(rados_list_ctx_t ctx); + + /* snapshots */ int rados_snap_create(const rados_pool_t pool, const char *snapname); int rados_snap_remove(const rados_pool_t pool, const char *snapname); diff --git a/src/include/librados.hpp b/src/include/librados.hpp index 9e60195e7f42d..9c9d2957f445f 100644 --- a/src/include/librados.hpp +++ b/src/include/librados.hpp @@ -69,12 +69,15 @@ public: int exec(pool_t pool, const std::string& oid, const char *cls, const char *method, bufferlist& inbl, bufferlist& outbl); + /* listing objects */ struct ListCtx { void *ctx; ListCtx() : ctx(NULL) {} }; + int list_objects_open(pool_t pool, Rados::ListCtx *ctx); + int list_objects_more(Rados::ListCtx ctx, int max, std::list& entries); + void list_objects_close(Rados::ListCtx ctx); - int list(pool_t pool, int max, std::list& entries, Rados::ListCtx& ctx); int list_pools(std::list& v); int get_pool_stats(std::list& v, std::map& stats); diff --git a/src/librados.cc b/src/librados.cc index 45845209634c5..236ccec29a948 100644 --- a/src/librados.cc +++ b/src/librados.cc @@ -135,8 +135,7 @@ public: int delete_pool(const rados_pool_t& pool); int change_pool_auid(const rados_pool_t& pool, unsigned long long auid); - int list(PoolCtx& pool, int max_entries, std::list& entries, - Objecter::ListContext *context); + int list(Objecter::ListContext *context, int max_entries); // --- aio --- struct AioCompletion { @@ -630,7 +629,8 @@ int RadosClient::snap_get_stamp(PoolCtx *pool, __u64 snapid, time_t *t) // IO -int RadosClient::list(PoolCtx& pool, int max_entries, std::list& entries, Objecter::ListContext *context) { +int RadosClient::list(Objecter::ListContext *context, int max_entries) +{ Cond cond; bool done; int r = 0; @@ -640,10 +640,8 @@ int RadosClient::list(PoolCtx& pool, int max_entries, std::list& entri if (context->at_end) return 0; - context->pool_id = pool.poolid; - context->pool_snap_seq = pool.snap_seq; - context->entries = &entries; context->max_entries = max_entries; + lock.Lock(); objecter->list_objects(context, new C_SafeCond(&mylock, &cond, &done, &r)); lock.Unlock(); @@ -1178,28 +1176,38 @@ int Rados::get_fs_stats(statfs_t& result) return r; } -int Rados::list(rados_pool_t pool, int max, std::list& entries, Rados::ListCtx& ctx) +int Rados::list_objects_open(pool_t pool, Rados::ListCtx *ctx) +{ + RadosClient::PoolCtx *p = (RadosClient::PoolCtx *)pool; + Objecter::ListContext *h = new Objecter::ListContext; + h->pool_id = p->poolid; + h->pool_snap_seq = p->snap_seq; + ctx->ctx = (void *)h; + return 0; +} + +int Rados::list_objects_more(Rados::ListCtx ctx, int max, std::list& entries) { if (!client) return -EINVAL; - Objecter::ListContext *op; - if (!ctx.ctx) { - ctx.ctx = new Objecter::ListContext(); - if (!ctx.ctx) - return -ENOMEM; - } - - op = (Objecter::ListContext *) ctx.ctx; - std::list e; - int r = ((RadosClient *)client)->list(*(RadosClient::PoolCtx *)pool, max, e, op); - while (!e.empty()) { - entries.push_back(e.front().name.c_str()); - e.pop_front(); + Objecter::ListContext *h = (Objecter::ListContext *)ctx.ctx; + h->list.clear(); + int r = ((RadosClient *)client)->list(h, max); + while (!h->list.empty()) { + entries.push_back(h->list.front().name.c_str()); + h->list.pop_front(); } return r; } +void Rados::list_objects_close(Rados::ListCtx ctx) +{ + Objecter::ListContext *h = (Objecter::ListContext *)ctx.ctx; + delete h; +} + + int Rados::create(rados_pool_t pool, const string& o, bool exclusive) { if (!client) @@ -1668,51 +1676,42 @@ extern "C" int rados_exec(rados_pool_t pool, const char *o, const char *cls, con } return ret; } -extern "C" void rados_pool_init_ctx(rados_list_ctx_t *ctx) + +/* list objects */ + +extern "C" int rados_list_objects_open(rados_pool_t pool, rados_list_ctx_t *listh) { - *ctx = NULL; + RadosClient::PoolCtx *ctx = (RadosClient::PoolCtx *)pool; + Objecter::ListContext *h = new Objecter::ListContext; + h->pool_id = ctx->poolid; + h->pool_snap_seq = ctx->snap_seq; + *listh = (void *)h; + return 0; } -extern "C" void rados_pool_close_ctx(rados_list_ctx_t *ctx) +extern "C" void rados_list_objects_close(rados_list_ctx_t ctx) { - if (*ctx) { - Objecter::ListContext *op = (Objecter::ListContext *)*ctx; - delete op; - *ctx = NULL; - } + Objecter::ListContext *op = (Objecter::ListContext *)ctx; + delete op; } -extern "C" int rados_pool_list_next(rados_pool_t pool, const char **entry, rados_list_ctx_t *listctx) +extern "C" int rados_list_objects_next(rados_list_ctx_t listctx, const char **entry) { + Objecter::ListContext *h = (Objecter::ListContext *)listctx; int ret; - RadosClient::PoolCtx *ctx = (RadosClient::PoolCtx *)pool; - - if (!*listctx) { - *listctx = new Objecter::ListContext; - if (!*listctx) - return -ENOMEM; - } - - - Objecter::ListContext *op = (Objecter::ListContext *)*listctx; - - //if the list is non-empty, this method has been called before - if(!op->list.empty()) - //so let's kill the previously-returned object - op->list.pop_front(); - if (op->list.empty()) { - op->list.clear(); - ret = radosp->list(*ctx, RADOS_LIST_MAX_ENTRIES, op->list, op); - if (!op->list.size()) { - delete op; - *listctx = NULL; + // if the list is non-empty, this method has been called before + if (!h->list.empty()) + // so let's kill the previously-returned object + h->list.pop_front(); + + if (h->list.empty()) { + ret = radosp->list(h, RADOS_LIST_MAX_ENTRIES); + if (!h->list.size()) return -ENOENT; - } } - *entry = op->list.front().name.c_str(); - + *entry = h->list.front().name.c_str(); return 0; } diff --git a/src/osdc/Objecter.cc b/src/osdc/Objecter.cc index 7fd7587d22db0..55b229d89ce99 100644 --- a/src/osdc/Objecter.cc +++ b/src/osdc/Objecter.cc @@ -565,7 +565,6 @@ void Objecter::list_objects(ListContext *list_context, Context *onfinish) { dout(20) << "pool_id " << list_context->pool_id << "\npool_snap_seq " << list_context->pool_snap_seq << "\nmax_entries " << list_context->max_entries - << "\n&entries " << list_context->entries << "\nlist_context " << list_context << "\nonfinish " << onfinish << "\nlist_context->current_pg" << list_context->current_pg @@ -620,7 +619,7 @@ void Objecter::_list_reply(ListContext *list_context, bufferlist *bl, Context *f << ", response.entries " << response.entries << dendl; if (response_size) { dout(20) << "got a response with objects, proceeding" << dendl; - list_context->entries->merge(response.entries); + list_context->list.merge(response.entries); list_context->max_entries -= response_size; dout(20) << "cleaning up and exiting" << dendl; if (!list_context->max_entries) { diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h index b5996611c9ec6..03ada7e41a744 100644 --- a/src/osdc/Objecter.h +++ b/src/osdc/Objecter.h @@ -289,15 +289,11 @@ public: int pool_id; int pool_snap_seq; int max_entries; - std::list *entries; - - //silly list for the C interface std::list list; ListContext() : current_pg(0), cookie(0), starting_pg_num(0), at_end(false), pool_id(0), - pool_snap_seq(0), max_entries(0), - entries(NULL) {} + pool_snap_seq(0), max_entries(0) {} }; struct C_List : public Context { diff --git a/src/rados.cc b/src/rados.cc index 66ac2b4a87d74..9d003434c79cb 100644 --- a/src/rados.cc +++ b/src/rados.cc @@ -207,9 +207,10 @@ int main(int argc, const char **argv) outstream = new ofstream(nargs[1]); Rados::ListCtx ctx; + rados.list_objects_open(p, &ctx); while (1) { list vec; - ret = rados.list(p, 1 << 10, vec, ctx); + ret = rados.list_objects_more(ctx, 1 << 10, vec); if (ret < 0) { cerr << "got error: " << strerror_r(-ret, buf, sizeof(buf)) << std::endl; goto out; @@ -220,6 +221,7 @@ int main(int argc, const char **argv) for (list::iterator iter = vec.begin(); iter != vec.end(); ++iter) *outstream << *iter << std::endl; } + rados.list_objects_close(ctx); if (!stdout) delete outstream; } diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index bd8920cc1c126..8c9b8114aaf54 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -141,12 +141,12 @@ int RGWRados::list_objects(string& id, string& bucket, int max, string& prefix, return r; - Rados::ListCtx ctx; #define MAX_ENTRIES 1000 - + Rados::ListCtx ctx; + rados->list_objects_open(pool, &ctx); do { list entries; - r = rados->list(pool, MAX_ENTRIES, entries, ctx); + r = rados->list_objects_more(ctx, MAX_ENTRIES, entries); if (r < 0) return r; @@ -157,6 +157,7 @@ int RGWRados::list_objects(string& id, string& bucket, int max, string& prefix, } } } while (r); + rados->list_objects_close(ctx); set::iterator p; if (!marker.empty()) diff --git a/src/testrados.c b/src/testrados.c index c909142304d93..0a6f94f7339a5 100644 --- a/src/testrados.c +++ b/src/testrados.c @@ -35,14 +35,6 @@ int main(int argc, const char **argv) r = rados_open_pool("foo", &pool); printf("rados_open_pool = %d, pool = %p\n", r, pool); - /* list objects */ - rados_list_ctx_t pctx; - rados_pool_init_ctx(&pctx); - const char *poolname; - while (rados_pool_list_next(pool, &poolname, &pctx) == 0) - printf("rados_pool_list_next got object '%s'\n", poolname); - rados_pool_close_ctx(&pctx); - /* snapshots */ r = rados_snap_create(pool, "snap1"); printf("rados_snap_create snap1 = %d\n", r); @@ -108,15 +100,15 @@ int main(int argc, const char **argv) rados_read(pool, "../b/bb_bb_bb\\foo\\bar", 0, buf2, 128); + /* list objects */ + rados_list_ctx_t h; + r = rados_list_objects_open(pool, &h); + printf("rados_list_objects_open = %d, h = %p\n", r, h); + const char *poolname; + while (rados_list_objects_next(h, &poolname) == 0) + printf("rados_list_objects_next got object '%s'\n", poolname); + rados_list_objects_close(h); - const char *entry; - rados_list_ctx_t ctx; - rados_pool_init_ctx(&ctx); - while (rados_pool_list_next(pool, &entry, &ctx) >= 0) { - printf("list entry: %s\n", entry); - } - rados_pool_close_ctx(&ctx); - /* delete a pool */ r = rados_delete_pool(pool); printf("rados_delete_pool = %d\n", r); diff --git a/src/testradospp.cc b/src/testradospp.cc index 4905c8f33db5d..b0fcba3113e15 100644 --- a/src/testradospp.cc +++ b/src/testradospp.cc @@ -95,10 +95,11 @@ int main(int argc, const char **argv) cout << "size=" << size << std::endl; Rados::ListCtx ctx; + rados.list_objects_open(pool, &ctx); int entries; do { list vec; - r = rados.list(pool, 2, vec, ctx); + r = rados.list_objects_more(ctx, 2, vec); entries = vec.size(); cout << "list result=" << r << " entries=" << entries << std::endl; list::iterator iter; @@ -106,6 +107,7 @@ int main(int argc, const char **argv) cout << *iter << std::endl; } } while (entries); + rados.list_objects_close(ctx); map attrset; -- 2.39.5