]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librados: remove deprecated object listing interfaces
authorSage Weil <sage@redhat.com>
Thu, 26 Jan 2017 22:25:23 +0000 (17:25 -0500)
committerSage Weil <sage@redhat.com>
Thu, 9 Feb 2017 02:50:27 +0000 (21:50 -0500)
These have been deprecated since giant.

Signed-off-by: Sage Weil <sage@redhat.com>
src/include/rados/librados.h
src/include/rados/librados.hpp
src/librados/librados.cc
src/test/librados/CMakeLists.txt
src/test/librados/list.cc
src/test/librados/nlist.cc [deleted file]

index 8f88375d00003dc45e87050284ca3b2a1aa74b2d..9f6f343c35eb1a2c4dc5a0e92709dabb67889b04 100644 (file)
@@ -968,7 +968,7 @@ CEPH_RADOS_API void rados_ioctx_set_namespace(rados_ioctx_t io,
 /** @} obj_loc */
 
 /**
- * @name New Listing Objects
+ * @name Listing Objects
  * @{
  */
 /**
@@ -1002,7 +1002,7 @@ CEPH_RADOS_API uint32_t rados_nobjects_list_seek(rados_list_ctx_t ctx,
 /**
  * Get the next object name and locator in the pool
  *
- * *entry and *key are valid until next call to rados_objects_list_*
+ * *entry and *key are valid until next call to rados_nobjects_list_*
  *
  * @param ctx iterator marking where you are in the listing
  * @param entry where to store the name of the entry
@@ -1076,43 +1076,6 @@ CEPH_RADOS_API void rados_object_list_slice(rados_ioctx_t io,
     rados_object_list_cursor *split_finish);
 
 
-/** @} New Listing Objects */
-
-/**
- * @name Deprecated Listing Objects
- *
- * Older listing objects interface.  Please use the new interface.
- * @{
- */
-/**
- * @warning Deprecated: Use rados_nobjects_list_open() instead
- */
-CEPH_RADOS_API int rados_objects_list_open(rados_ioctx_t io,
-                                           rados_list_ctx_t *ctx);
-
-/**
- * @warning Deprecated: Use rados_nobjects_list_get_pg_hash_position() instead
- */
-CEPH_RADOS_API uint32_t rados_objects_list_get_pg_hash_position(rados_list_ctx_t ctx);
-
-/**
- * @warning Deprecated: Use rados_nobjects_list_seek() instead
- */
-CEPH_RADOS_API uint32_t rados_objects_list_seek(rados_list_ctx_t ctx,
-                                                uint32_t pos);
-
-/**
- * @warning Deprecated: Use rados_nobjects_list_next() instead
- */
-CEPH_RADOS_API int rados_objects_list_next(rados_list_ctx_t ctx,
-                                           const char **entry,
-                                           const char **key);
-
-/**
- * @warning Deprecated: Use rados_nobjects_list_close() instead
- */
-CEPH_RADOS_API void rados_objects_list_close(rados_list_ctx_t ctx);
-
 /** @} Listing Objects */
 
 /**
index bb9ed6d5dd65bb8779dcd079c41a648f9700238b..6c7dcec10d76cf9d8d8daaf356746e0db088717c 100644 (file)
@@ -107,36 +107,6 @@ namespace librados
     NObjectIteratorImpl *impl;
   };
 
-  // DEPRECATED; Use NObjectIterator
-  class CEPH_RADOS_API ObjectIterator : public std::iterator <std::forward_iterator_tag, std::pair<std::string, std::string> > {
-  public:
-    static const ObjectIterator __EndObjectIterator;
-    ObjectIterator() {}
-    ObjectIterator(ObjListCtx *ctx_);
-    ~ObjectIterator();
-    ObjectIterator(const ObjectIterator &rhs);
-    ObjectIterator& operator=(const ObjectIterator& rhs);
-
-    bool operator==(const ObjectIterator& rhs) const;
-    bool operator!=(const ObjectIterator& rhs) const;
-    const std::pair<std::string, std::string>& operator*() const;
-    const std::pair<std::string, std::string>* operator->() const;
-    ObjectIterator &operator++(); // Preincrement
-    ObjectIterator operator++(int); // Postincrement
-    friend class IoCtx;
-
-    /// get current hash position of the iterator, rounded to the current pg
-    uint32_t get_pg_hash_position() const;
-
-    /// move the iterator to a given hash position.  this may (will!) be rounded to the nearest pg.
-    uint32_t seek(uint32_t pos);
-
-  private:
-    void get_next();
-    ceph::shared_ptr < ObjListCtx > ctx;
-    std::pair<std::string, std::string> cur_obj;
-  };
-
   class CEPH_RADOS_API ObjectCursor
   {
     public:
@@ -895,13 +865,6 @@ namespace librados
     /// Iterator indicating the end of a pool
     const NObjectIterator& nobjects_end() const;
 
-    // DEPRECATED
-    ObjectIterator objects_begin() __attribute__ ((deprecated));
-    /// Start enumerating objects for a pool starting from a hash position
-    ObjectIterator objects_begin(uint32_t start_hash_position) __attribute__ ((deprecated));
-    /// Iterator indicating the end of a pool
-    const ObjectIterator& objects_end() const __attribute__ ((deprecated));
-
     ObjectCursor object_list_begin();
     ObjectCursor object_list_end();
     bool object_list_is_end(const ObjectCursor &oc);
index ef8c71a24e58e9c92926e11d5fb41170bd262d9b..ad25a518d8592fda9c6b09e2f135c77f1987d424 100644 (file)
@@ -867,103 +867,6 @@ uint32_t librados::NObjectIterator::get_pg_hash_position() const
 
 const librados::NObjectIterator librados::NObjectIterator::__EndObjectIterator(NULL);
 
-// DEPRECATED; Use NObjectIterator instead
-///////////////////////////// ObjectIterator /////////////////////////////
-librados::ObjectIterator::ObjectIterator(ObjListCtx *ctx_)
-  : ctx(ctx_)
-{
-}
-
-librados::ObjectIterator::~ObjectIterator()
-{
-  ctx.reset();
-}
-
-librados::ObjectIterator::ObjectIterator(const ObjectIterator &rhs)
-{
-  *this = rhs;
-}
-
-librados::ObjectIterator& librados::ObjectIterator::operator=(
-  const librados::ObjectIterator &rhs)
-{
-  if (&rhs == this)
-    return *this;
-  if (rhs.ctx.get() == NULL) {
-    ctx.reset();
-    return *this;
-  }
-  Objecter::NListContext *list_ctx = new Objecter::NListContext(*rhs.ctx->nlc);
-  ctx.reset(new ObjListCtx(rhs.ctx->ctx, list_ctx, true));
-  cur_obj = rhs.cur_obj;
-  return *this;
-}
-
-bool librados::ObjectIterator::operator==(const librados::ObjectIterator& rhs) const {
-  if (ctx.get() == NULL)
-    return rhs.ctx.get() == NULL || rhs.ctx->nlc->at_end();
-  if (rhs.ctx.get() == NULL)
-    return ctx.get() == NULL || ctx->nlc->at_end();
-  return ctx.get() == rhs.ctx.get();
-}
-
-bool librados::ObjectIterator::operator!=(const librados::ObjectIterator& rhs) const {
-  return !(*this == rhs);
-}
-
-const pair<std::string, std::string>& librados::ObjectIterator::operator*() const {
-  return cur_obj;
-}
-
-const pair<std::string, std::string>* librados::ObjectIterator::operator->() const {
-  return &cur_obj;
-}
-
-librados::ObjectIterator& librados::ObjectIterator::operator++()
-{
-  get_next();
-  return *this;
-}
-
-librados::ObjectIterator librados::ObjectIterator::operator++(int)
-{
-  librados::ObjectIterator ret(*this);
-  get_next();
-  return ret;
-}
-
-uint32_t librados::ObjectIterator::seek(uint32_t pos)
-{
-  uint32_t r = rados_objects_list_seek(ctx.get(), pos);
-  get_next();
-  return r;
-}
-
-void librados::ObjectIterator::get_next()
-{
-  const char *entry, *key;
-  if (ctx->nlc->at_end())
-    return;
-  int ret = rados_objects_list_next(ctx.get(), &entry, &key);
-  if (ret == -ENOENT) {
-    return;
-  }
-  else if (ret) {
-    ostringstream oss;
-    oss << "rados returned " << cpp_strerror(ret);
-    throw std::runtime_error(oss.str());
-  }
-
-  cur_obj = make_pair(entry, key ? key : string());
-}
-
-uint32_t librados::ObjectIterator::get_pg_hash_position() const
-{
-  return ctx->nlc->get_pg_hash_position();
-}
-
-const librados::ObjectIterator librados::ObjectIterator::__EndObjectIterator(NULL);
-
 ///////////////////////////// PoolAsyncCompletion //////////////////////////////
 int librados::PoolAsyncCompletion::PoolAsyncCompletion::set_callback(void *cb_arg,
                                                                     rados_callback_t cb)
@@ -1804,40 +1707,6 @@ const librados::NObjectIterator& librados::IoCtx::nobjects_end() const
   return NObjectIterator::__EndObjectIterator;
 }
 
-// DEPRECATED; use n versions above
-librados::ObjectIterator librados::IoCtx::objects_begin()
-{
-  rados_list_ctx_t listh;
-  if (io_ctx_impl->oloc.nspace == librados::all_nspaces) {
-    ostringstream oss;
-    oss << "rados returned " << cpp_strerror(-EINVAL);
-    throw std::runtime_error(oss.str());
-  }
-  rados_objects_list_open(io_ctx_impl, &listh);
-  ObjectIterator iter((ObjListCtx*)listh);
-  iter.get_next();
-  return iter;
-}
-
-librados::ObjectIterator librados::IoCtx::objects_begin(uint32_t pos)
-{
-  rados_list_ctx_t listh;
-  if (io_ctx_impl->oloc.nspace == librados::all_nspaces) {
-    ostringstream oss;
-    oss << "rados returned " << cpp_strerror(-EINVAL);
-    throw std::runtime_error(oss.str());
-  }
-  rados_objects_list_open(io_ctx_impl, &listh);
-  ObjectIterator iter((ObjListCtx*)listh);
-  iter.seek(pos);
-  return iter;
-}
-
-const librados::ObjectIterator& librados::IoCtx::objects_end() const
-{
-  return ObjectIterator::__EndObjectIterator;
-}
-
 int librados::IoCtx::hit_set_list(uint32_t hash, AioCompletion *c,
                                  std::list< std::pair<time_t, time_t> > *pls)
 {
@@ -4255,10 +4124,6 @@ extern "C" int rados_nobjects_list_open(rados_ioctx_t io, rados_list_ctx_t *list
 {
   librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
 
-  // Let's do it the old way for backward compatbility if not using ANY_NSPACES
-  if (ctx->oloc.nspace != librados::all_nspaces)
-    return rados_objects_list_open(io, listh);
-
   tracepoint(librados, rados_nobjects_list_open_enter, io);
 
   Objecter::NListContext *h = new Objecter::NListContext;
@@ -4298,51 +4163,6 @@ extern "C" uint32_t rados_nobjects_list_get_pg_hash_position(
   return retval;
 }
 
-// Deprecated, but using it for compatibility with older OSDs
-extern "C" int rados_objects_list_open(rados_ioctx_t io, rados_list_ctx_t *listh)
-{
-  tracepoint(librados, rados_objects_list_open_enter, io);
-  librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
-  if (ctx->oloc.nspace == librados::all_nspaces)
-    return -EINVAL;
-  Objecter::NListContext *h = new Objecter::NListContext;
-  h->pool_id = ctx->poolid;
-  h->pool_snap_seq = ctx->snap_seq;
-  h->nspace = ctx->oloc.nspace;
-  *listh = (void *)new librados::ObjListCtx(ctx, h, true);
-  tracepoint(librados, rados_objects_list_open_exit, 0, *listh);
-  return 0;
-}
-
-// Deprecated, but using it for compatibility with older OSDs
-extern "C" void rados_objects_list_close(rados_list_ctx_t h)
-{
-  tracepoint(librados, rados_objects_list_close_enter, h);
-  librados::ObjListCtx *lh = (librados::ObjListCtx *)h;
-  delete lh;
-  tracepoint(librados, rados_objects_list_close_exit);
-}
-
-extern "C" uint32_t rados_objects_list_seek(rados_list_ctx_t listctx,
-                                           uint32_t pos)
-{
-  tracepoint(librados, rados_objects_list_seek_enter, listctx, pos);
-  librados::ObjListCtx *lh = (librados::ObjListCtx *)listctx;
-  uint32_t r = lh->ctx->nlist_seek(lh->nlc, pos);
-  tracepoint(librados, rados_objects_list_seek_exit, r);
-  return r;
-}
-
-extern "C" uint32_t rados_objects_list_get_pg_hash_position(
-  rados_list_ctx_t listctx)
-{
-  tracepoint(librados, rados_objects_list_get_pg_hash_position_enter, listctx);
-  librados::ObjListCtx *lh = (librados::ObjListCtx *)listctx;
-  uint32_t retval = lh->nlc->get_pg_hash_position();
-  tracepoint(librados, rados_objects_list_get_pg_hash_position_exit, retval);
-  return retval;
-}
-
 extern "C" int rados_nobjects_list_next(rados_list_ctx_t listctx, const char **entry, const char **key, const char **nspace)
 {
   tracepoint(librados, rados_nobjects_list_next_enter, listctx);
@@ -4380,47 +4200,6 @@ extern "C" int rados_nobjects_list_next(rados_list_ctx_t listctx, const char **e
   return 0;
 }
 
-// DEPRECATED
-extern "C" int rados_objects_list_next(rados_list_ctx_t listctx, const char **entry, const char **key)
-{
-  tracepoint(librados, rados_objects_list_next_enter, listctx);
-  librados::ObjListCtx *lh = (librados::ObjListCtx *)listctx;
-  Objecter::NListContext *h = lh->nlc;
-
-  // Calling wrong interface after rados_nobjects_list_open()
-  if (!lh->legacy_list_api)
-    return -EINVAL;
-
-  // 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()) {
-    int ret = lh->ctx->nlist(lh->nlc, RADOS_LIST_MAX_ENTRIES);
-    if (ret < 0) {
-      tracepoint(librados, rados_objects_list_next_exit, ret, NULL, NULL);
-      return ret;
-    }
-    if (h->list.empty()) {
-      tracepoint(librados, rados_objects_list_next_exit, -ENOENT, NULL, NULL);
-      return -ENOENT;
-    }
-  }
-
-  *entry = h->list.front().get_oid().c_str();
-
-  if (key) {
-    if (h->list.front().get_locator().size())
-      *key = h->list.front().get_locator().c_str();
-    else
-      *key = NULL;
-  }
-  tracepoint(librados, rados_objects_list_next_exit, 0, *entry, key);
-  return 0;
-}
-
-
 
 // -------------------------
 // aio
index 60939020f60b5916857d3b52e4fa165d1290633f..2194a3e1fa67c4e024e09661602c5a23c51e45fa 100644 (file)
@@ -61,15 +61,6 @@ set_target_properties(ceph_test_rados_api_list PROPERTIES COMPILE_FLAGS
 target_link_libraries(ceph_test_rados_api_list
   rados_a global ${UNITTEST_LIBS} radostest)
 
-# ceph_test_rados_api_nlist
-add_executable(ceph_test_rados_api_nlist
-  nlist.cc
-  )
-set_target_properties(ceph_test_rados_api_nlist PROPERTIES COMPILE_FLAGS
-  ${UNITTEST_CXX_FLAGS})
-target_link_libraries(ceph_test_rados_api_nlist
-  rados_a ${UNITTEST_LIBS} radostest)
-
 # ceph_test_rados_api_pool
 add_executable(ceph_test_rados_api_pool
   pool.cc
index e250be34aea8abaf7f072004e18e7d236aeb4aaf..a843ce33608a55adc58d972858112de7b93a6eed 100644 (file)
@@ -22,38 +22,34 @@ typedef RadosTestECNS LibRadosListEC;
 typedef RadosTestECPPNS LibRadosListECPP;
 typedef RadosTestNP LibRadosListNP;
 
+
 TEST_F(LibRadosList, ListObjects) {
   char buf[128];
   memset(buf, 0xcc, sizeof(buf));
   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
   rados_list_ctx_t ctx;
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
   const char *entry;
   bool foundit = false;
-  while (rados_objects_list_next(ctx, &entry, NULL) != -ENOENT) {
+  while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) != -ENOENT) {
     foundit = true;
     ASSERT_EQ(std::string(entry), "foo");
   }
   ASSERT_TRUE(foundit);
-  rados_objects_list_close(ctx);
+  rados_nobjects_list_close(ctx);
 }
 
-
-#pragma GCC diagnostic ignored "-Wpragmas"
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
 TEST_F(LibRadosListPP, ListObjectsPP) {
   char buf[128];
   memset(buf, 0xcc, sizeof(buf));
   bufferlist bl1;
   bl1.append(buf, sizeof(buf));
   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-  ObjectIterator iter(ioctx.objects_begin());
+  NObjectIterator iter(ioctx.nobjects_begin());
   bool foundit = false;
-  while (iter != ioctx.objects_end()) {
+  while (iter != ioctx.nobjects_end()) {
     foundit = true;
-    ASSERT_EQ((*iter).first, "foo");
+    ASSERT_EQ((*iter).get_oid(), "foo");
     ++iter;
   }
   ASSERT_TRUE(foundit);
@@ -65,21 +61,21 @@ TEST_F(LibRadosListPP, ListObjectsTwicePP) {
   bufferlist bl1;
   bl1.append(buf, sizeof(buf));
   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-  ObjectIterator iter(ioctx.objects_begin());
+  NObjectIterator iter(ioctx.nobjects_begin());
   bool foundit = false;
-  while (iter != ioctx.objects_end()) {
+  while (iter != ioctx.nobjects_end()) {
     foundit = true;
-    ASSERT_EQ((*iter).first, "foo");
+    ASSERT_EQ((*iter).get_oid(), "foo");
     ++iter;
   }
   ASSERT_TRUE(foundit);
   ++iter;
-  ASSERT_TRUE(iter == ioctx.objects_end());
+  ASSERT_TRUE(iter == ioctx.nobjects_end());
   foundit = false;
   iter.seek(0);
-  while (iter != ioctx.objects_end()) {
+  while (iter != ioctx.nobjects_end()) {
     foundit = true;
-    ASSERT_EQ((*iter).first, "foo");
+    ASSERT_EQ((*iter).get_oid(), "foo");
     ++iter;
   }
   ASSERT_TRUE(foundit);
@@ -93,28 +89,28 @@ TEST_F(LibRadosListPP, ListObjectsCopyIterPP) {
   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
 
   // make sure this is still valid after the original iterators are gone
-  ObjectIterator iter3;
+  NObjectIterator iter3;
   {
-    ObjectIterator iter(ioctx.objects_begin());
-    ObjectIterator iter2(iter);
+    NObjectIterator iter(ioctx.nobjects_begin());
+    NObjectIterator iter2(iter);
     iter3 = iter2;
-    ASSERT_EQ((*iter).first, "foo");
+    ASSERT_EQ((*iter).get_oid(), "foo");
     ++iter;
-    ASSERT_TRUE(iter == ioctx.objects_end());
+    ASSERT_TRUE(iter == ioctx.nobjects_end());
     ++iter;
-    ASSERT_TRUE(iter == ioctx.objects_end());
+    ASSERT_TRUE(iter == ioctx.nobjects_end());
 
-    ASSERT_EQ(iter2->first, "foo");
-    ASSERT_EQ(iter3->first, "foo");
+    ASSERT_EQ(iter2->get_oid(), "foo");
+    ASSERT_EQ(iter3->get_oid(), "foo");
     ++iter2;
-    ASSERT_TRUE(iter2 == ioctx.objects_end());
+    ASSERT_TRUE(iter2 == ioctx.nobjects_end());
   }
 
-  ASSERT_EQ(iter3->first, "foo");
+  ASSERT_EQ(iter3->get_oid(), "foo");
   iter3 = iter3;
-  ASSERT_EQ(iter3->first, "foo");
+  ASSERT_EQ(iter3->get_oid(), "foo");
   ++iter3;
-  ASSERT_TRUE(iter3 == ioctx.objects_end());
+  ASSERT_TRUE(iter3 == ioctx.nobjects_end());
 }
 
 TEST_F(LibRadosListPP, ListObjectsEndIter) {
@@ -124,27 +120,27 @@ TEST_F(LibRadosListPP, ListObjectsEndIter) {
   bl1.append(buf, sizeof(buf));
   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
 
-  ObjectIterator iter(ioctx.objects_begin());
-  ObjectIterator iter_end(ioctx.objects_end());
-  ObjectIterator iter_end2 = ioctx.objects_end();
+  NObjectIterator iter(ioctx.nobjects_begin());
+  NObjectIterator iter_end(ioctx.nobjects_end());
+  NObjectIterator iter_end2 = ioctx.nobjects_end();
   ASSERT_TRUE(iter_end == iter_end2);
-  ASSERT_TRUE(iter_end == ioctx.objects_end());
-  ASSERT_TRUE(iter_end2 == ioctx.objects_end());
+  ASSERT_TRUE(iter_end == ioctx.nobjects_end());
+  ASSERT_TRUE(iter_end2 == ioctx.nobjects_end());
 
-  ASSERT_EQ(iter->first, "foo");
+  ASSERT_EQ(iter->get_oid(), "foo");
   ++iter;
-  ASSERT_TRUE(iter == ioctx.objects_end());
+  ASSERT_TRUE(iter == ioctx.nobjects_end());
   ASSERT_TRUE(iter == iter_end);
   ASSERT_TRUE(iter == iter_end2);
-  ObjectIterator iter2 = iter;
-  ASSERT_TRUE(iter2 == ioctx.objects_end());
+  NObjectIterator iter2 = iter;
+  ASSERT_TRUE(iter2 == ioctx.nobjects_end());
   ASSERT_TRUE(iter2 == iter_end);
   ASSERT_TRUE(iter2 == iter_end2);
 }
 
-static void check_list(std::set<std::string>& myset, rados_list_ctx_t& ctx)
+static void check_list(std::set<std::string>& myset, rados_list_ctx_t& ctx, std::string check_nspace)
 {
-  const char *entry;
+  const char *entry, *nspace;
   std::set<std::string> orig_set(myset);
   /**
    * During splitting, we might see duplicate items.
@@ -152,16 +148,23 @@ static void check_list(std::set<std::string>& myset, rados_list_ctx_t& ctx)
    * we don't hit ENOENT until we have hit every item in myset
    * at least once.
    */
-  while (rados_objects_list_next(ctx, &entry, NULL) != -ENOENT) {
-    ASSERT_TRUE(orig_set.end() != orig_set.find(std::string(entry)));
-    myset.erase(std::string(entry));
+  int ret;
+  while ((ret = rados_nobjects_list_next(ctx, &entry, NULL, &nspace)) == 0) {
+    std::string test_name;
+    if (check_nspace == all_nspaces) {
+      test_name = std::string(nspace) + ":" + std::string(entry);
+    } else {
+      ASSERT_TRUE(std::string(nspace) == check_nspace);
+      test_name = std::string(entry);
+    }
+
+    ASSERT_TRUE(orig_set.end() != orig_set.find(test_name));
+    myset.erase(test_name);
   }
+  ASSERT_EQ(-ENOENT, ret);
   ASSERT_TRUE(myset.empty());
 }
 
-#pragma GCC diagnostic pop
-#pragma GCC diagnostic warning "-Wpragmas"
-
 TEST_F(LibRadosList, ListObjectsNS) {
   char buf[128];
   memset(buf, 0xcc, sizeof(buf));
@@ -180,7 +183,7 @@ TEST_F(LibRadosList, ListObjectsNS) {
   ASSERT_EQ(0, rados_write(ioctx, "foo6", buf, sizeof(buf), 0));
   ASSERT_EQ(0, rados_write(ioctx, "foo7", buf, sizeof(buf), 0));
 
-  std::set<std::string> def, ns1, ns2;
+  std::set<std::string> def, ns1, ns2, all;
   def.insert(std::string("foo1"));
   def.insert(std::string("foo2"));
   def.insert(std::string("foo3"));
@@ -189,38 +192,44 @@ TEST_F(LibRadosList, ListObjectsNS) {
   ns1.insert(std::string("foo5"));
   ns2.insert(std::string("foo6"));
   ns2.insert(std::string("foo7"));
+  all.insert(std::string(":foo1"));
+  all.insert(std::string(":foo2"));
+  all.insert(std::string(":foo3"));
+  all.insert(std::string("ns1:foo1"));
+  all.insert(std::string("ns1:foo4"));
+  all.insert(std::string("ns1:foo5"));
+  all.insert(std::string("ns2:foo6"));
+  all.insert(std::string("ns2:foo7"));
 
   rados_list_ctx_t ctx;
   // Check default namespace ""
   rados_ioctx_set_namespace(ioctx, "");
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
-  check_list(def, ctx);
-  rados_objects_list_close(ctx);
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
+  check_list(def, ctx, "");
+  rados_nobjects_list_close(ctx);
 
-  // Check default namespace "ns1"
+  // Check namespace "ns1"
   rados_ioctx_set_namespace(ioctx, "ns1");
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
-  check_list(ns1, ctx);
-  rados_objects_list_close(ctx);
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
+  check_list(ns1, ctx, "ns1");
+  rados_nobjects_list_close(ctx);
 
-  // Check default namespace "ns2"
+  // Check namespace "ns2"
   rados_ioctx_set_namespace(ioctx, "ns2");
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
-  check_list(ns2, ctx);
-  rados_objects_list_close(ctx);
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
+  check_list(ns2, ctx, "ns2");
+  rados_nobjects_list_close(ctx);
 
-  // Can't specify all namespaces using old interface
+  // Check ALL namespaces
   rados_ioctx_set_namespace(ioctx, LIBRADOS_ALL_NSPACES);
-  ASSERT_EQ(-EINVAL, rados_objects_list_open(ioctx, &ctx));
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
+  check_list(all, ctx, all_nspaces);
+  rados_nobjects_list_close(ctx);
 }
 
-#pragma GCC diagnostic ignored "-Wpragmas"
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
-static void check_listpp(std::set<std::string>& myset, IoCtx& ioctx)
+static void check_listpp(std::set<std::string>& myset, IoCtx& ioctx, std::string check_nspace)
 {
-  ObjectIterator iter(ioctx.objects_begin());
+  NObjectIterator iter(ioctx.nobjects_begin());
   std::set<std::string> orig_set(myset);
   /**
    * During splitting, we might see duplicate items.
@@ -228,9 +237,16 @@ static void check_listpp(std::set<std::string>& myset, IoCtx& ioctx)
    * we don't hit ENOENT until we have hit every item in myset
    * at least once.
    */
-  while (iter != ioctx.objects_end()) {
-    ASSERT_TRUE(orig_set.end() != orig_set.find(std::string((*iter).first)));
-    myset.erase(std::string((*iter).first));
+  while (iter != ioctx.nobjects_end()) {
+    std::string test_name;
+    if (check_nspace == all_nspaces) {
+      test_name = iter->get_nspace() + ":" + iter->get_oid();
+    } else {
+      ASSERT_TRUE(iter->get_nspace() == check_nspace);
+      test_name = iter->get_oid();
+    }
+    ASSERT_TRUE(orig_set.end() != orig_set.find(test_name));
+    myset.erase(test_name);
     ++iter;
   }
   ASSERT_TRUE(myset.empty());
@@ -256,7 +272,7 @@ TEST_F(LibRadosListPP, ListObjectsPPNS) {
   ASSERT_EQ(0, ioctx.write("foo6", bl1, sizeof(buf), 0));
   ASSERT_EQ(0, ioctx.write("foo7", bl1, sizeof(buf), 0));
 
-  std::set<std::string> def, ns1, ns2;
+  std::set<std::string> def, ns1, ns2, all;
   def.insert(std::string("foo1"));
   def.insert(std::string("foo2"));
   def.insert(std::string("foo3"));
@@ -265,18 +281,26 @@ TEST_F(LibRadosListPP, ListObjectsPPNS) {
   ns1.insert(std::string("foo5"));
   ns2.insert(std::string("foo6"));
   ns2.insert(std::string("foo7"));
+  all.insert(std::string(":foo1"));
+  all.insert(std::string(":foo2"));
+  all.insert(std::string(":foo3"));
+  all.insert(std::string("ns1:foo1"));
+  all.insert(std::string("ns1:foo4"));
+  all.insert(std::string("ns1:foo5"));
+  all.insert(std::string("ns2:foo6"));
+  all.insert(std::string("ns2:foo7"));
 
   ioctx.set_namespace("");
-  check_listpp(def, ioctx);
+  check_listpp(def, ioctx, "");
 
   ioctx.set_namespace("ns1");
-  check_listpp(ns1, ioctx);
+  check_listpp(ns1, ioctx, "ns1");
 
   ioctx.set_namespace("ns2");
-  check_listpp(ns2, ioctx);
+  check_listpp(ns2, ioctx, "ns2");
 
   ioctx.set_namespace(all_nspaces);
-  EXPECT_THROW(check_listpp(def, ioctx), std::runtime_error);
+  check_listpp(all, ioctx, all_nspaces);
 }
 
 TEST_F(LibRadosListPP, ListObjectsManyPP) {
@@ -289,13 +313,13 @@ TEST_F(LibRadosListPP, ListObjectsManyPP) {
     ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0));
   }
 
-  librados::ObjectIterator it = ioctx.objects_begin();
+  librados::NObjectIterator it = ioctx.nobjects_begin();
   std::set<std::string> saw_obj;
   std::set<int> saw_pg;
-  for (; it != ioctx.objects_end(); ++it) {
-    std::cout << it->first
+  for (; it != ioctx.nobjects_end(); ++it) {
+    std::cout << it->get_oid()
              << " " << it.get_pg_hash_position() << std::endl;
-    saw_obj.insert(it->first);
+    saw_obj.insert(it->get_oid());
     saw_pg.insert(it.get_pg_hash_position());
   }
   std::cout << "saw " << saw_pg.size() << " pgs " << std::endl;
@@ -315,27 +339,27 @@ TEST_F(LibRadosList, ListObjectsStart) {
   }
 
   rados_list_ctx_t ctx;
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
   std::map<int, std::set<std::string> > pg_to_obj;
   const char *entry;
-  while (rados_objects_list_next(ctx, &entry, NULL) == 0) {
-    uint32_t pos = rados_objects_list_get_pg_hash_position(ctx);
+  while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) == 0) {
+    uint32_t pos = rados_nobjects_list_get_pg_hash_position(ctx);
     std::cout << entry << " " << pos << std::endl;
     pg_to_obj[pos].insert(entry);
   }
-  rados_objects_list_close(ctx);
+  rados_nobjects_list_close(ctx);
 
   std::map<int, std::set<std::string> >::reverse_iterator p =
     pg_to_obj.rbegin();
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
   while (p != pg_to_obj.rend()) {
-    ASSERT_EQ((uint32_t)p->first, rados_objects_list_seek(ctx, p->first));
-    ASSERT_EQ(0, rados_objects_list_next(ctx, &entry, NULL));
+    ASSERT_EQ((uint32_t)p->first, rados_nobjects_list_seek(ctx, p->first));
+    ASSERT_EQ(0, rados_nobjects_list_next(ctx, &entry, NULL, NULL));
     std::cout << "have " << entry << " expect one of " << p->second << std::endl;
     ASSERT_TRUE(p->second.count(entry));
     ++p;
   }
-  rados_objects_list_close(ctx);
+  rados_nobjects_list_close(ctx);
 }
 
 TEST_F(LibRadosListPP, ListObjectsStartPP) {
@@ -348,20 +372,20 @@ TEST_F(LibRadosListPP, ListObjectsStartPP) {
     ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0));
   }
 
-  librados::ObjectIterator it = ioctx.objects_begin();
+  librados::NObjectIterator it = ioctx.nobjects_begin();
   std::map<int, std::set<std::string> > pg_to_obj;
-  for (; it != ioctx.objects_end(); ++it) {
-    std::cout << it->first << " " << it.get_pg_hash_position() << std::endl;
-    pg_to_obj[it.get_pg_hash_position()].insert(it->first);
+  for (; it != ioctx.nobjects_end(); ++it) {
+    std::cout << it->get_oid() << " " << it.get_pg_hash_position() << std::endl;
+    pg_to_obj[it.get_pg_hash_position()].insert(it->get_oid());
   }
 
   std::map<int, std::set<std::string> >::reverse_iterator p =
     pg_to_obj.rbegin();
-  it = ioctx.objects_begin(p->first);
+  it = ioctx.nobjects_begin(p->first);
   while (p != pg_to_obj.rend()) {
     ASSERT_EQ((uint32_t)p->first, it.seek(p->first));
-    std::cout << "have " << it->first << " expect one of " << p->second << std::endl;
-    ASSERT_TRUE(p->second.count(it->first));
+    std::cout << "have " << it->get_oid() << " expect one of " << p->second << std::endl;
+    ASSERT_TRUE(p->second.count(it->get_oid()));
     ++p;
   }
 }
@@ -371,15 +395,15 @@ TEST_F(LibRadosListEC, ListObjects) {
   memset(buf, 0xcc, sizeof(buf));
   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
   rados_list_ctx_t ctx;
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
   const char *entry;
   bool foundit = false;
-  while (rados_objects_list_next(ctx, &entry, NULL) != -ENOENT) {
+  while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) != -ENOENT) {
     foundit = true;
     ASSERT_EQ(std::string(entry), "foo");
   }
   ASSERT_TRUE(foundit);
-  rados_objects_list_close(ctx);
+  rados_nobjects_list_close(ctx);
 }
 
 TEST_F(LibRadosListECPP, ListObjectsPP) {
@@ -388,11 +412,11 @@ TEST_F(LibRadosListECPP, ListObjectsPP) {
   bufferlist bl1;
   bl1.append(buf, sizeof(buf));
   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-  ObjectIterator iter(ioctx.objects_begin());
+  NObjectIterator iter(ioctx.nobjects_begin());
   bool foundit = false;
-  while (iter != ioctx.objects_end()) {
+  while (iter != ioctx.nobjects_end()) {
     foundit = true;
-    ASSERT_EQ((*iter).first, "foo");
+    ASSERT_EQ((*iter).get_oid(), "foo");
     ++iter;
   }
   ASSERT_TRUE(foundit);
@@ -404,21 +428,21 @@ TEST_F(LibRadosListECPP, ListObjectsTwicePP) {
   bufferlist bl1;
   bl1.append(buf, sizeof(buf));
   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-  ObjectIterator iter(ioctx.objects_begin());
+  NObjectIterator iter(ioctx.nobjects_begin());
   bool foundit = false;
-  while (iter != ioctx.objects_end()) {
+  while (iter != ioctx.nobjects_end()) {
     foundit = true;
-    ASSERT_EQ((*iter).first, "foo");
+    ASSERT_EQ((*iter).get_oid(), "foo");
     ++iter;
   }
   ASSERT_TRUE(foundit);
   ++iter;
-  ASSERT_TRUE(iter == ioctx.objects_end());
+  ASSERT_TRUE(iter == ioctx.nobjects_end());
   foundit = false;
   iter.seek(0);
-  while (iter != ioctx.objects_end()) {
+  while (iter != ioctx.nobjects_end()) {
     foundit = true;
-    ASSERT_EQ((*iter).first, "foo");
+    ASSERT_EQ((*iter).get_oid(), "foo");
     ++iter;
   }
   ASSERT_TRUE(foundit);
@@ -432,28 +456,28 @@ TEST_F(LibRadosListECPP, ListObjectsCopyIterPP) {
   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
 
   // make sure this is still valid after the original iterators are gone
-  ObjectIterator iter3;
+  NObjectIterator iter3;
   {
-    ObjectIterator iter(ioctx.objects_begin());
-    ObjectIterator iter2(iter);
+    NObjectIterator iter(ioctx.nobjects_begin());
+    NObjectIterator iter2(iter);
     iter3 = iter2;
-    ASSERT_EQ((*iter).first, "foo");
+    ASSERT_EQ((*iter).get_oid(), "foo");
     ++iter;
-    ASSERT_TRUE(iter == ioctx.objects_end());
+    ASSERT_TRUE(iter == ioctx.nobjects_end());
     ++iter;
-    ASSERT_TRUE(iter == ioctx.objects_end());
+    ASSERT_TRUE(iter == ioctx.nobjects_end());
 
-    ASSERT_EQ(iter2->first, "foo");
-    ASSERT_EQ(iter3->first, "foo");
+    ASSERT_EQ(iter2->get_oid(), "foo");
+    ASSERT_EQ(iter3->get_oid(), "foo");
     ++iter2;
-    ASSERT_TRUE(iter2 == ioctx.objects_end());
+    ASSERT_TRUE(iter2 == ioctx.nobjects_end());
   }
 
-  ASSERT_EQ(iter3->first, "foo");
+  ASSERT_EQ(iter3->get_oid(), "foo");
   iter3 = iter3;
-  ASSERT_EQ(iter3->first, "foo");
+  ASSERT_EQ(iter3->get_oid(), "foo");
   ++iter3;
-  ASSERT_TRUE(iter3 == ioctx.objects_end());
+  ASSERT_TRUE(iter3 == ioctx.nobjects_end());
 }
 
 TEST_F(LibRadosListECPP, ListObjectsEndIter) {
@@ -463,27 +487,24 @@ TEST_F(LibRadosListECPP, ListObjectsEndIter) {
   bl1.append(buf, sizeof(buf));
   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
 
-  ObjectIterator iter(ioctx.objects_begin());
-  ObjectIterator iter_end(ioctx.objects_end());
-  ObjectIterator iter_end2 = ioctx.objects_end();
+  NObjectIterator iter(ioctx.nobjects_begin());
+  NObjectIterator iter_end(ioctx.nobjects_end());
+  NObjectIterator iter_end2 = ioctx.nobjects_end();
   ASSERT_TRUE(iter_end == iter_end2);
-  ASSERT_TRUE(iter_end == ioctx.objects_end());
-  ASSERT_TRUE(iter_end2 == ioctx.objects_end());
+  ASSERT_TRUE(iter_end == ioctx.nobjects_end());
+  ASSERT_TRUE(iter_end2 == ioctx.nobjects_end());
 
-  ASSERT_EQ(iter->first, "foo");
+  ASSERT_EQ(iter->get_oid(), "foo");
   ++iter;
-  ASSERT_TRUE(iter == ioctx.objects_end());
+  ASSERT_TRUE(iter == ioctx.nobjects_end());
   ASSERT_TRUE(iter == iter_end);
   ASSERT_TRUE(iter == iter_end2);
-  ObjectIterator iter2 = iter;
-  ASSERT_TRUE(iter2 == ioctx.objects_end());
+  NObjectIterator iter2 = iter;
+  ASSERT_TRUE(iter2 == ioctx.nobjects_end());
   ASSERT_TRUE(iter2 == iter_end);
   ASSERT_TRUE(iter2 == iter_end2);
 }
 
-#pragma GCC diagnostic pop
-#pragma GCC diagnostic warning "-Wpragmas"
-
 TEST_F(LibRadosListEC, ListObjectsNS) {
   char buf[128];
   memset(buf, 0xcc, sizeof(buf));
@@ -502,7 +523,7 @@ TEST_F(LibRadosListEC, ListObjectsNS) {
   ASSERT_EQ(0, rados_write(ioctx, "foo6", buf, sizeof(buf), 0));
   ASSERT_EQ(0, rados_write(ioctx, "foo7", buf, sizeof(buf), 0));
 
-  std::set<std::string> def, ns1, ns2;
+  std::set<std::string> def, ns1, ns2, all;
   def.insert(std::string("foo1"));
   def.insert(std::string("foo2"));
   def.insert(std::string("foo3"));
@@ -511,29 +532,39 @@ TEST_F(LibRadosListEC, ListObjectsNS) {
   ns1.insert(std::string("foo5"));
   ns2.insert(std::string("foo6"));
   ns2.insert(std::string("foo7"));
+  all.insert(std::string(":foo1"));
+  all.insert(std::string(":foo2"));
+  all.insert(std::string(":foo3"));
+  all.insert(std::string("ns1:foo1"));
+  all.insert(std::string("ns1:foo4"));
+  all.insert(std::string("ns1:foo5"));
+  all.insert(std::string("ns2:foo6"));
+  all.insert(std::string("ns2:foo7"));
 
   rados_list_ctx_t ctx;
   // Check default namespace ""
   rados_ioctx_set_namespace(ioctx, "");
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
-  check_list(def, ctx);
-  rados_objects_list_close(ctx);
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
+  check_list(def, ctx, "");
+  rados_nobjects_list_close(ctx);
 
   // Check default namespace "ns1"
   rados_ioctx_set_namespace(ioctx, "ns1");
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
-  check_list(ns1, ctx);
-  rados_objects_list_close(ctx);
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
+  check_list(ns1, ctx, "ns1");
+  rados_nobjects_list_close(ctx);
 
   // Check default namespace "ns2"
   rados_ioctx_set_namespace(ioctx, "ns2");
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
-  check_list(ns2, ctx);
-  rados_objects_list_close(ctx);
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
+  check_list(ns2, ctx, "ns2");
+  rados_nobjects_list_close(ctx);
 
-  // Can't specify all namespaces using old interface
+  // Check all namespaces
   rados_ioctx_set_namespace(ioctx, LIBRADOS_ALL_NSPACES);
-  ASSERT_EQ(-EINVAL, rados_objects_list_open(ioctx, &ctx));
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
+  check_list(all, ctx, all_nspaces);
+  rados_nobjects_list_close(ctx);
 }
 
 TEST_F(LibRadosListECPP, ListObjectsPPNS) {
@@ -567,22 +598,15 @@ TEST_F(LibRadosListECPP, ListObjectsPPNS) {
   ns2.insert(std::string("foo7"));
 
   ioctx.set_namespace("");
-  check_listpp(def, ioctx);
+  check_listpp(def, ioctx, "");
 
   ioctx.set_namespace("ns1");
-  check_listpp(ns1, ioctx);
+  check_listpp(ns1, ioctx, "ns1");
 
   ioctx.set_namespace("ns2");
-  check_listpp(ns2, ioctx);
-
-  ioctx.set_namespace(all_nspaces);
-  EXPECT_THROW(check_listpp(def, ioctx), std::runtime_error);
+  check_listpp(ns2, ioctx, "ns2");
 }
 
-#pragma GCC diagnostic ignored "-Wpragmas"
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
 TEST_F(LibRadosListECPP, ListObjectsManyPP) {
   char buf[128];
   memset(buf, 0xcc, sizeof(buf));
@@ -593,13 +617,13 @@ TEST_F(LibRadosListECPP, ListObjectsManyPP) {
     ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0));
   }
 
-  librados::ObjectIterator it = ioctx.objects_begin();
+  librados::NObjectIterator it = ioctx.nobjects_begin();
   std::set<std::string> saw_obj;
   std::set<int> saw_pg;
-  for (; it != ioctx.objects_end(); ++it) {
-    std::cout << it->first
+  for (; it != ioctx.nobjects_end(); ++it) {
+    std::cout << it->get_oid()
              << " " << it.get_pg_hash_position() << std::endl;
-    saw_obj.insert(it->first);
+    saw_obj.insert(it->get_oid());
     saw_pg.insert(it.get_pg_hash_position());
   }
   std::cout << "saw " << saw_pg.size() << " pgs " << std::endl;
@@ -619,27 +643,27 @@ TEST_F(LibRadosListEC, ListObjectsStart) {
   }
 
   rados_list_ctx_t ctx;
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
   std::map<int, std::set<std::string> > pg_to_obj;
   const char *entry;
-  while (rados_objects_list_next(ctx, &entry, NULL) == 0) {
-    uint32_t pos = rados_objects_list_get_pg_hash_position(ctx);
+  while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) == 0) {
+    uint32_t pos = rados_nobjects_list_get_pg_hash_position(ctx);
     std::cout << entry << " " << pos << std::endl;
     pg_to_obj[pos].insert(entry);
   }
-  rados_objects_list_close(ctx);
+  rados_nobjects_list_close(ctx);
 
   std::map<int, std::set<std::string> >::reverse_iterator p =
     pg_to_obj.rbegin();
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
   while (p != pg_to_obj.rend()) {
-    ASSERT_EQ((uint32_t)p->first, rados_objects_list_seek(ctx, p->first));
-    ASSERT_EQ(0, rados_objects_list_next(ctx, &entry, NULL));
+    ASSERT_EQ((uint32_t)p->first, rados_nobjects_list_seek(ctx, p->first));
+    ASSERT_EQ(0, rados_nobjects_list_next(ctx, &entry, NULL, NULL));
     std::cout << "have " << entry << " expect one of " << p->second << std::endl;
     ASSERT_TRUE(p->second.count(entry));
     ++p;
   }
-  rados_objects_list_close(ctx);
+  rados_nobjects_list_close(ctx);
 }
 
 TEST_F(LibRadosListECPP, ListObjectsStartPP) {
@@ -652,24 +676,91 @@ TEST_F(LibRadosListECPP, ListObjectsStartPP) {
     ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0));
   }
 
-  librados::ObjectIterator it = ioctx.objects_begin();
+  librados::NObjectIterator it = ioctx.nobjects_begin();
   std::map<int, std::set<std::string> > pg_to_obj;
-  for (; it != ioctx.objects_end(); ++it) {
-    std::cout << it->first << " " << it.get_pg_hash_position() << std::endl;
-    pg_to_obj[it.get_pg_hash_position()].insert(it->first);
+  for (; it != ioctx.nobjects_end(); ++it) {
+    std::cout << it->get_oid() << " " << it.get_pg_hash_position() << std::endl;
+    pg_to_obj[it.get_pg_hash_position()].insert(it->get_oid());
   }
 
   std::map<int, std::set<std::string> >::reverse_iterator p =
     pg_to_obj.rbegin();
-  it = ioctx.objects_begin(p->first);
+  it = ioctx.nobjects_begin(p->first);
   while (p != pg_to_obj.rend()) {
     ASSERT_EQ((uint32_t)p->first, it.seek(p->first));
-    std::cout << "have " << it->first << " expect one of " << p->second << std::endl;
-    ASSERT_TRUE(p->second.count(it->first));
+    std::cout << "have " << it->get_oid() << " expect one of " << p->second << std::endl;
+    ASSERT_TRUE(p->second.count(it->get_oid()));
     ++p;
   }
 }
 
+TEST_F(LibRadosListPP, ListObjectsFilterPP) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist obj_content;
+  obj_content.append(buf, sizeof(buf));
+
+  std::string target_str = "content";
+
+  // Write xattr bare, no ::encod'ing
+  bufferlist target_val;
+  target_val.append(target_str);
+  bufferlist nontarget_val;
+  nontarget_val.append("rhubarb");
+
+  ASSERT_EQ(0, ioctx.write("has_xattr", obj_content, obj_content.length(), 0));
+  ASSERT_EQ(0, ioctx.write("has_wrong_xattr", obj_content, obj_content.length(), 0));
+  ASSERT_EQ(0, ioctx.write("no_xattr", obj_content, obj_content.length(), 0));
+
+  ASSERT_EQ(0, ioctx.setxattr("has_xattr", "theattr", target_val));
+  ASSERT_EQ(0, ioctx.setxattr("has_wrong_xattr", "theattr", nontarget_val));
+
+  bufferlist filter_bl;
+  std::string filter_name = "plain";
+  ::encode(filter_name, filter_bl);
+  ::encode("_theattr", filter_bl);
+  ::encode(target_str, filter_bl);
+
+  NObjectIterator iter(ioctx.nobjects_begin(filter_bl));
+  bool foundit = false;
+  int k = 0;
+  while (iter != ioctx.nobjects_end()) {
+    foundit = true;
+    // We should only see the object that matches the filter
+    ASSERT_EQ((*iter).get_oid(), "has_xattr");
+    // We should only see it once
+    ASSERT_EQ(k, 0);
+    ++iter;
+    ++k;
+  }
+  ASSERT_TRUE(foundit);
+}
+
+TEST_F(LibRadosListNP, ListObjectsError) {
+  std::string pool_name;
+  rados_t cluster;
+  rados_ioctx_t ioctx;
+  pool_name = get_temp_pool_name();
+  ASSERT_EQ("", create_one_pool(pool_name, &cluster));
+  ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  rados_ioctx_set_namespace(ioctx, "");
+  ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  ASSERT_EQ(0, rados_pool_delete(cluster, pool_name.c_str()));
+
+  rados_list_ctx_t ctx;
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
+  const char *entry;
+  ASSERT_EQ(-ENOENT, rados_nobjects_list_next(ctx, &entry, NULL, NULL));
+  rados_nobjects_list_close(ctx);
+  rados_ioctx_destroy(ioctx);
+  rados_shutdown(cluster);
+}
+
+
+
+// ---------------------------------------------
 
 TEST_F(LibRadosList, EnumerateObjects) {
   char buf[128];
@@ -886,27 +977,6 @@ TEST_F(LibRadosListPP, EnumerateObjectsSplitPP) {
   ASSERT_EQ(n_objects, saw_obj.size());
 }
 
-TEST_F(LibRadosListNP, ListObjectsError) {
-  std::string pool_name;
-  rados_t cluster;
-  rados_ioctx_t ioctx;
-  pool_name = get_temp_pool_name();
-  ASSERT_EQ("", create_one_pool(pool_name, &cluster));
-  ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  rados_ioctx_set_namespace(ioctx, "");
-  ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
-  ASSERT_EQ(0, rados_pool_delete(cluster, pool_name.c_str()));
-  
-  rados_list_ctx_t ctx;
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
-  const char *entry;
-  ASSERT_EQ(-ENOENT, rados_objects_list_next(ctx, &entry, NULL));
-  rados_objects_list_close(ctx);
-  rados_ioctx_destroy(ioctx);
-  rados_shutdown(cluster);
-}
 
 TEST_F(LibRadosListPP, EnumerateObjectsFilterPP) {
   char buf[128];
diff --git a/src/test/librados/nlist.cc b/src/test/librados/nlist.cc
deleted file mode 100644 (file)
index c6fa82d..0000000
+++ /dev/null
@@ -1,755 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-#include "include/rados/librados.h"
-#include "include/rados/librados.hpp"
-#include "include/stringify.h"
-#include "test/librados/test.h"
-#include "test/librados/TestCase.h"
-
-#include "include/types.h"
-#include "gtest/gtest.h"
-#include <errno.h>
-#include <string>
-
-using namespace librados;
-
-typedef RadosTestNS LibRadosList;
-typedef RadosTestPPNS LibRadosListPP;
-typedef RadosTestECNS LibRadosListEC;
-typedef RadosTestECPPNS LibRadosListECPP;
-typedef RadosTestNP LibRadosListNP;
-
-TEST_F(LibRadosList, ListObjects) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
-  rados_list_ctx_t ctx;
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  const char *entry;
-  bool foundit = false;
-  while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) != -ENOENT) {
-    foundit = true;
-    ASSERT_EQ(std::string(entry), "foo");
-  }
-  ASSERT_TRUE(foundit);
-  rados_nobjects_list_close(ctx);
-}
-
-TEST_F(LibRadosListPP, ListObjectsPP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
-  ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-  NObjectIterator iter(ioctx.nobjects_begin());
-  bool foundit = false;
-  while (iter != ioctx.nobjects_end()) {
-    foundit = true;
-    ASSERT_EQ((*iter).get_oid(), "foo");
-    ++iter;
-  }
-  ASSERT_TRUE(foundit);
-}
-
-TEST_F(LibRadosListPP, ListObjectsTwicePP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
-  ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-  NObjectIterator iter(ioctx.nobjects_begin());
-  bool foundit = false;
-  while (iter != ioctx.nobjects_end()) {
-    foundit = true;
-    ASSERT_EQ((*iter).get_oid(), "foo");
-    ++iter;
-  }
-  ASSERT_TRUE(foundit);
-  ++iter;
-  ASSERT_TRUE(iter == ioctx.nobjects_end());
-  foundit = false;
-  iter.seek(0);
-  while (iter != ioctx.nobjects_end()) {
-    foundit = true;
-    ASSERT_EQ((*iter).get_oid(), "foo");
-    ++iter;
-  }
-  ASSERT_TRUE(foundit);
-}
-
-TEST_F(LibRadosListPP, ListObjectsCopyIterPP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
-  ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-
-  // make sure this is still valid after the original iterators are gone
-  NObjectIterator iter3;
-  {
-    NObjectIterator iter(ioctx.nobjects_begin());
-    NObjectIterator iter2(iter);
-    iter3 = iter2;
-    ASSERT_EQ((*iter).get_oid(), "foo");
-    ++iter;
-    ASSERT_TRUE(iter == ioctx.nobjects_end());
-    ++iter;
-    ASSERT_TRUE(iter == ioctx.nobjects_end());
-
-    ASSERT_EQ(iter2->get_oid(), "foo");
-    ASSERT_EQ(iter3->get_oid(), "foo");
-    ++iter2;
-    ASSERT_TRUE(iter2 == ioctx.nobjects_end());
-  }
-
-  ASSERT_EQ(iter3->get_oid(), "foo");
-  iter3 = iter3;
-  ASSERT_EQ(iter3->get_oid(), "foo");
-  ++iter3;
-  ASSERT_TRUE(iter3 == ioctx.nobjects_end());
-}
-
-TEST_F(LibRadosListPP, ListObjectsEndIter) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
-  ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-
-  NObjectIterator iter(ioctx.nobjects_begin());
-  NObjectIterator iter_end(ioctx.nobjects_end());
-  NObjectIterator iter_end2 = ioctx.nobjects_end();
-  ASSERT_TRUE(iter_end == iter_end2);
-  ASSERT_TRUE(iter_end == ioctx.nobjects_end());
-  ASSERT_TRUE(iter_end2 == ioctx.nobjects_end());
-
-  ASSERT_EQ(iter->get_oid(), "foo");
-  ++iter;
-  ASSERT_TRUE(iter == ioctx.nobjects_end());
-  ASSERT_TRUE(iter == iter_end);
-  ASSERT_TRUE(iter == iter_end2);
-  NObjectIterator iter2 = iter;
-  ASSERT_TRUE(iter2 == ioctx.nobjects_end());
-  ASSERT_TRUE(iter2 == iter_end);
-  ASSERT_TRUE(iter2 == iter_end2);
-}
-
-static void check_list(std::set<std::string>& myset, rados_list_ctx_t& ctx, std::string check_nspace)
-{
-  const char *entry, *nspace;
-  std::set<std::string> orig_set(myset);
-  /**
-   * During splitting, we might see duplicate items.
-   * We assert that every object returned is in myset and that
-   * we don't hit ENOENT until we have hit every item in myset
-   * at least once.
-   */
-  int ret;
-  while ((ret = rados_nobjects_list_next(ctx, &entry, NULL, &nspace)) == 0) {
-    std::string test_name;
-    if (check_nspace == all_nspaces) {
-      test_name = std::string(nspace) + ":" + std::string(entry);
-    } else {
-      ASSERT_TRUE(std::string(nspace) == check_nspace);
-      test_name = std::string(entry);
-    }
-
-    ASSERT_TRUE(orig_set.end() != orig_set.find(test_name));
-    myset.erase(test_name);
-  }
-  ASSERT_EQ(-ENOENT, ret);
-  ASSERT_TRUE(myset.empty());
-}
-
-TEST_F(LibRadosList, ListObjectsNS) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  // Create :foo1, :foo2, :foo3, n1:foo1, ns1:foo4, ns1:foo5, ns2:foo6, n2:foo7
-  rados_ioctx_set_namespace(ioctx, "");
-  ASSERT_EQ(0, rados_write(ioctx, "foo1", buf, sizeof(buf), 0));
-  rados_ioctx_set_namespace(ioctx, "ns1");
-  ASSERT_EQ(0, rados_write(ioctx, "foo1", buf, sizeof(buf), 0));
-  rados_ioctx_set_namespace(ioctx, "");
-  ASSERT_EQ(0, rados_write(ioctx, "foo2", buf, sizeof(buf), 0));
-  ASSERT_EQ(0, rados_write(ioctx, "foo3", buf, sizeof(buf), 0));
-  rados_ioctx_set_namespace(ioctx, "ns1");
-  ASSERT_EQ(0, rados_write(ioctx, "foo4", buf, sizeof(buf), 0));
-  ASSERT_EQ(0, rados_write(ioctx, "foo5", buf, sizeof(buf), 0));
-  rados_ioctx_set_namespace(ioctx, "ns2");
-  ASSERT_EQ(0, rados_write(ioctx, "foo6", buf, sizeof(buf), 0));
-  ASSERT_EQ(0, rados_write(ioctx, "foo7", buf, sizeof(buf), 0));
-
-  std::set<std::string> def, ns1, ns2, all;
-  def.insert(std::string("foo1"));
-  def.insert(std::string("foo2"));
-  def.insert(std::string("foo3"));
-  ns1.insert(std::string("foo1"));
-  ns1.insert(std::string("foo4"));
-  ns1.insert(std::string("foo5"));
-  ns2.insert(std::string("foo6"));
-  ns2.insert(std::string("foo7"));
-  all.insert(std::string(":foo1"));
-  all.insert(std::string(":foo2"));
-  all.insert(std::string(":foo3"));
-  all.insert(std::string("ns1:foo1"));
-  all.insert(std::string("ns1:foo4"));
-  all.insert(std::string("ns1:foo5"));
-  all.insert(std::string("ns2:foo6"));
-  all.insert(std::string("ns2:foo7"));
-
-  rados_list_ctx_t ctx;
-  // Check default namespace ""
-  rados_ioctx_set_namespace(ioctx, "");
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  check_list(def, ctx, "");
-  rados_nobjects_list_close(ctx);
-
-  // Check namespace "ns1"
-  rados_ioctx_set_namespace(ioctx, "ns1");
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  check_list(ns1, ctx, "ns1");
-  rados_nobjects_list_close(ctx);
-
-  // Check namespace "ns2"
-  rados_ioctx_set_namespace(ioctx, "ns2");
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  check_list(ns2, ctx, "ns2");
-  rados_nobjects_list_close(ctx);
-
-  // Check ALL namespaces
-  rados_ioctx_set_namespace(ioctx, LIBRADOS_ALL_NSPACES);
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  check_list(all, ctx, all_nspaces);
-  rados_nobjects_list_close(ctx);
-}
-
-static void check_listpp(std::set<std::string>& myset, IoCtx& ioctx, std::string check_nspace)
-{
-  NObjectIterator iter(ioctx.nobjects_begin());
-  std::set<std::string> orig_set(myset);
-  /**
-   * During splitting, we might see duplicate items.
-   * We assert that every object returned is in myset and that
-   * we don't hit ENOENT until we have hit every item in myset
-   * at least once.
-   */
-  while (iter != ioctx.nobjects_end()) {
-    std::string test_name;
-    if (check_nspace == all_nspaces) {
-      test_name = iter->get_nspace() + ":" + iter->get_oid();
-    } else {
-      ASSERT_TRUE(iter->get_nspace() == check_nspace);
-      test_name = iter->get_oid();
-    }
-    ASSERT_TRUE(orig_set.end() != orig_set.find(test_name));
-    myset.erase(test_name);
-    ++iter;
-  }
-  ASSERT_TRUE(myset.empty());
-}
-
-TEST_F(LibRadosListPP, ListObjectsPPNS) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
-  // Create :foo1, :foo2, :foo3, n1:foo1, ns1:foo4, ns1:foo5, ns2:foo6, n2:foo7
-  ioctx.set_namespace("");
-  ASSERT_EQ(0, ioctx.write("foo1", bl1, sizeof(buf), 0));
-  ioctx.set_namespace("ns1");
-  ASSERT_EQ(0, ioctx.write("foo1", bl1, sizeof(buf), 0));
-  ioctx.set_namespace("");
-  ASSERT_EQ(0, ioctx.write("foo2", bl1, sizeof(buf), 0));
-  ASSERT_EQ(0, ioctx.write("foo3", bl1, sizeof(buf), 0));
-  ioctx.set_namespace("ns1");
-  ASSERT_EQ(0, ioctx.write("foo4", bl1, sizeof(buf), 0));
-  ASSERT_EQ(0, ioctx.write("foo5", bl1, sizeof(buf), 0));
-  ioctx.set_namespace("ns2");
-  ASSERT_EQ(0, ioctx.write("foo6", bl1, sizeof(buf), 0));
-  ASSERT_EQ(0, ioctx.write("foo7", bl1, sizeof(buf), 0));
-
-  std::set<std::string> def, ns1, ns2, all;
-  def.insert(std::string("foo1"));
-  def.insert(std::string("foo2"));
-  def.insert(std::string("foo3"));
-  ns1.insert(std::string("foo1"));
-  ns1.insert(std::string("foo4"));
-  ns1.insert(std::string("foo5"));
-  ns2.insert(std::string("foo6"));
-  ns2.insert(std::string("foo7"));
-  all.insert(std::string(":foo1"));
-  all.insert(std::string(":foo2"));
-  all.insert(std::string(":foo3"));
-  all.insert(std::string("ns1:foo1"));
-  all.insert(std::string("ns1:foo4"));
-  all.insert(std::string("ns1:foo5"));
-  all.insert(std::string("ns2:foo6"));
-  all.insert(std::string("ns2:foo7"));
-
-  ioctx.set_namespace("");
-  check_listpp(def, ioctx, "");
-
-  ioctx.set_namespace("ns1");
-  check_listpp(ns1, ioctx, "ns1");
-
-  ioctx.set_namespace("ns2");
-  check_listpp(ns2, ioctx, "ns2");
-
-  ioctx.set_namespace(all_nspaces);
-  check_listpp(all, ioctx, all_nspaces);
-}
-
-TEST_F(LibRadosListPP, ListObjectsManyPP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl;
-  bl.append(buf, sizeof(buf));
-
-  for (int i=0; i<256; ++i) {
-    ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0));
-  }
-
-  librados::NObjectIterator it = ioctx.nobjects_begin();
-  std::set<std::string> saw_obj;
-  std::set<int> saw_pg;
-  for (; it != ioctx.nobjects_end(); ++it) {
-    std::cout << it->get_oid()
-             << " " << it.get_pg_hash_position() << std::endl;
-    saw_obj.insert(it->get_oid());
-    saw_pg.insert(it.get_pg_hash_position());
-  }
-  std::cout << "saw " << saw_pg.size() << " pgs " << std::endl;
-
-  // make sure they are 0..n
-  for (unsigned i = 0; i < saw_pg.size(); ++i)
-    ASSERT_TRUE(saw_pg.count(i));
-}
-
-TEST_F(LibRadosList, ListObjectsStart) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-
-  for (int i=0; i<16; ++i) {
-    string n = stringify(i);
-    ASSERT_EQ(0, rados_write(ioctx, n.c_str(), buf, sizeof(buf), 0));
-  }
-
-  rados_list_ctx_t ctx;
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  std::map<int, std::set<std::string> > pg_to_obj;
-  const char *entry;
-  while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) == 0) {
-    uint32_t pos = rados_objects_list_get_pg_hash_position(ctx);
-    std::cout << entry << " " << pos << std::endl;
-    pg_to_obj[pos].insert(entry);
-  }
-  rados_nobjects_list_close(ctx);
-
-  std::map<int, std::set<std::string> >::reverse_iterator p =
-    pg_to_obj.rbegin();
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  while (p != pg_to_obj.rend()) {
-    ASSERT_EQ((uint32_t)p->first, rados_objects_list_seek(ctx, p->first));
-    ASSERT_EQ(0, rados_nobjects_list_next(ctx, &entry, NULL, NULL));
-    std::cout << "have " << entry << " expect one of " << p->second << std::endl;
-    ASSERT_TRUE(p->second.count(entry));
-    ++p;
-  }
-  rados_nobjects_list_close(ctx);
-}
-
-TEST_F(LibRadosListPP, ListObjectsStartPP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl;
-  bl.append(buf, sizeof(buf));
-
-  for (int i=0; i<16; ++i) {
-    ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0));
-  }
-
-  librados::NObjectIterator it = ioctx.nobjects_begin();
-  std::map<int, std::set<std::string> > pg_to_obj;
-  for (; it != ioctx.nobjects_end(); ++it) {
-    std::cout << it->get_oid() << " " << it.get_pg_hash_position() << std::endl;
-    pg_to_obj[it.get_pg_hash_position()].insert(it->get_oid());
-  }
-
-  std::map<int, std::set<std::string> >::reverse_iterator p =
-    pg_to_obj.rbegin();
-  it = ioctx.nobjects_begin(p->first);
-  while (p != pg_to_obj.rend()) {
-    ASSERT_EQ((uint32_t)p->first, it.seek(p->first));
-    std::cout << "have " << it->get_oid() << " expect one of " << p->second << std::endl;
-    ASSERT_TRUE(p->second.count(it->get_oid()));
-    ++p;
-  }
-}
-
-TEST_F(LibRadosListEC, ListObjects) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
-  rados_list_ctx_t ctx;
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  const char *entry;
-  bool foundit = false;
-  while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) != -ENOENT) {
-    foundit = true;
-    ASSERT_EQ(std::string(entry), "foo");
-  }
-  ASSERT_TRUE(foundit);
-  rados_nobjects_list_close(ctx);
-}
-
-TEST_F(LibRadosListECPP, ListObjectsPP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
-  ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-  NObjectIterator iter(ioctx.nobjects_begin());
-  bool foundit = false;
-  while (iter != ioctx.nobjects_end()) {
-    foundit = true;
-    ASSERT_EQ((*iter).get_oid(), "foo");
-    ++iter;
-  }
-  ASSERT_TRUE(foundit);
-}
-
-TEST_F(LibRadosListECPP, ListObjectsTwicePP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
-  ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-  NObjectIterator iter(ioctx.nobjects_begin());
-  bool foundit = false;
-  while (iter != ioctx.nobjects_end()) {
-    foundit = true;
-    ASSERT_EQ((*iter).get_oid(), "foo");
-    ++iter;
-  }
-  ASSERT_TRUE(foundit);
-  ++iter;
-  ASSERT_TRUE(iter == ioctx.nobjects_end());
-  foundit = false;
-  iter.seek(0);
-  while (iter != ioctx.nobjects_end()) {
-    foundit = true;
-    ASSERT_EQ((*iter).get_oid(), "foo");
-    ++iter;
-  }
-  ASSERT_TRUE(foundit);
-}
-
-TEST_F(LibRadosListECPP, ListObjectsCopyIterPP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
-  ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-
-  // make sure this is still valid after the original iterators are gone
-  NObjectIterator iter3;
-  {
-    NObjectIterator iter(ioctx.nobjects_begin());
-    NObjectIterator iter2(iter);
-    iter3 = iter2;
-    ASSERT_EQ((*iter).get_oid(), "foo");
-    ++iter;
-    ASSERT_TRUE(iter == ioctx.nobjects_end());
-    ++iter;
-    ASSERT_TRUE(iter == ioctx.nobjects_end());
-
-    ASSERT_EQ(iter2->get_oid(), "foo");
-    ASSERT_EQ(iter3->get_oid(), "foo");
-    ++iter2;
-    ASSERT_TRUE(iter2 == ioctx.nobjects_end());
-  }
-
-  ASSERT_EQ(iter3->get_oid(), "foo");
-  iter3 = iter3;
-  ASSERT_EQ(iter3->get_oid(), "foo");
-  ++iter3;
-  ASSERT_TRUE(iter3 == ioctx.nobjects_end());
-}
-
-TEST_F(LibRadosListECPP, ListObjectsEndIter) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
-  ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-
-  NObjectIterator iter(ioctx.nobjects_begin());
-  NObjectIterator iter_end(ioctx.nobjects_end());
-  NObjectIterator iter_end2 = ioctx.nobjects_end();
-  ASSERT_TRUE(iter_end == iter_end2);
-  ASSERT_TRUE(iter_end == ioctx.nobjects_end());
-  ASSERT_TRUE(iter_end2 == ioctx.nobjects_end());
-
-  ASSERT_EQ(iter->get_oid(), "foo");
-  ++iter;
-  ASSERT_TRUE(iter == ioctx.nobjects_end());
-  ASSERT_TRUE(iter == iter_end);
-  ASSERT_TRUE(iter == iter_end2);
-  NObjectIterator iter2 = iter;
-  ASSERT_TRUE(iter2 == ioctx.nobjects_end());
-  ASSERT_TRUE(iter2 == iter_end);
-  ASSERT_TRUE(iter2 == iter_end2);
-}
-
-TEST_F(LibRadosListEC, ListObjectsNS) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  // Create :foo1, :foo2, :foo3, n1:foo1, ns1:foo4, ns1:foo5, ns2:foo6, n2:foo7
-  rados_ioctx_set_namespace(ioctx, "");
-  ASSERT_EQ(0, rados_write(ioctx, "foo1", buf, sizeof(buf), 0));
-  rados_ioctx_set_namespace(ioctx, "ns1");
-  ASSERT_EQ(0, rados_write(ioctx, "foo1", buf, sizeof(buf), 0));
-  rados_ioctx_set_namespace(ioctx, "");
-  ASSERT_EQ(0, rados_write(ioctx, "foo2", buf, sizeof(buf), 0));
-  ASSERT_EQ(0, rados_write(ioctx, "foo3", buf, sizeof(buf), 0));
-  rados_ioctx_set_namespace(ioctx, "ns1");
-  ASSERT_EQ(0, rados_write(ioctx, "foo4", buf, sizeof(buf), 0));
-  ASSERT_EQ(0, rados_write(ioctx, "foo5", buf, sizeof(buf), 0));
-  rados_ioctx_set_namespace(ioctx, "ns2");
-  ASSERT_EQ(0, rados_write(ioctx, "foo6", buf, sizeof(buf), 0));
-  ASSERT_EQ(0, rados_write(ioctx, "foo7", buf, sizeof(buf), 0));
-
-  std::set<std::string> def, ns1, ns2, all;
-  def.insert(std::string("foo1"));
-  def.insert(std::string("foo2"));
-  def.insert(std::string("foo3"));
-  ns1.insert(std::string("foo1"));
-  ns1.insert(std::string("foo4"));
-  ns1.insert(std::string("foo5"));
-  ns2.insert(std::string("foo6"));
-  ns2.insert(std::string("foo7"));
-  all.insert(std::string(":foo1"));
-  all.insert(std::string(":foo2"));
-  all.insert(std::string(":foo3"));
-  all.insert(std::string("ns1:foo1"));
-  all.insert(std::string("ns1:foo4"));
-  all.insert(std::string("ns1:foo5"));
-  all.insert(std::string("ns2:foo6"));
-  all.insert(std::string("ns2:foo7"));
-
-  rados_list_ctx_t ctx;
-  // Check default namespace ""
-  rados_ioctx_set_namespace(ioctx, "");
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  check_list(def, ctx, "");
-  rados_nobjects_list_close(ctx);
-
-  // Check default namespace "ns1"
-  rados_ioctx_set_namespace(ioctx, "ns1");
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  check_list(ns1, ctx, "ns1");
-  rados_nobjects_list_close(ctx);
-
-  // Check default namespace "ns2"
-  rados_ioctx_set_namespace(ioctx, "ns2");
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  check_list(ns2, ctx, "ns2");
-  rados_nobjects_list_close(ctx);
-
-  // Check all namespaces
-  rados_ioctx_set_namespace(ioctx, LIBRADOS_ALL_NSPACES);
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  check_list(all, ctx, all_nspaces);
-  rados_nobjects_list_close(ctx);
-}
-
-TEST_F(LibRadosListECPP, ListObjectsPPNS) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
-  // Create :foo1, :foo2, :foo3, n1:foo1, ns1:foo4, ns1:foo5, ns2:foo6, n2:foo7
-  ioctx.set_namespace("");
-  ASSERT_EQ(0, ioctx.write("foo1", bl1, sizeof(buf), 0));
-  ioctx.set_namespace("ns1");
-  ASSERT_EQ(0, ioctx.write("foo1", bl1, sizeof(buf), 0));
-  ioctx.set_namespace("");
-  ASSERT_EQ(0, ioctx.write("foo2", bl1, sizeof(buf), 0));
-  ASSERT_EQ(0, ioctx.write("foo3", bl1, sizeof(buf), 0));
-  ioctx.set_namespace("ns1");
-  ASSERT_EQ(0, ioctx.write("foo4", bl1, sizeof(buf), 0));
-  ASSERT_EQ(0, ioctx.write("foo5", bl1, sizeof(buf), 0));
-  ioctx.set_namespace("ns2");
-  ASSERT_EQ(0, ioctx.write("foo6", bl1, sizeof(buf), 0));
-  ASSERT_EQ(0, ioctx.write("foo7", bl1, sizeof(buf), 0));
-
-  std::set<std::string> def, ns1, ns2;
-  def.insert(std::string("foo1"));
-  def.insert(std::string("foo2"));
-  def.insert(std::string("foo3"));
-  ns1.insert(std::string("foo1"));
-  ns1.insert(std::string("foo4"));
-  ns1.insert(std::string("foo5"));
-  ns2.insert(std::string("foo6"));
-  ns2.insert(std::string("foo7"));
-
-  ioctx.set_namespace("");
-  check_listpp(def, ioctx, "");
-
-  ioctx.set_namespace("ns1");
-  check_listpp(ns1, ioctx, "ns1");
-
-  ioctx.set_namespace("ns2");
-  check_listpp(ns2, ioctx, "ns2");
-}
-
-TEST_F(LibRadosListECPP, ListObjectsManyPP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl;
-  bl.append(buf, sizeof(buf));
-
-  for (int i=0; i<256; ++i) {
-    ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0));
-  }
-
-  librados::NObjectIterator it = ioctx.nobjects_begin();
-  std::set<std::string> saw_obj;
-  std::set<int> saw_pg;
-  for (; it != ioctx.nobjects_end(); ++it) {
-    std::cout << it->get_oid()
-             << " " << it.get_pg_hash_position() << std::endl;
-    saw_obj.insert(it->get_oid());
-    saw_pg.insert(it.get_pg_hash_position());
-  }
-  std::cout << "saw " << saw_pg.size() << " pgs " << std::endl;
-
-  // make sure they are 0..n
-  for (unsigned i = 0; i < saw_pg.size(); ++i)
-    ASSERT_TRUE(saw_pg.count(i));
-}
-
-TEST_F(LibRadosListEC, ListObjectsStart) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-
-  for (int i=0; i<16; ++i) {
-    string n = stringify(i);
-    ASSERT_EQ(0, rados_write(ioctx, n.c_str(), buf, sizeof(buf), 0));
-  }
-
-  rados_list_ctx_t ctx;
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  std::map<int, std::set<std::string> > pg_to_obj;
-  const char *entry;
-  while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) == 0) {
-    uint32_t pos = rados_objects_list_get_pg_hash_position(ctx);
-    std::cout << entry << " " << pos << std::endl;
-    pg_to_obj[pos].insert(entry);
-  }
-  rados_nobjects_list_close(ctx);
-
-  std::map<int, std::set<std::string> >::reverse_iterator p =
-    pg_to_obj.rbegin();
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  while (p != pg_to_obj.rend()) {
-    ASSERT_EQ((uint32_t)p->first, rados_objects_list_seek(ctx, p->first));
-    ASSERT_EQ(0, rados_nobjects_list_next(ctx, &entry, NULL, NULL));
-    std::cout << "have " << entry << " expect one of " << p->second << std::endl;
-    ASSERT_TRUE(p->second.count(entry));
-    ++p;
-  }
-  rados_nobjects_list_close(ctx);
-}
-
-TEST_F(LibRadosListECPP, ListObjectsStartPP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl;
-  bl.append(buf, sizeof(buf));
-
-  for (int i=0; i<16; ++i) {
-    ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0));
-  }
-
-  librados::NObjectIterator it = ioctx.nobjects_begin();
-  std::map<int, std::set<std::string> > pg_to_obj;
-  for (; it != ioctx.nobjects_end(); ++it) {
-    std::cout << it->get_oid() << " " << it.get_pg_hash_position() << std::endl;
-    pg_to_obj[it.get_pg_hash_position()].insert(it->get_oid());
-  }
-
-  std::map<int, std::set<std::string> >::reverse_iterator p =
-    pg_to_obj.rbegin();
-  it = ioctx.nobjects_begin(p->first);
-  while (p != pg_to_obj.rend()) {
-    ASSERT_EQ((uint32_t)p->first, it.seek(p->first));
-    std::cout << "have " << it->get_oid() << " expect one of " << p->second << std::endl;
-    ASSERT_TRUE(p->second.count(it->get_oid()));
-    ++p;
-  }
-}
-
-TEST_F(LibRadosListPP, ListObjectsFilterPP) {
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist obj_content;
-  obj_content.append(buf, sizeof(buf));
-
-  std::string target_str = "content";
-
-  // Write xattr bare, no ::encod'ing
-  bufferlist target_val;
-  target_val.append(target_str);
-  bufferlist nontarget_val;
-  nontarget_val.append("rhubarb");
-
-  ASSERT_EQ(0, ioctx.write("has_xattr", obj_content, obj_content.length(), 0));
-  ASSERT_EQ(0, ioctx.write("has_wrong_xattr", obj_content, obj_content.length(), 0));
-  ASSERT_EQ(0, ioctx.write("no_xattr", obj_content, obj_content.length(), 0));
-
-  ASSERT_EQ(0, ioctx.setxattr("has_xattr", "theattr", target_val));
-  ASSERT_EQ(0, ioctx.setxattr("has_wrong_xattr", "theattr", nontarget_val));
-
-  bufferlist filter_bl;
-  std::string filter_name = "plain";
-  ::encode(filter_name, filter_bl);
-  ::encode("_theattr", filter_bl);
-  ::encode(target_str, filter_bl);
-
-  NObjectIterator iter(ioctx.nobjects_begin(filter_bl));
-  bool foundit = false;
-  int k = 0;
-  while (iter != ioctx.nobjects_end()) {
-    foundit = true;
-    // We should only see the object that matches the filter
-    ASSERT_EQ((*iter).get_oid(), "has_xattr");
-    // We should only see it once
-    ASSERT_EQ(k, 0);
-    ++iter;
-    ++k;
-  }
-  ASSERT_TRUE(foundit);
-}
-
-TEST_F(LibRadosListNP, ListObjectsError) {
-  std::string pool_name;
-  rados_t cluster;
-  rados_ioctx_t ioctx;
-  pool_name = get_temp_pool_name();
-  ASSERT_EQ("", create_one_pool(pool_name, &cluster));
-  ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  rados_ioctx_set_namespace(ioctx, "");
-  ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
-  ASSERT_EQ(0, rados_pool_delete(cluster, pool_name.c_str()));
-  
-  rados_list_ctx_t ctx;
-  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
-  const char *entry;
-  ASSERT_EQ(-ENOENT, rados_nobjects_list_next(ctx, &entry, NULL, NULL));
-  rados_nobjects_list_close(ctx);
-  rados_ioctx_destroy(ioctx);
-  rados_shutdown(cluster);
-}
-