]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
test: New and updated testing for pgls of all namespaces
authorDavid Zafman <dzafman@redhat.com>
Thu, 25 Sep 2014 05:48:05 +0000 (22:48 -0700)
committerDavid Zafman <dzafman@redhat.com>
Mon, 20 Oct 2014 17:47:50 +0000 (10:47 -0700)
Add pg_nls_response_t encoding type ceph-dencoder
New test ceph_test_rados_api_nlist
Add check for throw of error and EINVAL in old test case
Change tests to use new librados list interfaces
Now flush_evict_all() can really evict all objects

Fixes: #9031
Signed-off-by: David Zafman <dzafman@redhat.com>
src/test/Makefile.am
src/test/encoding/types.h
src/test/kv_store_bench.cc
src/test/librados/TestCase.cc
src/test/librados/TestCase.h
src/test/librados/list.cc
src/test/librados/nlist.cc [new file with mode: 0644]
src/test/librados/tier.cc
src/test/system/st_rados_list_objects.cc

index 8a35928a4840430c1922ddc6accb0260db9a2e99..5e8a97c3eb0c693a6439b968548af633426d0a6b 100644 (file)
@@ -784,6 +784,11 @@ ceph_test_rados_api_list_LDADD = $(LIBRADOS) $(UNITTEST_LDADD) $(RADOS_TEST_LDAD
 ceph_test_rados_api_list_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 bin_DEBUGPROGRAMS += ceph_test_rados_api_list
 
+ceph_test_rados_api_nlist_SOURCES = test/librados/nlist.cc
+ceph_test_rados_api_nlist_LDADD = $(LIBRADOS) $(UNITTEST_LDADD) $(RADOS_TEST_LDADD)
+ceph_test_rados_api_nlist_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+bin_DEBUGPROGRAMS += ceph_test_rados_api_nlist
+
 ceph_test_rados_api_pool_SOURCES = test/librados/pool.cc
 ceph_test_rados_api_pool_LDADD = $(LIBRADOS) $(UNITTEST_LDADD) $(RADOS_TEST_LDADD)
 ceph_test_rados_api_pool_CXXFLAGS = $(UNITTEST_CXXFLAGS)
index 9619072cb43dd1aedbbfad0c77c1a172f08cd749..56f39b08b914d6f40242910f2ab70bd1df1ef671 100644 (file)
@@ -63,6 +63,7 @@ TYPE(pg_log_t)
 TYPE(pg_missing_t::item)
 TYPE(pg_missing_t)
 TYPE(pg_ls_response_t)
+TYPE(pg_nls_response_t)
 TYPE(object_copy_cursor_t)
 TYPE(object_copy_data_t)
 TYPE(pg_create_t)
index 20f355209742f594161ee76374c1de31fe9a9200..6bf7d3883e99546f03665738e33f8b972f1342f7 100644 (file)
@@ -193,11 +193,11 @@ int KvStoreBench::setup(int argc, const char** argv) {
   io_ctx_ready = true;
 
   if (clear_first) {
-    librados::ObjectIterator it;
-    for (it = io_ctx.objects_begin(); it != io_ctx.objects_end(); ++it) {
+    librados::NObjectIterator it;
+    for (it = io_ctx.nobjects_begin(); it != io_ctx.nobjects_end(); ++it) {
       librados::ObjectWriteOperation rm;
       rm.remove();
-      io_ctx.operate(it->first, &rm);
+      io_ctx.operate(it->get_oid(), &rm);
     }
   }
 
index 9d9668e90808292bc3bf9012a844fb951c3650b3..27fbb1966ecc477e9dde1a6fd7efc42603a29a24 100644 (file)
@@ -7,6 +7,226 @@
 
 using namespace librados;
 
+std::string RadosTestNS::pool_name;
+rados_t RadosTestNS::s_cluster = NULL;
+
+void RadosTestNS::SetUpTestCase()
+{
+  pool_name = get_temp_pool_name();
+  ASSERT_EQ("", create_one_pool(pool_name, &s_cluster));
+}
+
+void RadosTestNS::TearDownTestCase()
+{
+  ASSERT_EQ(0, destroy_one_pool(pool_name, &s_cluster));
+}
+
+void RadosTestNS::SetUp()
+{
+  cluster = RadosTestNS::s_cluster;
+  ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
+  ASSERT_FALSE(rados_ioctx_pool_requires_alignment(ioctx));
+}
+
+void RadosTestNS::TearDown()
+{
+  cleanup_all_objects(ioctx);
+  rados_ioctx_destroy(ioctx);
+}
+
+void RadosTestNS::cleanup_all_objects(rados_ioctx_t ioctx)
+{
+  // remove all objects to avoid polluting other tests
+  rados_ioctx_set_namespace(ioctx, LIBRADOS_ALL_NSPACES);
+  rados_list_ctx_t list_ctx;
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &list_ctx));
+  int r;
+  const char *entry = NULL;
+  const char *key = NULL;
+  const char *nspace = NULL;
+  while ((r = rados_nobjects_list_next(list_ctx, &entry, &key, &nspace)) != -ENOENT) {
+    ASSERT_EQ(0, r);
+    rados_ioctx_locator_set_key(ioctx, key);
+    rados_ioctx_set_namespace(ioctx, nspace);
+    ASSERT_EQ(0, rados_remove(ioctx, entry));
+  }
+  rados_nobjects_list_close(list_ctx);
+}
+
+std::string RadosTestPPNS::pool_name;
+Rados RadosTestPPNS::s_cluster;
+
+void RadosTestPPNS::SetUpTestCase()
+{
+  pool_name = get_temp_pool_name();
+  ASSERT_EQ("", create_one_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestPPNS::TearDownTestCase()
+{
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestPPNS::SetUp()
+{
+  ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
+  ASSERT_FALSE(ioctx.pool_requires_alignment());
+}
+
+void RadosTestPPNS::TearDown()
+{
+  cleanup_all_objects(ioctx);
+  ioctx.close();
+}
+
+void RadosTestPPNS::cleanup_all_objects(librados::IoCtx ioctx)
+{
+  // remove all objects to avoid polluting other tests
+  ioctx.set_namespace(all_nspaces);
+  for (NObjectIterator it = ioctx.nobjects_begin();
+       it != ioctx.nobjects_end(); ++it) {
+    ioctx.locator_set_key(it->get_locator());
+    ioctx.set_namespace(it->get_nspace());
+    ASSERT_EQ(0, ioctx.remove(it->get_oid()));
+  }
+}
+
+std::string RadosTestParamPPNS::pool_name;
+std::string RadosTestParamPPNS::cache_pool_name;
+Rados RadosTestParamPPNS::s_cluster;
+
+void RadosTestParamPPNS::SetUpTestCase()
+{
+  pool_name = get_temp_pool_name();
+  ASSERT_EQ("", create_one_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestParamPPNS::TearDownTestCase()
+{
+  if (cache_pool_name.length()) {
+    // tear down tiers
+    bufferlist inbl;
+    ASSERT_EQ(0, s_cluster.mon_command(
+      "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+      "\"}",
+      inbl, NULL, NULL));
+    ASSERT_EQ(0, s_cluster.mon_command(
+      "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+      "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+      inbl, NULL, NULL));
+    ASSERT_EQ(0, s_cluster.mon_command(
+      "{\"prefix\": \"osd pool delete\", \"pool\": \"" + cache_pool_name +
+      "\", \"pool2\": \"" + cache_pool_name + "\", \"sure\": \"--yes-i-really-really-mean-it\"}",
+      inbl, NULL, NULL));
+    cache_pool_name = "";
+  }
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestParamPPNS::SetUp()
+{
+  if (strcmp(GetParam(), "cache") == 0 && cache_pool_name.empty()) {
+    cache_pool_name = get_temp_pool_name();
+    bufferlist inbl;
+    ASSERT_EQ(0, cluster.mon_command(
+      "{\"prefix\": \"osd pool create\", \"pool\": \"" + cache_pool_name +
+      "\", \"pg_num\": 4}",
+      inbl, NULL, NULL));
+    ASSERT_EQ(0, cluster.mon_command(
+      "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+      "\", \"tierpool\": \"" + cache_pool_name +
+      "\", \"force_nonempty\": \"--force-nonempty\" }",
+      inbl, NULL, NULL));
+    ASSERT_EQ(0, cluster.mon_command(
+      "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+      "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+      inbl, NULL, NULL));
+    ASSERT_EQ(0, cluster.mon_command(
+      "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+      "\", \"mode\": \"writeback\"}",
+      inbl, NULL, NULL));
+    cluster.wait_for_latest_osdmap();
+  }
+
+  ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
+  ASSERT_FALSE(ioctx.pool_requires_alignment());
+}
+
+void RadosTestParamPPNS::TearDown()
+{
+  cleanup_all_objects(ioctx);
+  ioctx.close();
+}
+
+void RadosTestParamPPNS::cleanup_all_objects(librados::IoCtx ioctx)
+{
+  // remove all objects to avoid polluting other tests
+  ioctx.set_namespace(all_nspaces);
+  for (NObjectIterator it = ioctx.nobjects_begin();
+       it != ioctx.nobjects_end(); ++it) {
+    ioctx.locator_set_key(it->get_locator());
+    ioctx.set_namespace(it->get_nspace());
+    ASSERT_EQ(0, ioctx.remove(it->get_oid()));
+  }
+}
+
+std::string RadosTestECNS::pool_name;
+rados_t RadosTestECNS::s_cluster = NULL;
+
+void RadosTestECNS::SetUpTestCase()
+{
+  pool_name = get_temp_pool_name();
+  ASSERT_EQ("", create_one_ec_pool(pool_name, &s_cluster));
+}
+
+void RadosTestECNS::TearDownTestCase()
+{
+  ASSERT_EQ(0, destroy_one_ec_pool(pool_name, &s_cluster));
+}
+
+void RadosTestECNS::SetUp()
+{
+  cluster = RadosTestECNS::s_cluster;
+  ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
+  ASSERT_TRUE(rados_ioctx_pool_requires_alignment(ioctx));
+  alignment = rados_ioctx_pool_required_alignment(ioctx);
+  ASSERT_NE((unsigned)0, alignment);
+}
+
+void RadosTestECNS::TearDown()
+{
+  cleanup_all_objects(ioctx);
+  rados_ioctx_destroy(ioctx);
+}
+
+std::string RadosTestECPPNS::pool_name;
+Rados RadosTestECPPNS::s_cluster;
+
+void RadosTestECPPNS::SetUpTestCase()
+{
+  pool_name = get_temp_pool_name();
+  ASSERT_EQ("", create_one_ec_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestECPPNS::TearDownTestCase()
+{
+  ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestECPPNS::SetUp()
+{
+  ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
+  ASSERT_TRUE(ioctx.pool_requires_alignment());
+  alignment = ioctx.pool_required_alignment();
+  ASSERT_NE((unsigned)0, alignment);
+}
+
+void RadosTestECPPNS::TearDown()
+{
+  cleanup_all_objects(ioctx);
+  ioctx.close();
+}
+
 std::string RadosTest::pool_name;
 rados_t RadosTest::s_cluster = NULL;
 
@@ -42,16 +262,16 @@ void RadosTest::cleanup_default_namespace(rados_ioctx_t ioctx)
   // other tests
   rados_ioctx_set_namespace(ioctx, "");
   rados_list_ctx_t list_ctx;
-  ASSERT_EQ(0, rados_objects_list_open(ioctx, &list_ctx));
+  ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &list_ctx));
   int r;
   const char *entry = NULL;
   const char *key = NULL;
-  while ((r = rados_objects_list_next(list_ctx, &entry, &key)) != -ENOENT) {
+  while ((r = rados_nobjects_list_next(list_ctx, &entry, &key, NULL)) != -ENOENT) {
     ASSERT_EQ(0, r);
     rados_ioctx_locator_set_key(ioctx, key);
     ASSERT_EQ(0, rados_remove(ioctx, entry));
   }
-  rados_objects_list_close(list_ctx);
+  rados_nobjects_list_close(list_ctx);
 }
 
 std::string RadosTestPP::pool_name;
@@ -87,10 +307,10 @@ void RadosTestPP::cleanup_default_namespace(librados::IoCtx ioctx)
   // remove all objects from the default namespace to avoid polluting
   // other tests
   ioctx.set_namespace("");
-  for (ObjectIterator it = ioctx.objects_begin();
-       it != ioctx.objects_end(); ++it) {
-    ioctx.locator_set_key(it->second);
-    ASSERT_EQ(0, ioctx.remove(it->first));
+  for (NObjectIterator it = ioctx.nobjects_begin();
+       it != ioctx.nobjects_end(); ++it) {
+    ioctx.locator_set_key(it->get_locator());
+    ASSERT_EQ(0, ioctx.remove(it->get_oid()));
   }
 }
 
@@ -168,10 +388,10 @@ void RadosTestParamPP::cleanup_default_namespace(librados::IoCtx ioctx)
   // remove all objects from the default namespace to avoid polluting
   // other tests
   ioctx.set_namespace("");
-  for (ObjectIterator it = ioctx.objects_begin();
-       it != ioctx.objects_end(); ++it) {
-    ioctx.locator_set_key(it->second);
-    ASSERT_EQ(0, ioctx.remove(it->first));
+  for (NObjectIterator it = ioctx.nobjects_begin();
+       it != ioctx.nobjects_end(); ++it) {
+    ioctx.locator_set_key(it->get_locator());
+    ASSERT_EQ(0, ioctx.remove(it->get_oid()));
   }
 }
 
index 4d8484ac3748900e231f5d159e12d7344cc805f2..0cad424c4793b529f4218e2ea7c798e36101baf7 100644 (file)
 
 #include <string>
 
+/**
+ * These test cases create a temporary pool that lives as long as the
+ * test case.  We initially use the default namespace and assume
+ * test will whatever namespaces it wants.  After each test all objects
+ * are removed.
+ *
+ * Since pool creation and deletion is slow, this allows many tests to
+ * run faster.
+ */
+class RadosTestNS : public ::testing::Test {
+public:
+  RadosTestNS() {}
+  virtual ~RadosTestNS() {}
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+  static void cleanup_all_objects(rados_ioctx_t ioctx);
+  static rados_t s_cluster;
+  static std::string pool_name;
+
+  virtual void SetUp();
+  virtual void TearDown();
+  rados_t cluster;
+  rados_ioctx_t ioctx;
+};
+
+class RadosTestPPNS : public ::testing::Test {
+public:
+  RadosTestPPNS() : cluster(s_cluster) {}
+  virtual ~RadosTestPPNS() {}
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+  static void cleanup_all_objects(librados::IoCtx ioctx);
+  static librados::Rados s_cluster;
+  static std::string pool_name;
+
+  virtual void SetUp();
+  virtual void TearDown();
+  librados::Rados &cluster;
+  librados::IoCtx ioctx;
+};
+
+class RadosTestParamPPNS : public ::testing::TestWithParam<const char*> {
+public:
+  RadosTestParamPPNS() : cluster(s_cluster) {}
+  virtual ~RadosTestParamPPNS() {}
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+protected:
+  static void cleanup_all_objects(librados::IoCtx ioctx);
+  static librados::Rados s_cluster;
+  static std::string pool_name;
+  static std::string cache_pool_name;
+
+  virtual void SetUp();
+  virtual void TearDown();
+  librados::Rados &cluster;
+  librados::IoCtx ioctx;
+};
+
+class RadosTestECNS : public RadosTestNS {
+public:
+  RadosTestECNS() {}
+  virtual ~RadosTestECNS() {}
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+  static rados_t s_cluster;
+  static std::string pool_name;
+
+  virtual void SetUp();
+  virtual void TearDown();
+  rados_t cluster;
+  rados_ioctx_t ioctx;
+  uint64_t alignment;
+};
+
+class RadosTestECPPNS : public RadosTestPPNS {
+public:
+  RadosTestECPPNS() : cluster(s_cluster) {}
+  virtual ~RadosTestECPPNS() {}
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+  static librados::Rados s_cluster;
+  static std::string pool_name;
+
+  virtual void SetUp();
+  virtual void TearDown();
+  librados::Rados &cluster;
+  librados::IoCtx ioctx;
+  uint64_t alignment;
+};
+
 /**
  * These test cases create a temporary pool that lives as long as the
  * test case.  Each test within a test case gets a new ioctx set to a
index e3fe007f860cc73e76b00425b4492ede003df49c..11e89a931cb56115a2c32b060cc294c326f5961c 100644 (file)
@@ -9,13 +9,14 @@
 #include "gtest/gtest.h"
 #include <errno.h>
 #include <string>
+#include <stdexcept>
 
 using namespace librados;
 
-typedef RadosTest LibRadosList;
-typedef RadosTestPP LibRadosListPP;
-typedef RadosTestEC LibRadosListEC;
-typedef RadosTestECPP LibRadosListECPP;
+typedef RadosTestNS LibRadosList;
+typedef RadosTestPPNS LibRadosListPP;
+typedef RadosTestECNS LibRadosListEC;
+typedef RadosTestECPPNS LibRadosListECPP;
 
 TEST_F(LibRadosList, ListObjects) {
   char buf[128];
@@ -195,6 +196,10 @@ TEST_F(LibRadosList, ListObjectsNS) {
   ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
   check_list(ns2, ctx);
   rados_objects_list_close(ctx);
+
+  // Can't specify all namespaces using old interface
+  rados_ioctx_set_namespace(ioctx, LIBRADOS_ALL_NSPACES);
+  ASSERT_EQ(-EINVAL, rados_objects_list_open(ioctx, &ctx));
 }
 
 static void check_listpp(std::set<std::string>& myset, IoCtx& ioctx)
@@ -253,6 +258,9 @@ TEST_F(LibRadosListPP, ListObjectsPPNS) {
 
   ioctx.set_namespace("ns2");
   check_listpp(ns2, ioctx);
+
+  ioctx.set_namespace(all_nspaces);
+  EXPECT_THROW(check_listpp(def, ioctx), std::runtime_error);
 }
 
 TEST_F(LibRadosListPP, ListObjectsManyPP) {
@@ -503,6 +511,10 @@ TEST_F(LibRadosListEC, ListObjectsNS) {
   ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
   check_list(ns2, ctx);
   rados_objects_list_close(ctx);
+
+  // Can't specify all namespaces using old interface
+  rados_ioctx_set_namespace(ioctx, LIBRADOS_ALL_NSPACES);
+  ASSERT_EQ(-EINVAL, rados_objects_list_open(ioctx, &ctx));
 }
 
 TEST_F(LibRadosListECPP, ListObjectsPPNS) {
@@ -543,6 +555,9 @@ TEST_F(LibRadosListECPP, ListObjectsPPNS) {
 
   ioctx.set_namespace("ns2");
   check_listpp(ns2, ioctx);
+
+  ioctx.set_namespace(all_nspaces);
+  EXPECT_THROW(check_listpp(def, ioctx), std::runtime_error);
 }
 
 TEST_F(LibRadosListECPP, ListObjectsManyPP) {
diff --git a/src/test/librados/nlist.cc b/src/test/librados/nlist.cc
new file mode 100644 (file)
index 0000000..2ffbbda
--- /dev/null
@@ -0,0 +1,689 @@
+// -*- 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;
+
+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;
+  }
+}
index ef7d80b5f2af20e5ded3d21c1dbae6d91b482055..51c53c4dd27857937fa551a5c9835f3276d28ac5 100644 (file)
@@ -37,16 +37,17 @@ typedef RadosTestECPP LibRadosTierECPP;
 void flush_evict_all(librados::Rados& cluster, librados::IoCtx& cache_ioctx)
 {
   bufferlist inbl;
-  cache_ioctx.set_namespace("");
-  for (ObjectIterator it = cache_ioctx.objects_begin();
-       it != cache_ioctx.objects_end(); ++it) {
-    cache_ioctx.locator_set_key(it->second);
+  cache_ioctx.set_namespace(all_nspaces);
+  for (NObjectIterator it = cache_ioctx.nobjects_begin();
+       it != cache_ioctx.nobjects_end(); ++it) {
+    cache_ioctx.locator_set_key(it->get_locator());
+    cache_ioctx.set_namespace(it->get_nspace());
     {
       ObjectReadOperation op;
       op.cache_flush();
       librados::AioCompletion *completion = cluster.aio_create_completion();
       cache_ioctx.aio_operate(
-        it->first, completion, &op,
+        it->get_oid(), completion, &op,
        librados::OPERATION_IGNORE_OVERLAY, NULL);
       completion->wait_for_safe();
       completion->get_return_value();
@@ -57,7 +58,7 @@ void flush_evict_all(librados::Rados& cluster, librados::IoCtx& cache_ioctx)
       op.cache_evict();
       librados::AioCompletion *completion = cluster.aio_create_completion();
       cache_ioctx.aio_operate(
-        it->first, completion, &op,
+        it->get_oid(), completion, &op,
        librados::OPERATION_IGNORE_OVERLAY, NULL);
       completion->wait_for_safe();
       completion->get_return_value();
@@ -109,7 +110,7 @@ protected:
     // wait for maps to settle before next test
     cluster.wait_for_latest_osdmap();
 
-    cleanup_default_namespace(cache_ioctx);
+    cleanup_all_objects(cache_ioctx);
 
     cache_ioctx.close();
   }
@@ -277,13 +278,13 @@ TEST_F(LibRadosTwoPoolsPP, Promote) {
 
   // verify the object is present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 }
 
@@ -615,13 +616,13 @@ TEST_F(LibRadosTwoPoolsPP, Whiteout) {
 
   // verify the whiteouts are there in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   ASSERT_EQ(-ENOENT, ioctx.remove("foo"));
@@ -686,13 +687,13 @@ TEST_F(LibRadosTwoPoolsPP, Evict) {
 
   // verify the object is present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   // evict
@@ -1073,17 +1074,17 @@ TEST_F(LibRadosTwoPoolsPP, TryFlush) {
 
   // verify the object is present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   // verify the object is NOT present in the base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it == ioctx.objects_end());
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 
   // verify dirty
@@ -1124,11 +1125,11 @@ TEST_F(LibRadosTwoPoolsPP, TryFlush) {
 
   // verify in base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it != ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it != ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo"));
     ++it;
-    ASSERT_TRUE(it == ioctx.objects_end());
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 
   // evict it
@@ -1145,8 +1146,8 @@ TEST_F(LibRadosTwoPoolsPP, TryFlush) {
 
   // verify no longer in cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 }
 
@@ -1183,17 +1184,17 @@ TEST_F(LibRadosTwoPoolsPP, Flush) {
 
   // verify the object is present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   // verify the object is NOT present in the base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it == ioctx.objects_end());
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 
   // verify dirty
@@ -1234,11 +1235,11 @@ TEST_F(LibRadosTwoPoolsPP, Flush) {
 
   // verify in base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it != ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it != ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo"));
     ++it;
-    ASSERT_TRUE(it == ioctx.objects_end());
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 
   // evict it
@@ -1255,8 +1256,8 @@ TEST_F(LibRadosTwoPoolsPP, Flush) {
 
   // verify no longer in cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   // read it again and verify the version is consistent
@@ -1300,13 +1301,13 @@ TEST_F(LibRadosTwoPoolsPP, Flush) {
 
   // verify no longer in cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
   // or base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it == ioctx.objects_end());
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 }
 
@@ -1368,17 +1369,17 @@ TEST_F(LibRadosTwoPoolsPP, FlushSnap) {
 
   // verify the object is present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   // verify the object is NOT present in the base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it == ioctx.objects_end());
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 
   // flush on head (should fail)
@@ -2209,12 +2210,12 @@ TEST_F(LibRadosTwoPoolsPP, PromoteOn2ndRead) {
 
   // verify the object is NOT present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    if (it != cache_ioctx.objects_end()) {
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    if (it != cache_ioctx.nobjects_end()) {
       if (dur > 1.0) {
        cout << " object got promoted, but read was slow, ignoring" << std::endl;
       } else {
-       ASSERT_TRUE(it == cache_ioctx.objects_end());
+       ASSERT_TRUE(it == cache_ioctx.nobjects_end());
       }
     }
   }
@@ -2224,11 +2225,11 @@ TEST_F(LibRadosTwoPoolsPP, PromoteOn2ndRead) {
     bufferlist bl;
     ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
 
-    ObjectIterator it = cache_ioctx.objects_begin();
-    if (it != cache_ioctx.objects_end()) {
-      ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    if (it != cache_ioctx.nobjects_end()) {
+      ASSERT_TRUE(it->get_oid() == string("foo"));
       ++it;
-      ASSERT_TRUE(it == cache_ioctx.objects_end());
+      ASSERT_TRUE(it == cache_ioctx.nobjects_end());
       break;
     }
 
@@ -2292,7 +2293,7 @@ protected:
     // wait for maps to settle before next test
     cluster.wait_for_latest_osdmap();
 
-    cleanup_default_namespace(cache_ioctx);
+    cleanup_all_objects(cache_ioctx);
 
     cache_ioctx.close();
   }
@@ -2461,13 +2462,13 @@ TEST_F(LibRadosTwoPoolsECPP, Promote) {
 
   // verify the object is present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 }
 
@@ -2726,13 +2727,13 @@ TEST_F(LibRadosTwoPoolsECPP, Whiteout) {
 
   // verify the whiteouts are there in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   ASSERT_EQ(-ENOENT, ioctx.remove("foo"));
@@ -2797,13 +2798,13 @@ TEST_F(LibRadosTwoPoolsECPP, Evict) {
 
   // verify the object is present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ASSERT_TRUE(it->get_oid() == string("foo") || it->get_oid() == string("bar"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   // evict
@@ -3108,17 +3109,17 @@ TEST_F(LibRadosTwoPoolsECPP, TryFlush) {
 
   // verify the object is present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   // verify the object is NOT present in the base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it == ioctx.objects_end());
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 
   // verify dirty
@@ -3159,11 +3160,11 @@ TEST_F(LibRadosTwoPoolsECPP, TryFlush) {
 
   // verify in base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it != ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it != ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo"));
     ++it;
-    ASSERT_TRUE(it == ioctx.objects_end());
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 
   // evict it
@@ -3180,8 +3181,8 @@ TEST_F(LibRadosTwoPoolsECPP, TryFlush) {
 
   // verify no longer in cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 }
 
@@ -3218,17 +3219,17 @@ TEST_F(LibRadosTwoPoolsECPP, Flush) {
 
   // verify the object is present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   // verify the object is NOT present in the base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it == ioctx.objects_end());
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 
   // verify dirty
@@ -3269,11 +3270,11 @@ TEST_F(LibRadosTwoPoolsECPP, Flush) {
 
   // verify in base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it != ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it != ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo"));
     ++it;
-    ASSERT_TRUE(it == ioctx.objects_end());
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 
   // evict it
@@ -3290,8 +3291,8 @@ TEST_F(LibRadosTwoPoolsECPP, Flush) {
 
   // verify no longer in cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   // read it again and verify the version is consistent
@@ -3335,13 +3336,13 @@ TEST_F(LibRadosTwoPoolsECPP, Flush) {
 
   // verify no longer in cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
   // or base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it == ioctx.objects_end());
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 }
 
@@ -3403,17 +3404,17 @@ TEST_F(LibRadosTwoPoolsECPP, FlushSnap) {
 
   // verify the object is present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    ASSERT_TRUE(it != cache_ioctx.nobjects_end());
+    ASSERT_TRUE(it->get_oid() == string("foo"));
     ++it;
-    ASSERT_TRUE(it == cache_ioctx.objects_end());
+    ASSERT_TRUE(it == cache_ioctx.nobjects_end());
   }
 
   // verify the object is NOT present in the base tier
   {
-    ObjectIterator it = ioctx.objects_begin();
-    ASSERT_TRUE(it == ioctx.objects_end());
+    NObjectIterator it = ioctx.nobjects_begin();
+    ASSERT_TRUE(it == ioctx.nobjects_end());
   }
 
   // flush on head (should fail)
@@ -4169,12 +4170,12 @@ TEST_F(LibRadosTwoPoolsECPP, PromoteOn2ndRead) {
 
   // verify the object is NOT present in the cache tier
   {
-    ObjectIterator it = cache_ioctx.objects_begin();
-    if (it != cache_ioctx.objects_end()) {
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    if (it != cache_ioctx.nobjects_end()) {
       if (dur > 1.0) {
        cout << " object got promoted, but read was slow, ignoring" << std::endl;
       } else {
-       ASSERT_TRUE(it == cache_ioctx.objects_end());
+       ASSERT_TRUE(it == cache_ioctx.nobjects_end());
       }
     }
   }
@@ -4184,11 +4185,11 @@ TEST_F(LibRadosTwoPoolsECPP, PromoteOn2ndRead) {
     bufferlist bl;
     ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
 
-    ObjectIterator it = cache_ioctx.objects_begin();
-    if (it != cache_ioctx.objects_end()) {
-      ASSERT_TRUE(it->first == string("foo"));
+    NObjectIterator it = cache_ioctx.nobjects_begin();
+    if (it != cache_ioctx.nobjects_end()) {
+      ASSERT_TRUE(it->get_oid() == string("foo"));
       ++it;
-      ASSERT_TRUE(it == cache_ioctx.objects_end());
+      ASSERT_TRUE(it == cache_ioctx.nobjects_end());
       break;
     }
 
index be6ead64987453fb179fe5de1ce5ee13524c836b..628fd510e913261b3c487f0ce214208923a61082 100644 (file)
@@ -69,9 +69,9 @@ run()
   const char *obj_name;
   rados_list_ctx_t h;
   printf("%s: listing objects.\n", get_id_str());
-  RETURN1_IF_NONZERO(rados_objects_list_open(io_ctx, &h));
+  RETURN1_IF_NONZERO(rados_nobjects_list_open(io_ctx, &h));
   while (true) {
-    int ret = rados_objects_list_next(h, &obj_name, NULL);
+    int ret = rados_nobjects_list_next(h, &obj_name, NULL, NULL);
     if (ret == -ENOENT) {
       break;
     }
@@ -92,7 +92,7 @@ run()
        m_midway_sem_post->post();
     }
   }
-  rados_objects_list_close(h);
+  rados_nobjects_list_close(h);
 
   printf("%s: saw %d objects\n", get_id_str(), saw);