summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--PendingReleaseNotes12
-rw-r--r--ceph.spec.in99
-rw-r--r--debian/ceph-base.dirs1
-rw-r--r--debian/control68
-rw-r--r--debian/librados-dev.install7
-rw-r--r--debian/librados3.install (renamed from debian/librados2.install)2
-rw-r--r--debian/libradospp-dev.install8
-rw-r--r--debian/libradospp1.install1
-rwxr-xr-xdebian/rules2
-rw-r--r--doc/install/upgrading-ceph.rst4
-rw-r--r--doc/man/8/ceph-deploy.rst4
-rw-r--r--doc/mgr/dashboard.rst26
-rw-r--r--doc/rados/operations/crush-map-edits.rst2
-rw-r--r--doc/rbd/iscsi-target-cli-manual-install.rst107
-rw-r--r--qa/distros/all/centos_7.5.yaml2
l---------qa/distros/supported-all-distro/centos_latest.yaml2
l---------qa/distros/supported-random-distro$/centos_latest.yaml2
l---------qa/distros/supported/centos_latest.yaml2
-rw-r--r--qa/packages/packages.yaml6
-rwxr-xr-xqa/qa_scripts/cephscrub.sh4
-rw-r--r--qa/suites/fs/upgrade/featureful_client/old_client/tasks/0-luminous.yaml1
-rw-r--r--qa/suites/fs/upgrade/featureful_client/upgraded_client/tasks/0-luminous.yaml1
-rw-r--r--qa/suites/fs/upgrade/snaps/tasks/0-luminous.yaml1
-rw-r--r--qa/suites/rados/thrash-old-clients/1-install/hammer.yaml2
-rw-r--r--qa/suites/rados/thrash-old-clients/1-install/jewel.yaml2
-rw-r--r--qa/suites/rados/thrash-old-clients/1-install/luminous.yaml1
-rw-r--r--qa/suites/rados/upgrade/luminous-x-singleton/1-install/luminous.yaml1
-rw-r--r--qa/suites/upgrade/luminous-x/parallel/1-ceph-install/luminous.yaml1
-rw-r--r--qa/tasks/radosgw_admin_rest.py1
-rw-r--r--qa/workunits/rados/0001-cmake-add-Findrados.cmake-and-use-it.patch71
-rwxr-xr-xqa/workunits/rados/test.sh15
-rwxr-xr-xqa/workunits/rados/test_envlibrados_for_rocksdb.sh6
-rw-r--r--src/CMakeLists.txt8
-rw-r--r--src/client/Client.cc15
-rw-r--r--src/client/Client.h7
-rw-r--r--src/cls/lock/cls_lock.cc71
-rw-r--r--src/cls/lock/cls_lock_client.cc21
-rw-r--r--src/cls/lock/cls_lock_client.h43
-rw-r--r--src/cls/lock/cls_lock_ops.cc2
-rw-r--r--src/cls/lock/cls_lock_ops.h3
-rw-r--r--src/cls/lock/cls_lock_types.h29
-rw-r--r--src/cls/lua/cls_lua_client.h2
-rw-r--r--src/cls/rbd/cls_rbd_types.cc10
-rw-r--r--src/cls/rbd/cls_rbd_types.h12
-rw-r--r--src/cls/rgw/cls_rgw.cc2
-rw-r--r--src/cls/rgw/cls_rgw_client.cc1
-rw-r--r--src/cls/rgw/cls_rgw_client.h2
-rw-r--r--src/cls/rgw/cls_rgw_types.h3
-rw-r--r--src/include/cephfs/libcephfs.h9
-rw-r--r--src/include/rados/librados.h6
-rw-r--r--src/include/rbd/librbd.h2
-rw-r--r--src/include/rbd/librbd.hpp2
-rw-r--r--src/libcephfs.cc7
-rw-r--r--src/librados/AioCompletionImpl.h2
-rw-r--r--src/librados/CMakeLists.txt67
-rw-r--r--src/librados/RadosClient.cc50
-rw-r--r--src/librados/RadosClient.h2
-rw-r--r--src/librados/librados_c.cc (renamed from src/librados/librados.cc)3079
-rw-r--r--src/librados/librados_cxx.cc2987
-rw-r--r--src/librados/librados_tp.cc9
-rw-r--r--src/librados/librados_util.cc61
-rw-r--r--src/librados/librados_util.h34
-rw-r--r--src/libradosstriper/CMakeLists.txt8
-rw-r--r--src/librbd/CMakeLists.txt2
-rw-r--r--src/librbd/Types.h9
-rw-r--r--src/librbd/api/Migration.cc49
-rw-r--r--src/librbd/image/RefreshRequest.cc7
-rw-r--r--src/librbd/librbd.cc6
-rw-r--r--src/mds/MDSDaemon.cc4
-rw-r--r--src/mds/MDSRank.cc8
-rw-r--r--src/pybind/mgr/dashboard/controllers/__init__.py33
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts122
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts51
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts39
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.ts5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.ts10
-rw-r--r--src/pybind/mgr/dashboard/module.py2
-rw-r--r--src/pybind/mgr/dashboard/settings.py4
-rw-r--r--src/pybind/mgr/dashboard/tests/helper.py6
-rw-r--r--src/pybind/mgr/dashboard/tests/test_api_auditing.py107
-rw-r--r--src/pybind/mgr/dashboard/tests/test_tools.py26
-rw-r--r--src/pybind/mgr/dashboard/tools.py56
-rw-r--r--src/pybind/rbd/rbd.pyx24
-rw-r--r--src/rbd_fuse/CMakeLists.txt2
-rw-r--r--src/rbd_fuse/rbd-fuse.cc85
-rw-r--r--src/rbd_replay/CMakeLists.txt2
-rw-r--r--src/rgw/CMakeLists.txt4
-rw-r--r--src/rgw/rgw_admin.cc14
-rw-r--r--src/rgw/rgw_bucket.cc1
-rw-r--r--src/rgw/rgw_cr_rados.cc2
-rw-r--r--src/rgw/rgw_rados.cc144
-rw-r--r--src/rgw/rgw_rados.h22
-rw-r--r--src/rgw/rgw_reshard.cc410
-rw-r--r--src/rgw/rgw_reshard.h96
-rw-r--r--src/test/CMakeLists.txt12
-rw-r--r--src/test/cls_hello/CMakeLists.txt4
-rw-r--r--src/test/cls_hello/test_cls_hello.cc2
-rw-r--r--src/test/cls_journal/CMakeLists.txt4
-rw-r--r--src/test/cls_journal/test_cls_journal.cc2
-rw-r--r--src/test/cls_lock/CMakeLists.txt4
-rw-r--r--src/test/cls_lock/test_cls_lock.cc180
-rw-r--r--src/test/cls_log/CMakeLists.txt4
-rw-r--r--src/test/cls_log/test_cls_log.cc2
-rw-r--r--src/test/cls_lua/CMakeLists.txt5
-rw-r--r--src/test/cls_lua/test_cls_lua.cc4
-rw-r--r--src/test/cls_numops/CMakeLists.txt4
-rw-r--r--src/test/cls_numops/test_cls_numops.cc2
-rw-r--r--src/test/cls_rbd/CMakeLists.txt4
-rw-r--r--src/test/cls_rbd/test_cls_rbd.cc8
-rw-r--r--src/test/cls_refcount/CMakeLists.txt4
-rw-r--r--src/test/cls_refcount/test_cls_refcount.cc2
-rw-r--r--src/test/cls_rgw/CMakeLists.txt4
-rw-r--r--src/test/cls_rgw/test_cls_rgw.cc2
-rw-r--r--src/test/cls_sdk/CMakeLists.txt4
-rw-r--r--src/test/cls_sdk/test_cls_sdk.cc2
-rw-r--r--src/test/cls_version/CMakeLists.txt4
-rw-r--r--src/test/cls_version/test_cls_version.cc4
-rwxr-xr-xsrc/test/encoding/readable.sh6
-rw-r--r--src/test/journal/CMakeLists.txt2
-rw-r--r--src/test/journal/RadosTestFixture.cc1
-rw-r--r--src/test/librados/CMakeLists.txt85
-rw-r--r--src/test/librados/TestCase.cc378
-rw-r--r--src/test/librados/TestCase.h124
-rw-r--r--src/test/librados/aio.cc2442
-rw-r--r--src/test/librados/aio_cxx.cc2443
-rw-r--r--src/test/librados/c_write_operations.cc2
-rw-r--r--src/test/librados/cls.cc10
-rw-r--r--src/test/librados/cmd.cc73
-rw-r--r--src/test/librados/cmd_cxx.cc92
-rw-r--r--src/test/librados/io.cc884
-rw-r--r--src/test/librados/io_cxx.cc904
-rw-r--r--src/test/librados/list.cc776
-rw-r--r--src/test/librados/list_cxx.cc773
-rw-r--r--src/test/librados/lock.cc204
-rw-r--r--src/test/librados/lock_cxx.cc193
-rw-r--r--src/test/librados/misc.cc1123
-rw-r--r--src/test/librados/misc_cxx.cc1151
-rw-r--r--src/test/librados/pool.cc7
-rw-r--r--src/test/librados/service.cc91
-rw-r--r--src/test/librados/service_cxx.cc104
-rw-r--r--src/test/librados/snapshots.cc676
-rw-r--r--src/test/librados/snapshots_cxx.cc689
-rw-r--r--src/test/librados/stat.cc157
-rw-r--r--src/test/librados/stat_cxx.cc163
-rw-r--r--src/test/librados/test.cc224
-rw-r--r--src/test/librados/test.h30
-rw-r--r--src/test/librados/test_cxx.cc203
-rw-r--r--src/test/librados/test_cxx.h19
-rw-r--r--src/test/librados/test_shared.cc44
-rw-r--r--src/test/librados/test_shared.h49
-rw-r--r--src/test/librados/testcase_cxx.cc390
-rw-r--r--src/test/librados/testcase_cxx.h130
-rw-r--r--src/test/librados/tier_cxx.cc (renamed from src/test/librados/tier.cc)5
-rw-r--r--src/test/librados/watch_notify.cc336
-rw-r--r--src/test/librados/watch_notify_cxx.cc364
-rw-r--r--src/test/librados_test_stub/LibradosTestStub.cc6
-rw-r--r--src/test/libradosstriper/CMakeLists.txt17
-rw-r--r--src/test/libradosstriper/TestCase.cc1
-rw-r--r--src/test/librbd/CMakeLists.txt12
-rw-r--r--src/test/librbd/test_Migration.cc2
-rw-r--r--src/test/librbd/test_fixture.cc1
-rw-r--r--src/test/librbd/test_librbd.cc1
-rw-r--r--src/test/librbd/test_main.cc1
-rw-r--r--src/test/multi_stress_watch.cc2
-rw-r--r--src/test/osd/CMakeLists.txt2
-rw-r--r--src/test/rbd_mirror/CMakeLists.txt8
-rw-r--r--src/test/rbd_mirror/test_ClusterWatcher.cc2
-rw-r--r--src/test/rbd_mirror/test_ImageReplayer.cc2
-rw-r--r--src/test/rbd_mirror/test_InstanceWatcher.cc2
-rw-r--r--src/test/rbd_mirror/test_LeaderWatcher.cc2
-rw-r--r--src/test/rbd_mirror/test_PoolWatcher.cc2
-rw-r--r--src/test/rbd_mirror/test_fixture.cc2
-rw-r--r--src/test/rbd_mirror/test_main.cc2
-rw-r--r--src/test/rbd_mirror/test_mock_ImageMap.cc9
-rw-r--r--src/test/rbd_mirror/test_mock_InstanceWatcher.cc2
-rw-r--r--src/test/test_stress_watch.cc4
-rw-r--r--src/tools/CMakeLists.txt6
-rw-r--r--src/tools/cephfs/CMakeLists.txt6
-rw-r--r--src/tools/rbd/CMakeLists.txt2
-rw-r--r--src/tools/rbd/action/DiskUsage.cc2
-rw-r--r--src/tools/rbd/action/Snap.cc1
-rw-r--r--src/tools/rbd/action/Status.cc11
-rw-r--r--src/tools/rbd_mirror/CMakeLists.txt2
-rw-r--r--src/tools/rbd_mirror/ImageReplayer.cc4
-rw-r--r--src/tools/rbd_nbd/CMakeLists.txt2
-rw-r--r--src/tracing/CMakeLists.txt2
186 files changed, 12821 insertions, 11285 deletions
diff --git a/PendingReleaseNotes b/PendingReleaseNotes
index 4206e77d302..c18ec2ecb1a 100644
--- a/PendingReleaseNotes
+++ b/PendingReleaseNotes
@@ -13,12 +13,12 @@
necessary for clients to give up capabilities in order for the MDS to fully
drop its cache. This is accomplished by asking all clients to trim as many
caps as possible. The timeout argument to the `cache drop` command controls
- how long the MDS waits for clients to complete trimming caps. Keep in mind
- that clients may still retain caps to open files which will prevent the
- metadata for those files from being dropped by both the client and the MDS.
- (This is an equivalent scenario to dropping the Linux
- page/buffer/inode/dentry caches with some processes pinning some
- inodes/dentries/pages in cache.)
+ how long the MDS waits for clients to complete trimming caps. This is optional
+ and is 0 by default (no timeout). Keep in mind that clients may still retain
+ caps to open files which will prevent the metadata for those files from being
+ dropped by both the client and the MDS. (This is an equivalent scenario to
+ dropping the Linux page/buffer/inode/dentry caches with some processes pinning
+ some inodes/dentries/pages in cache.)
* The mon_health_preluminous_compat and mon_health_preluminous_compat_warning
config options are removed, as the related functionality is more
diff --git a/ceph.spec.in b/ceph.spec.in
index 76d6cfd63a7..ab90027bcba 100644
--- a/ceph.spec.in
+++ b/ceph.spec.in
@@ -323,7 +323,8 @@ Group: System/Filesystems
Provides: ceph-test:/usr/bin/ceph-kvstore-tool
Requires: ceph-common = %{_epoch_prefix}%{version}-%{release}
Requires: librbd1 = %{_epoch_prefix}%{version}-%{release}
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: librados3 = %{_epoch_prefix}%{version}-%{release}
+Requires: libradospp1 = %{_epoch_prefix}%{version}-%{release}
Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release}
Requires: librgw2 = %{_epoch_prefix}%{version}-%{release}
%if 0%{with selinux}
@@ -360,7 +361,8 @@ Summary: Ceph Common
Group: System/Filesystems
%endif
Requires: librbd1 = %{_epoch_prefix}%{version}-%{release}
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: librados3 = %{_epoch_prefix}%{version}-%{release}
+Requires: libradospp1 = %{_epoch_prefix}%{version}-%{release}
Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release}
Requires: python%{_python_buildid}-rados = %{_epoch_prefix}%{version}-%{release}
Requires: python%{_python_buildid}-rbd = %{_epoch_prefix}%{version}-%{release}
@@ -457,7 +459,7 @@ Summary: Ceph fuse-based client
%if 0%{?suse_version}
Group: System/Filesystems
%endif
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: librados3 = %{_epoch_prefix}%{version}-%{release}
Requires: librbd1 = %{_epoch_prefix}%{version}-%{release}
%description -n rbd-fuse
FUSE based client to map Ceph rbd images to files
@@ -468,7 +470,7 @@ Summary: Ceph daemon for mirroring RBD images
Group: System/Filesystems
%endif
Requires: ceph-common = %{_epoch_prefix}%{version}-%{release}
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: libradospp1 = %{_epoch_prefix}%{version}-%{release}
%description -n rbd-mirror
Daemon for mirroring RBD images between Ceph clusters, streaming
changes asynchronously.
@@ -478,7 +480,7 @@ Summary: Ceph RBD client base on NBD
%if 0%{?suse_version}
Group: System/Filesystems
%endif
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: libradospp1 = %{_epoch_prefix}%{version}-%{release}
Requires: librbd1 = %{_epoch_prefix}%{version}-%{release}
%description -n rbd-nbd
NBD based client to map Ceph rbd images to local device
@@ -492,7 +494,8 @@ Requires: ceph-common = %{_epoch_prefix}%{version}-%{release}
%if 0%{with selinux}
Requires: ceph-selinux = %{_epoch_prefix}%{version}-%{release}
%endif
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: librados3 = %{_epoch_prefix}%{version}-%{release}
+Requires: libradospp1 = %{_epoch_prefix}%{version}-%{release}
Requires: librgw2 = %{_epoch_prefix}%{version}-%{release}
%if 0%{?rhel} || 0%{?fedora}
Requires: mailcap
@@ -531,7 +534,7 @@ ceph-osd is the object storage daemon for the Ceph distributed file
system. It is responsible for storing objects on a local file system
and providing access to them over the network.
-%package -n librados2
+%package -n librados3
Summary: RADOS distributed object store client library
%if 0%{?suse_version}
Group: System/Libraries
@@ -539,7 +542,7 @@ Group: System/Libraries
%if 0%{?rhel} || 0%{?fedora}
Obsoletes: ceph-libs < %{_epoch_prefix}%{version}-%{release}
%endif
-%description -n librados2
+%description -n librados3
RADOS is a reliable, autonomic distributed object storage cluster
developed as part of the Ceph distributed storage system. This is a
shared library allowing applications to access the distributed object
@@ -550,12 +553,33 @@ Summary: RADOS headers
%if 0%{?suse_version}
Group: Development/Libraries/C and C++
%endif
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: librados3 = %{_epoch_prefix}%{version}-%{release}
Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release}
-Provides: librados2-devel = %{_epoch_prefix}%{version}-%{release}
-Obsoletes: librados2-devel < %{_epoch_prefix}%{version}-%{release}
+Provides: librados3-devel = %{_epoch_prefix}%{version}-%{release}
+Obsoletes: librados3-devel < %{_epoch_prefix}%{version}-%{release}
%description -n librados-devel
-This package contains libraries and headers needed to develop programs
+This package contains C libraries and headers needed to develop programs
+that use RADOS object store.
+
+%package -n libradospp1
+Summary: RADOS distributed object store client C++ library
+%if 0%{?suse_version}
+Group: System/Libraries
+%endif
+%description -n libradospp1
+RADOS is a reliable, autonomic distributed object storage cluster
+developed as part of the Ceph distributed storage system. This is a
+shared library allowing C++ applications to access the distributed object
+store using a simple file-like interface.
+
+%package -n libradospp-devel
+Summary: RADOS headers
+%if 0%{?suse_version}
+Group: Development/Libraries/C and C++
+%endif
+Requires: libradospp1 = %{_epoch_prefix}%{version}-%{release}
+%description -n libradospp-devel
+This package contains C++ libraries and headers needed to develop programs
that use RADOS object store.
%package -n librgw2
@@ -563,7 +587,7 @@ Summary: RADOS gateway client library
%if 0%{?suse_version}
Group: System/Libraries
%endif
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: librados3 = %{_epoch_prefix}%{version}-%{release}
%description -n librgw2
This package provides a library implementation of the RADOS gateway
(distributed object store with S3 and Swift personalities).
@@ -612,7 +636,7 @@ Summary: Python 2 libraries for the RADOS object store
%if 0%{?suse_version}
Group: Development/Libraries/Python
%endif
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: librados3 = %{_epoch_prefix}%{version}-%{release}
Obsoletes: python-ceph < %{_epoch_prefix}%{version}-%{release}
%description -n python-rados
This package contains Python 2 libraries for interacting with Cephs RADOS
@@ -625,7 +649,7 @@ Summary: Python 3 libraries for the RADOS object store
Group: Development/Libraries/Python
%endif
Requires: python%{python3_pkgversion}
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: librados3 = %{_epoch_prefix}%{version}-%{release}
%description -n python%{python3_pkgversion}-rados
This package contains Python 3 libraries for interacting with Cephs RADOS
object store.
@@ -636,7 +660,8 @@ Summary: RADOS striping interface
%if 0%{?suse_version}
Group: System/Libraries
%endif
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: librados3 = %{_epoch_prefix}%{version}-%{release}
+Requires: libradospp1 = %{_epoch_prefix}%{version}-%{release}
%description -n libradosstriper1
Striping interface built on top of the rados library, allowing
to stripe bigger objects onto several standard rados objects using
@@ -649,6 +674,7 @@ Group: Development/Libraries/C and C++
%endif
Requires: libradosstriper1 = %{_epoch_prefix}%{version}-%{release}
Requires: librados-devel = %{_epoch_prefix}%{version}-%{release}
+Requires: libradospp-devel = %{_epoch_prefix}%{version}-%{release}
Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release}
Provides: libradosstriper1-devel = %{_epoch_prefix}%{version}-%{release}
Obsoletes: libradosstriper1-devel < %{_epoch_prefix}%{version}-%{release}
@@ -662,7 +688,8 @@ Summary: RADOS block device client library
%if 0%{?suse_version}
Group: System/Libraries
%endif
-Requires: librados2 = %{_epoch_prefix}%{version}-%{release}
+Requires: librados3 = %{_epoch_prefix}%{version}-%{release}
+Requires: libradospp1 = %{_epoch_prefix}%{version}-%{release}
%if 0%{?suse_version}
Requires(post): coreutils
%endif
@@ -682,6 +709,7 @@ Group: Development/Libraries/C and C++
%endif
Requires: librbd1 = %{_epoch_prefix}%{version}-%{release}
Requires: librados-devel = %{_epoch_prefix}%{version}-%{release}
+Requires: libradospp-devel = %{_epoch_prefix}%{version}-%{release}
Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release}
Provides: librbd1-devel = %{_epoch_prefix}%{version}-%{release}
Obsoletes: librbd1-devel < %{_epoch_prefix}%{version}-%{release}
@@ -867,7 +895,7 @@ Summary: RADOS object class development kit
%if 0%{?suse_version}
Group: Development/Libraries/C and C++
%endif
-Requires: librados2-devel = %{_epoch_prefix}%{version}-%{release}
+Requires: libradospp1-devel = %{_epoch_prefix}%{version}-%{release}
%description -n rados-objclass-devel
This package contains libraries and headers needed to develop RADOS object
class plugins.
@@ -1103,6 +1131,7 @@ mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/bootstrap-mds
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/bootstrap-rgw
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/bootstrap-mgr
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/bootstrap-rbd
+mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/bootstrap-rbd-mirror
%if 0%{?suse_version}
# create __pycache__ directories and their contents
@@ -1179,6 +1208,7 @@ rm -rf %{buildroot}
%attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/bootstrap-rgw
%attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/bootstrap-mgr
%attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/bootstrap-rbd
+%attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/bootstrap-rbd-mirror
%post base
/sbin/ldconfig
@@ -1661,29 +1691,22 @@ fi
%endif
-%files -n librados2
+%files -n librados3
%{_libdir}/librados.so.*
%dir %{_libdir}/ceph
-%{_libdir}/ceph/libceph-common.so*
+%{_libdir}/ceph/libceph-common.so.*
%if %{with lttng}
%{_libdir}/librados_tp.so.*
%endif
-%post -n librados2 -p /sbin/ldconfig
+%post -n librados3 -p /sbin/ldconfig
-%postun -n librados2 -p /sbin/ldconfig
+%postun -n librados3 -p /sbin/ldconfig
%files -n librados-devel
%dir %{_includedir}/rados
%{_includedir}/rados/librados.h
-%{_includedir}/rados/librados.hpp
-%{_includedir}/rados/buffer.h
-%{_includedir}/rados/buffer_fwd.h
-%{_includedir}/rados/inline_memory.h
-%{_includedir}/rados/page.h
-%{_includedir}/rados/crc32c.h
%{_includedir}/rados/rados_types.h
-%{_includedir}/rados/rados_types.hpp
%{_libdir}/librados.so
%if %{with lttng}
%{_libdir}/librados_tp.so
@@ -1691,6 +1714,24 @@ fi
%{_bindir}/librados-config
%{_mandir}/man8/librados-config.8*
+%files -n libradospp1
+%{_libdir}/libradospp.so.*
+
+%post -n libradospp1 -p /sbin/ldconfig
+
+%postun -n libradospp1 -p /sbin/ldconfig
+
+%files -n libradospp-devel
+%dir %{_includedir}/rados
+%{_includedir}/rados/buffer.h
+%{_includedir}/rados/buffer_fwd.h
+%{_includedir}/rados/crc32c.h
+%{_includedir}/rados/inline_memory.h
+%{_includedir}/rados/librados.hpp
+%{_includedir}/rados/page.h
+%{_includedir}/rados/rados_types.hpp
+%{_libdir}/libradospp.so
+
%if 0%{with python2}
%files -n python-rados
%{python_sitearch}/rados.so
diff --git a/debian/ceph-base.dirs b/debian/ceph-base.dirs
index 6f580230a65..d0b8a9e103c 100644
--- a/debian/ceph-base.dirs
+++ b/debian/ceph-base.dirs
@@ -3,6 +3,7 @@ var/lib/ceph/bootstrap-mgr
var/lib/ceph/bootstrap-osd
var/lib/ceph/bootstrap-rgw
var/lib/ceph/bootstrap-rbd
+var/lib/ceph/bootstrap-rbd-mirror
var/lib/ceph/tmp
var/lib/ceph/crash
var/lib/ceph/crash/posted
diff --git a/debian/control b/debian/control
index 381b4455b33..c40644392c5 100644
--- a/debian/control
+++ b/debian/control
@@ -107,7 +107,7 @@ Depends: binutils,
${shlibs:Depends},
Recommends: btrfs-tools,
ceph-mds (= ${binary:Version}),
- librados2 (= ${binary:Version}),
+ librados3 (= ${binary:Version}),
libradosstriper1 (= ${binary:Version}),
librbd1 (= ${binary:Version}),
ntp | time-daemon,
@@ -336,7 +336,7 @@ Description: debugging symbols for rbd-fuse
Package: rbd-mirror
Architecture: linux-any
Depends: ceph-common (= ${binary:Version}),
- librados2 (= ${binary:Version}),
+ librados3 (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends},
Description: Ceph daemon for mirroring RBD images
@@ -457,11 +457,13 @@ Description: OCF-compliant resource agents for Ceph
Ceph with OCF-compliant cluster resource managers,
such as Pacemaker.
-Package: librados2
+Package: librados3
Conflicts: librados,
librados1,
+ librados2
Replaces: librados,
librados1,
+ librados2,
Architecture: linux-any
Section: libs
Depends: ${misc:Depends},
@@ -472,13 +474,13 @@ Description: RADOS distributed object store client library
shared library allowing applications to access the distributed object
store using a simple file-like interface.
-Package: librados2-dbg
+Package: librados3-dbg
Conflicts: librados1-dbg,
Replaces: librados1-dbg,
Architecture: linux-any
Section: debug
Priority: extra
-Depends: librados2 (= ${binary:Version}),
+Depends: librados3 (= ${binary:Version}),
${misc:Depends},
Description: debugging symbols for librados
RADOS is a reliable, autonomic distributed object storage cluster
@@ -491,13 +493,13 @@ Description: debugging symbols for librados
Package: librados-dev
Architecture: linux-any
Section: libdevel
-Depends: librados2 (= ${binary:Version}),
+Depends: librados3 (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends},
Conflicts: librados1-dev,
- librados2-dev,
+ librados3-dev,
Replaces: librados1-dev,
- librados2-dev,
+ librados3-dev,
Description: RADOS distributed object store client library (development files)
RADOS is a reliable, autonomic distributed object storage cluster
developed as part of the Ceph distributed storage system. This is a
@@ -507,10 +509,50 @@ Description: RADOS distributed object store client library (development files)
This package contains development files needed for building applications that
link against librados.
+Package: libradospp1
+Architecture: linux-any
+Section: libs
+Depends: ${misc:Depends},
+ ${shlibs:Depends},
+Description: RADOS distributed object store client C++ library
+ RADOS is a reliable, autonomic distributed object storage cluster
+ developed as part of the Ceph distributed storage system. This is a
+ shared library allowing C++ applications to access the distributed object
+ store using a simple file-like C++ interface.
+
+Package: libradospp1-dbg
+Architecture: linux-any
+Section: debug
+Priority: extra
+Depends: libradospp1 (= ${binary:Version}),
+ ${misc:Depends},
+Description: debugging symbols for libradospp1
+ RADOS is a reliable, autonomic distributed object storage cluster
+ developed as part of the Ceph distributed storage system. This is a
+ shared library allowing applications to access the distributed object
+ store using a simple file-like interface in C++.
+ .
+ This package contains debugging symbols for libradospp.
+
+Package: libradospp-dev
+Architecture: linux-any
+Section: libdevel
+Depends: libradospp (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Description: RADOS distributed object store client C++ library (development files)
+ RADOS is a reliable, autonomic distributed object storage cluster
+ developed as part of the Ceph distributed storage system. This is a
+ shared library allowing applications to access the distributed object
+ store using a simple file-like interface.
+ .
+ This package contains development files needed for building C++ applications that
+ link against librados.
+
Package: libradosstriper1
Architecture: linux-any
Section: libs
-Depends: librados2 (= ${binary:Version}),
+Depends: librados3 (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends},
Description: RADOS striping interface
@@ -547,7 +589,7 @@ Description: RADOS striping interface (development files)
Package: librbd1
Architecture: linux-any
Section: libs
-Depends: librados2 (= ${binary:Version}),
+Depends: librados3 (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends},
Description: RADOS block device client library
@@ -646,7 +688,7 @@ Description: Ceph distributed file system client library (development files)
Package: librgw2
Architecture: linux-any
Section: libs
-Depends: librados2 (= ${binary:Version}),
+Depends: librados3 (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends},
Description: RADOS Gateway client library
@@ -759,7 +801,7 @@ Description: Meta-package for python libraries for the Ceph libraries
Package: python-rados
Architecture: linux-any
Section: python
-Depends: librados2 (= ${binary:Version}),
+Depends: librados3 (= ${binary:Version}),
${misc:Depends},
${python:Depends},
${shlibs:Depends},
@@ -793,7 +835,7 @@ Description: Python 2 libraries for the Ceph librados library
Package: python3-rados
Architecture: linux-any
Section: python
-Depends: librados2 (= ${binary:Version}),
+Depends: librados3 (= ${binary:Version}),
${misc:Depends},
${python3:Depends},
${shlibs:Depends},
diff --git a/debian/librados-dev.install b/debian/librados-dev.install
index d9410cae0e2..75d5ea7de73 100644
--- a/debian/librados-dev.install
+++ b/debian/librados-dev.install
@@ -1,13 +1,6 @@
usr/bin/librados-config
-usr/include/rados/buffer.h
-usr/include/rados/buffer_fwd.h
-usr/include/rados/crc32c.h
-usr/include/rados/inline_memory.h
usr/include/rados/librados.h
-usr/include/rados/librados.hpp
-usr/include/rados/page.h
usr/include/rados/rados_types.h
-usr/include/rados/rados_types.hpp
usr/lib/librados.so
usr/lib/librados_tp.so
usr/share/man/man8/librados-config.8
diff --git a/debian/librados2.install b/debian/librados3.install
index 3bdeedfd183..816e55fce2f 100644
--- a/debian/librados2.install
+++ b/debian/librados3.install
@@ -1,3 +1,3 @@
-usr/lib/ceph/libceph-common.so*
+usr/lib/ceph/libceph-common.so.*
usr/lib/librados.so.*
usr/lib/librados_tp.so.*
diff --git a/debian/libradospp-dev.install b/debian/libradospp-dev.install
new file mode 100644
index 00000000000..37d2d330efb
--- /dev/null
+++ b/debian/libradospp-dev.install
@@ -0,0 +1,8 @@
+usr/include/rados/buffer.h
+usr/include/rados/buffer_fwd.h
+usr/include/rados/crc32c.h
+usr/include/rados/inline_memory.h
+usr/include/rados/librados.hpp
+usr/include/rados/page.h
+usr/include/rados/rados_types.hpp
+usr/lib/libradospp.so
diff --git a/debian/libradospp1.install b/debian/libradospp1.install
new file mode 100644
index 00000000000..0e18366b247
--- /dev/null
+++ b/debian/libradospp1.install
@@ -0,0 +1 @@
+usr/lib/libradospp.so.*
diff --git a/debian/rules b/debian/rules
index 8579f42613f..940bbdb0749 100755
--- a/debian/rules
+++ b/debian/rules
@@ -98,7 +98,7 @@ override_dh_strip:
dh_strip -prbd-mirror --dbg-package=rbd-mirror-dbg
dh_strip -prbd-nbd --dbg-package=rbd-nbd-dbg
dh_strip -pceph-common --dbg-package=ceph-common-dbg
- dh_strip -plibrados2 --dbg-package=librados2-dbg
+ dh_strip -plibrados3 --dbg-package=librados3-dbg
dh_strip -plibradosstriper1 --dbg-package=libradosstriper1-dbg
dh_strip -plibrbd1 --dbg-package=librbd1-dbg
dh_strip -plibcephfs2 --dbg-package=libcephfs2-dbg
diff --git a/doc/install/upgrading-ceph.rst b/doc/install/upgrading-ceph.rst
index bf22b38ecab..6d4a0847994 100644
--- a/doc/install/upgrading-ceph.rst
+++ b/doc/install/upgrading-ceph.rst
@@ -214,12 +214,12 @@ Upgrading a Client
Once you have upgraded the packages and restarted daemons on your Ceph
cluster, we recommend upgrading ``ceph-common`` and client libraries
-(``librbd1`` and ``librados2``) on your client nodes too.
+(``librbd1`` , ``librados3`` and ``libradospp1``) on your client nodes too.
#. Upgrade the package::
ssh {client-host}
- apt-get update && sudo apt-get install ceph-common librados2 librbd1 python-rados python-rbd
+ apt-get update && sudo apt-get install ceph-common librados3 libradospp1 librbd1 python-rados python-rbd
#. Ensure that you have the latest version::
diff --git a/doc/man/8/ceph-deploy.rst b/doc/man/8/ceph-deploy.rst
index 9c8db106d81..e3778b8e5f4 100644
--- a/doc/man/8/ceph-deploy.rst
+++ b/doc/man/8/ceph-deploy.rst
@@ -330,7 +330,7 @@ uninstall
Remove Ceph packages from remote hosts. It detects the platform and distro of
selected host and uninstalls Ceph packages from it. However, some dependencies
-like ``librbd1`` and ``librados2`` will not be removed because they can cause
+like ``librbd1`` and ``librados3`` will not be removed because they can cause
issues with ``qemu-kvm``.
Usage::
@@ -345,7 +345,7 @@ purge
Remove Ceph packages from remote hosts and purge all data. It detects the
platform and distro of selected host, uninstalls Ceph packages and purges all
-data. However, some dependencies like ``librbd1`` and ``librados2`` will not be
+data. However, some dependencies like ``librbd1`` and ``librados3`` will not be
removed because they can cause issues with ``qemu-kvm``.
Usage::
diff --git a/doc/mgr/dashboard.rst b/doc/mgr/dashboard.rst
index 5473a7cbdeb..ac21ab42200 100644
--- a/doc/mgr/dashboard.rst
+++ b/doc/mgr/dashboard.rst
@@ -514,3 +514,29 @@ to use hyperlinks that include your prefix, you can set the
ceph config set mgr mgr/dashboard/url_prefix $PREFIX
so you can access the dashboard at ``http://$IP:$PORT/$PREFIX/``.
+
+
+Auditing
+--------
+
+The REST API is capable of logging PUT, POST and DELETE requests to the Ceph
+audit log. This feature is disabled by default, but can be enabled with the
+following command::
+
+ $ ceph dashboard set-audit-api-enabled <true|false>
+
+If enabled, the following parameters are logged per each request:
+
+* from - The origin of the request, e.g. https://[::1]:44410
+* path - The REST API path, e.g. /api/auth
+* method - e.g. PUT, POST or DELETE
+* user - The name of the user, otherwise 'None'
+
+The logging of the request payload (the arguments and their values) is enabled
+by default. Execute the following command to disable this behaviour::
+
+ $ ceph dashboard set-audit-api-log-payload <true|false>
+
+A log entry may look like this::
+
+ 2018-10-22 15:27:01.302514 mgr.x [INF] [DASHBOARD] from='https://[::ffff:127.0.0.1]:37022' path='/api/rgw/user/klaus' method='PUT' user='admin' params='{"max_buckets": "1000", "display_name": "Klaus Mustermann", "uid": "klaus", "suspended": "0", "email": "klaus.mustermann@ceph.com"}'
diff --git a/doc/rados/operations/crush-map-edits.rst b/doc/rados/operations/crush-map-edits.rst
index edf09529326..a0c99daccb3 100644
--- a/doc/rados/operations/crush-map-edits.rst
+++ b/doc/rados/operations/crush-map-edits.rst
@@ -377,7 +377,7 @@ A rule takes the following form::
min_size <min-size>
max_size <max-size>
step take <bucket-name> [class <device-class>]
- step [choose|chooseleaf] [firstn|indep] <N> <bucket-type>
+ step [choose|chooseleaf] [firstn|indep] <N> type <bucket-type>
step emit
}
diff --git a/doc/rbd/iscsi-target-cli-manual-install.rst b/doc/rbd/iscsi-target-cli-manual-install.rst
index 108cdbea2fc..888540957da 100644
--- a/doc/rbd/iscsi-target-cli-manual-install.rst
+++ b/doc/rbd/iscsi-target-cli-manual-install.rst
@@ -4,6 +4,24 @@ Manual ceph-iscsi-cli Installation
**Requirements**
+to complete the installation of ceph-iscsi-cli, there are 4 different steps:
+
+1. Install common packages from your Linux distribution's software repository
+2. Install Git to fetch the remaining packages directly from their Git repositories
+3. Ensure a compatible kernel is used or install a ceph-iscsi-test client
+4. Install all the components of ceph-iscsi-cli and start associated daemons:
+
+ - tcmu-runner
+ - rtslib-fb
+ - configshell-fb
+ - targetcli-fb
+ - ceph-iscsi-config
+ - ceph-iscsi-cli
+
+
+1. Install Common Packages
+==========================
+
The following packages will be used by ceph-iscsi-cli and target tools.
They must be installed from your Linux distribution's software repository
on each machine that will be a iSCSI gateway:
@@ -26,36 +44,68 @@ on each machine that will be a iSCSI gateway:
- python flask
- pyOpenSSL
-**Packages**
-- Linux Kernel
+2. Install Git
+==============
- If not using a distro kernel that contains the required Ceph iSCSI patches,
- then Linux kernel v4.16 or newer or the ceph-client ceph-iscsi-test
- branch must be used. To get the branch run:
+In order to install all the packages needed to run iSCSI with Ceph, you need to download them directly from their repository by using Git.
+On CentOS/RHEL execute:
- ::
+::
+
+ > sudo yum install git
+
+On Debian/Ubuntu execute:
+
+::
+
+ > sudo apt install git
+
+To know more about Git and how it works, please, visit https://git-scm.com
+
+
+3. Ensure a compatible kernel is used
+=====================================
+
+Ensure you use a supported kernel that contains the required Ceph iSCSI patches:
+
+- all Linux distribution with a kernel v4.16 or newer, or
+- Red Hat Enterprise Linux or CentOS 7.5 or later (in these distributions ceph-iscsi support is backported)
+If you are already using on the compatible kernels, you can go to next step.
+However, if you are NOT using a compatible kernel then ceph-client ceph-iscsi-test
+branch must be used. To get the branch run:
+
+ ::
+
> git clone https://github.com/ceph/ceph-client.git
> git checkout ceph-iscsi-test
-
- .. warning::
+
+ .. warning::
ceph-iscsi-test is not for production use. It should only be used
for proof of concept setups and testing. The kernel is only updated
with Ceph iSCSI patches. General security and bug fixes from upstream
are not applied.
-
- Check your distro's docs for specific instructions on how to build a
- kernel. The only Ceph iSCSI specific requirements are the following
- build options must be enabled:
-
- ::
-
+
+ Check your distro's docs for specific instructions on how to build a
+ kernel. The only Ceph iSCSI specific requirements are the following
+ build options must be enabled:
+
+ ::
+
CONFIG_TARGET_CORE=m
CONFIG_TCM_USER2=m
CONFIG_ISCSI_TARGET=m
-- tcmu-runner
+
+4. Install ceph-iscsi-cli
+========================================================
+
+Finally, the remaining tools can be fetched directly from their Git repositories and their associated services started
+
+
+tcmu-runner
+-----------
Installation:
@@ -64,7 +114,14 @@ on each machine that will be a iSCSI gateway:
> git clone https://github.com/open-iscsi/tcmu-runner
> cd tcmu-runner
- Ceph iSCSI requires systemd so the following build command must be used:
+ Run the following command to install all the needed dependencies:
+
+ ::
+
+ > ./extra/install_dep.sh
+
+ Now you can build the tcmu-runner.
+ To do so, use the following build command:
::
@@ -79,7 +136,9 @@ on each machine that will be a iSCSI gateway:
> systemctl enable tcmu-runner
> systemctl start tcmu-runner
-- rtslib-fb
+
+rtslib-fb
+---------
Installation:
@@ -89,7 +148,8 @@ on each machine that will be a iSCSI gateway:
> cd rtslib-fb
> python setup.py install
-- configshell-fb
+configshell-fb
+--------------
Installation:
@@ -99,7 +159,8 @@ on each machine that will be a iSCSI gateway:
> cd configshell-fb
> python setup.py install
-- targetcli-fb
+targetcli-fb
+------------
Installation:
@@ -115,7 +176,8 @@ on each machine that will be a iSCSI gateway:
on the system. If targets have been setup and are being managed by
targetcli the target service must be disabled.
-- ceph-iscsi-config
+ceph-iscsi-config
+-----------------
Installation:
@@ -134,7 +196,8 @@ on each machine that will be a iSCSI gateway:
> systemctl enable rbd-target-gw
> systemctl start rbd-target-gw
-- ceph-iscsi-cli
+ceph-iscsi-cli
+--------------
Installation:
diff --git a/qa/distros/all/centos_7.5.yaml b/qa/distros/all/centos_7.5.yaml
new file mode 100644
index 00000000000..54324576d75
--- /dev/null
+++ b/qa/distros/all/centos_7.5.yaml
@@ -0,0 +1,2 @@
+os_type: centos
+os_version: "7.5"
diff --git a/qa/distros/supported-all-distro/centos_latest.yaml b/qa/distros/supported-all-distro/centos_latest.yaml
index 4cc59dad1d4..10e4444a36f 120000
--- a/qa/distros/supported-all-distro/centos_latest.yaml
+++ b/qa/distros/supported-all-distro/centos_latest.yaml
@@ -1 +1 @@
-../all/centos_7.4.yaml \ No newline at end of file
+../all/centos_7.5.yaml \ No newline at end of file
diff --git a/qa/distros/supported-random-distro$/centos_latest.yaml b/qa/distros/supported-random-distro$/centos_latest.yaml
index 4cc59dad1d4..10e4444a36f 120000
--- a/qa/distros/supported-random-distro$/centos_latest.yaml
+++ b/qa/distros/supported-random-distro$/centos_latest.yaml
@@ -1 +1 @@
-../all/centos_7.4.yaml \ No newline at end of file
+../all/centos_7.5.yaml \ No newline at end of file
diff --git a/qa/distros/supported/centos_latest.yaml b/qa/distros/supported/centos_latest.yaml
index 4cc59dad1d4..10e4444a36f 120000
--- a/qa/distros/supported/centos_latest.yaml
+++ b/qa/distros/supported/centos_latest.yaml
@@ -1 +1 @@
-../all/centos_7.4.yaml \ No newline at end of file
+../all/centos_7.5.yaml \ No newline at end of file
diff --git a/qa/packages/packages.yaml b/qa/packages/packages.yaml
index e2120d3a31a..2b891af36c3 100644
--- a/qa/packages/packages.yaml
+++ b/qa/packages/packages.yaml
@@ -13,7 +13,7 @@ ceph:
- libcephfs-dev
- libcephfs-java
- libcephfs-jni
- - librados2
+ - librados3
- librbd1
- rbd-fuse
- ceph-common-dbg
@@ -24,7 +24,7 @@ ceph:
- ceph-osd-dbg
- ceph-test-dbg
- libcephfs2-dbg
- - librados2-dbg
+ - librados3-dbg
- libradosstriper1-dbg
- librbd1-dbg
- librgw2-dbg
@@ -42,7 +42,7 @@ ceph:
- libcephfs_jni1
- libcephfs2
- libcephfs-devel
- - librados2
+ - librados3
- librbd1
- python-ceph
- rbd-fuse
diff --git a/qa/qa_scripts/cephscrub.sh b/qa/qa_scripts/cephscrub.sh
index 331d5ce32d8..19bf075ced4 100755
--- a/qa/qa_scripts/cephscrub.sh
+++ b/qa/qa_scripts/cephscrub.sh
@@ -13,8 +13,8 @@ sudo apt-get -y purge ceph-fuse-dbg
sudo apt-get -y purge ceph-common
sudo apt-get -y purge ceph-common-dbg
sudo apt-get -y purge ceph-resource-agents
-sudo apt-get -y purge librados2
-sudo apt-get -y purge librados2-dbg
+sudo apt-get -y purge librados3
+sudo apt-get -y purge librados3-dbg
sudo apt-get -y purge librados-dev
sudo apt-get -y purge librbd1
sudo apt-get -y purge librbd1-dbg
diff --git a/qa/suites/fs/upgrade/featureful_client/old_client/tasks/0-luminous.yaml b/qa/suites/fs/upgrade/featureful_client/old_client/tasks/0-luminous.yaml
index bf627dc394c..6df131c3efb 100644
--- a/qa/suites/fs/upgrade/featureful_client/old_client/tasks/0-luminous.yaml
+++ b/qa/suites/fs/upgrade/featureful_client/old_client/tasks/0-luminous.yaml
@@ -4,6 +4,7 @@ meta:
tasks:
- install:
branch: luminous
+ exclude_packages: ['librados3']
- print: "**** done installing luminous"
- ceph:
log-whitelist:
diff --git a/qa/suites/fs/upgrade/featureful_client/upgraded_client/tasks/0-luminous.yaml b/qa/suites/fs/upgrade/featureful_client/upgraded_client/tasks/0-luminous.yaml
index bf627dc394c..6df131c3efb 100644
--- a/qa/suites/fs/upgrade/featureful_client/upgraded_client/tasks/0-luminous.yaml
+++ b/qa/suites/fs/upgrade/featureful_client/upgraded_client/tasks/0-luminous.yaml
@@ -4,6 +4,7 @@ meta:
tasks:
- install:
branch: luminous
+ exclude_packages: ['librados3']
- print: "**** done installing luminous"
- ceph:
log-whitelist:
diff --git a/qa/suites/fs/upgrade/snaps/tasks/0-luminous.yaml b/qa/suites/fs/upgrade/snaps/tasks/0-luminous.yaml
index bf627dc394c..6df131c3efb 100644
--- a/qa/suites/fs/upgrade/snaps/tasks/0-luminous.yaml
+++ b/qa/suites/fs/upgrade/snaps/tasks/0-luminous.yaml
@@ -4,6 +4,7 @@ meta:
tasks:
- install:
branch: luminous
+ exclude_packages: ['librados3']
- print: "**** done installing luminous"
- ceph:
log-whitelist:
diff --git a/qa/suites/rados/thrash-old-clients/1-install/hammer.yaml b/qa/suites/rados/thrash-old-clients/1-install/hammer.yaml
index b2c6b62d812..2aee309cf47 100644
--- a/qa/suites/rados/thrash-old-clients/1-install/hammer.yaml
+++ b/qa/suites/rados/thrash-old-clients/1-install/hammer.yaml
@@ -9,7 +9,7 @@ overrides:
tasks:
- install:
branch: hammer
- exclude_packages: ['ceph-mgr','libcephfs2','libcephfs-devel','libcephfs-dev']
+ exclude_packages: ['ceph-mgr','libcephfs2','libcephfs-devel','libcephfs-dev', 'librados3', 'libradospp-devel']
- install.upgrade:
mon.a:
mon.b:
diff --git a/qa/suites/rados/thrash-old-clients/1-install/jewel.yaml b/qa/suites/rados/thrash-old-clients/1-install/jewel.yaml
index b68ee3d30bc..e04a61fd57e 100644
--- a/qa/suites/rados/thrash-old-clients/1-install/jewel.yaml
+++ b/qa/suites/rados/thrash-old-clients/1-install/jewel.yaml
@@ -1,7 +1,7 @@
tasks:
- install:
branch: jewel
- exclude_packages: ['ceph-mgr','libcephfs2','libcephfs-devel','libcephfs-dev']
+ exclude_packages: ['ceph-mgr','libcephfs2','libcephfs-devel','libcephfs-dev', 'librados3']
- install.upgrade:
mon.a:
mon.b:
diff --git a/qa/suites/rados/thrash-old-clients/1-install/luminous.yaml b/qa/suites/rados/thrash-old-clients/1-install/luminous.yaml
index 1961c8914ec..d8a590f8541 100644
--- a/qa/suites/rados/thrash-old-clients/1-install/luminous.yaml
+++ b/qa/suites/rados/thrash-old-clients/1-install/luminous.yaml
@@ -1,6 +1,7 @@
tasks:
- install:
branch: luminous
+ exclude_packages: ['librados3']
- install.upgrade:
mon.a:
mon.b:
diff --git a/qa/suites/rados/upgrade/luminous-x-singleton/1-install/luminous.yaml b/qa/suites/rados/upgrade/luminous-x-singleton/1-install/luminous.yaml
index c84176f4161..9900058541e 100644
--- a/qa/suites/rados/upgrade/luminous-x-singleton/1-install/luminous.yaml
+++ b/qa/suites/rados/upgrade/luminous-x-singleton/1-install/luminous.yaml
@@ -8,6 +8,7 @@ meta:
tasks:
- install:
branch: luminous
+ exclude_packages: ['librados3']
- print: "**** done install luminous"
- ceph:
- print: "**** done ceph"
diff --git a/qa/suites/upgrade/luminous-x/parallel/1-ceph-install/luminous.yaml b/qa/suites/upgrade/luminous-x/parallel/1-ceph-install/luminous.yaml
index 3d57f792b97..069234b8028 100644
--- a/qa/suites/upgrade/luminous-x/parallel/1-ceph-install/luminous.yaml
+++ b/qa/suites/upgrade/luminous-x/parallel/1-ceph-install/luminous.yaml
@@ -6,6 +6,7 @@ meta:
tasks:
- install:
branch: luminous
+ exclude_packages: ['librados3']
- print: "**** done installing luminous"
- ceph:
log-whitelist:
diff --git a/qa/tasks/radosgw_admin_rest.py b/qa/tasks/radosgw_admin_rest.py
index 8a4bf3c0fee..28e47e53b7d 100644
--- a/qa/tasks/radosgw_admin_rest.py
+++ b/qa/tasks/radosgw_admin_rest.py
@@ -382,6 +382,7 @@ def task(ctx, config):
assert ret == 200
assert out['owner'] == user1
+ assert out['tenant'] == ''
bucket_id = out['id']
# TESTCASE 'bucket-stats4','bucket','stats','new empty bucket','succeeds, expected bucket ID'
diff --git a/qa/workunits/rados/0001-cmake-add-Findrados.cmake-and-use-it.patch b/qa/workunits/rados/0001-cmake-add-Findrados.cmake-and-use-it.patch
new file mode 100644
index 00000000000..4ab359d317b
--- /dev/null
+++ b/qa/workunits/rados/0001-cmake-add-Findrados.cmake-and-use-it.patch
@@ -0,0 +1,71 @@
+From 7535e5f47353658f966eb4dce344154678463e04 Mon Sep 17 00:00:00 2001
+From: Kefu Chai <tchaikov@gmail.com>
+Date: Mon, 29 Oct 2018 19:14:54 +0800
+Subject: [PATCH] cmake: add Findrados.cmake and use it
+
+ceph has extracted libradospp out from librados. the former offers the
+C++ API, while the latter offers the C API.
+
+Signed-off-by: Kefu Chai <tchaikov@gmail.com>
+---
+ CMakeLists.txt | 3 ++-
+ cmake/modules/Findradospp.cmake | 33 +++++++++++++++++++++++++++++++++
+ 2 files changed, 35 insertions(+), 1 deletion(-)
+ create mode 100644 cmake/modules/Findradospp.cmake
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 6cb80cd10..48c61f928 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -731,7 +731,8 @@ option(WITH_LIBRADOS "Build with librados" OFF)
+ if(WITH_LIBRADOS)
+ list(APPEND SOURCES
+ utilities/env_librados.cc)
+- list(APPEND THIRDPARTY_LIBS rados)
++ find_package(radospp REQUIRED)
++ list(APPEND THIRDPARTY_LIBS rados::radospp)
+ endif()
+
+ if(WIN32)
+diff --git a/cmake/modules/Findradospp.cmake b/cmake/modules/Findradospp.cmake
+new file mode 100644
+index 000000000..18822adb9
+--- /dev/null
++++ b/cmake/modules/Findradospp.cmake
+@@ -0,0 +1,33 @@
++# - Find RADOS
++# Find librados library and includes
++#
++# RADOSPP_INCLUDE_DIR - where to find librados.hpp.
++# RADOSPP_LIBRARIES - List of libraries when using radospp.
++# radospp_FOUND - True if radospp found.
++
++find_path(RADOSPP_INCLUDE_DIR
++ NAMES rados/librados.hpp
++ HINTS ${LIBRADOS_ROOT}/include)
++
++find_library(RADOSPP_LIBRARIES
++ NAMES radospp
++ HINTS ${LIBRADOS_ROOT}/lib)
++
++include(FindPackageHandleStandardArgs)
++find_package_handle_standard_args(radospp
++ DEFAULT_MSG RADOSPP_LIBRARIES RADOSPP_INCLUDE_DIR)
++
++mark_as_advanced(
++ RADOSPP_INCLUDE_DIR
++ RADOSPP_LIBRARIES)
++
++message(STATUS "${RADOSPP_INCLUDE_DIR}")
++message(STATUS "${RADOSPP_LIBRARIES}")
++message(STATUS "${radospp_FOUND}")
++if(radospp_FOUND AND NOT (TARGET rados::radospp))
++ add_library(rados::radospp UNKNOWN IMPORTED)
++ set_target_properties(rados::radospp PROPERTIES
++ INTERFACE_INCLUDE_DIRECTORIES "${RADOSPP_INCLUDE_DIR}"
++ IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
++ IMPORTED_LOCATION "${RADOSPP_LIBRARIES}")
++endif()
+--
+2.19.1
+
diff --git a/qa/workunits/rados/test.sh b/qa/workunits/rados/test.sh
index 082c638b0ec..a2f5e0499db 100755
--- a/qa/workunits/rados/test.sh
+++ b/qa/workunits/rados/test.sh
@@ -15,9 +15,18 @@ trap cleanup EXIT ERR HUP INT QUIT
declare -A pids
for f in \
- api_aio api_io api_asio api_list api_lock api_misc \
- api_tier api_pool api_snapshots api_stat api_watch_notify api_cmd \
- api_service \
+ api_aio api_aio_pp \
+ api_io api_io_pp \
+ api_asio api_list \
+ api_lock api_lock_pp \
+ api_misc api_misc_pp \
+ api_tier_pp \
+ api_pool \
+ api_snapshots api_snapshots_pp \
+ api_stat api_stat_pp \
+ api_watch_notify api_watch_notify_pp \
+ api_cmd api_cmd_pp \
+ api_service api_service_pp \
api_c_write_operations \
api_c_read_operations \
list_parallel \
diff --git a/qa/workunits/rados/test_envlibrados_for_rocksdb.sh b/qa/workunits/rados/test_envlibrados_for_rocksdb.sh
index 05281cbb445..1ea2c26b527 100755
--- a/qa/workunits/rados/test_envlibrados_for_rocksdb.sh
+++ b/qa/workunits/rados/test_envlibrados_for_rocksdb.sh
@@ -42,10 +42,10 @@ CURRENT_PATH=`pwd`
# for rocksdb
case $(lsb_release -si) in
Ubuntu|Debian|Devuan)
- install g++ libsnappy-dev zlib1g-dev libbz2-dev librados-dev
+ install g++ libsnappy-dev zlib1g-dev libbz2-dev libradospp-dev
;;
CentOS|Fedora|RedHatEnterpriseServer)
- install gcc-c++.x86_64 snappy-devel zlib zlib-devel bzip2 bzip2-devel librados2-devel.x86_64
+ install gcc-c++.x86_64 snappy-devel zlib zlib-devel bzip2 bzip2-devel libradospp-devel.x86_64
;;
*)
echo "$(lsb_release -si) is unknown, $@ will have to be installed manually."
@@ -73,6 +73,8 @@ git clone https://github.com/facebook/rocksdb.git --depth 1
# compile code
cd rocksdb
+patch -p1 $(dirname $0)/0001-cmake-add-Findrados.cmake-and-use-it.patch
+
mkdir build && cd build && cmake -DWITH_LIBRADOS=ON -DWITH_SNAPPY=ON -DWITH_GFLAGS=OFF -DFAIL_ON_WARNINGS=OFF ..
make rocksdb_env_librados_test -j8
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 43c44388f30..f999f877a69 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -397,7 +397,7 @@ add_library(ceph-common SHARED ${ceph_common_objs})
target_link_libraries(ceph-common ${ceph_common_deps})
# appease dpkg-shlibdeps
set_target_properties(ceph-common PROPERTIES
- SOVERSION 0
+ SOVERSION 1
INSTALL_RPATH "")
if(NOT APPLE AND NOT FREEBSD)
# Apple uses Mach-O, not ELF. so this option does not apply to APPLE.
@@ -413,7 +413,11 @@ if(NOT APPLE AND NOT FREEBSD)
PROPERTY LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions")
endif()
-install(TARGETS ceph-common DESTINATION ${CMAKE_INSTALL_PKGLIBDIR})
+install(
+ TARGETS ceph-common
+ LIBRARY
+ DESTINATION ${CMAKE_INSTALL_PKGLIBDIR}
+ NAMELINK_SKIP)
if(${WITH_LTTNG})
add_subdirectory(tracing)
diff --git a/src/client/Client.cc b/src/client/Client.cc
index 767d08fafa4..426abac9cfe 100644
--- a/src/client/Client.cc
+++ b/src/client/Client.cc
@@ -272,7 +272,8 @@ Client::Client(Messenger *m, MonClient *mc, Objecter *objecter_)
interrupt_finisher(m->cct),
remount_finisher(m->cct),
objecter_finisher(m->cct),
- m_command_hook(this)
+ m_command_hook(this),
+ fscid(0)
{
_reset_faked_inos();
@@ -2512,6 +2513,12 @@ void Client::handle_osd_map(MOSDMap *m)
return o.is_blacklisted(myaddrs);});
}
+ // Always subscribe to next osdmap for blacklisted client
+ // until this client is not blacklisted.
+ if (blacklisted) {
+ objecter->maybe_request_map();
+ }
+
if (objecter->osdmap_full_flag()) {
_handle_full_flag(-1);
} else {
@@ -5772,13 +5779,13 @@ int Client::subscribe_mdsmap(const std::string &fs_name)
r = fetch_fsmap(true);
if (r < 0)
return r;
- fs_cluster_id_t cid = fsmap_user->get_fs_cid(resolved_fs_name);
- if (cid == FS_CLUSTER_ID_NONE) {
+ fscid = fsmap_user->get_fs_cid(resolved_fs_name);
+ if (fscid == FS_CLUSTER_ID_NONE) {
return -ENOENT;
}
std::ostringstream oss;
- oss << want << "." << cid;
+ oss << want << "." << fscid;
want = oss.str();
}
ldout(cct, 10) << "Subscribing to map '" << want << "'" << dendl;
diff --git a/src/client/Client.h b/src/client/Client.h
index 2c8e29fbef6..7e4b4b0fcfd 100644
--- a/src/client/Client.h
+++ b/src/client/Client.h
@@ -303,6 +303,10 @@ public:
const std::string& fs_name);
void finish_reclaim();
+ fs_cluster_id_t get_fs_cid() {
+ return fscid;
+ }
+
int mds_command(
const std::string &mds_spec,
const std::vector<std::string>& cmd,
@@ -1239,6 +1243,9 @@ private:
bool _use_faked_inos;
+ // Cluster fsid
+ fs_cluster_id_t fscid;
+
// file handles, etc.
interval_set<int> free_fd_set; // unused fds
ceph::unordered_map<int, Fh*> fd_map;
diff --git a/src/cls/lock/cls_lock.cc b/src/cls/lock/cls_lock.cc
index 12311b1a3c0..88ea6a71b0c 100644
--- a/src/cls/lock/cls_lock.cc
+++ b/src/cls/lock/cls_lock.cc
@@ -34,7 +34,18 @@ CLS_NAME(lock)
#define LOCK_PREFIX "lock."
-static int read_lock(cls_method_context_t hctx, const string& name, lock_info_t *lock)
+static int clean_lock(cls_method_context_t hctx)
+{
+ int r = cls_cxx_remove(hctx);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int read_lock(cls_method_context_t hctx,
+ const string& name,
+ lock_info_t *lock)
{
bufferlist bl;
string key = LOCK_PREFIX;
@@ -67,16 +78,20 @@ static int read_lock(cls_method_context_t hctx, const string& name, lock_info_t
map<locker_id_t, locker_info_t>::iterator iter = lock->lockers.begin();
while (iter != lock->lockers.end()) {
- map<locker_id_t, locker_info_t>::iterator next = iter;
- ++next;
-
struct locker_info_t& info = iter->second;
if (!info.expiration.is_zero() && info.expiration < now) {
CLS_LOG(20, "expiring locker");
- lock->lockers.erase(iter);
+ iter = lock->lockers.erase(iter);
+ } else {
+ ++iter;
}
+ }
- iter = next;
+ if (lock->lockers.empty() && cls_lock_is_ephemeral(lock->lock_type)) {
+ r = clean_lock(hctx);
+ if (r < 0) {
+ CLS_ERR("error, on read, cleaning lock object %s", cpp_strerror(r).c_str());
+ }
}
return 0;
@@ -122,24 +137,35 @@ static int lock_obj(cls_method_context_t hctx,
const string& cookie,
const string& tag)
{
- bool exclusive = lock_type == LOCK_EXCLUSIVE;
+ bool exclusive = cls_lock_is_exclusive(lock_type);
lock_info_t linfo;
- bool fail_if_exists = (flags & LOCK_FLAG_RENEW) == 0;
+ bool fail_if_exists = (flags & LOCK_FLAG_MAY_RENEW) == 0;
+ bool fail_if_does_not_exist = flags & LOCK_FLAG_MUST_RENEW;
- CLS_LOG(20, "requested lock_type=%s fail_if_exists=%d", cls_lock_type_str(lock_type), fail_if_exists);
- if (lock_type != LOCK_EXCLUSIVE &&
- lock_type != LOCK_SHARED)
+ CLS_LOG(20,
+ "requested lock_type=%s fail_if_exists=%d fail_if_does_not_exist=%d",
+ cls_lock_type_str(lock_type), fail_if_exists, fail_if_does_not_exist);
+ if (!cls_lock_is_valid(lock_type)) {
return -EINVAL;
+ }
if (name.empty())
return -EINVAL;
+ if (!fail_if_exists && fail_if_does_not_exist) {
+ // at most one of LOCK_FLAG_MAY_RENEW and LOCK_FLAG_MUST_RENEW may
+ // be set since they have different implications if the lock does
+ // not already exist
+ return -EINVAL;
+ }
+
// see if there's already a locker
int r = read_lock(hctx, name, &linfo);
if (r < 0 && r != -ENOENT) {
CLS_ERR("Could not read lock info: %s", cpp_strerror(r).c_str());
return r;
}
+
map<locker_id_t, locker_info_t>& lockers = linfo.lockers;
map<locker_id_t, locker_info_t>::iterator iter;
@@ -161,11 +187,13 @@ static int lock_obj(cls_method_context_t hctx,
CLS_LOG(20, "existing_lock_type=%s", cls_lock_type_str(existing_lock_type));
iter = lockers.find(id);
if (iter != lockers.end()) {
- if (fail_if_exists) {
+ if (fail_if_exists && !fail_if_does_not_exist) {
return -EEXIST;
} else {
lockers.erase(iter); // remove old entry
}
+ } else if (fail_if_does_not_exist) {
+ return -ENOENT;
}
if (!lockers.empty()) {
@@ -236,9 +264,9 @@ static int lock_op(cls_method_context_t hctx,
* entity or cookie is wrong), or -errno on other error.
*/
static int remove_lock(cls_method_context_t hctx,
- const string& name,
- entity_name_t& locker,
- const string& cookie)
+ const string& name,
+ entity_name_t& locker,
+ const string& cookie)
{
// get current lockers
lock_info_t linfo;
@@ -258,7 +286,12 @@ static int remove_lock(cls_method_context_t hctx,
}
lockers.erase(iter);
- r = write_lock(hctx, name, linfo);
+ if (cls_lock_is_ephemeral(linfo.lock_type)) {
+ ceph_assert(lockers.empty());
+ r = clean_lock(hctx);
+ } else {
+ r = write_lock(hctx, name, linfo);
+ }
return r;
}
@@ -302,7 +335,7 @@ static int unlock_op(cls_method_context_t hctx,
* is wrong), or -errno on other (unexpected) error.
*/
static int break_lock(cls_method_context_t hctx,
- bufferlist *in, bufferlist *out)
+ bufferlist *in, bufferlist *out)
{
CLS_LOG(20, "break_lock");
cls_lock_break_op op;
@@ -422,7 +455,7 @@ int assert_locked(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
return -EINVAL;
}
- if (op.type != LOCK_EXCLUSIVE && op.type != LOCK_SHARED) {
+ if (!cls_lock_is_valid(op.type)) {
return -EINVAL;
}
@@ -494,7 +527,7 @@ int set_cookie(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
return -EINVAL;
}
- if (op.type != LOCK_EXCLUSIVE && op.type != LOCK_SHARED) {
+ if (!cls_lock_is_valid(op.type)) {
return -EINVAL;
}
diff --git a/src/cls/lock/cls_lock_client.cc b/src/cls/lock/cls_lock_client.cc
index 19f6a575e61..498d573f20d 100644
--- a/src/cls/lock/cls_lock_client.cc
+++ b/src/cls/lock/cls_lock_client.cc
@@ -208,14 +208,19 @@ namespace rados {
rados_op->exec("lock", "set_cookie", in);
}
+ void Lock::assert_locked_shared(ObjectOperation *op)
+ {
+ assert_locked(op, name, LOCK_SHARED, cookie, tag);
+ }
+
void Lock::assert_locked_exclusive(ObjectOperation *op)
{
assert_locked(op, name, LOCK_EXCLUSIVE, cookie, tag);
}
- void Lock::assert_locked_shared(ObjectOperation *op)
+ void Lock::assert_locked_exclusive_ephemeral(ObjectOperation *op)
{
- assert_locked(op, name, LOCK_SHARED, cookie, tag);
+ assert_locked(op, name, LOCK_EXCLUSIVE_EPHEMERAL, cookie, tag);
}
void Lock::lock_shared(ObjectWriteOperation *op)
@@ -242,6 +247,18 @@ namespace rados {
cookie, tag, description, duration, flags);
}
+ void Lock::lock_exclusive_ephemeral(ObjectWriteOperation *op)
+ {
+ lock(op, name, LOCK_EXCLUSIVE_EPHEMERAL,
+ cookie, tag, description, duration, flags);
+ }
+
+ int Lock::lock_exclusive_ephemeral(IoCtx *ioctx, const string& oid)
+ {
+ return lock(ioctx, oid, name, LOCK_EXCLUSIVE_EPHEMERAL,
+ cookie, tag, description, duration, flags);
+ }
+
void Lock::unlock(ObjectWriteOperation *op)
{
rados::cls::lock::unlock(op, name, cookie);
diff --git a/src/cls/lock/cls_lock_client.h b/src/cls/lock/cls_lock_client.h
index 43e14e6a493..446b6b59af2 100644
--- a/src/cls/lock/cls_lock_client.h
+++ b/src/cls/lock/cls_lock_client.h
@@ -4,6 +4,8 @@
#ifndef CEPH_CLS_LOCK_CLIENT_H
#define CEPH_CLS_LOCK_CLIENT_H
+#include <chrono>
+
#include "cls/lock/cls_lock_types.h"
namespace librados {
@@ -87,26 +89,53 @@ namespace rados {
void set_tag(const std::string& t) { tag = t; }
void set_description(const std::string& desc) { description = desc; }
void set_duration(const utime_t& e) { duration = e; }
- void set_renew(bool renew) {
+ void set_duration(const ceph::timespan& d) {
+ duration = utime_t(ceph::real_clock::zero() + d);
+ }
+
+ void set_may_renew(bool renew) {
if (renew) {
- flags |= LOCK_FLAG_RENEW;
+ flags |= LOCK_FLAG_MAY_RENEW;
+ flags &= ~LOCK_FLAG_MUST_RENEW; // if may then not must
} else {
- flags &= ~LOCK_FLAG_RENEW;
+ flags &= ~LOCK_FLAG_MAY_RENEW;
+ }
+ }
+
+ void set_must_renew(bool renew) {
+ if (renew) {
+ flags |= LOCK_FLAG_MUST_RENEW;
+ flags &= ~LOCK_FLAG_MAY_RENEW; // if must then not may
+ } else {
+ flags &= ~LOCK_FLAG_MUST_RENEW;
}
}
- void assert_locked_exclusive(librados::ObjectOperation *rados_op);
void assert_locked_shared(librados::ObjectOperation *rados_op);
+ void assert_locked_exclusive(librados::ObjectOperation *rados_op);
+ void assert_locked_exclusive_ephemeral(librados::ObjectOperation *rados_op);
/* ObjectWriteOperation */
- void lock_exclusive(librados::ObjectWriteOperation *ioctx);
void lock_shared(librados::ObjectWriteOperation *ioctx);
+ void lock_exclusive(librados::ObjectWriteOperation *ioctx);
+
+ // Be careful when using an exclusive ephemeral lock; it is
+ // intended strictly for cases when a lock object exists
+ // solely for a lock in a given process and the object is no
+ // longer needed when the lock is unlocked or expired, as the
+ // cls back-end will make an effort to delete it.
+ void lock_exclusive_ephemeral(librados::ObjectWriteOperation *ioctx);
void unlock(librados::ObjectWriteOperation *ioctx);
- void break_lock(librados::ObjectWriteOperation *ioctx, const entity_name_t& locker);
+ void break_lock(librados::ObjectWriteOperation *ioctx,
+ const entity_name_t& locker);
/* IoCtx */
- int lock_exclusive(librados::IoCtx *ioctx, const std::string& oid);
int lock_shared(librados::IoCtx *ioctx, const std::string& oid);
+ int lock_exclusive(librados::IoCtx *ioctx, const std::string& oid);
+
+ // NB: see above comment on exclusive ephemeral locks
+ int lock_exclusive_ephemeral(librados::IoCtx *ioctx,
+ const std::string& oid);
int unlock(librados::IoCtx *ioctx, const std::string& oid);
int break_lock(librados::IoCtx *ioctx, const std::string& oid,
const entity_name_t& locker);
diff --git a/src/cls/lock/cls_lock_ops.cc b/src/cls/lock/cls_lock_ops.cc
index 0edeaeac339..28c08f34476 100644
--- a/src/cls/lock/cls_lock_ops.cc
+++ b/src/cls/lock/cls_lock_ops.cc
@@ -45,7 +45,7 @@ void cls_lock_lock_op::generate_test_instances(list<cls_lock_lock_op*>& o)
i->tag = "tag";
i->description = "description";
i->duration = utime_t(5, 0);
- i->flags = LOCK_FLAG_RENEW;
+ i->flags = LOCK_FLAG_MAY_RENEW;
o.push_back(i);
o.push_back(new cls_lock_lock_op);
}
diff --git a/src/cls/lock/cls_lock_ops.h b/src/cls/lock/cls_lock_ops.h
index 0138f6e0c2b..5d22452b3b2 100644
--- a/src/cls/lock/cls_lock_ops.h
+++ b/src/cls/lock/cls_lock_ops.h
@@ -1,3 +1,6 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
#ifndef CEPH_CLS_LOCK_OPS_H
#define CEPH_CLS_LOCK_OPS_H
diff --git a/src/cls/lock/cls_lock_types.h b/src/cls/lock/cls_lock_types.h
index d88786c6e87..75796996e7b 100644
--- a/src/cls/lock/cls_lock_types.h
+++ b/src/cls/lock/cls_lock_types.h
@@ -1,3 +1,6 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
#ifndef CEPH_CLS_LOCK_TYPES_H
#define CEPH_CLS_LOCK_TYPES_H
@@ -7,12 +10,14 @@
#include "msg/msg_types.h"
/* lock flags */
-#define LOCK_FLAG_RENEW 0x1 /* idempotent lock acquire */
+#define LOCK_FLAG_MAY_RENEW 0x1 /* idempotent lock acquire */
+#define LOCK_FLAG_MUST_RENEW 0x2 /* lock must already be acquired */
enum ClsLockType {
- LOCK_NONE = 0,
- LOCK_EXCLUSIVE = 1,
- LOCK_SHARED = 2,
+ LOCK_NONE = 0,
+ LOCK_EXCLUSIVE = 1,
+ LOCK_SHARED = 2,
+ LOCK_EXCLUSIVE_EPHEMERAL = 3, /* lock object is removed @ unlock */
};
inline const char *cls_lock_type_str(ClsLockType type)
@@ -24,11 +29,27 @@ inline const char *cls_lock_type_str(ClsLockType type)
return "exclusive";
case LOCK_SHARED:
return "shared";
+ case LOCK_EXCLUSIVE_EPHEMERAL:
+ return "exclusive-ephemeral";
default:
return "<unknown>";
}
}
+inline bool cls_lock_is_exclusive(ClsLockType type) {
+ return LOCK_EXCLUSIVE == type || LOCK_EXCLUSIVE_EPHEMERAL == type;
+}
+
+inline bool cls_lock_is_ephemeral(ClsLockType type) {
+ return LOCK_EXCLUSIVE_EPHEMERAL == type;
+}
+
+inline bool cls_lock_is_valid(ClsLockType type) {
+ return LOCK_SHARED == type ||
+ LOCK_EXCLUSIVE == type ||
+ LOCK_EXCLUSIVE_EPHEMERAL == type;
+}
+
namespace rados {
namespace cls {
namespace lock {
diff --git a/src/cls/lua/cls_lua_client.h b/src/cls/lua/cls_lua_client.h
index e37906993c9..c1ed4369f63 100644
--- a/src/cls/lua/cls_lua_client.h
+++ b/src/cls/lua/cls_lua_client.h
@@ -2,7 +2,7 @@
#define CLS_LUA_CLIENT_HPP
#include <string>
-#include "include/buffer_fwd.h" // for bufferlist
+#include "include/rados/librados.hpp"
namespace librados {
class IoCtx;
diff --git a/src/cls/rbd/cls_rbd_types.cc b/src/cls/rbd/cls_rbd_types.cc
index 0c779a812d8..1d7f932e970 100644
--- a/src/cls/rbd/cls_rbd_types.cc
+++ b/src/cls/rbd/cls_rbd_types.cc
@@ -812,6 +812,7 @@ void MigrationSpec::encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
encode(header_type, bl);
encode(pool_id, bl);
+ encode(pool_namespace, bl);
encode(image_name, bl);
encode(image_id, bl);
encode(snap_seqs, bl);
@@ -827,6 +828,7 @@ void MigrationSpec::decode(bufferlist::const_iterator& bl) {
DECODE_START(1, bl);
decode(header_type, bl);
decode(pool_id, bl);
+ decode(pool_namespace, bl);
decode(image_name, bl);
decode(image_id, bl);
decode(snap_seqs, bl);
@@ -853,6 +855,7 @@ std::ostream& operator<<(std::ostream& os,
void MigrationSpec::dump(Formatter *f) const {
f->dump_stream("header_type") << header_type;
f->dump_int("pool_id", pool_id);
+ f->dump_string("pool_namespace", pool_namespace);
f->dump_string("image_name", image_name);
f->dump_string("image_id", image_id);
f->dump_stream("snap_seqs") << snap_seqs;
@@ -862,9 +865,9 @@ void MigrationSpec::dump(Formatter *f) const {
void MigrationSpec::generate_test_instances(std::list<MigrationSpec*> &o) {
o.push_back(new MigrationSpec());
- o.push_back(new MigrationSpec(MIGRATION_HEADER_TYPE_SRC, 1, "image_name",
- "image_id", {{1, 2}}, 123, true, true,
- MIGRATION_STATE_PREPARED, "description"));
+ o.push_back(new MigrationSpec(MIGRATION_HEADER_TYPE_SRC, 1, "ns",
+ "image_name", "image_id", {{1, 2}}, 123, true,
+ true, MIGRATION_STATE_PREPARED, "description"));
}
std::ostream& operator<<(std::ostream& os,
@@ -872,6 +875,7 @@ std::ostream& operator<<(std::ostream& os,
os << "["
<< "header_type=" << migration_spec.header_type << ", "
<< "pool_id=" << migration_spec.pool_id << ", "
+ << "pool_namespace=" << migration_spec.pool_namespace << ", "
<< "image_name=" << migration_spec.image_name << ", "
<< "image_id=" << migration_spec.image_id << ", "
<< "snap_seqs=" << migration_spec.snap_seqs << ", "
diff --git a/src/cls/rbd/cls_rbd_types.h b/src/cls/rbd/cls_rbd_types.h
index ac914081ed9..18a9eeff01d 100644
--- a/src/cls/rbd/cls_rbd_types.h
+++ b/src/cls/rbd/cls_rbd_types.h
@@ -716,6 +716,7 @@ std::ostream& operator<<(std::ostream& os,
struct MigrationSpec {
MigrationHeaderType header_type = MIGRATION_HEADER_TYPE_SRC;
int64_t pool_id = -1;
+ std::string pool_namespace;
std::string image_name;
std::string image_id;
std::map<uint64_t, uint64_t> snap_seqs;
@@ -728,11 +729,13 @@ struct MigrationSpec {
MigrationSpec() {
}
MigrationSpec(MigrationHeaderType header_type, int64_t pool_id,
+ const std::string& pool_namespace,
const std::string &image_name, const std::string &image_id,
const std::map<uint64_t, uint64_t> &snap_seqs, uint64_t overlap,
bool mirroring, bool flatten, MigrationState state,
const std::string &state_description)
- : header_type(header_type), pool_id(pool_id), image_name(image_name),
+ : header_type(header_type), pool_id(pool_id),
+ pool_namespace(pool_namespace), image_name(image_name),
image_id(image_id), snap_seqs(snap_seqs), overlap(overlap),
flatten(flatten), mirroring(mirroring), state(state),
state_description(state_description) {
@@ -746,9 +749,10 @@ struct MigrationSpec {
inline bool operator==(const MigrationSpec& ms) const {
return header_type == ms.header_type && pool_id == ms.pool_id &&
- image_name == ms.image_name && image_id == ms.image_id &&
- snap_seqs == ms.snap_seqs && overlap == ms.overlap &&
- flatten == ms.flatten && mirroring == ms.mirroring && state == ms.state &&
+ pool_namespace == ms.pool_namespace && image_name == ms.image_name &&
+ image_id == ms.image_id && snap_seqs == ms.snap_seqs &&
+ overlap == ms.overlap && flatten == ms.flatten &&
+ mirroring == ms.mirroring && state == ms.state &&
state_description == ms.state_description;
}
};
diff --git a/src/cls/rgw/cls_rgw.cc b/src/cls/rgw/cls_rgw.cc
index 8f6207d3a66..7aec0edd139 100644
--- a/src/cls/rgw/cls_rgw.cc
+++ b/src/cls/rgw/cls_rgw.cc
@@ -3764,7 +3764,7 @@ static int rgw_set_bucket_resharding(cls_method_context_t hctx, bufferlist *in,
static int rgw_clear_bucket_resharding(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
- cls_rgw_set_bucket_resharding_op op;
+ cls_rgw_clear_bucket_resharding_op op;
auto in_iter = in->cbegin();
try {
diff --git a/src/cls/rgw/cls_rgw_client.cc b/src/cls/rgw/cls_rgw_client.cc
index f2bb2b9c712..3f264635453 100644
--- a/src/cls/rgw/cls_rgw_client.cc
+++ b/src/cls/rgw/cls_rgw_client.cc
@@ -960,4 +960,3 @@ int CLSRGWIssueSetBucketResharding::issue_op(int shard_id, const string& oid)
{
return issue_set_bucket_resharding(io_ctx, oid, entry, &manager);
}
-
diff --git a/src/cls/rgw/cls_rgw_client.h b/src/cls/rgw/cls_rgw_client.h
index 86fc3a4f1f8..1f3c1687f0a 100644
--- a/src/cls/rgw/cls_rgw_client.h
+++ b/src/cls/rgw/cls_rgw_client.h
@@ -537,7 +537,7 @@ int cls_rgw_reshard_get(librados::IoCtx& io_ctx, const string& oid, cls_rgw_resh
int cls_rgw_reshard_get_head(librados::IoCtx& io_ctx, const string& oid, cls_rgw_reshard_entry& entry);
void cls_rgw_reshard_remove(librados::ObjectWriteOperation& op, const cls_rgw_reshard_entry& entry);
-/* resharding attribute */
+/* resharding attribute on bucket index shard headers */
int cls_rgw_set_bucket_resharding(librados::IoCtx& io_ctx, const string& oid,
const cls_rgw_bucket_instance_entry& entry);
int cls_rgw_clear_bucket_resharding(librados::IoCtx& io_ctx, const string& oid);
diff --git a/src/cls/rgw/cls_rgw_types.h b/src/cls/rgw/cls_rgw_types.h
index 4dd823e3776..14316235c8f 100644
--- a/src/cls/rgw/cls_rgw_types.h
+++ b/src/cls/rgw/cls_rgw_types.h
@@ -1,3 +1,6 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
#ifndef CEPH_CLS_RGW_TYPES_H
#define CEPH_CLS_RGW_TYPES_H
diff --git a/src/include/cephfs/libcephfs.h b/src/include/cephfs/libcephfs.h
index 31e31950973..dbb84a1e2d2 100644
--- a/src/include/cephfs/libcephfs.h
+++ b/src/include/cephfs/libcephfs.h
@@ -279,6 +279,15 @@ int ceph_select_filesystem(struct ceph_mount_info *cmount, const char *fs_name);
int ceph_mount(struct ceph_mount_info *cmount, const char *root);
/**
+ * Return cluster ID for a mounted ceph filesystem
+ *
+ * Every ceph filesystem has a filesystem ID associated with it. This
+ * function returns that value. If the ceph_mount_info does not refer to a
+ * mounted filesystem, this returns a negative error code.
+ */
+int64_t ceph_get_fs_cid(struct ceph_mount_info *cmount);
+
+/**
* Execute a management command remotely on an MDS.
*
* Must have called ceph_init or ceph_mount before calling this.
diff --git a/src/include/rados/librados.h b/src/include/rados/librados.h
index 86334802615..ee2a0dbcdfe 100644
--- a/src/include/rados/librados.h
+++ b/src/include/rados/librados.h
@@ -39,9 +39,9 @@ extern "C" {
#define CEPH_OSD_TMAP_RM 'r'
#endif
-#define LIBRADOS_VER_MAJOR 0
-#define LIBRADOS_VER_MINOR 69
-#define LIBRADOS_VER_EXTRA 1
+#define LIBRADOS_VER_MAJOR 3
+#define LIBRADOS_VER_MINOR 0
+#define LIBRADOS_VER_EXTRA 0
#define LIBRADOS_VERSION(maj, min, extra) ((maj << 16) + (min << 8) + extra)
diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h
index 4c381614533..74101216106 100644
--- a/src/include/rbd/librbd.h
+++ b/src/include/rbd/librbd.h
@@ -241,9 +241,11 @@ typedef enum {
typedef struct {
int64_t source_pool_id;
+ char *source_pool_namespace;
char *source_image_name;
char *source_image_id;
int64_t dest_pool_id;
+ char *dest_pool_namespace;
char *dest_image_name;
char *dest_image_id;
rbd_image_migration_state_t state;
diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp
index 1447484a7e7..380fc4d4ece 100644
--- a/src/include/rbd/librbd.hpp
+++ b/src/include/rbd/librbd.hpp
@@ -132,9 +132,11 @@ namespace librbd {
typedef struct {
int64_t source_pool_id;
+ std::string source_pool_namespace;
std::string source_image_name;
std::string source_image_id;
int64_t dest_pool_id;
+ std::string dest_pool_namespace;
std::string dest_image_name;
std::string dest_image_id;
image_migration_state_t state;
diff --git a/src/libcephfs.cc b/src/libcephfs.cc
index 0d8ad43f9f5..38f9fc7ddd5 100644
--- a/src/libcephfs.cc
+++ b/src/libcephfs.cc
@@ -538,6 +538,13 @@ extern "C" struct UserPerm *ceph_mount_perms(struct ceph_mount_info *cmount)
return &cmount->default_perms;
}
+extern "C" int64_t ceph_get_fs_cid(struct ceph_mount_info *cmount)
+{
+ if (!cmount->is_mounted())
+ return -ENOTCONN;
+ return cmount->get_client()->get_fs_cid();
+}
+
extern "C" int ceph_mount_perms_set(struct ceph_mount_info *cmount,
struct UserPerm *perms)
{
diff --git a/src/librados/AioCompletionImpl.h b/src/librados/AioCompletionImpl.h
index e7b895358f6..98fa4e0c883 100644
--- a/src/librados/AioCompletionImpl.h
+++ b/src/librados/AioCompletionImpl.h
@@ -19,8 +19,6 @@
#include "common/Mutex.h"
#include "include/buffer.h"
-#include "include/rados/librados.h"
-#include "include/rados/librados.hpp"
#include "include/xlist.h"
#include "osd/osd_types.h"
diff --git a/src/librados/CMakeLists.txt b/src/librados/CMakeLists.txt
index 34d6af6a919..4985e824baa 100644
--- a/src/librados/CMakeLists.txt
+++ b/src/librados/CMakeLists.txt
@@ -1,38 +1,71 @@
-add_library(librados_objs OBJECT
+add_library(librados_impl STATIC
IoCtxImpl.cc
RadosXattrIter.cc
- RadosClient.cc)
-add_library(librados_api_obj OBJECT
- librados.cc)
+ RadosClient.cc
+ librados_util.cc
+ librados_tp.cc
+ $<TARGET_OBJECTS:common_buffer_obj>)
+
+add_library(rados_c_api OBJECT
+ librados_c.cc)
+add_library(rados_cxx_api OBJECT
+ librados_cxx.cc)
+add_library(rados_cxx STATIC
+ $<TARGET_OBJECTS:rados_cxx_api>)
if(WITH_LTTNG)
- add_dependencies(librados_api_obj librados-tp)
+ add_dependencies(librados_impl librados-tp)
+ add_dependencies(rados_c_api librados-tp)
+ add_dependencies(rados_cxx_api librados-tp)
endif()
+
+# C API
+add_library(librados ${CEPH_SHARED}
+ $<TARGET_OBJECTS:rados_c_api>)
if(ENABLE_SHARED)
- add_library(librados ${CEPH_SHARED}
- $<TARGET_OBJECTS:librados_api_obj>
- $<TARGET_OBJECTS:librados_objs>
- $<TARGET_OBJECTS:common_buffer_obj>)
set_target_properties(librados PROPERTIES
OUTPUT_NAME rados
- VERSION 2.0.0
- SOVERSION 2
+ VERSION 3.0.0
+ SOVERSION 3
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON)
if(NOT APPLE)
set_property(TARGET librados APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,--exclude-libs,ALL")
endif()
-else(ENABLE_SHARED)
- add_library(librados STATIC
- $<TARGET_OBJECTS:librados_api_obj>
- $<TARGET_OBJECTS:librados_objs>)
-endif(ENABLE_SHARED)
+ if(WITH_STATIC_LIBSTDCXX)
+ set_property(TARGET librados APPEND_STRING PROPERTY
+ LINK_FLAGS " -static-libstdc++ -static-libgcc")
+ endif()
+endif()
+
target_link_libraries(librados PRIVATE
+ rados_cxx librados_impl
osdc ceph-common cls_lock_client
${BLKID_LIBRARIES} ${CRYPTO_LIBS} ${EXTRALIBS})
-target_link_libraries(librados ${rados_libs})
install(TARGETS librados DESTINATION ${CMAKE_INSTALL_LIBDIR})
+# C++ API
+add_library(librados-cxx ${CEPH_SHARED}
+ $<TARGET_OBJECTS:rados_cxx_api>)
+if(ENABLE_SHARED)
+ set_target_properties(librados-cxx PROPERTIES
+ OUTPUT_NAME radospp
+ VERSION 1.0.0
+ SOVERSION 1
+ CXX_VISIBILITY_PRESET hidden
+ VISIBILITY_INLINES_HIDDEN ON)
+ if(NOT APPLE)
+ set_property(TARGET librados-cxx APPEND_STRING PROPERTY
+ LINK_FLAGS " -Wl,--exclude-libs,ALL")
+ endif()
+endif(ENABLE_SHARED)
+target_link_libraries(librados-cxx
+ PUBLIC
+ librados
+ PRIVATE
+ librados_impl cls_lock_client ceph-common)
+install(TARGETS librados-cxx DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
if(WITH_LTTNG AND WITH_EVENTTRACE)
add_dependencies(librados_api_obj eventtrace_tp)
endif()
diff --git a/src/librados/RadosClient.cc b/src/librados/RadosClient.cc
index ec7010e487e..4adc3755cf0 100644
--- a/src/librados/RadosClient.cc
+++ b/src/librados/RadosClient.cc
@@ -25,7 +25,9 @@
#include "common/ceph_context.h"
#include "common/config.h"
#include "common/common_init.h"
+#include "common/ceph_json.h"
#include "common/errno.h"
+#include "common/ceph_json.h"
#include "include/buffer.h"
#include "include/stringify.h"
#include "include/util.h"
@@ -1118,3 +1120,51 @@ mon_feature_t librados::RadosClient::get_required_monitor_features() const
return monclient.with_monmap([](const MonMap &monmap) {
return monmap.get_required_features(); } );
}
+
+int librados::RadosClient::get_inconsistent_pgs(int64_t pool_id,
+ std::vector<std::string>* pgs)
+{
+ vector<string> cmd = {
+ "{\"prefix\": \"pg ls\","
+ "\"pool\": " + std::to_string(pool_id) + ","
+ "\"states\": [\"inconsistent\"],"
+ "\"format\": \"json\"}"
+ };
+ bufferlist inbl, outbl;
+ string outstring;
+ if (auto ret = mgr_command(cmd, inbl, &outbl, &outstring); ret) {
+ return ret;
+ }
+ if (!outbl.length()) {
+ // no pg returned
+ return 0;
+ }
+ JSONParser parser;
+ if (!parser.parse(outbl.c_str(), outbl.length())) {
+ return -EINVAL;
+ }
+ vector<string> v;
+ if (!parser.is_array()) {
+ JSONObj *pgstat_obj = parser.find_obj("pg_stats");
+ if (!pgstat_obj)
+ return 0;
+ auto s = pgstat_obj->get_data();
+ JSONParser pg_stats;
+ if (!pg_stats.parse(s.c_str(), s.length())) {
+ return -EINVAL;
+ }
+ v = pg_stats.get_array_elements();
+ } else {
+ v = parser.get_array_elements();
+ }
+ for (auto i : v) {
+ JSONParser pg_json;
+ if (!pg_json.parse(i.c_str(), i.length())) {
+ return -EINVAL;
+ }
+ string pgid;
+ JSONDecoder::decode_json("pgid", pgid, &pg_json);
+ pgs->emplace_back(std::move(pgid));
+ }
+ return 0;
+}
diff --git a/src/librados/RadosClient.h b/src/librados/RadosClient.h
index 1a3fe8c29d5..cc0cc002934 100644
--- a/src/librados/RadosClient.h
+++ b/src/librados/RadosClient.h
@@ -172,6 +172,8 @@ public:
std::map<std::string,std::string>&& status);
mon_feature_t get_required_monitor_features() const;
+
+ int get_inconsistent_pgs(int64_t pool_id, std::vector<std::string>* pgs);
};
#endif
diff --git a/src/librados/librados.cc b/src/librados/librados_c.cc
index 32627385b52..d6f0c225b29 100644
--- a/src/librados/librados.cc
+++ b/src/librados/librados_c.cc
@@ -1,16 +1,5 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2012 Sage Weil <sage@newdream.net>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- *
- */
#include <limits.h>
@@ -22,7 +11,6 @@
#include "common/TracepointProvider.h"
#include "common/hobject.h"
#include "include/rados/librados.h"
-#include "include/rados/librados.hpp"
#include "include/types.h"
#include <include/stringify.h>
@@ -32,6 +20,7 @@
#include "librados/RadosClient.h"
#include "librados/RadosXattrIter.h"
#include "librados/ListObjectImpl.h"
+#include "librados/librados_util.h"
#include <cls/lock/cls_lock_client.h>
#include <string>
@@ -64,24 +53,7 @@ using std::runtime_error;
#define RADOS_LIST_MAX_ENTRIES 1024
-namespace {
-
-TracepointProvider::Traits tracepoint_traits("librados_tp.so", "rados_tracing");
-
-uint8_t get_checksum_op_type(rados_checksum_type_t type) {
- switch (type) {
- case LIBRADOS_CHECKSUM_TYPE_XXHASH32:
- return CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH32;
- case LIBRADOS_CHECKSUM_TYPE_XXHASH64:
- return CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH64;
- case LIBRADOS_CHECKSUM_TYPE_CRC32C:
- return CEPH_OSD_CHECKSUM_OP_TYPE_CRC32C;
- default:
- return -1;
- }
-}
-
-} // anonymous namespace
+static TracepointProvider::Traits tracepoint_traits("librados_tp.so", "rados_tracing");
/*
* Structure of this file
@@ -103,2759 +75,6 @@ uint8_t get_checksum_op_type(rados_checksum_type_t type) {
* +--------------------------------------+
*/
-namespace librados {
-
-struct ObjectOperationImpl {
- ::ObjectOperation o;
- real_time rt;
- real_time *prt;
-
- ObjectOperationImpl() : prt(NULL) {}
-};
-
-}
-
-size_t librados::ObjectOperation::size()
-{
- ::ObjectOperation *o = &impl->o;
- return o->size();
-}
-
-static void set_op_flags(::ObjectOperation *o, int flags)
-{
- int rados_flags = 0;
- if (flags & LIBRADOS_OP_FLAG_EXCL)
- rados_flags |= CEPH_OSD_OP_FLAG_EXCL;
- if (flags & LIBRADOS_OP_FLAG_FAILOK)
- rados_flags |= CEPH_OSD_OP_FLAG_FAILOK;
- if (flags & LIBRADOS_OP_FLAG_FADVISE_RANDOM)
- rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_RANDOM;
- if (flags & LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL)
- rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL;
- if (flags & LIBRADOS_OP_FLAG_FADVISE_WILLNEED)
- rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_WILLNEED;
- if (flags & LIBRADOS_OP_FLAG_FADVISE_DONTNEED)
- rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_DONTNEED;
- if (flags & LIBRADOS_OP_FLAG_FADVISE_NOCACHE)
- rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_NOCACHE;
- o->set_last_op_flags(rados_flags);
-}
-
-//deprcated
-void librados::ObjectOperation::set_op_flags(ObjectOperationFlags flags)
-{
- ::set_op_flags(&impl->o, (int)flags);
-}
-
-void librados::ObjectOperation::set_op_flags2(int flags)
-{
- ::ObjectOperation *o = &impl->o;
- ::set_op_flags(o, flags);
-}
-
-void librados::ObjectOperation::cmpext(uint64_t off,
- bufferlist &cmp_bl,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->cmpext(off, cmp_bl, prval);
-}
-
-void librados::ObjectOperation::cmpxattr(const char *name, uint8_t op, const bufferlist& v)
-{
- ::ObjectOperation *o = &impl->o;
- o->cmpxattr(name, op, CEPH_OSD_CMPXATTR_MODE_STRING, v);
-}
-
-void librados::ObjectOperation::cmpxattr(const char *name, uint8_t op, uint64_t v)
-{
- ::ObjectOperation *o = &impl->o;
- bufferlist bl;
- encode(v, bl);
- o->cmpxattr(name, op, CEPH_OSD_CMPXATTR_MODE_U64, bl);
-}
-
-void librados::ObjectOperation::assert_version(uint64_t ver)
-{
- ::ObjectOperation *o = &impl->o;
- o->assert_version(ver);
-}
-
-void librados::ObjectOperation::assert_exists()
-{
- ::ObjectOperation *o = &impl->o;
- o->stat(NULL, (ceph::real_time*) NULL, NULL);
-}
-
-void librados::ObjectOperation::exec(const char *cls, const char *method, bufferlist& inbl)
-{
- ::ObjectOperation *o = &impl->o;
- o->call(cls, method, inbl);
-}
-
-void librados::ObjectOperation::exec(const char *cls, const char *method, bufferlist& inbl, bufferlist *outbl, int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->call(cls, method, inbl, outbl, NULL, prval);
-}
-
-class ObjectOpCompletionCtx : public Context {
- librados::ObjectOperationCompletion *completion;
- bufferlist bl;
-public:
- explicit ObjectOpCompletionCtx(librados::ObjectOperationCompletion *c) : completion(c) {}
- void finish(int r) override {
- completion->handle_completion(r, bl);
- delete completion;
- }
-
- bufferlist *outbl() {
- return &bl;
- }
-};
-
-void librados::ObjectOperation::exec(const char *cls, const char *method, bufferlist& inbl, librados::ObjectOperationCompletion *completion)
-{
- ::ObjectOperation *o = &impl->o;
-
- ObjectOpCompletionCtx *ctx = new ObjectOpCompletionCtx(completion);
-
- o->call(cls, method, inbl, ctx->outbl(), ctx, NULL);
-}
-
-void librados::ObjectReadOperation::stat(uint64_t *psize, time_t *pmtime, int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->stat(psize, pmtime, prval);
-}
-
-void librados::ObjectReadOperation::stat2(uint64_t *psize, struct timespec *pts, int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->stat(psize, pts, prval);
-}
-
-void librados::ObjectReadOperation::read(size_t off, uint64_t len, bufferlist *pbl, int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->read(off, len, pbl, prval, NULL);
-}
-
-void librados::ObjectReadOperation::sparse_read(uint64_t off, uint64_t len,
- std::map<uint64_t,uint64_t> *m,
- bufferlist *data_bl, int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->sparse_read(off, len, m, data_bl, prval);
-}
-
-void librados::ObjectReadOperation::checksum(rados_checksum_type_t type,
- const bufferlist &init_value_bl,
- uint64_t off, size_t len,
- size_t chunk_size, bufferlist *pbl,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->checksum(get_checksum_op_type(type), init_value_bl, off, len, chunk_size,
- pbl, prval, nullptr);
-}
-
-void librados::ObjectReadOperation::tmap_get(bufferlist *pbl, int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->tmap_get(pbl, prval);
-}
-
-void librados::ObjectReadOperation::getxattr(const char *name, bufferlist *pbl, int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->getxattr(name, pbl, prval);
-}
-
-void librados::ObjectReadOperation::omap_get_vals(
- const std::string &start_after,
- const std::string &filter_prefix,
- uint64_t max_return,
- std::map<std::string, bufferlist> *out_vals,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_get_vals(start_after, filter_prefix, max_return, out_vals, nullptr,
- prval);
-}
-
-void librados::ObjectReadOperation::omap_get_vals2(
- const std::string &start_after,
- const std::string &filter_prefix,
- uint64_t max_return,
- std::map<std::string, bufferlist> *out_vals,
- bool *pmore,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_get_vals(start_after, filter_prefix, max_return, out_vals, pmore,
- prval);
-}
-
-void librados::ObjectReadOperation::omap_get_vals(
- const std::string &start_after,
- uint64_t max_return,
- std::map<std::string, bufferlist> *out_vals,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_get_vals(start_after, "", max_return, out_vals, nullptr, prval);
-}
-
-void librados::ObjectReadOperation::omap_get_vals2(
- const std::string &start_after,
- uint64_t max_return,
- std::map<std::string, bufferlist> *out_vals,
- bool *pmore,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_get_vals(start_after, "", max_return, out_vals, pmore, prval);
-}
-
-void librados::ObjectReadOperation::omap_get_keys(
- const std::string &start_after,
- uint64_t max_return,
- std::set<std::string> *out_keys,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_get_keys(start_after, max_return, out_keys, nullptr, prval);
-}
-
-void librados::ObjectReadOperation::omap_get_keys2(
- const std::string &start_after,
- uint64_t max_return,
- std::set<std::string> *out_keys,
- bool *pmore,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_get_keys(start_after, max_return, out_keys, pmore, prval);
-}
-
-void librados::ObjectReadOperation::omap_get_header(bufferlist *bl, int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_get_header(bl, prval);
-}
-
-void librados::ObjectReadOperation::omap_get_vals_by_keys(
- const std::set<std::string> &keys,
- std::map<std::string, bufferlist> *map,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_get_vals_by_keys(keys, map, prval);
-}
-
-void librados::ObjectOperation::omap_cmp(
- const std::map<std::string, pair<bufferlist, int> > &assertions,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_cmp(assertions, prval);
-}
-
-void librados::ObjectReadOperation::list_watchers(
- list<obj_watch_t> *out_watchers,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->list_watchers(out_watchers, prval);
-}
-
-void librados::ObjectReadOperation::list_snaps(
- snap_set_t *out_snaps,
- int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->list_snaps(out_snaps, prval);
-}
-
-void librados::ObjectReadOperation::is_dirty(bool *is_dirty, int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->is_dirty(is_dirty, prval);
-}
-
-int librados::IoCtx::omap_get_vals(const std::string& oid,
- const std::string& orig_start_after,
- const std::string& filter_prefix,
- uint64_t max_return,
- std::map<std::string, bufferlist> *out_vals)
-{
- bool first = true;
- string start_after = orig_start_after;
- bool more = true;
- while (max_return > 0 && more) {
- std::map<std::string,bufferlist> out;
- ObjectReadOperation op;
- op.omap_get_vals2(start_after, filter_prefix, max_return, &out, &more,
- nullptr);
- bufferlist bl;
- int ret = operate(oid, &op, &bl);
- if (ret < 0) {
- return ret;
- }
- if (more) {
- if (out.empty()) {
- return -EINVAL; // wth
- }
- start_after = out.rbegin()->first;
- }
- if (out.size() <= max_return) {
- max_return -= out.size();
- } else {
- max_return = 0;
- }
- if (first) {
- out_vals->swap(out);
- first = false;
- } else {
- out_vals->insert(out.begin(), out.end());
- out.clear();
- }
- }
- return 0;
-}
-
-int librados::IoCtx::omap_get_vals2(
- const std::string& oid,
- const std::string& start_after,
- const std::string& filter_prefix,
- uint64_t max_return,
- std::map<std::string, bufferlist> *out_vals,
- bool *pmore)
-{
- ObjectReadOperation op;
- int r;
- op.omap_get_vals2(start_after, filter_prefix, max_return, out_vals, pmore, &r);
- bufferlist bl;
- int ret = operate(oid, &op, &bl);
- if (ret < 0)
- return ret;
- return r;
-}
-
-void librados::ObjectReadOperation::getxattrs(map<string, bufferlist> *pattrs, int *prval)
-{
- ::ObjectOperation *o = &impl->o;
- o->getxattrs(pattrs, prval);
-}
-
-void librados::ObjectWriteOperation::mtime(time_t *pt)
-{
- if (pt) {
- impl->rt = ceph::real_clock::from_time_t(*pt);
- impl->prt = &impl->rt;
- }
-}
-
-void librados::ObjectWriteOperation::mtime2(struct timespec *pts)
-{
- if (pts) {
- impl->rt = ceph::real_clock::from_timespec(*pts);
- impl->prt = &impl->rt;
- }
-}
-
-void librados::ObjectWriteOperation::create(bool exclusive)
-{
- ::ObjectOperation *o = &impl->o;
- o->create(exclusive);
-}
-
-void librados::ObjectWriteOperation::create(bool exclusive,
- const std::string& category) // unused
-{
- ::ObjectOperation *o = &impl->o;
- o->create(exclusive);
-}
-
-void librados::ObjectWriteOperation::write(uint64_t off, const bufferlist& bl)
-{
- ::ObjectOperation *o = &impl->o;
- bufferlist c = bl;
- o->write(off, c);
-}
-
-void librados::ObjectWriteOperation::write_full(const bufferlist& bl)
-{
- ::ObjectOperation *o = &impl->o;
- bufferlist c = bl;
- o->write_full(c);
-}
-
-void librados::ObjectWriteOperation::writesame(uint64_t off, uint64_t write_len,
- const bufferlist& bl)
-{
- ::ObjectOperation *o = &impl->o;
- bufferlist c = bl;
- o->writesame(off, write_len, c);
-}
-
-void librados::ObjectWriteOperation::append(const bufferlist& bl)
-{
- ::ObjectOperation *o = &impl->o;
- bufferlist c = bl;
- o->append(c);
-}
-
-void librados::ObjectWriteOperation::remove()
-{
- ::ObjectOperation *o = &impl->o;
- o->remove();
-}
-
-void librados::ObjectWriteOperation::truncate(uint64_t off)
-{
- ::ObjectOperation *o = &impl->o;
- o->truncate(off);
-}
-
-void librados::ObjectWriteOperation::zero(uint64_t off, uint64_t len)
-{
- ::ObjectOperation *o = &impl->o;
- o->zero(off, len);
-}
-
-void librados::ObjectWriteOperation::rmxattr(const char *name)
-{
- ::ObjectOperation *o = &impl->o;
- o->rmxattr(name);
-}
-
-void librados::ObjectWriteOperation::setxattr(const char *name, const bufferlist& v)
-{
- ::ObjectOperation *o = &impl->o;
- o->setxattr(name, v);
-}
-
-void librados::ObjectWriteOperation::omap_set(
- const map<string, bufferlist> &map)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_set(map);
-}
-
-void librados::ObjectWriteOperation::omap_set_header(const bufferlist &bl)
-{
- bufferlist c = bl;
- ::ObjectOperation *o = &impl->o;
- o->omap_set_header(c);
-}
-
-void librados::ObjectWriteOperation::omap_clear()
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_clear();
-}
-
-void librados::ObjectWriteOperation::omap_rm_keys(
- const std::set<std::string> &to_rm)
-{
- ::ObjectOperation *o = &impl->o;
- o->omap_rm_keys(to_rm);
-}
-
-void librados::ObjectWriteOperation::copy_from(const std::string& src,
- const IoCtx& src_ioctx,
- uint64_t src_version)
-{
- copy_from2(src, src_ioctx, src_version, 0);
-}
-
-void librados::ObjectWriteOperation::copy_from2(const std::string& src,
- const IoCtx& src_ioctx,
- uint64_t src_version,
- uint32_t src_fadvise_flags)
-{
- ::ObjectOperation *o = &impl->o;
- o->copy_from(object_t(src), src_ioctx.io_ctx_impl->snap_seq,
- src_ioctx.io_ctx_impl->oloc, src_version, 0, src_fadvise_flags);
-}
-
-void librados::ObjectWriteOperation::undirty()
-{
- ::ObjectOperation *o = &impl->o;
- o->undirty();
-}
-
-void librados::ObjectReadOperation::cache_flush()
-{
- ::ObjectOperation *o = &impl->o;
- o->cache_flush();
-}
-
-void librados::ObjectReadOperation::cache_try_flush()
-{
- ::ObjectOperation *o = &impl->o;
- o->cache_try_flush();
-}
-
-void librados::ObjectReadOperation::cache_evict()
-{
- ::ObjectOperation *o = &impl->o;
- o->cache_evict();
-}
-
-void librados::ObjectWriteOperation::set_redirect(const std::string& tgt_obj,
- const IoCtx& tgt_ioctx,
- uint64_t tgt_version,
- int flag)
-{
- ::ObjectOperation *o = &impl->o;
- o->set_redirect(object_t(tgt_obj), tgt_ioctx.io_ctx_impl->snap_seq,
- tgt_ioctx.io_ctx_impl->oloc, tgt_version, flag);
-}
-
-void librados::ObjectWriteOperation::set_chunk(uint64_t src_offset,
- uint64_t src_length,
- const IoCtx& tgt_ioctx,
- string tgt_oid,
- uint64_t tgt_offset,
- int flag)
-{
- ::ObjectOperation *o = &impl->o;
- o->set_chunk(src_offset, src_length,
- tgt_ioctx.io_ctx_impl->oloc, object_t(tgt_oid), tgt_offset, flag);
-}
-
-void librados::ObjectWriteOperation::tier_promote()
-{
- ::ObjectOperation *o = &impl->o;
- o->tier_promote();
-}
-
-void librados::ObjectWriteOperation::unset_manifest()
-{
- ::ObjectOperation *o = &impl->o;
- o->unset_manifest();
-}
-
-void librados::ObjectWriteOperation::tmap_put(const bufferlist &bl)
-{
- ::ObjectOperation *o = &impl->o;
- bufferlist c = bl;
- o->tmap_put(c);
-}
-
-void librados::ObjectWriteOperation::tmap_update(const bufferlist& cmdbl)
-{
- ::ObjectOperation *o = &impl->o;
- bufferlist c = cmdbl;
- o->tmap_update(c);
-}
-
-void librados::ObjectWriteOperation::selfmanaged_snap_rollback(snap_t snapid)
-{
- ::ObjectOperation *o = &impl->o;
- o->rollback(snapid);
-}
-
-// You must specify the snapid not the name normally used with pool snapshots
-void librados::ObjectWriteOperation::snap_rollback(snap_t snapid)
-{
- ::ObjectOperation *o = &impl->o;
- o->rollback(snapid);
-}
-
-void librados::ObjectWriteOperation::set_alloc_hint(
- uint64_t expected_object_size,
- uint64_t expected_write_size)
-{
- ::ObjectOperation *o = &impl->o;
- o->set_alloc_hint(expected_object_size, expected_write_size, 0);
-}
-void librados::ObjectWriteOperation::set_alloc_hint2(
- uint64_t expected_object_size,
- uint64_t expected_write_size,
- uint32_t flags)
-{
- ::ObjectOperation *o = &impl->o;
- o->set_alloc_hint(expected_object_size, expected_write_size, flags);
-}
-
-void librados::ObjectWriteOperation::cache_pin()
-{
- ::ObjectOperation *o = &impl->o;
- o->cache_pin();
-}
-
-void librados::ObjectWriteOperation::cache_unpin()
-{
- ::ObjectOperation *o = &impl->o;
- o->cache_unpin();
-}
-
-librados::WatchCtx::
-~WatchCtx()
-{
-}
-
-librados::WatchCtx2::
-~WatchCtx2()
-{
-}
-
-
-struct librados::ObjListCtx {
- librados::IoCtxImpl dupctx;
- librados::IoCtxImpl *ctx;
- Objecter::NListContext *nlc;
- bool legacy_list_api;
-
- ObjListCtx(IoCtxImpl *c, Objecter::NListContext *nl, bool legacy=false)
- : nlc(nl),
- legacy_list_api(legacy) {
- // Get our own private IoCtxImpl so that namespace setting isn't
- // changed by caller between uses.
- ctx = &dupctx;
- dupctx.dup(*c);
- }
- ~ObjListCtx() {
- ctx = NULL;
- delete nlc;
- }
-};
-
-///////////////////////////// NObjectIteratorImpl /////////////////////////////
-librados::NObjectIteratorImpl::NObjectIteratorImpl(ObjListCtx *ctx_)
- : ctx(ctx_)
-{
-}
-
-librados::NObjectIteratorImpl::~NObjectIteratorImpl()
-{
- ctx.reset();
-}
-
-librados::NObjectIteratorImpl::NObjectIteratorImpl(const NObjectIteratorImpl &rhs)
-{
- *this = rhs;
-}
-
-librados::NObjectIteratorImpl& librados::NObjectIteratorImpl::operator=(const librados::NObjectIteratorImpl &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));
- cur_obj = rhs.cur_obj;
- return *this;
-}
-
-bool librados::NObjectIteratorImpl::operator==(const librados::NObjectIteratorImpl& rhs) const {
-
- if (ctx.get() == NULL) {
- if (rhs.ctx.get() == NULL)
- return true;
- return rhs.ctx->nlc->at_end();
- }
- if (rhs.ctx.get() == NULL) {
- // Redundant but same as ObjectIterator version
- if (ctx.get() == NULL)
- return true;
- return ctx->nlc->at_end();
- }
- return ctx.get() == rhs.ctx.get();
-}
-
-bool librados::NObjectIteratorImpl::operator!=(const librados::NObjectIteratorImpl& rhs) const {
- return !(*this == rhs);
-}
-
-const librados::ListObject& librados::NObjectIteratorImpl::operator*() const {
- return cur_obj;
-}
-
-const librados::ListObject* librados::NObjectIteratorImpl::operator->() const {
- return &cur_obj;
-}
-
-librados::NObjectIteratorImpl& librados::NObjectIteratorImpl::operator++()
-{
- get_next();
- return *this;
-}
-
-librados::NObjectIteratorImpl librados::NObjectIteratorImpl::operator++(int)
-{
- librados::NObjectIteratorImpl ret(*this);
- get_next();
- return ret;
-}
-
-uint32_t librados::NObjectIteratorImpl::seek(uint32_t pos)
-{
- uint32_t r = rados_nobjects_list_seek(ctx.get(), pos);
- get_next();
- return r;
-}
-
-uint32_t librados::NObjectIteratorImpl::seek(const ObjectCursor& cursor)
-{
- uint32_t r = rados_nobjects_list_seek_cursor(ctx.get(), (rados_object_list_cursor)cursor.c_cursor);
- get_next();
- return r;
-}
-
-librados::ObjectCursor librados::NObjectIteratorImpl::get_cursor()
-{
- librados::ObjListCtx *lh = (librados::ObjListCtx *)ctx.get();
- librados::ObjectCursor oc;
- oc.set(lh->ctx->nlist_get_cursor(lh->nlc));
- return oc;
-}
-
-void librados::NObjectIteratorImpl::set_filter(const bufferlist &bl)
-{
- ceph_assert(ctx);
- ctx->nlc->filter = bl;
-}
-
-void librados::NObjectIteratorImpl::get_next()
-{
- const char *entry, *key, *nspace;
- if (ctx->nlc->at_end())
- return;
- int ret = rados_nobjects_list_next(ctx.get(), &entry, &key, &nspace);
- if (ret == -ENOENT) {
- return;
- }
- else if (ret) {
- ostringstream oss;
- oss << "rados returned " << cpp_strerror(ret);
- throw std::runtime_error(oss.str());
- }
-
- if (cur_obj.impl == NULL)
- cur_obj.impl = new ListObjectImpl();
- cur_obj.impl->nspace = nspace;
- cur_obj.impl->oid = entry;
- cur_obj.impl->locator = key ? key : string();
-}
-
-uint32_t librados::NObjectIteratorImpl::get_pg_hash_position() const
-{
- return ctx->nlc->get_pg_hash_position();
-}
-
-///////////////////////////// NObjectIterator /////////////////////////////
-librados::NObjectIterator::NObjectIterator(ObjListCtx *ctx_)
-{
- impl = new NObjectIteratorImpl(ctx_);
-}
-
-librados::NObjectIterator::~NObjectIterator()
-{
- delete impl;
-}
-
-librados::NObjectIterator::NObjectIterator(const NObjectIterator &rhs)
-{
- if (rhs.impl == NULL) {
- impl = NULL;
- return;
- }
- impl = new NObjectIteratorImpl();
- *impl = *(rhs.impl);
-}
-
-librados::NObjectIterator& librados::NObjectIterator::operator=(const librados::NObjectIterator &rhs)
-{
- if (rhs.impl == NULL) {
- delete impl;
- impl = NULL;
- return *this;
- }
- if (impl == NULL)
- impl = new NObjectIteratorImpl();
- *impl = *(rhs.impl);
- return *this;
-}
-
-bool librados::NObjectIterator::operator==(const librados::NObjectIterator& rhs) const
-{
- if (impl && rhs.impl) {
- return *impl == *(rhs.impl);
- } else {
- return impl == rhs.impl;
- }
-}
-
-bool librados::NObjectIterator::operator!=(const librados::NObjectIterator& rhs) const
-{
- return !(*this == rhs);
-}
-
-const librados::ListObject& librados::NObjectIterator::operator*() const {
- ceph_assert(impl);
- return *(impl->get_listobjectp());
-}
-
-const librados::ListObject* librados::NObjectIterator::operator->() const {
- ceph_assert(impl);
- return impl->get_listobjectp();
-}
-
-librados::NObjectIterator& librados::NObjectIterator::operator++()
-{
- ceph_assert(impl);
- impl->get_next();
- return *this;
-}
-
-librados::NObjectIterator librados::NObjectIterator::operator++(int)
-{
- librados::NObjectIterator ret(*this);
- impl->get_next();
- return ret;
-}
-
-uint32_t librados::NObjectIterator::seek(uint32_t pos)
-{
- ceph_assert(impl);
- return impl->seek(pos);
-}
-
-uint32_t librados::NObjectIterator::seek(const ObjectCursor& cursor)
-{
- ceph_assert(impl);
- return impl->seek(cursor);
-}
-
-librados::ObjectCursor librados::NObjectIterator::get_cursor()
-{
- ceph_assert(impl);
- return impl->get_cursor();
-}
-
-void librados::NObjectIterator::set_filter(const bufferlist &bl)
-{
- impl->set_filter(bl);
-}
-
-void librados::NObjectIterator::get_next()
-{
- ceph_assert(impl);
- impl->get_next();
-}
-
-uint32_t librados::NObjectIterator::get_pg_hash_position() const
-{
- ceph_assert(impl);
- return impl->get_pg_hash_position();
-}
-
-const librados::NObjectIterator librados::NObjectIterator::__EndObjectIterator(NULL);
-
-///////////////////////////// PoolAsyncCompletion //////////////////////////////
-int librados::PoolAsyncCompletion::PoolAsyncCompletion::set_callback(void *cb_arg,
- rados_callback_t cb)
-{
- PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
- return c->set_callback(cb_arg, cb);
-}
-
-int librados::PoolAsyncCompletion::PoolAsyncCompletion::wait()
-{
- PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
- return c->wait();
-}
-
-bool librados::PoolAsyncCompletion::PoolAsyncCompletion::is_complete()
-{
- PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
- return c->is_complete();
-}
-
-int librados::PoolAsyncCompletion::PoolAsyncCompletion::get_return_value()
-{
- PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
- return c->get_return_value();
-}
-
-void librados::PoolAsyncCompletion::PoolAsyncCompletion::release()
-{
- PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
- c->release();
- delete this;
-}
-
-///////////////////////////// AioCompletion //////////////////////////////
-int librados::AioCompletion::AioCompletion::set_complete_callback(void *cb_arg, rados_callback_t cb)
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->set_complete_callback(cb_arg, cb);
-}
-
-int librados::AioCompletion::AioCompletion::set_safe_callback(void *cb_arg, rados_callback_t cb)
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->set_safe_callback(cb_arg, cb);
-}
-
-int librados::AioCompletion::AioCompletion::wait_for_complete()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->wait_for_complete();
-}
-
-int librados::AioCompletion::AioCompletion::wait_for_safe()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->wait_for_safe();
-}
-
-bool librados::AioCompletion::AioCompletion::is_complete()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->is_complete();
-}
-
-bool librados::AioCompletion::AioCompletion::is_safe()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->is_safe();
-}
-
-int librados::AioCompletion::AioCompletion::wait_for_complete_and_cb()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->wait_for_complete_and_cb();
-}
-
-int librados::AioCompletion::AioCompletion::wait_for_safe_and_cb()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->wait_for_safe_and_cb();
-}
-
-bool librados::AioCompletion::AioCompletion::is_complete_and_cb()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->is_complete_and_cb();
-}
-
-bool librados::AioCompletion::AioCompletion::is_safe_and_cb()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->is_safe_and_cb();
-}
-
-int librados::AioCompletion::AioCompletion::get_return_value()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->get_return_value();
-}
-
-int librados::AioCompletion::AioCompletion::get_version()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->get_version();
-}
-
-uint64_t librados::AioCompletion::AioCompletion::get_version64()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- return c->get_version();
-}
-
-void librados::AioCompletion::AioCompletion::release()
-{
- AioCompletionImpl *c = (AioCompletionImpl *)pc;
- c->release();
- delete this;
-}
-
-///////////////////////////// IoCtx //////////////////////////////
-librados::IoCtx::IoCtx() : io_ctx_impl(NULL)
-{
-}
-
-void librados::IoCtx::from_rados_ioctx_t(rados_ioctx_t p, IoCtx &io)
-{
- IoCtxImpl *io_ctx_impl = (IoCtxImpl*)p;
-
- io.io_ctx_impl = io_ctx_impl;
- if (io_ctx_impl) {
- io_ctx_impl->get();
- }
-}
-
-librados::IoCtx::IoCtx(const IoCtx& rhs)
-{
- io_ctx_impl = rhs.io_ctx_impl;
- if (io_ctx_impl) {
- io_ctx_impl->get();
- }
-}
-
-librados::IoCtx& librados::IoCtx::operator=(const IoCtx& rhs)
-{
- if (io_ctx_impl)
- io_ctx_impl->put();
- io_ctx_impl = rhs.io_ctx_impl;
- io_ctx_impl->get();
- return *this;
-}
-
-librados::IoCtx::~IoCtx()
-{
- close();
-}
-
-void librados::IoCtx::close()
-{
- if (io_ctx_impl)
- io_ctx_impl->put();
- io_ctx_impl = 0;
-}
-
-void librados::IoCtx::dup(const IoCtx& rhs)
-{
- if (io_ctx_impl)
- io_ctx_impl->put();
- io_ctx_impl = new IoCtxImpl();
- io_ctx_impl->get();
- io_ctx_impl->dup(*rhs.io_ctx_impl);
-}
-
-int librados::IoCtx::set_auid(uint64_t auid_)
-{
- return -EOPNOTSUPP;
-}
-
-int librados::IoCtx::set_auid_async(uint64_t auid_, PoolAsyncCompletion *c)
-{
- return -EOPNOTSUPP;
-}
-
-int librados::IoCtx::get_auid(uint64_t *auid_)
-{
- return -EOPNOTSUPP;
-}
-
-bool librados::IoCtx::pool_requires_alignment()
-{
- return io_ctx_impl->client->pool_requires_alignment(get_id());
-}
-
-int librados::IoCtx::pool_requires_alignment2(bool *requires)
-{
- return io_ctx_impl->client->pool_requires_alignment2(get_id(), requires);
-}
-
-uint64_t librados::IoCtx::pool_required_alignment()
-{
- return io_ctx_impl->client->pool_required_alignment(get_id());
-}
-
-int librados::IoCtx::pool_required_alignment2(uint64_t *alignment)
-{
- return io_ctx_impl->client->pool_required_alignment2(get_id(), alignment);
-}
-
-std::string librados::IoCtx::get_pool_name()
-{
- std::string s;
- io_ctx_impl->client->pool_get_name(get_id(), &s);
- return s;
-}
-
-std::string librados::IoCtx::get_pool_name() const
-{
- return io_ctx_impl->get_cached_pool_name();
-}
-
-uint64_t librados::IoCtx::get_instance_id() const
-{
- return io_ctx_impl->client->get_instance_id();
-}
-
-int librados::IoCtx::create(const std::string& oid, bool exclusive)
-{
- object_t obj(oid);
- return io_ctx_impl->create(obj, exclusive);
-}
-
-int librados::IoCtx::create(const std::string& oid, bool exclusive,
- const std::string& category) // unused
-{
- object_t obj(oid);
- return io_ctx_impl->create(obj, exclusive);
-}
-
-int librados::IoCtx::write(const std::string& oid, bufferlist& bl, size_t len, uint64_t off)
-{
- object_t obj(oid);
- return io_ctx_impl->write(obj, bl, len, off);
-}
-
-int librados::IoCtx::append(const std::string& oid, bufferlist& bl, size_t len)
-{
- object_t obj(oid);
- return io_ctx_impl->append(obj, bl, len);
-}
-
-int librados::IoCtx::write_full(const std::string& oid, bufferlist& bl)
-{
- object_t obj(oid);
- return io_ctx_impl->write_full(obj, bl);
-}
-
-int librados::IoCtx::writesame(const std::string& oid, bufferlist& bl,
- size_t write_len, uint64_t off)
-{
- object_t obj(oid);
- return io_ctx_impl->writesame(obj, bl, write_len, off);
-}
-
-
-int librados::IoCtx::read(const std::string& oid, bufferlist& bl, size_t len, uint64_t off)
-{
- object_t obj(oid);
- return io_ctx_impl->read(obj, bl, len, off);
-}
-
-int librados::IoCtx::checksum(const std::string& oid,
- rados_checksum_type_t type,
- const bufferlist &init_value_bl, size_t len,
- uint64_t off, size_t chunk_size, bufferlist *pbl)
-{
- object_t obj(oid);
- return io_ctx_impl->checksum(obj, get_checksum_op_type(type), init_value_bl,
- len, off, chunk_size, pbl);
-}
-
-int librados::IoCtx::remove(const std::string& oid)
-{
- object_t obj(oid);
- return io_ctx_impl->remove(obj);
-}
-
-int librados::IoCtx::remove(const std::string& oid, int flags)
-{
- object_t obj(oid);
- return io_ctx_impl->remove(obj, flags);
-}
-
-int librados::IoCtx::trunc(const std::string& oid, uint64_t size)
-{
- object_t obj(oid);
- return io_ctx_impl->trunc(obj, size);
-}
-
-int librados::IoCtx::mapext(const std::string& oid, uint64_t off, size_t len,
- std::map<uint64_t,uint64_t>& m)
-{
- object_t obj(oid);
- return io_ctx_impl->mapext(obj, off, len, m);
-}
-
-int librados::IoCtx::cmpext(const std::string& oid, uint64_t off, bufferlist& cmp_bl)
-{
- object_t obj(oid);
- return io_ctx_impl->cmpext(obj, off, cmp_bl);
-}
-
-int librados::IoCtx::sparse_read(const std::string& oid, std::map<uint64_t,uint64_t>& m,
- bufferlist& bl, size_t len, uint64_t off)
-{
- object_t obj(oid);
- return io_ctx_impl->sparse_read(obj, m, bl, len, off);
-}
-
-int librados::IoCtx::getxattr(const std::string& oid, const char *name, bufferlist& bl)
-{
- object_t obj(oid);
- return io_ctx_impl->getxattr(obj, name, bl);
-}
-
-int librados::IoCtx::getxattrs(const std::string& oid, map<std::string, bufferlist>& attrset)
-{
- object_t obj(oid);
- return io_ctx_impl->getxattrs(obj, attrset);
-}
-
-int librados::IoCtx::setxattr(const std::string& oid, const char *name, bufferlist& bl)
-{
- object_t obj(oid);
- return io_ctx_impl->setxattr(obj, name, bl);
-}
-
-int librados::IoCtx::rmxattr(const std::string& oid, const char *name)
-{
- object_t obj(oid);
- return io_ctx_impl->rmxattr(obj, name);
-}
-
-int librados::IoCtx::stat(const std::string& oid, uint64_t *psize, time_t *pmtime)
-{
- object_t obj(oid);
- return io_ctx_impl->stat(obj, psize, pmtime);
-}
-
-int librados::IoCtx::stat2(const std::string& oid, uint64_t *psize, struct timespec *pts)
-{
- object_t obj(oid);
- return io_ctx_impl->stat2(obj, psize, pts);
-}
-
-int librados::IoCtx::exec(const std::string& oid, const char *cls, const char *method,
- bufferlist& inbl, bufferlist& outbl)
-{
- object_t obj(oid);
- return io_ctx_impl->exec(obj, cls, method, inbl, outbl);
-}
-
-int librados::IoCtx::tmap_update(const std::string& oid, bufferlist& cmdbl)
-{
- object_t obj(oid);
- return io_ctx_impl->tmap_update(obj, cmdbl);
-}
-
-int librados::IoCtx::tmap_put(const std::string& oid, bufferlist& bl)
-{
- object_t obj(oid);
- return io_ctx_impl->tmap_put(obj, bl);
-}
-
-int librados::IoCtx::tmap_get(const std::string& oid, bufferlist& bl)
-{
- object_t obj(oid);
- return io_ctx_impl->tmap_get(obj, bl);
-}
-
-int librados::IoCtx::tmap_to_omap(const std::string& oid, bool nullok)
-{
- object_t obj(oid);
- return io_ctx_impl->tmap_to_omap(obj, nullok);
-}
-
-int librados::IoCtx::omap_get_vals(const std::string& oid,
- const std::string& start_after,
- uint64_t max_return,
- std::map<std::string, bufferlist> *out_vals)
-{
- return omap_get_vals(oid, start_after, string(), max_return, out_vals);
-}
-
-int librados::IoCtx::omap_get_vals2(
- const std::string& oid,
- const std::string& start_after,
- uint64_t max_return,
- std::map<std::string, bufferlist> *out_vals,
- bool *pmore)
-{
- ObjectReadOperation op;
- int r;
- op.omap_get_vals2(start_after, max_return, out_vals, pmore, &r);
- bufferlist bl;
- int ret = operate(oid, &op, &bl);
- if (ret < 0)
- return ret;
- return r;
-}
-
-int librados::IoCtx::omap_get_keys(const std::string& oid,
- const std::string& orig_start_after,
- uint64_t max_return,
- std::set<std::string> *out_keys)
-{
- bool first = true;
- string start_after = orig_start_after;
- bool more = true;
- while (max_return > 0 && more) {
- std::set<std::string> out;
- ObjectReadOperation op;
- op.omap_get_keys2(start_after, max_return, &out, &more, nullptr);
- bufferlist bl;
- int ret = operate(oid, &op, &bl);
- if (ret < 0) {
- return ret;
- }
- if (more) {
- if (out.empty()) {
- return -EINVAL; // wth
- }
- start_after = *out.rbegin();
- }
- if (out.size() <= max_return) {
- max_return -= out.size();
- } else {
- max_return = 0;
- }
- if (first) {
- out_keys->swap(out);
- first = false;
- } else {
- out_keys->insert(out.begin(), out.end());
- out.clear();
- }
- }
- return 0;
-}
-
-int librados::IoCtx::omap_get_keys2(
- const std::string& oid,
- const std::string& start_after,
- uint64_t max_return,
- std::set<std::string> *out_keys,
- bool *pmore)
-{
- ObjectReadOperation op;
- int r;
- op.omap_get_keys2(start_after, max_return, out_keys, pmore, &r);
- bufferlist bl;
- int ret = operate(oid, &op, &bl);
- if (ret < 0)
- return ret;
- return r;
-}
-
-int librados::IoCtx::omap_get_header(const std::string& oid,
- bufferlist *bl)
-{
- ObjectReadOperation op;
- int r;
- op.omap_get_header(bl, &r);
- bufferlist b;
- int ret = operate(oid, &op, &b);
- if (ret < 0)
- return ret;
-
- return r;
-}
-
-int librados::IoCtx::omap_get_vals_by_keys(const std::string& oid,
- const std::set<std::string>& keys,
- std::map<std::string, bufferlist> *vals)
-{
- ObjectReadOperation op;
- int r;
- bufferlist bl;
- op.omap_get_vals_by_keys(keys, vals, &r);
- int ret = operate(oid, &op, &bl);
- if (ret < 0)
- return ret;
-
- return r;
-}
-
-int librados::IoCtx::omap_set(const std::string& oid,
- const map<string, bufferlist>& m)
-{
- ObjectWriteOperation op;
- op.omap_set(m);
- return operate(oid, &op);
-}
-
-int librados::IoCtx::omap_set_header(const std::string& oid,
- const bufferlist& bl)
-{
- ObjectWriteOperation op;
- op.omap_set_header(bl);
- return operate(oid, &op);
-}
-
-int librados::IoCtx::omap_clear(const std::string& oid)
-{
- ObjectWriteOperation op;
- op.omap_clear();
- return operate(oid, &op);
-}
-
-int librados::IoCtx::omap_rm_keys(const std::string& oid,
- const std::set<std::string>& keys)
-{
- ObjectWriteOperation op;
- op.omap_rm_keys(keys);
- return operate(oid, &op);
-}
-
-
-
-static int translate_flags(int flags)
-{
- int op_flags = 0;
- if (flags & librados::OPERATION_BALANCE_READS)
- op_flags |= CEPH_OSD_FLAG_BALANCE_READS;
- if (flags & librados::OPERATION_LOCALIZE_READS)
- op_flags |= CEPH_OSD_FLAG_LOCALIZE_READS;
- if (flags & librados::OPERATION_ORDER_READS_WRITES)
- op_flags |= CEPH_OSD_FLAG_RWORDERED;
- if (flags & librados::OPERATION_IGNORE_CACHE)
- op_flags |= CEPH_OSD_FLAG_IGNORE_CACHE;
- if (flags & librados::OPERATION_SKIPRWLOCKS)
- op_flags |= CEPH_OSD_FLAG_SKIPRWLOCKS;
- if (flags & librados::OPERATION_IGNORE_OVERLAY)
- op_flags |= CEPH_OSD_FLAG_IGNORE_OVERLAY;
- if (flags & librados::OPERATION_FULL_TRY)
- op_flags |= CEPH_OSD_FLAG_FULL_TRY;
- if (flags & librados::OPERATION_FULL_FORCE)
- op_flags |= CEPH_OSD_FLAG_FULL_FORCE;
- if (flags & librados::OPERATION_IGNORE_REDIRECT)
- op_flags |= CEPH_OSD_FLAG_IGNORE_REDIRECT;
- if (flags & librados::OPERATION_ORDERSNAP)
- op_flags |= CEPH_OSD_FLAG_ORDERSNAP;
-
- return op_flags;
-}
-
-int librados::IoCtx::operate(const std::string& oid, librados::ObjectWriteOperation *o)
-{
- object_t obj(oid);
- return io_ctx_impl->operate(obj, &o->impl->o, (ceph::real_time *)o->impl->prt);
-}
-
-int librados::IoCtx::operate(const std::string& oid, librados::ObjectReadOperation *o, bufferlist *pbl)
-{
- object_t obj(oid);
- return io_ctx_impl->operate_read(obj, &o->impl->o, pbl);
-}
-
-int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
- librados::ObjectWriteOperation *o)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
- io_ctx_impl->snapc, 0);
-}
-int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
- ObjectWriteOperation *o, int flags)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
- io_ctx_impl->snapc,
- translate_flags(flags));
-}
-
-int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
- librados::ObjectWriteOperation *o,
- snap_t snap_seq, std::vector<snap_t>& snaps)
-{
- object_t obj(oid);
- vector<snapid_t> snv;
- snv.resize(snaps.size());
- for (size_t i = 0; i < snaps.size(); ++i)
- snv[i] = snaps[i];
- SnapContext snapc(snap_seq, snv);
- return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
- snapc, 0);
-}
-
-int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
- librados::ObjectWriteOperation *o,
- snap_t snap_seq, std::vector<snap_t>& snaps,
- const blkin_trace_info *trace_info)
-{
- object_t obj(oid);
- vector<snapid_t> snv;
- snv.resize(snaps.size());
- for (size_t i = 0; i < snaps.size(); ++i)
- snv[i] = snaps[i];
- SnapContext snapc(snap_seq, snv);
- return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
- snapc, 0, trace_info);
-}
-
-int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
- librados::ObjectWriteOperation *o,
- snap_t snap_seq, std::vector<snap_t>& snaps, int flags,
- const blkin_trace_info *trace_info)
-{
- object_t obj(oid);
- vector<snapid_t> snv;
- snv.resize(snaps.size());
- for (size_t i = 0; i < snaps.size(); ++i)
- snv[i] = snaps[i];
- SnapContext snapc(snap_seq, snv);
- return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc, snapc,
- translate_flags(flags), trace_info);
-}
-
-int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
- librados::ObjectReadOperation *o,
- bufferlist *pbl)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
- 0, pbl);
-}
-
-// deprecated
-int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
- librados::ObjectReadOperation *o,
- snap_t snapid_unused_deprecated,
- int flags, bufferlist *pbl)
-{
- object_t obj(oid);
- int op_flags = 0;
- if (flags & OPERATION_BALANCE_READS)
- op_flags |= CEPH_OSD_FLAG_BALANCE_READS;
- if (flags & OPERATION_LOCALIZE_READS)
- op_flags |= CEPH_OSD_FLAG_LOCALIZE_READS;
- if (flags & OPERATION_ORDER_READS_WRITES)
- op_flags |= CEPH_OSD_FLAG_RWORDERED;
-
- return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
- op_flags, pbl);
-}
-
-int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
- librados::ObjectReadOperation *o,
- int flags, bufferlist *pbl)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
- translate_flags(flags), pbl);
-}
-
-int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
- librados::ObjectReadOperation *o,
- int flags, bufferlist *pbl, const blkin_trace_info *trace_info)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
- translate_flags(flags), pbl, trace_info);
-}
-
-void librados::IoCtx::snap_set_read(snap_t seq)
-{
- io_ctx_impl->set_snap_read(seq);
-}
-
-int librados::IoCtx::selfmanaged_snap_set_write_ctx(snap_t seq, vector<snap_t>& snaps)
-{
- vector<snapid_t> snv;
- snv.resize(snaps.size());
- for (unsigned i=0; i<snaps.size(); i++)
- snv[i] = snaps[i];
- return io_ctx_impl->set_snap_write_context(seq, snv);
-}
-
-int librados::IoCtx::snap_create(const char *snapname)
-{
- return io_ctx_impl->snap_create(snapname);
-}
-
-int librados::IoCtx::snap_lookup(const char *name, snap_t *snapid)
-{
- return io_ctx_impl->snap_lookup(name, snapid);
-}
-
-int librados::IoCtx::snap_get_stamp(snap_t snapid, time_t *t)
-{
- return io_ctx_impl->snap_get_stamp(snapid, t);
-}
-
-int librados::IoCtx::snap_get_name(snap_t snapid, std::string *s)
-{
- return io_ctx_impl->snap_get_name(snapid, s);
-}
-
-int librados::IoCtx::snap_remove(const char *snapname)
-{
- return io_ctx_impl->snap_remove(snapname);
-}
-
-int librados::IoCtx::snap_list(std::vector<snap_t> *snaps)
-{
- return io_ctx_impl->snap_list(snaps);
-}
-
-int librados::IoCtx::snap_rollback(const std::string& oid, const char *snapname)
-{
- return io_ctx_impl->rollback(oid, snapname);
-}
-
-// Deprecated name kept for backward compatibility
-int librados::IoCtx::rollback(const std::string& oid, const char *snapname)
-{
- return snap_rollback(oid, snapname);
-}
-
-int librados::IoCtx::selfmanaged_snap_create(uint64_t *snapid)
-{
- return io_ctx_impl->selfmanaged_snap_create(snapid);
-}
-
-void librados::IoCtx::aio_selfmanaged_snap_create(uint64_t *snapid,
- AioCompletion *c)
-{
- io_ctx_impl->aio_selfmanaged_snap_create(snapid, c->pc);
-}
-
-int librados::IoCtx::selfmanaged_snap_remove(uint64_t snapid)
-{
- return io_ctx_impl->selfmanaged_snap_remove(snapid);
-}
-
-void librados::IoCtx::aio_selfmanaged_snap_remove(uint64_t snapid,
- AioCompletion *c)
-{
- io_ctx_impl->aio_selfmanaged_snap_remove(snapid, c->pc);
-}
-
-int librados::IoCtx::selfmanaged_snap_rollback(const std::string& oid, uint64_t snapid)
-{
- return io_ctx_impl->selfmanaged_snap_rollback_object(oid,
- io_ctx_impl->snapc,
- snapid);
-}
-
-int librados::IoCtx::lock_exclusive(const std::string &oid, const std::string &name,
- const std::string &cookie,
- const std::string &description,
- struct timeval * duration, uint8_t flags)
-{
- utime_t dur = utime_t();
- if (duration)
- dur.set_from_timeval(duration);
-
- return rados::cls::lock::lock(this, oid, name, LOCK_EXCLUSIVE, cookie, "",
- description, dur, flags);
-}
-
-int librados::IoCtx::lock_shared(const std::string &oid, const std::string &name,
- const std::string &cookie, const std::string &tag,
- const std::string &description,
- struct timeval * duration, uint8_t flags)
-{
- utime_t dur = utime_t();
- if (duration)
- dur.set_from_timeval(duration);
-
- return rados::cls::lock::lock(this, oid, name, LOCK_SHARED, cookie, tag,
- description, dur, flags);
-}
-
-int librados::IoCtx::unlock(const std::string &oid, const std::string &name,
- const std::string &cookie)
-{
- return rados::cls::lock::unlock(this, oid, name, cookie);
-}
-
-struct AioUnlockCompletion : public librados::ObjectOperationCompletion {
- librados::AioCompletionImpl *completion;
- AioUnlockCompletion(librados::AioCompletion *c) : completion(c->pc) {
- completion->get();
- };
- void handle_completion(int r, bufferlist& outbl) override {
- rados_callback_t cb = completion->callback_complete;
- void *cb_arg = completion->callback_complete_arg;
- cb(completion, cb_arg);
- completion->lock.Lock();
- completion->callback_complete = NULL;
- completion->cond.Signal();
- completion->put_unlock();
- }
-};
-
-int librados::IoCtx::aio_unlock(const std::string &oid, const std::string &name,
- const std::string &cookie, AioCompletion *c)
-{
- return rados::cls::lock::aio_unlock(this, oid, name, cookie, c);
-}
-
-int librados::IoCtx::break_lock(const std::string &oid, const std::string &name,
- const std::string &client, const std::string &cookie)
-{
- entity_name_t locker;
- if (!locker.parse(client))
- return -EINVAL;
- return rados::cls::lock::break_lock(this, oid, name, cookie, locker);
-}
-
-int librados::IoCtx::list_lockers(const std::string &oid, const std::string &name,
- int *exclusive,
- std::string *tag,
- std::list<librados::locker_t> *lockers)
-{
- std::list<librados::locker_t> tmp_lockers;
- map<rados::cls::lock::locker_id_t, rados::cls::lock::locker_info_t> rados_lockers;
- std::string tmp_tag;
- ClsLockType tmp_type;
- int r = rados::cls::lock::get_lock_info(this, oid, name, &rados_lockers, &tmp_type, &tmp_tag);
- if (r < 0)
- return r;
-
- map<rados::cls::lock::locker_id_t, rados::cls::lock::locker_info_t>::iterator map_it;
- for (map_it = rados_lockers.begin(); map_it != rados_lockers.end(); ++map_it) {
- librados::locker_t locker;
- locker.client = stringify(map_it->first.locker);
- locker.cookie = map_it->first.cookie;
- locker.address = stringify(map_it->second.addr);
- tmp_lockers.push_back(locker);
- }
-
- if (lockers)
- *lockers = tmp_lockers;
- if (tag)
- *tag = tmp_tag;
- if (exclusive) {
- if (tmp_type == LOCK_EXCLUSIVE)
- *exclusive = 1;
- else
- *exclusive = 0;
- }
-
- return tmp_lockers.size();
-}
-
-librados::NObjectIterator librados::IoCtx::nobjects_begin()
-{
- bufferlist bl;
- return nobjects_begin(bl);
-}
-
-librados::NObjectIterator librados::IoCtx::nobjects_begin(
- const bufferlist &filter)
-{
- rados_list_ctx_t listh;
- rados_nobjects_list_open(io_ctx_impl, &listh);
- NObjectIterator iter((ObjListCtx*)listh);
- if (filter.length() > 0) {
- iter.set_filter(filter);
- }
- iter.get_next();
- return iter;
-}
-
-librados::NObjectIterator librados::IoCtx::nobjects_begin(uint32_t pos)
-{
- bufferlist bl;
- return nobjects_begin(pos, bl);
-}
-
-librados::NObjectIterator librados::IoCtx::nobjects_begin(
- uint32_t pos, const bufferlist &filter)
-{
- rados_list_ctx_t listh;
- rados_nobjects_list_open(io_ctx_impl, &listh);
- NObjectIterator iter((ObjListCtx*)listh);
- if (filter.length() > 0) {
- iter.set_filter(filter);
- }
- iter.seek(pos);
- return iter;
-}
-
-librados::NObjectIterator librados::IoCtx::nobjects_begin(const ObjectCursor& cursor)
-{
- bufferlist bl;
- return nobjects_begin(cursor, bl);
-}
-
-librados::NObjectIterator librados::IoCtx::nobjects_begin(
- const ObjectCursor& cursor, const bufferlist &filter)
-{
- rados_list_ctx_t listh;
- rados_nobjects_list_open(io_ctx_impl, &listh);
- NObjectIterator iter((ObjListCtx*)listh);
- if (filter.length() > 0) {
- iter.set_filter(filter);
- }
- iter.seek(cursor);
- return iter;
-}
-
-const librados::NObjectIterator& librados::IoCtx::nobjects_end() const
-{
- return NObjectIterator::__EndObjectIterator;
-}
-
-int librados::IoCtx::hit_set_list(uint32_t hash, AioCompletion *c,
- std::list< std::pair<time_t, time_t> > *pls)
-{
- return io_ctx_impl->hit_set_list(hash, c->pc, pls);
-}
-
-int librados::IoCtx::hit_set_get(uint32_t hash, AioCompletion *c, time_t stamp,
- bufferlist *pbl)
-{
- return io_ctx_impl->hit_set_get(hash, c->pc, stamp, pbl);
-}
-
-
-
-uint64_t librados::IoCtx::get_last_version()
-{
- return io_ctx_impl->last_version();
-}
-
-int librados::IoCtx::aio_read(const std::string& oid, librados::AioCompletion *c,
- bufferlist *pbl, size_t len, uint64_t off)
-{
- return io_ctx_impl->aio_read(oid, c->pc, pbl, len, off,
- io_ctx_impl->snap_seq);
-}
-
-int librados::IoCtx::aio_read(const std::string& oid, librados::AioCompletion *c,
- bufferlist *pbl, size_t len, uint64_t off,
- uint64_t snapid)
-{
- return io_ctx_impl->aio_read(oid, c->pc, pbl, len, off, snapid);
-}
-
-int librados::IoCtx::aio_exec(const std::string& oid,
- librados::AioCompletion *c, const char *cls,
- const char *method, bufferlist& inbl,
- bufferlist *outbl)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_exec(obj, c->pc, cls, method, inbl, outbl);
-}
-
-int librados::IoCtx::aio_cmpext(const std::string& oid,
- librados::AioCompletion *c,
- uint64_t off,
- bufferlist& cmp_bl)
-{
- return io_ctx_impl->aio_cmpext(oid, c->pc, off, cmp_bl);
-}
-
-int librados::IoCtx::aio_sparse_read(const std::string& oid, librados::AioCompletion *c,
- std::map<uint64_t,uint64_t> *m, bufferlist *data_bl,
- size_t len, uint64_t off)
-{
- return io_ctx_impl->aio_sparse_read(oid, c->pc,
- m, data_bl, len, off,
- io_ctx_impl->snap_seq);
-}
-
-int librados::IoCtx::aio_sparse_read(const std::string& oid, librados::AioCompletion *c,
- std::map<uint64_t,uint64_t> *m, bufferlist *data_bl,
- size_t len, uint64_t off, uint64_t snapid)
-{
- return io_ctx_impl->aio_sparse_read(oid, c->pc,
- m, data_bl, len, off, snapid);
-}
-
-int librados::IoCtx::aio_write(const std::string& oid, librados::AioCompletion *c,
- const bufferlist& bl, size_t len, uint64_t off)
-{
- return io_ctx_impl->aio_write(oid, c->pc, bl, len, off);
-}
-
-int librados::IoCtx::aio_append(const std::string& oid, librados::AioCompletion *c,
- const bufferlist& bl, size_t len)
-{
- return io_ctx_impl->aio_append(oid, c->pc, bl, len);
-}
-
-int librados::IoCtx::aio_write_full(const std::string& oid, librados::AioCompletion *c,
- const bufferlist& bl)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_write_full(obj, c->pc, bl);
-}
-
-int librados::IoCtx::aio_writesame(const std::string& oid, librados::AioCompletion *c,
- const bufferlist& bl, size_t write_len,
- uint64_t off)
-{
- return io_ctx_impl->aio_writesame(oid, c->pc, bl, write_len, off);
-}
-
-
-int librados::IoCtx::aio_remove(const std::string& oid, librados::AioCompletion *c)
-{
- return io_ctx_impl->aio_remove(oid, c->pc);
-}
-
-int librados::IoCtx::aio_remove(const std::string& oid, librados::AioCompletion *c, int flags)
-{
- return io_ctx_impl->aio_remove(oid, c->pc, flags);
-}
-
-int librados::IoCtx::aio_flush_async(librados::AioCompletion *c)
-{
- io_ctx_impl->flush_aio_writes_async(c->pc);
- return 0;
-}
-
-int librados::IoCtx::aio_flush()
-{
- io_ctx_impl->flush_aio_writes();
- return 0;
-}
-
-struct AioGetxattrDataPP {
- AioGetxattrDataPP(librados::AioCompletionImpl *c, bufferlist *_bl) :
- bl(_bl), completion(c) {}
- bufferlist *bl;
- struct librados::C_AioCompleteAndSafe completion;
-};
-
-static void rados_aio_getxattr_completepp(rados_completion_t c, void *arg) {
- AioGetxattrDataPP *cdata = reinterpret_cast<AioGetxattrDataPP*>(arg);
- int rc = rados_aio_get_return_value(c);
- if (rc >= 0) {
- rc = cdata->bl->length();
- }
- cdata->completion.finish(rc);
- delete cdata;
-}
-
-int librados::IoCtx::aio_getxattr(const std::string& oid, librados::AioCompletion *c,
- const char *name, bufferlist& bl)
-{
- // create data object to be passed to async callback
- AioGetxattrDataPP *cdata = new AioGetxattrDataPP(c->pc, &bl);
- if (!cdata) {
- return -ENOMEM;
- }
- // create completion callback
- librados::AioCompletionImpl *comp = new librados::AioCompletionImpl;
- comp->set_complete_callback(cdata, rados_aio_getxattr_completepp);
- // call actual getxattr from IoCtxImpl
- object_t obj(oid);
- return io_ctx_impl->aio_getxattr(obj, comp, name, bl);
-}
-
-int librados::IoCtx::aio_getxattrs(const std::string& oid, AioCompletion *c,
- map<std::string, bufferlist>& attrset)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_getxattrs(obj, c->pc, attrset);
-}
-
-int librados::IoCtx::aio_setxattr(const std::string& oid, AioCompletion *c,
- const char *name, bufferlist& bl)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_setxattr(obj, c->pc, name, bl);
-}
-
-int librados::IoCtx::aio_rmxattr(const std::string& oid, AioCompletion *c,
- const char *name)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_rmxattr(obj, c->pc, name);
-}
-
-int librados::IoCtx::aio_stat(const std::string& oid, librados::AioCompletion *c,
- uint64_t *psize, time_t *pmtime)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_stat(obj, c->pc, psize, pmtime);
-}
-
-int librados::IoCtx::aio_cancel(librados::AioCompletion *c)
-{
- return io_ctx_impl->aio_cancel(c->pc);
-}
-
-int librados::IoCtx::watch(const string& oid, uint64_t ver, uint64_t *cookie,
- librados::WatchCtx *ctx)
-{
- object_t obj(oid);
- return io_ctx_impl->watch(obj, cookie, ctx, NULL);
-}
-
-int librados::IoCtx::watch2(const string& oid, uint64_t *cookie,
- librados::WatchCtx2 *ctx2)
-{
- object_t obj(oid);
- return io_ctx_impl->watch(obj, cookie, NULL, ctx2);
-}
-
-int librados::IoCtx::watch3(const string& oid, uint64_t *cookie,
- librados::WatchCtx2 *ctx2, uint32_t timeout)
-{
- object_t obj(oid);
- return io_ctx_impl->watch(obj, cookie, NULL, ctx2, timeout);
-}
-
-int librados::IoCtx::aio_watch(const string& oid, AioCompletion *c,
- uint64_t *cookie,
- librados::WatchCtx2 *ctx2)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_watch(obj, c->pc, cookie, NULL, ctx2);
-}
-
-int librados::IoCtx::aio_watch2(const string& oid, AioCompletion *c,
- uint64_t *cookie,
- librados::WatchCtx2 *ctx2,
- uint32_t timeout)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_watch(obj, c->pc, cookie, NULL, ctx2, timeout);
-}
-
-int librados::IoCtx::unwatch(const string& oid, uint64_t handle)
-{
- return io_ctx_impl->unwatch(handle);
-}
-
-int librados::IoCtx::unwatch2(uint64_t handle)
-{
- return io_ctx_impl->unwatch(handle);
-}
-
-int librados::IoCtx::aio_unwatch(uint64_t handle, AioCompletion *c)
-{
- return io_ctx_impl->aio_unwatch(handle, c->pc);
-}
-
-int librados::IoCtx::watch_check(uint64_t handle)
-{
- return io_ctx_impl->watch_check(handle);
-}
-
-int librados::IoCtx::notify(const string& oid, uint64_t ver, bufferlist& bl)
-{
- object_t obj(oid);
- return io_ctx_impl->notify(obj, bl, 0, NULL, NULL, NULL);
-}
-
-int librados::IoCtx::notify2(const string& oid, bufferlist& bl,
- uint64_t timeout_ms, bufferlist *preplybl)
-{
- object_t obj(oid);
- return io_ctx_impl->notify(obj, bl, timeout_ms, preplybl, NULL, NULL);
-}
-
-int librados::IoCtx::aio_notify(const string& oid, AioCompletion *c,
- bufferlist& bl, uint64_t timeout_ms,
- bufferlist *preplybl)
-{
- object_t obj(oid);
- return io_ctx_impl->aio_notify(obj, c->pc, bl, timeout_ms, preplybl, NULL,
- NULL);
-}
-
-void librados::IoCtx::notify_ack(const std::string& o,
- uint64_t notify_id, uint64_t handle,
- bufferlist& bl)
-{
- io_ctx_impl->notify_ack(o, notify_id, handle, bl);
-}
-
-int librados::IoCtx::list_watchers(const std::string& oid,
- std::list<obj_watch_t> *out_watchers)
-{
- ObjectReadOperation op;
- int r;
- op.list_watchers(out_watchers, &r);
- bufferlist bl;
- int ret = operate(oid, &op, &bl);
- if (ret < 0)
- return ret;
-
- return r;
-}
-
-int librados::IoCtx::list_snaps(const std::string& oid,
- snap_set_t *out_snaps)
-{
- ObjectReadOperation op;
- int r;
- if (io_ctx_impl->snap_seq != CEPH_SNAPDIR)
- return -EINVAL;
- op.list_snaps(out_snaps, &r);
- bufferlist bl;
- int ret = operate(oid, &op, &bl);
- if (ret < 0)
- return ret;
-
- return r;
-}
-
-void librados::IoCtx::set_notify_timeout(uint32_t timeout)
-{
- io_ctx_impl->set_notify_timeout(timeout);
-}
-
-int librados::IoCtx::set_alloc_hint(const std::string& o,
- uint64_t expected_object_size,
- uint64_t expected_write_size)
-{
- object_t oid(o);
- return io_ctx_impl->set_alloc_hint(oid, expected_object_size,
- expected_write_size, 0);
-}
-
-int librados::IoCtx::set_alloc_hint2(const std::string& o,
- uint64_t expected_object_size,
- uint64_t expected_write_size,
- uint32_t flags)
-{
- object_t oid(o);
- return io_ctx_impl->set_alloc_hint(oid, expected_object_size,
- expected_write_size, flags);
-}
-
-void librados::IoCtx::set_assert_version(uint64_t ver)
-{
- io_ctx_impl->set_assert_version(ver);
-}
-
-void librados::IoCtx::locator_set_key(const string& key)
-{
- io_ctx_impl->oloc.key = key;
-}
-
-void librados::IoCtx::set_namespace(const string& nspace)
-{
- io_ctx_impl->oloc.nspace = nspace;
-}
-
-std::string librados::IoCtx::get_namespace() const
-{
- return io_ctx_impl->oloc.nspace;
-}
-
-int64_t librados::IoCtx::get_id()
-{
- return io_ctx_impl->get_id();
-}
-
-uint32_t librados::IoCtx::get_object_hash_position(const std::string& oid)
-{
- uint32_t hash;
- int r = io_ctx_impl->get_object_hash_position(oid, &hash);
- if (r < 0)
- hash = 0;
- return hash;
-}
-
-uint32_t librados::IoCtx::get_object_pg_hash_position(const std::string& oid)
-{
- uint32_t hash;
- int r = io_ctx_impl->get_object_pg_hash_position(oid, &hash);
- if (r < 0)
- hash = 0;
- return hash;
-}
-
-int librados::IoCtx::get_object_hash_position2(
- const std::string& oid, uint32_t *hash_position)
-{
- return io_ctx_impl->get_object_hash_position(oid, hash_position);
-}
-
-int librados::IoCtx::get_object_pg_hash_position2(
- const std::string& oid, uint32_t *pg_hash_position)
-{
- return io_ctx_impl->get_object_pg_hash_position(oid, pg_hash_position);
-}
-
-librados::config_t librados::IoCtx::cct()
-{
- return (config_t)io_ctx_impl->client->cct;
-}
-
-librados::IoCtx::IoCtx(IoCtxImpl *io_ctx_impl_)
- : io_ctx_impl(io_ctx_impl_)
-{
-}
-
-void librados::IoCtx::set_osdmap_full_try()
-{
- io_ctx_impl->objecter->set_osdmap_full_try();
-}
-
-void librados::IoCtx::unset_osdmap_full_try()
-{
- io_ctx_impl->objecter->unset_osdmap_full_try();
-}
-
-///////////////////////////// Rados //////////////////////////////
-void librados::Rados::version(int *major, int *minor, int *extra)
-{
- rados_version(major, minor, extra);
-}
-
-librados::Rados::Rados() : client(NULL)
-{
-}
-
-librados::Rados::Rados(IoCtx &ioctx)
-{
- client = ioctx.io_ctx_impl->client;
- ceph_assert(client != NULL);
- client->get();
-}
-
-librados::Rados::~Rados()
-{
- shutdown();
-}
-
-int librados::Rados::init(const char * const id)
-{
- return rados_create((rados_t *)&client, id);
-}
-
-int librados::Rados::init2(const char * const name,
- const char * const clustername, uint64_t flags)
-{
- return rados_create2((rados_t *)&client, clustername, name, flags);
-}
-
-int librados::Rados::init_with_context(config_t cct_)
-{
- return rados_create_with_context((rados_t *)&client, (rados_config_t)cct_);
-}
-
-int librados::Rados::connect()
-{
- return client->connect();
-}
-
-librados::config_t librados::Rados::cct()
-{
- return (config_t)client->cct;
-}
-
-int librados::Rados::watch_flush()
-{
- if (!client)
- return -EINVAL;
- return client->watch_flush();
-}
-
-int librados::Rados::aio_watch_flush(AioCompletion *c)
-{
- if (!client)
- return -EINVAL;
- return client->async_watch_flush(c->pc);
-}
-
-void librados::Rados::shutdown()
-{
- if (!client)
- return;
- if (client->put()) {
- client->shutdown();
- delete client;
- client = NULL;
- }
-}
-
-uint64_t librados::Rados::get_instance_id()
-{
- return client->get_instance_id();
-}
-
-int librados::Rados::get_min_compatible_osd(int8_t* require_osd_release)
-{
- return client->get_min_compatible_osd(require_osd_release);
-}
-
-int librados::Rados::get_min_compatible_client(int8_t* min_compat_client,
- int8_t* require_min_compat_client)
-{
- return client->get_min_compatible_client(min_compat_client,
- require_min_compat_client);
-}
-
-int librados::Rados::conf_read_file(const char * const path) const
-{
- return rados_conf_read_file((rados_t)client, path);
-}
-
-int librados::Rados::conf_parse_argv(int argc, const char ** argv) const
-{
- return rados_conf_parse_argv((rados_t)client, argc, argv);
-}
-
-int librados::Rados::conf_parse_argv_remainder(int argc, const char ** argv,
- const char ** remargv) const
-{
- return rados_conf_parse_argv_remainder((rados_t)client, argc, argv, remargv);
-}
-
-int librados::Rados::conf_parse_env(const char *name) const
-{
- return rados_conf_parse_env((rados_t)client, name);
-}
-
-int librados::Rados::conf_set(const char *option, const char *value)
-{
- return rados_conf_set((rados_t)client, option, value);
-}
-
-int librados::Rados::conf_get(const char *option, std::string &val)
-{
- char *str = NULL;
- const auto& conf = client->cct->_conf;
- int ret = conf.get_val(option, &str, -1);
- if (ret) {
- free(str);
- return ret;
- }
- val = str;
- free(str);
- return 0;
-}
-
-int librados::Rados::service_daemon_register(
- const std::string& service, ///< service name (e.g., 'rgw')
- const std::string& name, ///< daemon name (e.g., 'gwfoo')
- const std::map<std::string,std::string>& metadata) ///< static metadata about daemon
-{
- return client->service_daemon_register(service, name, metadata);
-}
-
-int librados::Rados::service_daemon_update_status(
- std::map<std::string,std::string>&& status)
-{
- return client->service_daemon_update_status(std::move(status));
-}
-
-int librados::Rados::pool_create(const char *name)
-{
- string str(name);
- return client->pool_create(str);
-}
-
-int librados::Rados::pool_create(const char *name, uint64_t auid)
-{
- if (auid != CEPH_AUTH_UID_DEFAULT) {
- return -EINVAL;
- }
- string str(name);
- return client->pool_create(str);
-}
-
-int librados::Rados::pool_create(const char *name, uint64_t auid, __u8 crush_rule)
-{
- if (auid != CEPH_AUTH_UID_DEFAULT) {
- return -EINVAL;
- }
- string str(name);
- return client->pool_create(str, crush_rule);
-}
-
-int librados::Rados::pool_create_with_rule(const char *name, __u8 crush_rule)
-{
- string str(name);
- return client->pool_create(str, crush_rule);
-}
-
-int librados::Rados::pool_create_async(const char *name, PoolAsyncCompletion *c)
-{
- string str(name);
- return client->pool_create_async(str, c->pc);
-}
-
-int librados::Rados::pool_create_async(const char *name, uint64_t auid, PoolAsyncCompletion *c)
-{
- if (auid != CEPH_AUTH_UID_DEFAULT) {
- return -EINVAL;
- }
- string str(name);
- return client->pool_create_async(str, c->pc);
-}
-
-int librados::Rados::pool_create_async(const char *name, uint64_t auid, __u8 crush_rule,
- PoolAsyncCompletion *c)
-{
- if (auid != CEPH_AUTH_UID_DEFAULT) {
- return -EINVAL;
- }
- string str(name);
- return client->pool_create_async(str, c->pc, crush_rule);
-}
-
-int librados::Rados::pool_create_with_rule_async(
- const char *name, __u8 crush_rule,
- PoolAsyncCompletion *c)
-{
- string str(name);
- return client->pool_create_async(str, c->pc, crush_rule);
-}
-
-int librados::Rados::pool_get_base_tier(int64_t pool_id, int64_t* base_tier)
-{
- tracepoint(librados, rados_pool_get_base_tier_enter, (rados_t)client, pool_id);
- int retval = client->pool_get_base_tier(pool_id, base_tier);
- tracepoint(librados, rados_pool_get_base_tier_exit, retval, *base_tier);
- return retval;
-}
-
-int librados::Rados::pool_delete(const char *name)
-{
- return client->pool_delete(name);
-}
-
-int librados::Rados::pool_delete_async(const char *name, PoolAsyncCompletion *c)
-{
- return client->pool_delete_async(name, c->pc);
-}
-
-int librados::Rados::pool_list(std::list<std::string>& v)
-{
- std::list<std::pair<int64_t, std::string> > pools;
- int r = client->pool_list(pools);
- if (r < 0) {
- return r;
- }
-
- v.clear();
- for (std::list<std::pair<int64_t, std::string> >::iterator it = pools.begin();
- it != pools.end(); ++it) {
- v.push_back(it->second);
- }
- return 0;
-}
-
-int librados::Rados::pool_list2(std::list<std::pair<int64_t, std::string> >& v)
-{
- return client->pool_list(v);
-}
-
-int64_t librados::Rados::pool_lookup(const char *name)
-{
- return client->lookup_pool(name);
-}
-
-int librados::Rados::pool_reverse_lookup(int64_t id, std::string *name)
-{
- return client->pool_get_name(id, name);
-}
-
-int librados::Rados::mon_command(string cmd, const bufferlist& inbl,
- bufferlist *outbl, string *outs)
-{
- vector<string> cmdvec;
- cmdvec.push_back(cmd);
- return client->mon_command(cmdvec, inbl, outbl, outs);
-}
-
-int librados::Rados::osd_command(int osdid, std::string cmd, const bufferlist& inbl,
- bufferlist *outbl, std::string *outs)
-{
- vector<string> cmdvec;
- cmdvec.push_back(cmd);
- return client->osd_command(osdid, cmdvec, inbl, outbl, outs);
-}
-
-int librados::Rados::mgr_command(std::string cmd, const bufferlist& inbl,
- bufferlist *outbl, std::string *outs)
-{
- vector<string> cmdvec;
- cmdvec.push_back(cmd);
- return client->mgr_command(cmdvec, inbl, outbl, outs);
-}
-
-
-
-int librados::Rados::pg_command(const char *pgstr, std::string cmd, const bufferlist& inbl,
- bufferlist *outbl, std::string *outs)
-{
- vector<string> cmdvec;
- cmdvec.push_back(cmd);
-
- pg_t pgid;
- if (!pgid.parse(pgstr))
- return -EINVAL;
-
- return client->pg_command(pgid, cmdvec, inbl, outbl, outs);
-}
-
-int librados::Rados::ioctx_create(const char *name, IoCtx &io)
-{
- rados_ioctx_t p;
- int ret = rados_ioctx_create((rados_t)client, name, &p);
- if (ret)
- return ret;
- io.close();
- io.io_ctx_impl = (IoCtxImpl*)p;
- return 0;
-}
-
-int librados::Rados::ioctx_create2(int64_t pool_id, IoCtx &io)
-{
- rados_ioctx_t p;
- int ret = rados_ioctx_create2((rados_t)client, pool_id, &p);
- if (ret)
- return ret;
- io.close();
- io.io_ctx_impl = (IoCtxImpl*)p;
- return 0;
-}
-
-void librados::Rados::test_blacklist_self(bool set)
-{
- client->blacklist_self(set);
-}
-
-int librados::Rados::get_pool_stats(std::list<string>& v,
- stats_map& result)
-{
- map<string,::pool_stat_t> rawresult;
- int r = client->get_pool_stats(v, rawresult);
- for (map<string,::pool_stat_t>::iterator p = rawresult.begin();
- p != rawresult.end();
- ++p) {
- pool_stat_t& pv = result[p->first];
- object_stat_sum_t *sum = &p->second.stats.sum;
- pv.num_kb = shift_round_up(sum->num_bytes, 10);
- pv.num_bytes = sum->num_bytes;
- pv.num_objects = sum->num_objects;
- pv.num_object_clones = sum->num_object_clones;
- pv.num_object_copies = sum->num_object_copies;
- pv.num_objects_missing_on_primary = sum->num_objects_missing_on_primary;
- pv.num_objects_unfound = sum->num_objects_unfound;
- pv.num_objects_degraded = sum->num_objects_degraded;
- pv.num_rd = sum->num_rd;
- pv.num_rd_kb = sum->num_rd_kb;
- pv.num_wr = sum->num_wr;
- pv.num_wr_kb = sum->num_wr_kb;
- }
- return r;
-}
-
-int librados::Rados::get_pool_stats(std::list<string>& v,
- std::map<string, stats_map>& result)
-{
- stats_map m;
- int r = get_pool_stats(v, m);
- if (r < 0)
- return r;
- for (map<string,pool_stat_t>::iterator p = m.begin();
- p != m.end();
- ++p) {
- result[p->first][string()] = p->second;
- }
- return r;
-}
-
-int librados::Rados::get_pool_stats(std::list<string>& v,
- string& category, // unused
- std::map<string, stats_map>& result)
-{
- return -EOPNOTSUPP;
-}
-
-bool librados::Rados::get_pool_is_selfmanaged_snaps_mode(const std::string& pool)
-{
- return client->get_pool_is_selfmanaged_snaps_mode(pool);
-}
-
-int librados::Rados::cluster_stat(cluster_stat_t& result)
-{
- ceph_statfs stats;
- int r = client->get_fs_stats(stats);
- result.kb = stats.kb;
- result.kb_used = stats.kb_used;
- result.kb_avail = stats.kb_avail;
- result.num_objects = stats.num_objects;
- return r;
-}
-
-int librados::Rados::cluster_fsid(string *fsid)
-{
- return client->get_fsid(fsid);
-}
-
-namespace librados {
- struct PlacementGroupImpl {
- pg_t pgid;
- };
-
- PlacementGroup::PlacementGroup()
- : impl{new PlacementGroupImpl}
- {}
-
- PlacementGroup::PlacementGroup(const PlacementGroup& pg)
- : impl{new PlacementGroupImpl}
- {
- impl->pgid = pg.impl->pgid;
- }
-
- PlacementGroup::~PlacementGroup()
- {}
-
- bool PlacementGroup::parse(const char* s)
- {
- return impl->pgid.parse(s);
- }
-}
-
-std::ostream& librados::operator<<(std::ostream& out,
- const librados::PlacementGroup& pg)
-{
- return out << pg.impl->pgid;
-}
-
-namespace {
- int decode_json(JSONObj *obj, pg_t& pg)
- {
- string pg_str;
- JSONDecoder::decode_json("pgid", pg_str, obj);
- if (pg.parse(pg_str.c_str())) {
- return 0;
- } else {
- return -EINVAL;
- }
- }
-
- int get_inconsistent_pgs(librados::RadosClient& client,
- int64_t pool_id,
- std::vector<librados::PlacementGroup>* pgs)
- {
- vector<string> cmd = {
- "{\"prefix\": \"pg ls\","
- "\"pool\": " + std::to_string(pool_id) + ","
- "\"states\": [\"inconsistent\"],"
- "\"format\": \"json\"}"
- };
- bufferlist inbl, outbl;
- string outstring;
- int ret = client.mgr_command(cmd, inbl, &outbl, &outstring);
- if (ret) {
- return ret;
- }
- if (!outbl.length()) {
- // no pg returned
- return ret;
- }
- JSONParser parser;
- if (!parser.parse(outbl.c_str(), outbl.length())) {
- return -EINVAL;
- }
-
- vector<string> v;
- if (!parser.is_array()) {
- JSONObj *pgstat_obj = parser.find_obj("pg_stats");
- if (NULL == pgstat_obj)
- return 0;
- string s = pgstat_obj->get_data();
- JSONParser pg_stats;
- if (!pg_stats.parse(s.c_str(), s.length()))
- return -EINVAL;
- v = pg_stats.get_array_elements();
- }
- else {
- v = parser.get_array_elements();
- }
-
- for (auto i : v) {
- JSONParser pg_json;
- if (!pg_json.parse(i.c_str(), i.length())) {
- return -EINVAL;
- }
- librados::PlacementGroup pg;
- if (decode_json(&pg_json, pg.impl->pgid)) {
- return -EINVAL;
- }
- pgs->emplace_back(pg);
- }
- return 0;
- }
-}
-
-int librados::Rados::get_inconsistent_pgs(int64_t pool_id,
- std::vector<PlacementGroup>* pgs)
-{
- return ::get_inconsistent_pgs(*client, pool_id, pgs);
-}
-
-int librados::Rados::get_inconsistent_objects(const PlacementGroup& pg,
- const object_id_t &start_after,
- unsigned max_return,
- AioCompletion *c,
- std::vector<inconsistent_obj_t>* objects,
- uint32_t* interval)
-{
- IoCtx ioctx;
- const pg_t pgid = pg.impl->pgid;
- int r = ioctx_create2(pgid.pool(), ioctx);
- if (r < 0) {
- return r;
- }
-
- return ioctx.io_ctx_impl->get_inconsistent_objects(pgid,
- start_after,
- max_return,
- c->pc,
- objects,
- interval);
-}
-
-int librados::Rados::get_inconsistent_snapsets(const PlacementGroup& pg,
- const object_id_t &start_after,
- unsigned max_return,
- AioCompletion *c,
- std::vector<inconsistent_snapset_t>* snapsets,
- uint32_t* interval)
-{
- IoCtx ioctx;
- const pg_t pgid = pg.impl->pgid;
- int r = ioctx_create2(pgid.pool(), ioctx);
- if (r < 0) {
- return r;
- }
-
- return ioctx.io_ctx_impl->get_inconsistent_snapsets(pgid,
- start_after,
- max_return,
- c->pc,
- snapsets,
- interval);
-}
-
-int librados::Rados::wait_for_latest_osdmap()
-{
- return client->wait_for_latest_osdmap();
-}
-
-int librados::Rados::blacklist_add(const std::string& client_address,
- uint32_t expire_seconds)
-{
- return client->blacklist_add(client_address, expire_seconds);
-}
-
-librados::PoolAsyncCompletion *librados::Rados::pool_async_create_completion()
-{
- PoolAsyncCompletionImpl *c = new PoolAsyncCompletionImpl;
- return new PoolAsyncCompletion(c);
-}
-
-librados::AioCompletion *librados::Rados::aio_create_completion()
-{
- AioCompletionImpl *c = new AioCompletionImpl;
- return new AioCompletion(c);
-}
-
-librados::AioCompletion *librados::Rados::aio_create_completion(void *cb_arg,
- callback_t cb_complete,
- callback_t cb_safe)
-{
- AioCompletionImpl *c;
- int r = rados_aio_create_completion(cb_arg, cb_complete, cb_safe, (void**)&c);
- ceph_assert(r == 0);
- return new AioCompletion(c);
-}
-
-librados::ObjectOperation::ObjectOperation()
-{
- impl = new ObjectOperationImpl;
-}
-
-librados::ObjectOperation::~ObjectOperation()
-{
- delete impl;
-}
-
///////////////////////////// C API //////////////////////////////
static CephContext *rados_create_cct(const char * const clustername,
@@ -3378,9 +597,8 @@ CEPH_RADOS_API int rados_inconsistent_pg_list(rados_t cluster, int64_t pool_id,
{
tracepoint(librados, rados_inconsistent_pg_list_enter, cluster, pool_id, len);
librados::RadosClient *client = (librados::RadosClient *)cluster;
- std::vector<librados::PlacementGroup> pgs;
- int r = ::get_inconsistent_pgs(*client, pool_id, &pgs);
- if (r < 0) {
+ std::vector<std::string> pgs;
+ if (int r = client->get_inconsistent_pgs(pool_id, &pgs); r < 0) {
tracepoint(librados, rados_inconsistent_pg_list_exit, r);
return r;
}
@@ -3394,10 +612,7 @@ CEPH_RADOS_API int rados_inconsistent_pg_list(rados_t cluster, int64_t pool_id,
if (b)
memset(b, 0, len);
int needed = 0;
- for (const auto pg : pgs) {
- std::ostringstream ss;
- ss << pg;
- auto s = ss.str();
+ for (const auto& s : pgs) {
unsigned rl = s.length() + 1;
if (b && len >= rl) {
tracepoint(librados, rados_inconsistent_pg_list_pg, s.c_str());
@@ -5633,7 +2848,7 @@ extern "C" void rados_release_write_op(rados_write_op_t write_op)
extern "C" void rados_write_op_set_flags(rados_write_op_t write_op, int flags)
{
tracepoint(librados, rados_write_op_set_flags_enter, write_op, flags);
- set_op_flags((::ObjectOperation *)write_op, flags);
+ ((::ObjectOperation *)write_op)->set_last_op_flags(get_op_flags(flags));
tracepoint(librados, rados_write_op_set_flags_exit);
}
@@ -6014,7 +3229,7 @@ extern "C" void rados_release_read_op(rados_read_op_t read_op)
extern "C" void rados_read_op_set_flags(rados_read_op_t read_op, int flags)
{
tracepoint(librados, rados_read_op_set_flags_enter, read_op, flags);
- set_op_flags((::ObjectOperation *)read_op, flags);
+ ((::ObjectOperation *)read_op)->set_last_op_flags(get_op_flags(flags));
tracepoint(librados, rados_read_op_set_flags_exit);
}
@@ -6346,7 +3561,7 @@ extern "C" void rados_read_op_omap_get_keys2(rados_read_op_t read_op,
tracepoint(librados, rados_read_op_omap_get_keys_exit, *iter);
}
-void internal_rados_read_op_omap_get_vals_by_keys(rados_read_op_t read_op,
+static void internal_rados_read_op_omap_get_vals_by_keys(rados_read_op_t read_op,
set<string>& to_get,
rados_omap_iter_t *iter,
int *prval)
@@ -6492,67 +3707,6 @@ extern "C" int rados_cache_unpin(rados_ioctx_t io, const char *o)
return retval;
}
-
-///////////////////////////// ListObject //////////////////////////////
-librados::ListObject::ListObject() : impl(NULL)
-{
-}
-
-librados::ListObject::ListObject(librados::ListObjectImpl *i): impl(i)
-{
-}
-
-librados::ListObject::ListObject(const ListObject& rhs)
-{
- if (rhs.impl == NULL) {
- impl = NULL;
- return;
- }
- impl = new ListObjectImpl();
- *impl = *(rhs.impl);
-}
-
-librados::ListObject& librados::ListObject::operator=(const ListObject& rhs)
-{
- if (rhs.impl == NULL) {
- delete impl;
- impl = NULL;
- return *this;
- }
- if (impl == NULL)
- impl = new ListObjectImpl();
- *impl = *(rhs.impl);
- return *this;
-}
-
-librados::ListObject::~ListObject()
-{
- if (impl)
- delete impl;
- impl = NULL;
-}
-
-const std::string& librados::ListObject::get_nspace() const
-{
- return impl->get_nspace();
-}
-
-const std::string& librados::ListObject::get_oid() const
-{
- return impl->get_oid();
-}
-
-const std::string& librados::ListObject::get_locator() const
-{
- return impl->get_locator();
-}
-
-std::ostream& librados::operator<<(std::ostream& out, const librados::ListObject& lop)
-{
- out << *(lop.impl);
- return out;
-}
-
CEPH_RADOS_API void rados_object_list_slice(
rados_ioctx_t io,
const rados_object_list_cursor start,
@@ -6581,220 +3735,3 @@ CEPH_RADOS_API void rados_object_list_slice(
split_start_hobj,
split_finish_hobj);
}
-
-librados::ObjectCursor::ObjectCursor()
-{
- c_cursor = (rados_object_list_cursor)new hobject_t();
-}
-
-librados::ObjectCursor::~ObjectCursor()
-{
- hobject_t *h = (hobject_t *)c_cursor;
- delete h;
-}
-
-librados::ObjectCursor::ObjectCursor(rados_object_list_cursor c)
-{
- if (!c) {
- c_cursor = nullptr;
- } else {
- c_cursor = (rados_object_list_cursor)new hobject_t(*(hobject_t *)c);
- }
-}
-
-librados::ObjectCursor& librados::ObjectCursor::operator=(const librados::ObjectCursor& rhs)
-{
- if (rhs.c_cursor != nullptr) {
- hobject_t *h = (hobject_t*)rhs.c_cursor;
- c_cursor = (rados_object_list_cursor)(new hobject_t(*h));
- } else {
- c_cursor = nullptr;
- }
- return *this;
-}
-
-bool librados::ObjectCursor::operator<(const librados::ObjectCursor &rhs) const
-{
- const hobject_t lhs_hobj = (c_cursor == nullptr) ? hobject_t() : *((hobject_t*)c_cursor);
- const hobject_t rhs_hobj = (rhs.c_cursor == nullptr) ? hobject_t() : *((hobject_t*)(rhs.c_cursor));
- return lhs_hobj < rhs_hobj;
-}
-
-bool librados::ObjectCursor::operator==(const librados::ObjectCursor &rhs) const
-{
- const hobject_t lhs_hobj = (c_cursor == nullptr) ? hobject_t() : *((hobject_t*)c_cursor);
- const hobject_t rhs_hobj = (rhs.c_cursor == nullptr) ? hobject_t() : *((hobject_t*)(rhs.c_cursor));
- return cmp(lhs_hobj, rhs_hobj) == 0;
-}
-librados::ObjectCursor::ObjectCursor(const librados::ObjectCursor &rhs)
-{
- *this = rhs;
-}
-
-librados::ObjectCursor librados::IoCtx::object_list_begin()
-{
- hobject_t *h = new hobject_t(io_ctx_impl->objecter->enumerate_objects_begin());
- ObjectCursor oc;
- oc.set((rados_object_list_cursor)h);
- return oc;
-}
-
-
-librados::ObjectCursor librados::IoCtx::object_list_end()
-{
- hobject_t *h = new hobject_t(io_ctx_impl->objecter->enumerate_objects_end());
- librados::ObjectCursor oc;
- oc.set((rados_object_list_cursor)h);
- return oc;
-}
-
-
-void librados::ObjectCursor::set(rados_object_list_cursor c)
-{
- delete (hobject_t*)c_cursor;
- c_cursor = c;
-}
-
-string librados::ObjectCursor::to_str() const
-{
- stringstream ss;
- ss << *(hobject_t *)c_cursor;
- return ss.str();
-}
-
-bool librados::ObjectCursor::from_str(const string& s)
-{
- if (s.empty()) {
- *(hobject_t *)c_cursor = hobject_t();
- return true;
- }
- return ((hobject_t *)c_cursor)->parse(s);
-}
-
-CEPH_RADOS_API std::ostream& librados::operator<<(std::ostream& os, const librados::ObjectCursor& oc)
-{
- if (oc.c_cursor) {
- os << *(hobject_t *)oc.c_cursor;
- } else {
- os << hobject_t();
- }
- return os;
-}
-
-bool librados::IoCtx::object_list_is_end(const ObjectCursor &oc)
-{
- hobject_t *h = (hobject_t *)oc.c_cursor;
- return h->is_max();
-}
-
-int librados::IoCtx::object_list(const ObjectCursor &start,
- const ObjectCursor &finish,
- const size_t result_item_count,
- const bufferlist &filter,
- std::vector<ObjectItem> *result,
- ObjectCursor *next)
-{
- ceph_assert(result != nullptr);
- ceph_assert(next != nullptr);
- result->clear();
-
- C_SaferCond cond;
- hobject_t next_hash;
- std::list<librados::ListObjectImpl> obj_result;
- io_ctx_impl->objecter->enumerate_objects(
- io_ctx_impl->poolid,
- io_ctx_impl->oloc.nspace,
- *((hobject_t*)start.c_cursor),
- *((hobject_t*)finish.c_cursor),
- result_item_count,
- filter,
- &obj_result,
- &next_hash,
- &cond);
-
- int r = cond.wait();
- if (r < 0) {
- next->set((rados_object_list_cursor)(new hobject_t(hobject_t::get_max())));
- return r;
- }
-
- next->set((rados_object_list_cursor)(new hobject_t(next_hash)));
-
- for (std::list<librados::ListObjectImpl>::iterator i = obj_result.begin();
- i != obj_result.end(); ++i) {
- ObjectItem oi;
- oi.oid = i->oid;
- oi.nspace = i->nspace;
- oi.locator = i->locator;
- result->push_back(oi);
- }
-
- return obj_result.size();
-}
-
-void librados::IoCtx::object_list_slice(
- const ObjectCursor start,
- const ObjectCursor finish,
- const size_t n,
- const size_t m,
- ObjectCursor *split_start,
- ObjectCursor *split_finish)
-{
- ceph_assert(split_start != nullptr);
- ceph_assert(split_finish != nullptr);
-
- io_ctx_impl->object_list_slice(
- *((hobject_t*)(start.c_cursor)),
- *((hobject_t*)(finish.c_cursor)),
- n,
- m,
- (hobject_t*)(split_start->c_cursor),
- (hobject_t*)(split_finish->c_cursor));
-}
-
-int librados::IoCtx::application_enable(const std::string& app_name,
- bool force)
-{
- return io_ctx_impl->application_enable(app_name, force);
-}
-
-int librados::IoCtx::application_enable_async(const std::string& app_name,
- bool force,
- PoolAsyncCompletion *c)
-{
- io_ctx_impl->application_enable_async(app_name, force, c->pc);
- return 0;
-}
-
-int librados::IoCtx::application_list(std::set<std::string> *app_names)
-{
- return io_ctx_impl->application_list(app_names);
-}
-
-int librados::IoCtx::application_metadata_get(const std::string& app_name,
- const std::string &key,
- std::string* value)
-{
- return io_ctx_impl->application_metadata_get(app_name, key, value);
-}
-
-int librados::IoCtx::application_metadata_set(const std::string& app_name,
- const std::string &key,
- const std::string& value)
-{
- return io_ctx_impl->application_metadata_set(app_name, key, value);
-}
-
-int librados::IoCtx::application_metadata_remove(const std::string& app_name,
- const std::string &key)
-{
- return io_ctx_impl->application_metadata_remove(app_name, key);
-}
-
-int librados::IoCtx::application_metadata_list(const std::string& app_name,
- std::map<std::string, std::string> *values)
-{
- return io_ctx_impl->application_metadata_list(app_name, values);
-}
-
-
diff --git a/src/librados/librados_cxx.cc b/src/librados/librados_cxx.cc
new file mode 100644
index 00000000000..c1d2f3fd10c
--- /dev/null
+++ b/src/librados/librados_cxx.cc
@@ -0,0 +1,2987 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2012 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include <limits.h>
+
+#include "common/config.h"
+#include "common/errno.h"
+#include "common/ceph_argparse.h"
+#include "common/ceph_json.h"
+#include "common/common_init.h"
+#include "common/TracepointProvider.h"
+#include "common/hobject.h"
+#include "include/rados/librados.h"
+#include "include/rados/librados.hpp"
+#include "include/types.h"
+#include <include/stringify.h>
+
+#include "librados/AioCompletionImpl.h"
+#include "librados/IoCtxImpl.h"
+#include "librados/PoolAsyncCompletionImpl.h"
+#include "librados/RadosClient.h"
+#include "librados/RadosXattrIter.h"
+#include "librados/ListObjectImpl.h"
+#include "librados/librados_util.h"
+#include "cls/lock/cls_lock_client.h"
+
+#include <string>
+#include <map>
+#include <set>
+#include <vector>
+#include <list>
+#include <stdexcept>
+
+#ifdef WITH_LTTNG
+#define TRACEPOINT_DEFINE
+#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
+#include "tracing/librados.h"
+#undef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
+#undef TRACEPOINT_DEFINE
+#else
+#define tracepoint(...)
+#endif
+
+using std::string;
+using std::map;
+using std::set;
+using std::vector;
+using std::list;
+using std::runtime_error;
+
+#define dout_subsys ceph_subsys_rados
+#undef dout_prefix
+#define dout_prefix *_dout << "librados: "
+
+static TracepointProvider::Traits tracepoint_traits("librados_tp.so", "rados_tracing");
+
+/*
+ * Structure of this file
+ *
+ * RadosClient and the related classes are the internal implementation of librados.
+ * Above that layer sits the C API, found in include/rados/librados.h, and
+ * the C++ API, found in include/rados/librados.hpp
+ *
+ * The C++ API sometimes implements things in terms of the C API.
+ * Both the C++ and C API rely on RadosClient.
+ *
+ * Visually:
+ * +--------------------------------------+
+ * | C++ API |
+ * +--------------------+ |
+ * | C API | |
+ * +--------------------+-----------------+
+ * | RadosClient |
+ * +--------------------------------------+
+ */
+
+namespace librados {
+
+struct ObjectOperationImpl {
+ ::ObjectOperation o;
+ real_time rt;
+ real_time *prt;
+
+ ObjectOperationImpl() : prt(NULL) {}
+};
+
+}
+
+size_t librados::ObjectOperation::size()
+{
+ ::ObjectOperation *o = &impl->o;
+ return o->size();
+}
+
+//deprcated
+void librados::ObjectOperation::set_op_flags(ObjectOperationFlags flags)
+{
+ set_op_flags2((int)flags);
+}
+
+void librados::ObjectOperation::set_op_flags2(int flags)
+{
+ impl->o.set_last_op_flags(get_op_flags(flags));
+}
+
+void librados::ObjectOperation::cmpext(uint64_t off,
+ bufferlist &cmp_bl,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->cmpext(off, cmp_bl, prval);
+}
+
+void librados::ObjectOperation::cmpxattr(const char *name, uint8_t op, const bufferlist& v)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->cmpxattr(name, op, CEPH_OSD_CMPXATTR_MODE_STRING, v);
+}
+
+void librados::ObjectOperation::cmpxattr(const char *name, uint8_t op, uint64_t v)
+{
+ ::ObjectOperation *o = &impl->o;
+ bufferlist bl;
+ encode(v, bl);
+ o->cmpxattr(name, op, CEPH_OSD_CMPXATTR_MODE_U64, bl);
+}
+
+void librados::ObjectOperation::assert_version(uint64_t ver)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->assert_version(ver);
+}
+
+void librados::ObjectOperation::assert_exists()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->stat(NULL, (ceph::real_time*) NULL, NULL);
+}
+
+void librados::ObjectOperation::exec(const char *cls, const char *method, bufferlist& inbl)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->call(cls, method, inbl);
+}
+
+void librados::ObjectOperation::exec(const char *cls, const char *method, bufferlist& inbl, bufferlist *outbl, int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->call(cls, method, inbl, outbl, NULL, prval);
+}
+
+class ObjectOpCompletionCtx : public Context {
+ librados::ObjectOperationCompletion *completion;
+ bufferlist bl;
+public:
+ explicit ObjectOpCompletionCtx(librados::ObjectOperationCompletion *c) : completion(c) {}
+ void finish(int r) override {
+ completion->handle_completion(r, bl);
+ delete completion;
+ }
+
+ bufferlist *outbl() {
+ return &bl;
+ }
+};
+
+void librados::ObjectOperation::exec(const char *cls, const char *method, bufferlist& inbl, librados::ObjectOperationCompletion *completion)
+{
+ ::ObjectOperation *o = &impl->o;
+
+ ObjectOpCompletionCtx *ctx = new ObjectOpCompletionCtx(completion);
+
+ o->call(cls, method, inbl, ctx->outbl(), ctx, NULL);
+}
+
+void librados::ObjectReadOperation::stat(uint64_t *psize, time_t *pmtime, int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->stat(psize, pmtime, prval);
+}
+
+void librados::ObjectReadOperation::stat2(uint64_t *psize, struct timespec *pts, int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->stat(psize, pts, prval);
+}
+
+void librados::ObjectReadOperation::read(size_t off, uint64_t len, bufferlist *pbl, int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->read(off, len, pbl, prval, NULL);
+}
+
+void librados::ObjectReadOperation::sparse_read(uint64_t off, uint64_t len,
+ std::map<uint64_t,uint64_t> *m,
+ bufferlist *data_bl, int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->sparse_read(off, len, m, data_bl, prval);
+}
+
+void librados::ObjectReadOperation::checksum(rados_checksum_type_t type,
+ const bufferlist &init_value_bl,
+ uint64_t off, size_t len,
+ size_t chunk_size, bufferlist *pbl,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->checksum(get_checksum_op_type(type), init_value_bl, off, len, chunk_size,
+ pbl, prval, nullptr);
+}
+
+void librados::ObjectReadOperation::tmap_get(bufferlist *pbl, int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->tmap_get(pbl, prval);
+}
+
+void librados::ObjectReadOperation::getxattr(const char *name, bufferlist *pbl, int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->getxattr(name, pbl, prval);
+}
+
+void librados::ObjectReadOperation::omap_get_vals(
+ const std::string &start_after,
+ const std::string &filter_prefix,
+ uint64_t max_return,
+ std::map<std::string, bufferlist> *out_vals,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_get_vals(start_after, filter_prefix, max_return, out_vals, nullptr,
+ prval);
+}
+
+void librados::ObjectReadOperation::omap_get_vals2(
+ const std::string &start_after,
+ const std::string &filter_prefix,
+ uint64_t max_return,
+ std::map<std::string, bufferlist> *out_vals,
+ bool *pmore,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_get_vals(start_after, filter_prefix, max_return, out_vals, pmore,
+ prval);
+}
+
+void librados::ObjectReadOperation::omap_get_vals(
+ const std::string &start_after,
+ uint64_t max_return,
+ std::map<std::string, bufferlist> *out_vals,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_get_vals(start_after, "", max_return, out_vals, nullptr, prval);
+}
+
+void librados::ObjectReadOperation::omap_get_vals2(
+ const std::string &start_after,
+ uint64_t max_return,
+ std::map<std::string, bufferlist> *out_vals,
+ bool *pmore,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_get_vals(start_after, "", max_return, out_vals, pmore, prval);
+}
+
+void librados::ObjectReadOperation::omap_get_keys(
+ const std::string &start_after,
+ uint64_t max_return,
+ std::set<std::string> *out_keys,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_get_keys(start_after, max_return, out_keys, nullptr, prval);
+}
+
+void librados::ObjectReadOperation::omap_get_keys2(
+ const std::string &start_after,
+ uint64_t max_return,
+ std::set<std::string> *out_keys,
+ bool *pmore,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_get_keys(start_after, max_return, out_keys, pmore, prval);
+}
+
+void librados::ObjectReadOperation::omap_get_header(bufferlist *bl, int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_get_header(bl, prval);
+}
+
+void librados::ObjectReadOperation::omap_get_vals_by_keys(
+ const std::set<std::string> &keys,
+ std::map<std::string, bufferlist> *map,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_get_vals_by_keys(keys, map, prval);
+}
+
+void librados::ObjectOperation::omap_cmp(
+ const std::map<std::string, pair<bufferlist, int> > &assertions,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_cmp(assertions, prval);
+}
+
+void librados::ObjectReadOperation::list_watchers(
+ list<obj_watch_t> *out_watchers,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->list_watchers(out_watchers, prval);
+}
+
+void librados::ObjectReadOperation::list_snaps(
+ snap_set_t *out_snaps,
+ int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->list_snaps(out_snaps, prval);
+}
+
+void librados::ObjectReadOperation::is_dirty(bool *is_dirty, int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->is_dirty(is_dirty, prval);
+}
+
+int librados::IoCtx::omap_get_vals(const std::string& oid,
+ const std::string& orig_start_after,
+ const std::string& filter_prefix,
+ uint64_t max_return,
+ std::map<std::string, bufferlist> *out_vals)
+{
+ bool first = true;
+ string start_after = orig_start_after;
+ bool more = true;
+ while (max_return > 0 && more) {
+ std::map<std::string,bufferlist> out;
+ ObjectReadOperation op;
+ op.omap_get_vals2(start_after, filter_prefix, max_return, &out, &more,
+ nullptr);
+ bufferlist bl;
+ int ret = operate(oid, &op, &bl);
+ if (ret < 0) {
+ return ret;
+ }
+ if (more) {
+ if (out.empty()) {
+ return -EINVAL; // wth
+ }
+ start_after = out.rbegin()->first;
+ }
+ if (out.size() <= max_return) {
+ max_return -= out.size();
+ } else {
+ max_return = 0;
+ }
+ if (first) {
+ out_vals->swap(out);
+ first = false;
+ } else {
+ out_vals->insert(out.begin(), out.end());
+ out.clear();
+ }
+ }
+ return 0;
+}
+
+int librados::IoCtx::omap_get_vals2(
+ const std::string& oid,
+ const std::string& start_after,
+ const std::string& filter_prefix,
+ uint64_t max_return,
+ std::map<std::string, bufferlist> *out_vals,
+ bool *pmore)
+{
+ ObjectReadOperation op;
+ int r;
+ op.omap_get_vals2(start_after, filter_prefix, max_return, out_vals, pmore, &r);
+ bufferlist bl;
+ int ret = operate(oid, &op, &bl);
+ if (ret < 0)
+ return ret;
+ return r;
+}
+
+void librados::ObjectReadOperation::getxattrs(map<string, bufferlist> *pattrs, int *prval)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->getxattrs(pattrs, prval);
+}
+
+void librados::ObjectWriteOperation::mtime(time_t *pt)
+{
+ if (pt) {
+ impl->rt = ceph::real_clock::from_time_t(*pt);
+ impl->prt = &impl->rt;
+ }
+}
+
+void librados::ObjectWriteOperation::mtime2(struct timespec *pts)
+{
+ if (pts) {
+ impl->rt = ceph::real_clock::from_timespec(*pts);
+ impl->prt = &impl->rt;
+ }
+}
+
+void librados::ObjectWriteOperation::create(bool exclusive)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->create(exclusive);
+}
+
+void librados::ObjectWriteOperation::create(bool exclusive,
+ const std::string& category) // unused
+{
+ ::ObjectOperation *o = &impl->o;
+ o->create(exclusive);
+}
+
+void librados::ObjectWriteOperation::write(uint64_t off, const bufferlist& bl)
+{
+ ::ObjectOperation *o = &impl->o;
+ bufferlist c = bl;
+ o->write(off, c);
+}
+
+void librados::ObjectWriteOperation::write_full(const bufferlist& bl)
+{
+ ::ObjectOperation *o = &impl->o;
+ bufferlist c = bl;
+ o->write_full(c);
+}
+
+void librados::ObjectWriteOperation::writesame(uint64_t off, uint64_t write_len,
+ const bufferlist& bl)
+{
+ ::ObjectOperation *o = &impl->o;
+ bufferlist c = bl;
+ o->writesame(off, write_len, c);
+}
+
+void librados::ObjectWriteOperation::append(const bufferlist& bl)
+{
+ ::ObjectOperation *o = &impl->o;
+ bufferlist c = bl;
+ o->append(c);
+}
+
+void librados::ObjectWriteOperation::remove()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->remove();
+}
+
+void librados::ObjectWriteOperation::truncate(uint64_t off)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->truncate(off);
+}
+
+void librados::ObjectWriteOperation::zero(uint64_t off, uint64_t len)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->zero(off, len);
+}
+
+void librados::ObjectWriteOperation::rmxattr(const char *name)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->rmxattr(name);
+}
+
+void librados::ObjectWriteOperation::setxattr(const char *name, const bufferlist& v)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->setxattr(name, v);
+}
+
+void librados::ObjectWriteOperation::omap_set(
+ const map<string, bufferlist> &map)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_set(map);
+}
+
+void librados::ObjectWriteOperation::omap_set_header(const bufferlist &bl)
+{
+ bufferlist c = bl;
+ ::ObjectOperation *o = &impl->o;
+ o->omap_set_header(c);
+}
+
+void librados::ObjectWriteOperation::omap_clear()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_clear();
+}
+
+void librados::ObjectWriteOperation::omap_rm_keys(
+ const std::set<std::string> &to_rm)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->omap_rm_keys(to_rm);
+}
+
+void librados::ObjectWriteOperation::copy_from(const std::string& src,
+ const IoCtx& src_ioctx,
+ uint64_t src_version)
+{
+ copy_from2(src, src_ioctx, src_version, 0);
+}
+
+void librados::ObjectWriteOperation::copy_from2(const std::string& src,
+ const IoCtx& src_ioctx,
+ uint64_t src_version,
+ uint32_t src_fadvise_flags)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->copy_from(object_t(src), src_ioctx.io_ctx_impl->snap_seq,
+ src_ioctx.io_ctx_impl->oloc, src_version, 0, src_fadvise_flags);
+}
+
+void librados::ObjectWriteOperation::undirty()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->undirty();
+}
+
+void librados::ObjectReadOperation::cache_flush()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->cache_flush();
+}
+
+void librados::ObjectReadOperation::cache_try_flush()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->cache_try_flush();
+}
+
+void librados::ObjectReadOperation::cache_evict()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->cache_evict();
+}
+
+void librados::ObjectWriteOperation::set_redirect(const std::string& tgt_obj,
+ const IoCtx& tgt_ioctx,
+ uint64_t tgt_version,
+ int flag)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->set_redirect(object_t(tgt_obj), tgt_ioctx.io_ctx_impl->snap_seq,
+ tgt_ioctx.io_ctx_impl->oloc, tgt_version, flag);
+}
+
+void librados::ObjectWriteOperation::set_chunk(uint64_t src_offset,
+ uint64_t src_length,
+ const IoCtx& tgt_ioctx,
+ string tgt_oid,
+ uint64_t tgt_offset,
+ int flag)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->set_chunk(src_offset, src_length,
+ tgt_ioctx.io_ctx_impl->oloc, object_t(tgt_oid), tgt_offset, flag);
+}
+
+void librados::ObjectWriteOperation::tier_promote()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->tier_promote();
+}
+
+void librados::ObjectWriteOperation::unset_manifest()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->unset_manifest();
+}
+
+void librados::ObjectWriteOperation::tmap_put(const bufferlist &bl)
+{
+ ::ObjectOperation *o = &impl->o;
+ bufferlist c = bl;
+ o->tmap_put(c);
+}
+
+void librados::ObjectWriteOperation::tmap_update(const bufferlist& cmdbl)
+{
+ ::ObjectOperation *o = &impl->o;
+ bufferlist c = cmdbl;
+ o->tmap_update(c);
+}
+
+void librados::ObjectWriteOperation::selfmanaged_snap_rollback(snap_t snapid)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->rollback(snapid);
+}
+
+// You must specify the snapid not the name normally used with pool snapshots
+void librados::ObjectWriteOperation::snap_rollback(snap_t snapid)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->rollback(snapid);
+}
+
+void librados::ObjectWriteOperation::set_alloc_hint(
+ uint64_t expected_object_size,
+ uint64_t expected_write_size)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->set_alloc_hint(expected_object_size, expected_write_size, 0);
+}
+void librados::ObjectWriteOperation::set_alloc_hint2(
+ uint64_t expected_object_size,
+ uint64_t expected_write_size,
+ uint32_t flags)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->set_alloc_hint(expected_object_size, expected_write_size, flags);
+}
+
+void librados::ObjectWriteOperation::cache_pin()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->cache_pin();
+}
+
+void librados::ObjectWriteOperation::cache_unpin()
+{
+ ::ObjectOperation *o = &impl->o;
+ o->cache_unpin();
+}
+
+librados::WatchCtx::
+~WatchCtx()
+{
+}
+
+librados::WatchCtx2::
+~WatchCtx2()
+{
+}
+
+///////////////////////////// NObjectIteratorImpl /////////////////////////////
+librados::NObjectIteratorImpl::NObjectIteratorImpl(ObjListCtx *ctx_)
+ : ctx(ctx_)
+{
+}
+
+librados::NObjectIteratorImpl::~NObjectIteratorImpl()
+{
+ ctx.reset();
+}
+
+librados::NObjectIteratorImpl::NObjectIteratorImpl(const NObjectIteratorImpl &rhs)
+{
+ *this = rhs;
+}
+
+librados::NObjectIteratorImpl& librados::NObjectIteratorImpl::operator=(const librados::NObjectIteratorImpl &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));
+ cur_obj = rhs.cur_obj;
+ return *this;
+}
+
+bool librados::NObjectIteratorImpl::operator==(const librados::NObjectIteratorImpl& rhs) const {
+
+ if (ctx.get() == NULL) {
+ if (rhs.ctx.get() == NULL)
+ return true;
+ return rhs.ctx->nlc->at_end();
+ }
+ if (rhs.ctx.get() == NULL) {
+ // Redundant but same as ObjectIterator version
+ if (ctx.get() == NULL)
+ return true;
+ return ctx->nlc->at_end();
+ }
+ return ctx.get() == rhs.ctx.get();
+}
+
+bool librados::NObjectIteratorImpl::operator!=(const librados::NObjectIteratorImpl& rhs) const {
+ return !(*this == rhs);
+}
+
+const librados::ListObject& librados::NObjectIteratorImpl::operator*() const {
+ return cur_obj;
+}
+
+const librados::ListObject* librados::NObjectIteratorImpl::operator->() const {
+ return &cur_obj;
+}
+
+librados::NObjectIteratorImpl& librados::NObjectIteratorImpl::operator++()
+{
+ get_next();
+ return *this;
+}
+
+librados::NObjectIteratorImpl librados::NObjectIteratorImpl::operator++(int)
+{
+ librados::NObjectIteratorImpl ret(*this);
+ get_next();
+ return ret;
+}
+
+uint32_t librados::NObjectIteratorImpl::seek(uint32_t pos)
+{
+ uint32_t r = rados_nobjects_list_seek(ctx.get(), pos);
+ get_next();
+ return r;
+}
+
+uint32_t librados::NObjectIteratorImpl::seek(const ObjectCursor& cursor)
+{
+ uint32_t r = rados_nobjects_list_seek_cursor(ctx.get(), (rados_object_list_cursor)cursor.c_cursor);
+ get_next();
+ return r;
+}
+
+librados::ObjectCursor librados::NObjectIteratorImpl::get_cursor()
+{
+ librados::ObjListCtx *lh = (librados::ObjListCtx *)ctx.get();
+ librados::ObjectCursor oc;
+ oc.set(lh->ctx->nlist_get_cursor(lh->nlc));
+ return oc;
+}
+
+void librados::NObjectIteratorImpl::set_filter(const bufferlist &bl)
+{
+ ceph_assert(ctx);
+ ctx->nlc->filter = bl;
+}
+
+void librados::NObjectIteratorImpl::get_next()
+{
+ const char *entry, *key, *nspace;
+ if (ctx->nlc->at_end())
+ return;
+ int ret = rados_nobjects_list_next(ctx.get(), &entry, &key, &nspace);
+ if (ret == -ENOENT) {
+ return;
+ }
+ else if (ret) {
+ ostringstream oss;
+ oss << "rados returned " << cpp_strerror(ret);
+ throw std::runtime_error(oss.str());
+ }
+
+ if (cur_obj.impl == NULL)
+ cur_obj.impl = new ListObjectImpl();
+ cur_obj.impl->nspace = nspace;
+ cur_obj.impl->oid = entry;
+ cur_obj.impl->locator = key ? key : string();
+}
+
+uint32_t librados::NObjectIteratorImpl::get_pg_hash_position() const
+{
+ return ctx->nlc->get_pg_hash_position();
+}
+
+///////////////////////////// NObjectIterator /////////////////////////////
+librados::NObjectIterator::NObjectIterator(ObjListCtx *ctx_)
+{
+ impl = new NObjectIteratorImpl(ctx_);
+}
+
+librados::NObjectIterator::~NObjectIterator()
+{
+ delete impl;
+}
+
+librados::NObjectIterator::NObjectIterator(const NObjectIterator &rhs)
+{
+ if (rhs.impl == NULL) {
+ impl = NULL;
+ return;
+ }
+ impl = new NObjectIteratorImpl();
+ *impl = *(rhs.impl);
+}
+
+librados::NObjectIterator& librados::NObjectIterator::operator=(const librados::NObjectIterator &rhs)
+{
+ if (rhs.impl == NULL) {
+ delete impl;
+ impl = NULL;
+ return *this;
+ }
+ if (impl == NULL)
+ impl = new NObjectIteratorImpl();
+ *impl = *(rhs.impl);
+ return *this;
+}
+
+bool librados::NObjectIterator::operator==(const librados::NObjectIterator& rhs) const
+{
+ if (impl && rhs.impl) {
+ return *impl == *(rhs.impl);
+ } else {
+ return impl == rhs.impl;
+ }
+}
+
+bool librados::NObjectIterator::operator!=(const librados::NObjectIterator& rhs) const
+{
+ return !(*this == rhs);
+}
+
+const librados::ListObject& librados::NObjectIterator::operator*() const {
+ ceph_assert(impl);
+ return *(impl->get_listobjectp());
+}
+
+const librados::ListObject* librados::NObjectIterator::operator->() const {
+ ceph_assert(impl);
+ return impl->get_listobjectp();
+}
+
+librados::NObjectIterator& librados::NObjectIterator::operator++()
+{
+ ceph_assert(impl);
+ impl->get_next();
+ return *this;
+}
+
+librados::NObjectIterator librados::NObjectIterator::operator++(int)
+{
+ librados::NObjectIterator ret(*this);
+ impl->get_next();
+ return ret;
+}
+
+uint32_t librados::NObjectIterator::seek(uint32_t pos)
+{
+ ceph_assert(impl);
+ return impl->seek(pos);
+}
+
+uint32_t librados::NObjectIterator::seek(const ObjectCursor& cursor)
+{
+ ceph_assert(impl);
+ return impl->seek(cursor);
+}
+
+librados::ObjectCursor librados::NObjectIterator::get_cursor()
+{
+ ceph_assert(impl);
+ return impl->get_cursor();
+}
+
+void librados::NObjectIterator::set_filter(const bufferlist &bl)
+{
+ impl->set_filter(bl);
+}
+
+void librados::NObjectIterator::get_next()
+{
+ ceph_assert(impl);
+ impl->get_next();
+}
+
+uint32_t librados::NObjectIterator::get_pg_hash_position() const
+{
+ ceph_assert(impl);
+ return impl->get_pg_hash_position();
+}
+
+const librados::NObjectIterator librados::NObjectIterator::__EndObjectIterator(NULL);
+
+///////////////////////////// PoolAsyncCompletion //////////////////////////////
+int librados::PoolAsyncCompletion::PoolAsyncCompletion::set_callback(void *cb_arg,
+ rados_callback_t cb)
+{
+ PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
+ return c->set_callback(cb_arg, cb);
+}
+
+int librados::PoolAsyncCompletion::PoolAsyncCompletion::wait()
+{
+ PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
+ return c->wait();
+}
+
+bool librados::PoolAsyncCompletion::PoolAsyncCompletion::is_complete()
+{
+ PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
+ return c->is_complete();
+}
+
+int librados::PoolAsyncCompletion::PoolAsyncCompletion::get_return_value()
+{
+ PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
+ return c->get_return_value();
+}
+
+void librados::PoolAsyncCompletion::PoolAsyncCompletion::release()
+{
+ PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
+ c->release();
+ delete this;
+}
+
+///////////////////////////// AioCompletion //////////////////////////////
+int librados::AioCompletion::AioCompletion::set_complete_callback(void *cb_arg, rados_callback_t cb)
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->set_complete_callback(cb_arg, cb);
+}
+
+int librados::AioCompletion::AioCompletion::set_safe_callback(void *cb_arg, rados_callback_t cb)
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->set_safe_callback(cb_arg, cb);
+}
+
+int librados::AioCompletion::AioCompletion::wait_for_complete()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->wait_for_complete();
+}
+
+int librados::AioCompletion::AioCompletion::wait_for_safe()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->wait_for_safe();
+}
+
+bool librados::AioCompletion::AioCompletion::is_complete()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->is_complete();
+}
+
+bool librados::AioCompletion::AioCompletion::is_safe()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->is_safe();
+}
+
+int librados::AioCompletion::AioCompletion::wait_for_complete_and_cb()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->wait_for_complete_and_cb();
+}
+
+int librados::AioCompletion::AioCompletion::wait_for_safe_and_cb()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->wait_for_safe_and_cb();
+}
+
+bool librados::AioCompletion::AioCompletion::is_complete_and_cb()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->is_complete_and_cb();
+}
+
+bool librados::AioCompletion::AioCompletion::is_safe_and_cb()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->is_safe_and_cb();
+}
+
+int librados::AioCompletion::AioCompletion::get_return_value()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->get_return_value();
+}
+
+int librados::AioCompletion::AioCompletion::get_version()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->get_version();
+}
+
+uint64_t librados::AioCompletion::AioCompletion::get_version64()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ return c->get_version();
+}
+
+void librados::AioCompletion::AioCompletion::release()
+{
+ AioCompletionImpl *c = (AioCompletionImpl *)pc;
+ c->release();
+ delete this;
+}
+
+///////////////////////////// IoCtx //////////////////////////////
+librados::IoCtx::IoCtx() : io_ctx_impl(NULL)
+{
+}
+
+void librados::IoCtx::from_rados_ioctx_t(rados_ioctx_t p, IoCtx &io)
+{
+ IoCtxImpl *io_ctx_impl = (IoCtxImpl*)p;
+
+ io.io_ctx_impl = io_ctx_impl;
+ if (io_ctx_impl) {
+ io_ctx_impl->get();
+ }
+}
+
+librados::IoCtx::IoCtx(const IoCtx& rhs)
+{
+ io_ctx_impl = rhs.io_ctx_impl;
+ if (io_ctx_impl) {
+ io_ctx_impl->get();
+ }
+}
+
+librados::IoCtx& librados::IoCtx::operator=(const IoCtx& rhs)
+{
+ if (io_ctx_impl)
+ io_ctx_impl->put();
+ io_ctx_impl = rhs.io_ctx_impl;
+ io_ctx_impl->get();
+ return *this;
+}
+
+librados::IoCtx::~IoCtx()
+{
+ close();
+}
+
+void librados::IoCtx::close()
+{
+ if (io_ctx_impl)
+ io_ctx_impl->put();
+ io_ctx_impl = 0;
+}
+
+void librados::IoCtx::dup(const IoCtx& rhs)
+{
+ if (io_ctx_impl)
+ io_ctx_impl->put();
+ io_ctx_impl = new IoCtxImpl();
+ io_ctx_impl->get();
+ io_ctx_impl->dup(*rhs.io_ctx_impl);
+}
+
+int librados::IoCtx::set_auid(uint64_t auid_)
+{
+ return -EOPNOTSUPP;
+}
+
+int librados::IoCtx::set_auid_async(uint64_t auid_, PoolAsyncCompletion *c)
+{
+ return -EOPNOTSUPP;
+}
+
+int librados::IoCtx::get_auid(uint64_t *auid_)
+{
+ return -EOPNOTSUPP;
+}
+
+bool librados::IoCtx::pool_requires_alignment()
+{
+ return io_ctx_impl->client->pool_requires_alignment(get_id());
+}
+
+int librados::IoCtx::pool_requires_alignment2(bool *requires)
+{
+ return io_ctx_impl->client->pool_requires_alignment2(get_id(), requires);
+}
+
+uint64_t librados::IoCtx::pool_required_alignment()
+{
+ return io_ctx_impl->client->pool_required_alignment(get_id());
+}
+
+int librados::IoCtx::pool_required_alignment2(uint64_t *alignment)
+{
+ return io_ctx_impl->client->pool_required_alignment2(get_id(), alignment);
+}
+
+std::string librados::IoCtx::get_pool_name()
+{
+ std::string s;
+ io_ctx_impl->client->pool_get_name(get_id(), &s);
+ return s;
+}
+
+std::string librados::IoCtx::get_pool_name() const
+{
+ return io_ctx_impl->get_cached_pool_name();
+}
+
+uint64_t librados::IoCtx::get_instance_id() const
+{
+ return io_ctx_impl->client->get_instance_id();
+}
+
+int librados::IoCtx::create(const std::string& oid, bool exclusive)
+{
+ object_t obj(oid);
+ return io_ctx_impl->create(obj, exclusive);
+}
+
+int librados::IoCtx::create(const std::string& oid, bool exclusive,
+ const std::string& category) // unused
+{
+ object_t obj(oid);
+ return io_ctx_impl->create(obj, exclusive);
+}
+
+int librados::IoCtx::write(const std::string& oid, bufferlist& bl, size_t len, uint64_t off)
+{
+ object_t obj(oid);
+ return io_ctx_impl->write(obj, bl, len, off);
+}
+
+int librados::IoCtx::append(const std::string& oid, bufferlist& bl, size_t len)
+{
+ object_t obj(oid);
+ return io_ctx_impl->append(obj, bl, len);
+}
+
+int librados::IoCtx::write_full(const std::string& oid, bufferlist& bl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->write_full(obj, bl);
+}
+
+int librados::IoCtx::writesame(const std::string& oid, bufferlist& bl,
+ size_t write_len, uint64_t off)
+{
+ object_t obj(oid);
+ return io_ctx_impl->writesame(obj, bl, write_len, off);
+}
+
+
+int librados::IoCtx::read(const std::string& oid, bufferlist& bl, size_t len, uint64_t off)
+{
+ object_t obj(oid);
+ return io_ctx_impl->read(obj, bl, len, off);
+}
+
+int librados::IoCtx::checksum(const std::string& oid,
+ rados_checksum_type_t type,
+ const bufferlist &init_value_bl, size_t len,
+ uint64_t off, size_t chunk_size, bufferlist *pbl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->checksum(obj, get_checksum_op_type(type), init_value_bl,
+ len, off, chunk_size, pbl);
+}
+
+int librados::IoCtx::remove(const std::string& oid)
+{
+ object_t obj(oid);
+ return io_ctx_impl->remove(obj);
+}
+
+int librados::IoCtx::remove(const std::string& oid, int flags)
+{
+ object_t obj(oid);
+ return io_ctx_impl->remove(obj, flags);
+}
+
+int librados::IoCtx::trunc(const std::string& oid, uint64_t size)
+{
+ object_t obj(oid);
+ return io_ctx_impl->trunc(obj, size);
+}
+
+int librados::IoCtx::mapext(const std::string& oid, uint64_t off, size_t len,
+ std::map<uint64_t,uint64_t>& m)
+{
+ object_t obj(oid);
+ return io_ctx_impl->mapext(obj, off, len, m);
+}
+
+int librados::IoCtx::cmpext(const std::string& oid, uint64_t off, bufferlist& cmp_bl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->cmpext(obj, off, cmp_bl);
+}
+
+int librados::IoCtx::sparse_read(const std::string& oid, std::map<uint64_t,uint64_t>& m,
+ bufferlist& bl, size_t len, uint64_t off)
+{
+ object_t obj(oid);
+ return io_ctx_impl->sparse_read(obj, m, bl, len, off);
+}
+
+int librados::IoCtx::getxattr(const std::string& oid, const char *name, bufferlist& bl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->getxattr(obj, name, bl);
+}
+
+int librados::IoCtx::getxattrs(const std::string& oid, map<std::string, bufferlist>& attrset)
+{
+ object_t obj(oid);
+ return io_ctx_impl->getxattrs(obj, attrset);
+}
+
+int librados::IoCtx::setxattr(const std::string& oid, const char *name, bufferlist& bl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->setxattr(obj, name, bl);
+}
+
+int librados::IoCtx::rmxattr(const std::string& oid, const char *name)
+{
+ object_t obj(oid);
+ return io_ctx_impl->rmxattr(obj, name);
+}
+
+int librados::IoCtx::stat(const std::string& oid, uint64_t *psize, time_t *pmtime)
+{
+ object_t obj(oid);
+ return io_ctx_impl->stat(obj, psize, pmtime);
+}
+
+int librados::IoCtx::stat2(const std::string& oid, uint64_t *psize, struct timespec *pts)
+{
+ object_t obj(oid);
+ return io_ctx_impl->stat2(obj, psize, pts);
+}
+
+int librados::IoCtx::exec(const std::string& oid, const char *cls, const char *method,
+ bufferlist& inbl, bufferlist& outbl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->exec(obj, cls, method, inbl, outbl);
+}
+
+int librados::IoCtx::tmap_update(const std::string& oid, bufferlist& cmdbl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->tmap_update(obj, cmdbl);
+}
+
+int librados::IoCtx::tmap_put(const std::string& oid, bufferlist& bl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->tmap_put(obj, bl);
+}
+
+int librados::IoCtx::tmap_get(const std::string& oid, bufferlist& bl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->tmap_get(obj, bl);
+}
+
+int librados::IoCtx::tmap_to_omap(const std::string& oid, bool nullok)
+{
+ object_t obj(oid);
+ return io_ctx_impl->tmap_to_omap(obj, nullok);
+}
+
+int librados::IoCtx::omap_get_vals(const std::string& oid,
+ const std::string& start_after,
+ uint64_t max_return,
+ std::map<std::string, bufferlist> *out_vals)
+{
+ return omap_get_vals(oid, start_after, string(), max_return, out_vals);
+}
+
+int librados::IoCtx::omap_get_vals2(
+ const std::string& oid,
+ const std::string& start_after,
+ uint64_t max_return,
+ std::map<std::string, bufferlist> *out_vals,
+ bool *pmore)
+{
+ ObjectReadOperation op;
+ int r;
+ op.omap_get_vals2(start_after, max_return, out_vals, pmore, &r);
+ bufferlist bl;
+ int ret = operate(oid, &op, &bl);
+ if (ret < 0)
+ return ret;
+ return r;
+}
+
+int librados::IoCtx::omap_get_keys(const std::string& oid,
+ const std::string& orig_start_after,
+ uint64_t max_return,
+ std::set<std::string> *out_keys)
+{
+ bool first = true;
+ string start_after = orig_start_after;
+ bool more = true;
+ while (max_return > 0 && more) {
+ std::set<std::string> out;
+ ObjectReadOperation op;
+ op.omap_get_keys2(start_after, max_return, &out, &more, nullptr);
+ bufferlist bl;
+ int ret = operate(oid, &op, &bl);
+ if (ret < 0) {
+ return ret;
+ }
+ if (more) {
+ if (out.empty()) {
+ return -EINVAL; // wth
+ }
+ start_after = *out.rbegin();
+ }
+ if (out.size() <= max_return) {
+ max_return -= out.size();
+ } else {
+ max_return = 0;
+ }
+ if (first) {
+ out_keys->swap(out);
+ first = false;
+ } else {
+ out_keys->insert(out.begin(), out.end());
+ out.clear();
+ }
+ }
+ return 0;
+}
+
+int librados::IoCtx::omap_get_keys2(
+ const std::string& oid,
+ const std::string& start_after,
+ uint64_t max_return,
+ std::set<std::string> *out_keys,
+ bool *pmore)
+{
+ ObjectReadOperation op;
+ int r;
+ op.omap_get_keys2(start_after, max_return, out_keys, pmore, &r);
+ bufferlist bl;
+ int ret = operate(oid, &op, &bl);
+ if (ret < 0)
+ return ret;
+ return r;
+}
+
+int librados::IoCtx::omap_get_header(const std::string& oid,
+ bufferlist *bl)
+{
+ ObjectReadOperation op;
+ int r;
+ op.omap_get_header(bl, &r);
+ bufferlist b;
+ int ret = operate(oid, &op, &b);
+ if (ret < 0)
+ return ret;
+
+ return r;
+}
+
+int librados::IoCtx::omap_get_vals_by_keys(const std::string& oid,
+ const std::set<std::string>& keys,
+ std::map<std::string, bufferlist> *vals)
+{
+ ObjectReadOperation op;
+ int r;
+ bufferlist bl;
+ op.omap_get_vals_by_keys(keys, vals, &r);
+ int ret = operate(oid, &op, &bl);
+ if (ret < 0)
+ return ret;
+
+ return r;
+}
+
+int librados::IoCtx::omap_set(const std::string& oid,
+ const map<string, bufferlist>& m)
+{
+ ObjectWriteOperation op;
+ op.omap_set(m);
+ return operate(oid, &op);
+}
+
+int librados::IoCtx::omap_set_header(const std::string& oid,
+ const bufferlist& bl)
+{
+ ObjectWriteOperation op;
+ op.omap_set_header(bl);
+ return operate(oid, &op);
+}
+
+int librados::IoCtx::omap_clear(const std::string& oid)
+{
+ ObjectWriteOperation op;
+ op.omap_clear();
+ return operate(oid, &op);
+}
+
+int librados::IoCtx::omap_rm_keys(const std::string& oid,
+ const std::set<std::string>& keys)
+{
+ ObjectWriteOperation op;
+ op.omap_rm_keys(keys);
+ return operate(oid, &op);
+}
+
+int librados::IoCtx::operate(const std::string& oid, librados::ObjectWriteOperation *o)
+{
+ object_t obj(oid);
+ return io_ctx_impl->operate(obj, &o->impl->o, (ceph::real_time *)o->impl->prt);
+}
+
+int librados::IoCtx::operate(const std::string& oid, librados::ObjectReadOperation *o, bufferlist *pbl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->operate_read(obj, &o->impl->o, pbl);
+}
+
+int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
+ librados::ObjectWriteOperation *o)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
+ io_ctx_impl->snapc, 0);
+}
+int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
+ ObjectWriteOperation *o, int flags)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
+ io_ctx_impl->snapc,
+ translate_flags(flags));
+}
+
+int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
+ librados::ObjectWriteOperation *o,
+ snap_t snap_seq, std::vector<snap_t>& snaps)
+{
+ object_t obj(oid);
+ vector<snapid_t> snv;
+ snv.resize(snaps.size());
+ for (size_t i = 0; i < snaps.size(); ++i)
+ snv[i] = snaps[i];
+ SnapContext snapc(snap_seq, snv);
+ return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
+ snapc, 0);
+}
+
+int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
+ librados::ObjectWriteOperation *o,
+ snap_t snap_seq, std::vector<snap_t>& snaps,
+ const blkin_trace_info *trace_info)
+{
+ object_t obj(oid);
+ vector<snapid_t> snv;
+ snv.resize(snaps.size());
+ for (size_t i = 0; i < snaps.size(); ++i)
+ snv[i] = snaps[i];
+ SnapContext snapc(snap_seq, snv);
+ return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
+ snapc, 0, trace_info);
+}
+
+int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
+ librados::ObjectWriteOperation *o,
+ snap_t snap_seq, std::vector<snap_t>& snaps, int flags,
+ const blkin_trace_info *trace_info)
+{
+ object_t obj(oid);
+ vector<snapid_t> snv;
+ snv.resize(snaps.size());
+ for (size_t i = 0; i < snaps.size(); ++i)
+ snv[i] = snaps[i];
+ SnapContext snapc(snap_seq, snv);
+ return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc, snapc,
+ translate_flags(flags), trace_info);
+}
+
+int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
+ librados::ObjectReadOperation *o,
+ bufferlist *pbl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
+ 0, pbl);
+}
+
+// deprecated
+int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
+ librados::ObjectReadOperation *o,
+ snap_t snapid_unused_deprecated,
+ int flags, bufferlist *pbl)
+{
+ object_t obj(oid);
+ int op_flags = 0;
+ if (flags & OPERATION_BALANCE_READS)
+ op_flags |= CEPH_OSD_FLAG_BALANCE_READS;
+ if (flags & OPERATION_LOCALIZE_READS)
+ op_flags |= CEPH_OSD_FLAG_LOCALIZE_READS;
+ if (flags & OPERATION_ORDER_READS_WRITES)
+ op_flags |= CEPH_OSD_FLAG_RWORDERED;
+
+ return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
+ op_flags, pbl);
+}
+
+int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
+ librados::ObjectReadOperation *o,
+ int flags, bufferlist *pbl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
+ translate_flags(flags), pbl);
+}
+
+int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
+ librados::ObjectReadOperation *o,
+ int flags, bufferlist *pbl, const blkin_trace_info *trace_info)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
+ translate_flags(flags), pbl, trace_info);
+}
+
+void librados::IoCtx::snap_set_read(snap_t seq)
+{
+ io_ctx_impl->set_snap_read(seq);
+}
+
+int librados::IoCtx::selfmanaged_snap_set_write_ctx(snap_t seq, vector<snap_t>& snaps)
+{
+ vector<snapid_t> snv;
+ snv.resize(snaps.size());
+ for (unsigned i=0; i<snaps.size(); i++)
+ snv[i] = snaps[i];
+ return io_ctx_impl->set_snap_write_context(seq, snv);
+}
+
+int librados::IoCtx::snap_create(const char *snapname)
+{
+ return io_ctx_impl->snap_create(snapname);
+}
+
+int librados::IoCtx::snap_lookup(const char *name, snap_t *snapid)
+{
+ return io_ctx_impl->snap_lookup(name, snapid);
+}
+
+int librados::IoCtx::snap_get_stamp(snap_t snapid, time_t *t)
+{
+ return io_ctx_impl->snap_get_stamp(snapid, t);
+}
+
+int librados::IoCtx::snap_get_name(snap_t snapid, std::string *s)
+{
+ return io_ctx_impl->snap_get_name(snapid, s);
+}
+
+int librados::IoCtx::snap_remove(const char *snapname)
+{
+ return io_ctx_impl->snap_remove(snapname);
+}
+
+int librados::IoCtx::snap_list(std::vector<snap_t> *snaps)
+{
+ return io_ctx_impl->snap_list(snaps);
+}
+
+int librados::IoCtx::snap_rollback(const std::string& oid, const char *snapname)
+{
+ return io_ctx_impl->rollback(oid, snapname);
+}
+
+// Deprecated name kept for backward compatibility
+int librados::IoCtx::rollback(const std::string& oid, const char *snapname)
+{
+ return snap_rollback(oid, snapname);
+}
+
+int librados::IoCtx::selfmanaged_snap_create(uint64_t *snapid)
+{
+ return io_ctx_impl->selfmanaged_snap_create(snapid);
+}
+
+void librados::IoCtx::aio_selfmanaged_snap_create(uint64_t *snapid,
+ AioCompletion *c)
+{
+ io_ctx_impl->aio_selfmanaged_snap_create(snapid, c->pc);
+}
+
+int librados::IoCtx::selfmanaged_snap_remove(uint64_t snapid)
+{
+ return io_ctx_impl->selfmanaged_snap_remove(snapid);
+}
+
+void librados::IoCtx::aio_selfmanaged_snap_remove(uint64_t snapid,
+ AioCompletion *c)
+{
+ io_ctx_impl->aio_selfmanaged_snap_remove(snapid, c->pc);
+}
+
+int librados::IoCtx::selfmanaged_snap_rollback(const std::string& oid, uint64_t snapid)
+{
+ return io_ctx_impl->selfmanaged_snap_rollback_object(oid,
+ io_ctx_impl->snapc,
+ snapid);
+}
+
+int librados::IoCtx::lock_exclusive(const std::string &oid, const std::string &name,
+ const std::string &cookie,
+ const std::string &description,
+ struct timeval * duration, uint8_t flags)
+{
+ utime_t dur = utime_t();
+ if (duration)
+ dur.set_from_timeval(duration);
+
+ return rados::cls::lock::lock(this, oid, name, LOCK_EXCLUSIVE, cookie, "",
+ description, dur, flags);
+}
+
+int librados::IoCtx::lock_shared(const std::string &oid, const std::string &name,
+ const std::string &cookie, const std::string &tag,
+ const std::string &description,
+ struct timeval * duration, uint8_t flags)
+{
+ utime_t dur = utime_t();
+ if (duration)
+ dur.set_from_timeval(duration);
+
+ return rados::cls::lock::lock(this, oid, name, LOCK_SHARED, cookie, tag,
+ description, dur, flags);
+}
+
+int librados::IoCtx::unlock(const std::string &oid, const std::string &name,
+ const std::string &cookie)
+{
+ return rados::cls::lock::unlock(this, oid, name, cookie);
+}
+
+struct AioUnlockCompletion : public librados::ObjectOperationCompletion {
+ librados::AioCompletionImpl *completion;
+ AioUnlockCompletion(librados::AioCompletion *c) : completion(c->pc) {
+ completion->get();
+ };
+ void handle_completion(int r, bufferlist& outbl) override {
+ rados_callback_t cb = completion->callback_complete;
+ void *cb_arg = completion->callback_complete_arg;
+ cb(completion, cb_arg);
+ completion->lock.Lock();
+ completion->callback_complete = NULL;
+ completion->cond.Signal();
+ completion->put_unlock();
+ }
+};
+
+int librados::IoCtx::aio_unlock(const std::string &oid, const std::string &name,
+ const std::string &cookie, AioCompletion *c)
+{
+ return rados::cls::lock::aio_unlock(this, oid, name, cookie, c);
+}
+
+int librados::IoCtx::break_lock(const std::string &oid, const std::string &name,
+ const std::string &client, const std::string &cookie)
+{
+ entity_name_t locker;
+ if (!locker.parse(client))
+ return -EINVAL;
+ return rados::cls::lock::break_lock(this, oid, name, cookie, locker);
+}
+
+int librados::IoCtx::list_lockers(const std::string &oid, const std::string &name,
+ int *exclusive,
+ std::string *tag,
+ std::list<librados::locker_t> *lockers)
+{
+ std::list<librados::locker_t> tmp_lockers;
+ map<rados::cls::lock::locker_id_t, rados::cls::lock::locker_info_t> rados_lockers;
+ std::string tmp_tag;
+ ClsLockType tmp_type;
+ int r = rados::cls::lock::get_lock_info(this, oid, name, &rados_lockers, &tmp_type, &tmp_tag);
+ if (r < 0)
+ return r;
+
+ map<rados::cls::lock::locker_id_t, rados::cls::lock::locker_info_t>::iterator map_it;
+ for (map_it = rados_lockers.begin(); map_it != rados_lockers.end(); ++map_it) {
+ librados::locker_t locker;
+ locker.client = stringify(map_it->first.locker);
+ locker.cookie = map_it->first.cookie;
+ locker.address = stringify(map_it->second.addr);
+ tmp_lockers.push_back(locker);
+ }
+
+ if (lockers)
+ *lockers = tmp_lockers;
+ if (tag)
+ *tag = tmp_tag;
+ if (exclusive) {
+ if (tmp_type == LOCK_EXCLUSIVE)
+ *exclusive = 1;
+ else
+ *exclusive = 0;
+ }
+
+ return tmp_lockers.size();
+}
+
+librados::NObjectIterator librados::IoCtx::nobjects_begin()
+{
+ bufferlist bl;
+ return nobjects_begin(bl);
+}
+
+librados::NObjectIterator librados::IoCtx::nobjects_begin(
+ const bufferlist &filter)
+{
+ rados_list_ctx_t listh;
+ rados_nobjects_list_open(io_ctx_impl, &listh);
+ NObjectIterator iter((ObjListCtx*)listh);
+ if (filter.length() > 0) {
+ iter.set_filter(filter);
+ }
+ iter.get_next();
+ return iter;
+}
+
+librados::NObjectIterator librados::IoCtx::nobjects_begin(uint32_t pos)
+{
+ bufferlist bl;
+ return nobjects_begin(pos, bl);
+}
+
+librados::NObjectIterator librados::IoCtx::nobjects_begin(
+ uint32_t pos, const bufferlist &filter)
+{
+ rados_list_ctx_t listh;
+ rados_nobjects_list_open(io_ctx_impl, &listh);
+ NObjectIterator iter((ObjListCtx*)listh);
+ if (filter.length() > 0) {
+ iter.set_filter(filter);
+ }
+ iter.seek(pos);
+ return iter;
+}
+
+librados::NObjectIterator librados::IoCtx::nobjects_begin(const ObjectCursor& cursor)
+{
+ bufferlist bl;
+ return nobjects_begin(cursor, bl);
+}
+
+librados::NObjectIterator librados::IoCtx::nobjects_begin(
+ const ObjectCursor& cursor, const bufferlist &filter)
+{
+ rados_list_ctx_t listh;
+ rados_nobjects_list_open(io_ctx_impl, &listh);
+ NObjectIterator iter((ObjListCtx*)listh);
+ if (filter.length() > 0) {
+ iter.set_filter(filter);
+ }
+ iter.seek(cursor);
+ return iter;
+}
+
+const librados::NObjectIterator& librados::IoCtx::nobjects_end() const
+{
+ return NObjectIterator::__EndObjectIterator;
+}
+
+int librados::IoCtx::hit_set_list(uint32_t hash, AioCompletion *c,
+ std::list< std::pair<time_t, time_t> > *pls)
+{
+ return io_ctx_impl->hit_set_list(hash, c->pc, pls);
+}
+
+int librados::IoCtx::hit_set_get(uint32_t hash, AioCompletion *c, time_t stamp,
+ bufferlist *pbl)
+{
+ return io_ctx_impl->hit_set_get(hash, c->pc, stamp, pbl);
+}
+
+
+
+uint64_t librados::IoCtx::get_last_version()
+{
+ return io_ctx_impl->last_version();
+}
+
+int librados::IoCtx::aio_read(const std::string& oid, librados::AioCompletion *c,
+ bufferlist *pbl, size_t len, uint64_t off)
+{
+ return io_ctx_impl->aio_read(oid, c->pc, pbl, len, off,
+ io_ctx_impl->snap_seq);
+}
+
+int librados::IoCtx::aio_read(const std::string& oid, librados::AioCompletion *c,
+ bufferlist *pbl, size_t len, uint64_t off,
+ uint64_t snapid)
+{
+ return io_ctx_impl->aio_read(oid, c->pc, pbl, len, off, snapid);
+}
+
+int librados::IoCtx::aio_exec(const std::string& oid,
+ librados::AioCompletion *c, const char *cls,
+ const char *method, bufferlist& inbl,
+ bufferlist *outbl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_exec(obj, c->pc, cls, method, inbl, outbl);
+}
+
+int librados::IoCtx::aio_cmpext(const std::string& oid,
+ librados::AioCompletion *c,
+ uint64_t off,
+ bufferlist& cmp_bl)
+{
+ return io_ctx_impl->aio_cmpext(oid, c->pc, off, cmp_bl);
+}
+
+int librados::IoCtx::aio_sparse_read(const std::string& oid, librados::AioCompletion *c,
+ std::map<uint64_t,uint64_t> *m, bufferlist *data_bl,
+ size_t len, uint64_t off)
+{
+ return io_ctx_impl->aio_sparse_read(oid, c->pc,
+ m, data_bl, len, off,
+ io_ctx_impl->snap_seq);
+}
+
+int librados::IoCtx::aio_sparse_read(const std::string& oid, librados::AioCompletion *c,
+ std::map<uint64_t,uint64_t> *m, bufferlist *data_bl,
+ size_t len, uint64_t off, uint64_t snapid)
+{
+ return io_ctx_impl->aio_sparse_read(oid, c->pc,
+ m, data_bl, len, off, snapid);
+}
+
+int librados::IoCtx::aio_write(const std::string& oid, librados::AioCompletion *c,
+ const bufferlist& bl, size_t len, uint64_t off)
+{
+ return io_ctx_impl->aio_write(oid, c->pc, bl, len, off);
+}
+
+int librados::IoCtx::aio_append(const std::string& oid, librados::AioCompletion *c,
+ const bufferlist& bl, size_t len)
+{
+ return io_ctx_impl->aio_append(oid, c->pc, bl, len);
+}
+
+int librados::IoCtx::aio_write_full(const std::string& oid, librados::AioCompletion *c,
+ const bufferlist& bl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_write_full(obj, c->pc, bl);
+}
+
+int librados::IoCtx::aio_writesame(const std::string& oid, librados::AioCompletion *c,
+ const bufferlist& bl, size_t write_len,
+ uint64_t off)
+{
+ return io_ctx_impl->aio_writesame(oid, c->pc, bl, write_len, off);
+}
+
+
+int librados::IoCtx::aio_remove(const std::string& oid, librados::AioCompletion *c)
+{
+ return io_ctx_impl->aio_remove(oid, c->pc);
+}
+
+int librados::IoCtx::aio_remove(const std::string& oid, librados::AioCompletion *c, int flags)
+{
+ return io_ctx_impl->aio_remove(oid, c->pc, flags);
+}
+
+int librados::IoCtx::aio_flush_async(librados::AioCompletion *c)
+{
+ io_ctx_impl->flush_aio_writes_async(c->pc);
+ return 0;
+}
+
+int librados::IoCtx::aio_flush()
+{
+ io_ctx_impl->flush_aio_writes();
+ return 0;
+}
+
+struct AioGetxattrDataPP {
+ AioGetxattrDataPP(librados::AioCompletionImpl *c, bufferlist *_bl) :
+ bl(_bl), completion(c) {}
+ bufferlist *bl;
+ struct librados::C_AioCompleteAndSafe completion;
+};
+
+static void rados_aio_getxattr_completepp(rados_completion_t c, void *arg) {
+ AioGetxattrDataPP *cdata = reinterpret_cast<AioGetxattrDataPP*>(arg);
+ int rc = rados_aio_get_return_value(c);
+ if (rc >= 0) {
+ rc = cdata->bl->length();
+ }
+ cdata->completion.finish(rc);
+ delete cdata;
+}
+
+int librados::IoCtx::aio_getxattr(const std::string& oid, librados::AioCompletion *c,
+ const char *name, bufferlist& bl)
+{
+ // create data object to be passed to async callback
+ AioGetxattrDataPP *cdata = new AioGetxattrDataPP(c->pc, &bl);
+ if (!cdata) {
+ return -ENOMEM;
+ }
+ // create completion callback
+ librados::AioCompletionImpl *comp = new librados::AioCompletionImpl;
+ comp->set_complete_callback(cdata, rados_aio_getxattr_completepp);
+ // call actual getxattr from IoCtxImpl
+ object_t obj(oid);
+ return io_ctx_impl->aio_getxattr(obj, comp, name, bl);
+}
+
+int librados::IoCtx::aio_getxattrs(const std::string& oid, AioCompletion *c,
+ map<std::string, bufferlist>& attrset)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_getxattrs(obj, c->pc, attrset);
+}
+
+int librados::IoCtx::aio_setxattr(const std::string& oid, AioCompletion *c,
+ const char *name, bufferlist& bl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_setxattr(obj, c->pc, name, bl);
+}
+
+int librados::IoCtx::aio_rmxattr(const std::string& oid, AioCompletion *c,
+ const char *name)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_rmxattr(obj, c->pc, name);
+}
+
+int librados::IoCtx::aio_stat(const std::string& oid, librados::AioCompletion *c,
+ uint64_t *psize, time_t *pmtime)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_stat(obj, c->pc, psize, pmtime);
+}
+
+int librados::IoCtx::aio_cancel(librados::AioCompletion *c)
+{
+ return io_ctx_impl->aio_cancel(c->pc);
+}
+
+int librados::IoCtx::watch(const string& oid, uint64_t ver, uint64_t *cookie,
+ librados::WatchCtx *ctx)
+{
+ object_t obj(oid);
+ return io_ctx_impl->watch(obj, cookie, ctx, NULL);
+}
+
+int librados::IoCtx::watch2(const string& oid, uint64_t *cookie,
+ librados::WatchCtx2 *ctx2)
+{
+ object_t obj(oid);
+ return io_ctx_impl->watch(obj, cookie, NULL, ctx2);
+}
+
+int librados::IoCtx::watch3(const string& oid, uint64_t *cookie,
+ librados::WatchCtx2 *ctx2, uint32_t timeout)
+{
+ object_t obj(oid);
+ return io_ctx_impl->watch(obj, cookie, NULL, ctx2, timeout);
+}
+
+int librados::IoCtx::aio_watch(const string& oid, AioCompletion *c,
+ uint64_t *cookie,
+ librados::WatchCtx2 *ctx2)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_watch(obj, c->pc, cookie, NULL, ctx2);
+}
+
+int librados::IoCtx::aio_watch2(const string& oid, AioCompletion *c,
+ uint64_t *cookie,
+ librados::WatchCtx2 *ctx2,
+ uint32_t timeout)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_watch(obj, c->pc, cookie, NULL, ctx2, timeout);
+}
+
+int librados::IoCtx::unwatch(const string& oid, uint64_t handle)
+{
+ return io_ctx_impl->unwatch(handle);
+}
+
+int librados::IoCtx::unwatch2(uint64_t handle)
+{
+ return io_ctx_impl->unwatch(handle);
+}
+
+int librados::IoCtx::aio_unwatch(uint64_t handle, AioCompletion *c)
+{
+ return io_ctx_impl->aio_unwatch(handle, c->pc);
+}
+
+int librados::IoCtx::watch_check(uint64_t handle)
+{
+ return io_ctx_impl->watch_check(handle);
+}
+
+int librados::IoCtx::notify(const string& oid, uint64_t ver, bufferlist& bl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->notify(obj, bl, 0, NULL, NULL, NULL);
+}
+
+int librados::IoCtx::notify2(const string& oid, bufferlist& bl,
+ uint64_t timeout_ms, bufferlist *preplybl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->notify(obj, bl, timeout_ms, preplybl, NULL, NULL);
+}
+
+int librados::IoCtx::aio_notify(const string& oid, AioCompletion *c,
+ bufferlist& bl, uint64_t timeout_ms,
+ bufferlist *preplybl)
+{
+ object_t obj(oid);
+ return io_ctx_impl->aio_notify(obj, c->pc, bl, timeout_ms, preplybl, NULL,
+ NULL);
+}
+
+void librados::IoCtx::notify_ack(const std::string& o,
+ uint64_t notify_id, uint64_t handle,
+ bufferlist& bl)
+{
+ io_ctx_impl->notify_ack(o, notify_id, handle, bl);
+}
+
+int librados::IoCtx::list_watchers(const std::string& oid,
+ std::list<obj_watch_t> *out_watchers)
+{
+ ObjectReadOperation op;
+ int r;
+ op.list_watchers(out_watchers, &r);
+ bufferlist bl;
+ int ret = operate(oid, &op, &bl);
+ if (ret < 0)
+ return ret;
+
+ return r;
+}
+
+int librados::IoCtx::list_snaps(const std::string& oid,
+ snap_set_t *out_snaps)
+{
+ ObjectReadOperation op;
+ int r;
+ if (io_ctx_impl->snap_seq != CEPH_SNAPDIR)
+ return -EINVAL;
+ op.list_snaps(out_snaps, &r);
+ bufferlist bl;
+ int ret = operate(oid, &op, &bl);
+ if (ret < 0)
+ return ret;
+
+ return r;
+}
+
+void librados::IoCtx::set_notify_timeout(uint32_t timeout)
+{
+ io_ctx_impl->set_notify_timeout(timeout);
+}
+
+int librados::IoCtx::set_alloc_hint(const std::string& o,
+ uint64_t expected_object_size,
+ uint64_t expected_write_size)
+{
+ object_t oid(o);
+ return io_ctx_impl->set_alloc_hint(oid, expected_object_size,
+ expected_write_size, 0);
+}
+
+int librados::IoCtx::set_alloc_hint2(const std::string& o,
+ uint64_t expected_object_size,
+ uint64_t expected_write_size,
+ uint32_t flags)
+{
+ object_t oid(o);
+ return io_ctx_impl->set_alloc_hint(oid, expected_object_size,
+ expected_write_size, flags);
+}
+
+void librados::IoCtx::set_assert_version(uint64_t ver)
+{
+ io_ctx_impl->set_assert_version(ver);
+}
+
+void librados::IoCtx::locator_set_key(const string& key)
+{
+ io_ctx_impl->oloc.key = key;
+}
+
+void librados::IoCtx::set_namespace(const string& nspace)
+{
+ io_ctx_impl->oloc.nspace = nspace;
+}
+
+std::string librados::IoCtx::get_namespace() const
+{
+ return io_ctx_impl->oloc.nspace;
+}
+
+int64_t librados::IoCtx::get_id()
+{
+ return io_ctx_impl->get_id();
+}
+
+uint32_t librados::IoCtx::get_object_hash_position(const std::string& oid)
+{
+ uint32_t hash;
+ int r = io_ctx_impl->get_object_hash_position(oid, &hash);
+ if (r < 0)
+ hash = 0;
+ return hash;
+}
+
+uint32_t librados::IoCtx::get_object_pg_hash_position(const std::string& oid)
+{
+ uint32_t hash;
+ int r = io_ctx_impl->get_object_pg_hash_position(oid, &hash);
+ if (r < 0)
+ hash = 0;
+ return hash;
+}
+
+int librados::IoCtx::get_object_hash_position2(
+ const std::string& oid, uint32_t *hash_position)
+{
+ return io_ctx_impl->get_object_hash_position(oid, hash_position);
+}
+
+int librados::IoCtx::get_object_pg_hash_position2(
+ const std::string& oid, uint32_t *pg_hash_position)
+{
+ return io_ctx_impl->get_object_pg_hash_position(oid, pg_hash_position);
+}
+
+librados::config_t librados::IoCtx::cct()
+{
+ return (config_t)io_ctx_impl->client->cct;
+}
+
+librados::IoCtx::IoCtx(IoCtxImpl *io_ctx_impl_)
+ : io_ctx_impl(io_ctx_impl_)
+{
+}
+
+void librados::IoCtx::set_osdmap_full_try()
+{
+ io_ctx_impl->objecter->set_osdmap_full_try();
+}
+
+void librados::IoCtx::unset_osdmap_full_try()
+{
+ io_ctx_impl->objecter->unset_osdmap_full_try();
+}
+
+///////////////////////////// Rados //////////////////////////////
+void librados::Rados::version(int *major, int *minor, int *extra)
+{
+ rados_version(major, minor, extra);
+}
+
+librados::Rados::Rados() : client(NULL)
+{
+}
+
+librados::Rados::Rados(IoCtx &ioctx)
+{
+ client = ioctx.io_ctx_impl->client;
+ ceph_assert(client != NULL);
+ client->get();
+}
+
+librados::Rados::~Rados()
+{
+ shutdown();
+}
+
+int librados::Rados::init(const char * const id)
+{
+ return rados_create((rados_t *)&client, id);
+}
+
+int librados::Rados::init2(const char * const name,
+ const char * const clustername, uint64_t flags)
+{
+ return rados_create2((rados_t *)&client, clustername, name, flags);
+}
+
+int librados::Rados::init_with_context(config_t cct_)
+{
+ return rados_create_with_context((rados_t *)&client, (rados_config_t)cct_);
+}
+
+int librados::Rados::connect()
+{
+ return client->connect();
+}
+
+librados::config_t librados::Rados::cct()
+{
+ return (config_t)client->cct;
+}
+
+int librados::Rados::watch_flush()
+{
+ if (!client)
+ return -EINVAL;
+ return client->watch_flush();
+}
+
+int librados::Rados::aio_watch_flush(AioCompletion *c)
+{
+ if (!client)
+ return -EINVAL;
+ return client->async_watch_flush(c->pc);
+}
+
+void librados::Rados::shutdown()
+{
+ if (!client)
+ return;
+ if (client->put()) {
+ client->shutdown();
+ delete client;
+ client = NULL;
+ }
+}
+
+uint64_t librados::Rados::get_instance_id()
+{
+ return client->get_instance_id();
+}
+
+int librados::Rados::get_min_compatible_osd(int8_t* require_osd_release)
+{
+ return client->get_min_compatible_osd(require_osd_release);
+}
+
+int librados::Rados::get_min_compatible_client(int8_t* min_compat_client,
+ int8_t* require_min_compat_client)
+{
+ return client->get_min_compatible_client(min_compat_client,
+ require_min_compat_client);
+}
+
+int librados::Rados::conf_read_file(const char * const path) const
+{
+ return rados_conf_read_file((rados_t)client, path);
+}
+
+int librados::Rados::conf_parse_argv(int argc, const char ** argv) const
+{
+ return rados_conf_parse_argv((rados_t)client, argc, argv);
+}
+
+int librados::Rados::conf_parse_argv_remainder(int argc, const char ** argv,
+ const char ** remargv) const
+{
+ return rados_conf_parse_argv_remainder((rados_t)client, argc, argv, remargv);
+}
+
+int librados::Rados::conf_parse_env(const char *name) const
+{
+ return rados_conf_parse_env((rados_t)client, name);
+}
+
+int librados::Rados::conf_set(const char *option, const char *value)
+{
+ return rados_conf_set((rados_t)client, option, value);
+}
+
+int librados::Rados::conf_get(const char *option, std::string &val)
+{
+ char *str = NULL;
+ const auto& conf = client->cct->_conf;
+ int ret = conf.get_val(option, &str, -1);
+ if (ret) {
+ free(str);
+ return ret;
+ }
+ val = str;
+ free(str);
+ return 0;
+}
+
+int librados::Rados::service_daemon_register(
+ const std::string& service, ///< service name (e.g., 'rgw')
+ const std::string& name, ///< daemon name (e.g., 'gwfoo')
+ const std::map<std::string,std::string>& metadata) ///< static metadata about daemon
+{
+ return client->service_daemon_register(service, name, metadata);
+}
+
+int librados::Rados::service_daemon_update_status(
+ std::map<std::string,std::string>&& status)
+{
+ return client->service_daemon_update_status(std::move(status));
+}
+
+int librados::Rados::pool_create(const char *name)
+{
+ string str(name);
+ return client->pool_create(str);
+}
+
+int librados::Rados::pool_create(const char *name, uint64_t auid)
+{
+ if (auid != CEPH_AUTH_UID_DEFAULT) {
+ return -EINVAL;
+ }
+ string str(name);
+ return client->pool_create(str);
+}
+
+int librados::Rados::pool_create(const char *name, uint64_t auid, __u8 crush_rule)
+{
+ if (auid != CEPH_AUTH_UID_DEFAULT) {
+ return -EINVAL;
+ }
+ string str(name);
+ return client->pool_create(str, crush_rule);
+}
+
+int librados::Rados::pool_create_with_rule(const char *name, __u8 crush_rule)
+{
+ string str(name);
+ return client->pool_create(str, crush_rule);
+}
+
+int librados::Rados::pool_create_async(const char *name, PoolAsyncCompletion *c)
+{
+ string str(name);
+ return client->pool_create_async(str, c->pc);
+}
+
+int librados::Rados::pool_create_async(const char *name, uint64_t auid, PoolAsyncCompletion *c)
+{
+ if (auid != CEPH_AUTH_UID_DEFAULT) {
+ return -EINVAL;
+ }
+ string str(name);
+ return client->pool_create_async(str, c->pc);
+}
+
+int librados::Rados::pool_create_async(const char *name, uint64_t auid, __u8 crush_rule,
+ PoolAsyncCompletion *c)
+{
+ if (auid != CEPH_AUTH_UID_DEFAULT) {
+ return -EINVAL;
+ }
+ string str(name);
+ return client->pool_create_async(str, c->pc, crush_rule);
+}
+
+int librados::Rados::pool_create_with_rule_async(
+ const char *name, __u8 crush_rule,
+ PoolAsyncCompletion *c)
+{
+ string str(name);
+ return client->pool_create_async(str, c->pc, crush_rule);
+}
+
+int librados::Rados::pool_get_base_tier(int64_t pool_id, int64_t* base_tier)
+{
+ tracepoint(librados, rados_pool_get_base_tier_enter, (rados_t)client, pool_id);
+ int retval = client->pool_get_base_tier(pool_id, base_tier);
+ tracepoint(librados, rados_pool_get_base_tier_exit, retval, *base_tier);
+ return retval;
+}
+
+int librados::Rados::pool_delete(const char *name)
+{
+ return client->pool_delete(name);
+}
+
+int librados::Rados::pool_delete_async(const char *name, PoolAsyncCompletion *c)
+{
+ return client->pool_delete_async(name, c->pc);
+}
+
+int librados::Rados::pool_list(std::list<std::string>& v)
+{
+ std::list<std::pair<int64_t, std::string> > pools;
+ int r = client->pool_list(pools);
+ if (r < 0) {
+ return r;
+ }
+
+ v.clear();
+ for (std::list<std::pair<int64_t, std::string> >::iterator it = pools.begin();
+ it != pools.end(); ++it) {
+ v.push_back(it->second);
+ }
+ return 0;
+}
+
+int librados::Rados::pool_list2(std::list<std::pair<int64_t, std::string> >& v)
+{
+ return client->pool_list(v);
+}
+
+int64_t librados::Rados::pool_lookup(const char *name)
+{
+ return client->lookup_pool(name);
+}
+
+int librados::Rados::pool_reverse_lookup(int64_t id, std::string *name)
+{
+ return client->pool_get_name(id, name);
+}
+
+int librados::Rados::mon_command(string cmd, const bufferlist& inbl,
+ bufferlist *outbl, string *outs)
+{
+ vector<string> cmdvec;
+ cmdvec.push_back(cmd);
+ return client->mon_command(cmdvec, inbl, outbl, outs);
+}
+
+int librados::Rados::osd_command(int osdid, std::string cmd, const bufferlist& inbl,
+ bufferlist *outbl, std::string *outs)
+{
+ vector<string> cmdvec;
+ cmdvec.push_back(cmd);
+ return client->osd_command(osdid, cmdvec, inbl, outbl, outs);
+}
+
+int librados::Rados::mgr_command(std::string cmd, const bufferlist& inbl,
+ bufferlist *outbl, std::string *outs)
+{
+ vector<string> cmdvec;
+ cmdvec.push_back(cmd);
+ return client->mgr_command(cmdvec, inbl, outbl, outs);
+}
+
+
+
+int librados::Rados::pg_command(const char *pgstr, std::string cmd, const bufferlist& inbl,
+ bufferlist *outbl, std::string *outs)
+{
+ vector<string> cmdvec;
+ cmdvec.push_back(cmd);
+
+ pg_t pgid;
+ if (!pgid.parse(pgstr))
+ return -EINVAL;
+
+ return client->pg_command(pgid, cmdvec, inbl, outbl, outs);
+}
+
+int librados::Rados::ioctx_create(const char *name, IoCtx &io)
+{
+ rados_ioctx_t p;
+ int ret = rados_ioctx_create((rados_t)client, name, &p);
+ if (ret)
+ return ret;
+ io.close();
+ io.io_ctx_impl = (IoCtxImpl*)p;
+ return 0;
+}
+
+int librados::Rados::ioctx_create2(int64_t pool_id, IoCtx &io)
+{
+ rados_ioctx_t p;
+ int ret = rados_ioctx_create2((rados_t)client, pool_id, &p);
+ if (ret)
+ return ret;
+ io.close();
+ io.io_ctx_impl = (IoCtxImpl*)p;
+ return 0;
+}
+
+void librados::Rados::test_blacklist_self(bool set)
+{
+ client->blacklist_self(set);
+}
+
+int librados::Rados::get_pool_stats(std::list<string>& v,
+ stats_map& result)
+{
+ map<string,::pool_stat_t> rawresult;
+ int r = client->get_pool_stats(v, rawresult);
+ for (map<string,::pool_stat_t>::iterator p = rawresult.begin();
+ p != rawresult.end();
+ ++p) {
+ pool_stat_t& pv = result[p->first];
+ object_stat_sum_t *sum = &p->second.stats.sum;
+ pv.num_kb = shift_round_up(sum->num_bytes, 10);
+ pv.num_bytes = sum->num_bytes;
+ pv.num_objects = sum->num_objects;
+ pv.num_object_clones = sum->num_object_clones;
+ pv.num_object_copies = sum->num_object_copies;
+ pv.num_objects_missing_on_primary = sum->num_objects_missing_on_primary;
+ pv.num_objects_unfound = sum->num_objects_unfound;
+ pv.num_objects_degraded = sum->num_objects_degraded;
+ pv.num_rd = sum->num_rd;
+ pv.num_rd_kb = sum->num_rd_kb;
+ pv.num_wr = sum->num_wr;
+ pv.num_wr_kb = sum->num_wr_kb;
+ }
+ return r;
+}
+
+int librados::Rados::get_pool_stats(std::list<string>& v,
+ std::map<string, stats_map>& result)
+{
+ stats_map m;
+ int r = get_pool_stats(v, m);
+ if (r < 0)
+ return r;
+ for (map<string,pool_stat_t>::iterator p = m.begin();
+ p != m.end();
+ ++p) {
+ result[p->first][string()] = p->second;
+ }
+ return r;
+}
+
+int librados::Rados::get_pool_stats(std::list<string>& v,
+ string& category, // unused
+ std::map<string, stats_map>& result)
+{
+ return -EOPNOTSUPP;
+}
+
+bool librados::Rados::get_pool_is_selfmanaged_snaps_mode(const std::string& pool)
+{
+ return client->get_pool_is_selfmanaged_snaps_mode(pool);
+}
+
+int librados::Rados::cluster_stat(cluster_stat_t& result)
+{
+ ceph_statfs stats;
+ int r = client->get_fs_stats(stats);
+ result.kb = stats.kb;
+ result.kb_used = stats.kb_used;
+ result.kb_avail = stats.kb_avail;
+ result.num_objects = stats.num_objects;
+ return r;
+}
+
+int librados::Rados::cluster_fsid(string *fsid)
+{
+ return client->get_fsid(fsid);
+}
+
+namespace librados {
+ struct PlacementGroupImpl {
+ pg_t pgid;
+ };
+
+ PlacementGroup::PlacementGroup()
+ : impl{new PlacementGroupImpl}
+ {}
+
+ PlacementGroup::PlacementGroup(const PlacementGroup& pg)
+ : impl{new PlacementGroupImpl}
+ {
+ impl->pgid = pg.impl->pgid;
+ }
+
+ PlacementGroup::~PlacementGroup()
+ {}
+
+ bool PlacementGroup::parse(const char* s)
+ {
+ return impl->pgid.parse(s);
+ }
+}
+
+std::ostream& librados::operator<<(std::ostream& out,
+ const librados::PlacementGroup& pg)
+{
+ return out << pg.impl->pgid;
+}
+
+int librados::Rados::get_inconsistent_pgs(int64_t pool_id,
+ std::vector<PlacementGroup>* pgs)
+{
+ std::vector<string> pgids;
+ if (auto ret = client->get_inconsistent_pgs(pool_id, &pgids); ret) {
+ return ret;
+ }
+ for (const auto& pgid : pgids) {
+ librados::PlacementGroup pg;
+ if (!pg.parse(pgid.c_str())) {
+ return -EINVAL;
+ }
+ pgs->emplace_back(pg);
+ }
+ return 0;
+}
+
+int librados::Rados::get_inconsistent_objects(const PlacementGroup& pg,
+ const object_id_t &start_after,
+ unsigned max_return,
+ AioCompletion *c,
+ std::vector<inconsistent_obj_t>* objects,
+ uint32_t* interval)
+{
+ IoCtx ioctx;
+ const pg_t pgid = pg.impl->pgid;
+ int r = ioctx_create2(pgid.pool(), ioctx);
+ if (r < 0) {
+ return r;
+ }
+
+ return ioctx.io_ctx_impl->get_inconsistent_objects(pgid,
+ start_after,
+ max_return,
+ c->pc,
+ objects,
+ interval);
+}
+
+int librados::Rados::get_inconsistent_snapsets(const PlacementGroup& pg,
+ const object_id_t &start_after,
+ unsigned max_return,
+ AioCompletion *c,
+ std::vector<inconsistent_snapset_t>* snapsets,
+ uint32_t* interval)
+{
+ IoCtx ioctx;
+ const pg_t pgid = pg.impl->pgid;
+ int r = ioctx_create2(pgid.pool(), ioctx);
+ if (r < 0) {
+ return r;
+ }
+
+ return ioctx.io_ctx_impl->get_inconsistent_snapsets(pgid,
+ start_after,
+ max_return,
+ c->pc,
+ snapsets,
+ interval);
+}
+
+int librados::Rados::wait_for_latest_osdmap()
+{
+ return client->wait_for_latest_osdmap();
+}
+
+int librados::Rados::blacklist_add(const std::string& client_address,
+ uint32_t expire_seconds)
+{
+ return client->blacklist_add(client_address, expire_seconds);
+}
+
+librados::PoolAsyncCompletion *librados::Rados::pool_async_create_completion()
+{
+ PoolAsyncCompletionImpl *c = new PoolAsyncCompletionImpl;
+ return new PoolAsyncCompletion(c);
+}
+
+librados::AioCompletion *librados::Rados::aio_create_completion()
+{
+ AioCompletionImpl *c = new AioCompletionImpl;
+ return new AioCompletion(c);
+}
+
+librados::AioCompletion *librados::Rados::aio_create_completion(void *cb_arg,
+ callback_t cb_complete,
+ callback_t cb_safe)
+{
+ AioCompletionImpl *c;
+ int r = rados_aio_create_completion(cb_arg, cb_complete, cb_safe, (void**)&c);
+ ceph_assert(r == 0);
+ return new AioCompletion(c);
+}
+
+librados::ObjectOperation::ObjectOperation()
+{
+ impl = new ObjectOperationImpl;
+}
+
+librados::ObjectOperation::~ObjectOperation()
+{
+ delete impl;
+}
+
+///////////////////////////// ListObject //////////////////////////////
+librados::ListObject::ListObject() : impl(NULL)
+{
+}
+
+librados::ListObject::ListObject(librados::ListObjectImpl *i): impl(i)
+{
+}
+
+librados::ListObject::ListObject(const ListObject& rhs)
+{
+ if (rhs.impl == NULL) {
+ impl = NULL;
+ return;
+ }
+ impl = new ListObjectImpl();
+ *impl = *(rhs.impl);
+}
+
+librados::ListObject& librados::ListObject::operator=(const ListObject& rhs)
+{
+ if (rhs.impl == NULL) {
+ delete impl;
+ impl = NULL;
+ return *this;
+ }
+ if (impl == NULL)
+ impl = new ListObjectImpl();
+ *impl = *(rhs.impl);
+ return *this;
+}
+
+librados::ListObject::~ListObject()
+{
+ if (impl)
+ delete impl;
+ impl = NULL;
+}
+
+const std::string& librados::ListObject::get_nspace() const
+{
+ return impl->get_nspace();
+}
+
+const std::string& librados::ListObject::get_oid() const
+{
+ return impl->get_oid();
+}
+
+const std::string& librados::ListObject::get_locator() const
+{
+ return impl->get_locator();
+}
+
+std::ostream& librados::operator<<(std::ostream& out, const librados::ListObject& lop)
+{
+ out << *(lop.impl);
+ return out;
+}
+
+librados::ObjectCursor::ObjectCursor()
+{
+ c_cursor = (rados_object_list_cursor)new hobject_t();
+}
+
+librados::ObjectCursor::~ObjectCursor()
+{
+ hobject_t *h = (hobject_t *)c_cursor;
+ delete h;
+}
+
+librados::ObjectCursor::ObjectCursor(rados_object_list_cursor c)
+{
+ if (!c) {
+ c_cursor = nullptr;
+ } else {
+ c_cursor = (rados_object_list_cursor)new hobject_t(*(hobject_t *)c);
+ }
+}
+
+librados::ObjectCursor& librados::ObjectCursor::operator=(const librados::ObjectCursor& rhs)
+{
+ if (rhs.c_cursor != nullptr) {
+ hobject_t *h = (hobject_t*)rhs.c_cursor;
+ c_cursor = (rados_object_list_cursor)(new hobject_t(*h));
+ } else {
+ c_cursor = nullptr;
+ }
+ return *this;
+}
+
+bool librados::ObjectCursor::operator<(const librados::ObjectCursor &rhs) const
+{
+ const hobject_t lhs_hobj = (c_cursor == nullptr) ? hobject_t() : *((hobject_t*)c_cursor);
+ const hobject_t rhs_hobj = (rhs.c_cursor == nullptr) ? hobject_t() : *((hobject_t*)(rhs.c_cursor));
+ return lhs_hobj < rhs_hobj;
+}
+
+bool librados::ObjectCursor::operator==(const librados::ObjectCursor &rhs) const
+{
+ const hobject_t lhs_hobj = (c_cursor == nullptr) ? hobject_t() : *((hobject_t*)c_cursor);
+ const hobject_t rhs_hobj = (rhs.c_cursor == nullptr) ? hobject_t() : *((hobject_t*)(rhs.c_cursor));
+ return cmp(lhs_hobj, rhs_hobj) == 0;
+}
+librados::ObjectCursor::ObjectCursor(const librados::ObjectCursor &rhs)
+{
+ *this = rhs;
+}
+
+librados::ObjectCursor librados::IoCtx::object_list_begin()
+{
+ hobject_t *h = new hobject_t(io_ctx_impl->objecter->enumerate_objects_begin());
+ ObjectCursor oc;
+ oc.set((rados_object_list_cursor)h);
+ return oc;
+}
+
+
+librados::ObjectCursor librados::IoCtx::object_list_end()
+{
+ hobject_t *h = new hobject_t(io_ctx_impl->objecter->enumerate_objects_end());
+ librados::ObjectCursor oc;
+ oc.set((rados_object_list_cursor)h);
+ return oc;
+}
+
+
+void librados::ObjectCursor::set(rados_object_list_cursor c)
+{
+ delete (hobject_t*)c_cursor;
+ c_cursor = c;
+}
+
+string librados::ObjectCursor::to_str() const
+{
+ stringstream ss;
+ ss << *(hobject_t *)c_cursor;
+ return ss.str();
+}
+
+bool librados::ObjectCursor::from_str(const string& s)
+{
+ if (s.empty()) {
+ *(hobject_t *)c_cursor = hobject_t();
+ return true;
+ }
+ return ((hobject_t *)c_cursor)->parse(s);
+}
+
+CEPH_RADOS_API std::ostream& librados::operator<<(std::ostream& os, const librados::ObjectCursor& oc)
+{
+ if (oc.c_cursor) {
+ os << *(hobject_t *)oc.c_cursor;
+ } else {
+ os << hobject_t();
+ }
+ return os;
+}
+
+bool librados::IoCtx::object_list_is_end(const ObjectCursor &oc)
+{
+ hobject_t *h = (hobject_t *)oc.c_cursor;
+ return h->is_max();
+}
+
+int librados::IoCtx::object_list(const ObjectCursor &start,
+ const ObjectCursor &finish,
+ const size_t result_item_count,
+ const bufferlist &filter,
+ std::vector<ObjectItem> *result,
+ ObjectCursor *next)
+{
+ ceph_assert(result != nullptr);
+ ceph_assert(next != nullptr);
+ result->clear();
+
+ C_SaferCond cond;
+ hobject_t next_hash;
+ std::list<librados::ListObjectImpl> obj_result;
+ io_ctx_impl->objecter->enumerate_objects(
+ io_ctx_impl->poolid,
+ io_ctx_impl->oloc.nspace,
+ *((hobject_t*)start.c_cursor),
+ *((hobject_t*)finish.c_cursor),
+ result_item_count,
+ filter,
+ &obj_result,
+ &next_hash,
+ &cond);
+
+ int r = cond.wait();
+ if (r < 0) {
+ next->set((rados_object_list_cursor)(new hobject_t(hobject_t::get_max())));
+ return r;
+ }
+
+ next->set((rados_object_list_cursor)(new hobject_t(next_hash)));
+
+ for (std::list<librados::ListObjectImpl>::iterator i = obj_result.begin();
+ i != obj_result.end(); ++i) {
+ ObjectItem oi;
+ oi.oid = i->oid;
+ oi.nspace = i->nspace;
+ oi.locator = i->locator;
+ result->push_back(oi);
+ }
+
+ return obj_result.size();
+}
+
+void librados::IoCtx::object_list_slice(
+ const ObjectCursor start,
+ const ObjectCursor finish,
+ const size_t n,
+ const size_t m,
+ ObjectCursor *split_start,
+ ObjectCursor *split_finish)
+{
+ ceph_assert(split_start != nullptr);
+ ceph_assert(split_finish != nullptr);
+
+ io_ctx_impl->object_list_slice(
+ *((hobject_t*)(start.c_cursor)),
+ *((hobject_t*)(finish.c_cursor)),
+ n,
+ m,
+ (hobject_t*)(split_start->c_cursor),
+ (hobject_t*)(split_finish->c_cursor));
+}
+
+int librados::IoCtx::application_enable(const std::string& app_name,
+ bool force)
+{
+ return io_ctx_impl->application_enable(app_name, force);
+}
+
+int librados::IoCtx::application_enable_async(const std::string& app_name,
+ bool force,
+ PoolAsyncCompletion *c)
+{
+ io_ctx_impl->application_enable_async(app_name, force, c->pc);
+ return 0;
+}
+
+int librados::IoCtx::application_list(std::set<std::string> *app_names)
+{
+ return io_ctx_impl->application_list(app_names);
+}
+
+int librados::IoCtx::application_metadata_get(const std::string& app_name,
+ const std::string &key,
+ std::string* value)
+{
+ return io_ctx_impl->application_metadata_get(app_name, key, value);
+}
+
+int librados::IoCtx::application_metadata_set(const std::string& app_name,
+ const std::string &key,
+ const std::string& value)
+{
+ return io_ctx_impl->application_metadata_set(app_name, key, value);
+}
+
+int librados::IoCtx::application_metadata_remove(const std::string& app_name,
+ const std::string &key)
+{
+ return io_ctx_impl->application_metadata_remove(app_name, key);
+}
+
+int librados::IoCtx::application_metadata_list(const std::string& app_name,
+ std::map<std::string, std::string> *values)
+{
+ return io_ctx_impl->application_metadata_list(app_name, values);
+}
diff --git a/src/librados/librados_tp.cc b/src/librados/librados_tp.cc
new file mode 100644
index 00000000000..b696de871b6
--- /dev/null
+++ b/src/librados/librados_tp.cc
@@ -0,0 +1,9 @@
+#include "acconfig.h"
+
+#ifdef WITH_LTTNG
+#define TRACEPOINT_DEFINE
+#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
+#include "tracing/librados.h"
+#undef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
+#undef TRACEPOINT_DEFINE
+#endif
diff --git a/src/librados/librados_util.cc b/src/librados/librados_util.cc
new file mode 100644
index 00000000000..109bf9ab680
--- /dev/null
+++ b/src/librados/librados_util.cc
@@ -0,0 +1,61 @@
+#include "librados_util.h"
+
+uint8_t get_checksum_op_type(rados_checksum_type_t type) {
+ switch (type) {
+ case LIBRADOS_CHECKSUM_TYPE_XXHASH32:
+ return CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH32;
+ case LIBRADOS_CHECKSUM_TYPE_XXHASH64:
+ return CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH64;
+ case LIBRADOS_CHECKSUM_TYPE_CRC32C:
+ return CEPH_OSD_CHECKSUM_OP_TYPE_CRC32C;
+ default:
+ return -1;
+ }
+}
+
+int get_op_flags(int flags)
+{
+ int rados_flags = 0;
+ if (flags & LIBRADOS_OP_FLAG_EXCL)
+ rados_flags |= CEPH_OSD_OP_FLAG_EXCL;
+ if (flags & LIBRADOS_OP_FLAG_FAILOK)
+ rados_flags |= CEPH_OSD_OP_FLAG_FAILOK;
+ if (flags & LIBRADOS_OP_FLAG_FADVISE_RANDOM)
+ rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_RANDOM;
+ if (flags & LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL)
+ rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL;
+ if (flags & LIBRADOS_OP_FLAG_FADVISE_WILLNEED)
+ rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_WILLNEED;
+ if (flags & LIBRADOS_OP_FLAG_FADVISE_DONTNEED)
+ rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_DONTNEED;
+ if (flags & LIBRADOS_OP_FLAG_FADVISE_NOCACHE)
+ rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_NOCACHE;
+ return rados_flags;
+}
+
+int translate_flags(int flags)
+{
+ int op_flags = 0;
+ if (flags & librados::OPERATION_BALANCE_READS)
+ op_flags |= CEPH_OSD_FLAG_BALANCE_READS;
+ if (flags & librados::OPERATION_LOCALIZE_READS)
+ op_flags |= CEPH_OSD_FLAG_LOCALIZE_READS;
+ if (flags & librados::OPERATION_ORDER_READS_WRITES)
+ op_flags |= CEPH_OSD_FLAG_RWORDERED;
+ if (flags & librados::OPERATION_IGNORE_CACHE)
+ op_flags |= CEPH_OSD_FLAG_IGNORE_CACHE;
+ if (flags & librados::OPERATION_SKIPRWLOCKS)
+ op_flags |= CEPH_OSD_FLAG_SKIPRWLOCKS;
+ if (flags & librados::OPERATION_IGNORE_OVERLAY)
+ op_flags |= CEPH_OSD_FLAG_IGNORE_OVERLAY;
+ if (flags & librados::OPERATION_FULL_TRY)
+ op_flags |= CEPH_OSD_FLAG_FULL_TRY;
+ if (flags & librados::OPERATION_FULL_FORCE)
+ op_flags |= CEPH_OSD_FLAG_FULL_FORCE;
+ if (flags & librados::OPERATION_IGNORE_REDIRECT)
+ op_flags |= CEPH_OSD_FLAG_IGNORE_REDIRECT;
+ if (flags & librados::OPERATION_ORDERSNAP)
+ op_flags |= CEPH_OSD_FLAG_ORDERSNAP;
+
+ return op_flags;
+}
diff --git a/src/librados/librados_util.h b/src/librados/librados_util.h
new file mode 100644
index 00000000000..ab9c461f42a
--- /dev/null
+++ b/src/librados/librados_util.h
@@ -0,0 +1,34 @@
+#include <cstdint>
+#include "acconfig.h"
+#include "include/rados/librados.h"
+#include "IoCtxImpl.h"
+
+#ifdef WITH_LTTNG
+#include "tracing/librados.h"
+#else
+#define tracepoint(...)
+#endif
+
+uint8_t get_checksum_op_type(rados_checksum_type_t type);
+int get_op_flags(int flags);
+int translate_flags(int flags);
+
+struct librados::ObjListCtx {
+ librados::IoCtxImpl dupctx;
+ librados::IoCtxImpl *ctx;
+ Objecter::NListContext *nlc;
+ bool legacy_list_api;
+
+ ObjListCtx(IoCtxImpl *c, Objecter::NListContext *nl, bool legacy=false)
+ : nlc(nl),
+ legacy_list_api(legacy) {
+ // Get our own private IoCtxImpl so that namespace setting isn't
+ // changed by caller between uses.
+ ctx = &dupctx;
+ dupctx.dup(*c);
+ }
+ ~ObjListCtx() {
+ ctx = NULL;
+ delete nlc;
+ }
+};
diff --git a/src/libradosstriper/CMakeLists.txt b/src/libradosstriper/CMakeLists.txt
index 5b2dd7566af..d9d022f675f 100644
--- a/src/libradosstriper/CMakeLists.txt
+++ b/src/libradosstriper/CMakeLists.txt
@@ -3,10 +3,12 @@ set(libradosstriper_srcs
RadosStriperImpl.cc
MultiAioCompletionImpl.cc)
add_library(radosstriper ${CEPH_SHARED}
- ${libradosstriper_srcs}
- $<TARGET_OBJECTS:librados_objs>)
+ ${libradosstriper_srcs})
target_link_libraries(radosstriper
- PRIVATE librados cls_lock_client osdc ceph-common pthread ${CRYPTO_LIBS} ${EXTRALIBS})
+ PRIVATE
+ librados-cxx
+ librados_impl cls_lock_client osdc ceph-common
+ pthread ${CRYPTO_LIBS} ${EXTRALIBS})
set_target_properties(radosstriper PROPERTIES
OUPUT_NAME radosstriper
VERSION 1.0.0
diff --git a/src/librbd/CMakeLists.txt b/src/librbd/CMakeLists.txt
index 2ba963ed0db..5501dc633c2 100644
--- a/src/librbd/CMakeLists.txt
+++ b/src/librbd/CMakeLists.txt
@@ -153,7 +153,7 @@ target_link_libraries(librbd PRIVATE
rbd_internal
rbd_types
journal
- librados
+ librados-cxx
cls_rbd_client
cls_lock_client
cls_journal_client
diff --git a/src/librbd/Types.h b/src/librbd/Types.h
index 5b9f1793714..3f1104478eb 100644
--- a/src/librbd/Types.h
+++ b/src/librbd/Types.h
@@ -96,6 +96,7 @@ enum {
struct MigrationInfo {
int64_t pool_id = -1;
+ std::string pool_namespace;
std::string image_name;
std::string image_id;
deep_copy::SnapMap snap_map;
@@ -104,11 +105,13 @@ struct MigrationInfo {
MigrationInfo() {
}
- MigrationInfo(int64_t pool_id, std::string image_name, std::string image_id,
+ MigrationInfo(int64_t pool_id, const std::string& pool_namespace,
+ const std::string& image_name, const std::string& image_id,
const deep_copy::SnapMap &snap_map, uint64_t overlap,
bool flatten)
- : pool_id(pool_id), image_name(image_name), image_id(image_id),
- snap_map(snap_map), overlap(overlap), flatten(flatten) {
+ : pool_id(pool_id), pool_namespace(pool_namespace), image_name(image_name),
+ image_id(image_id), snap_map(snap_map), overlap(overlap),
+ flatten(flatten) {
}
bool empty() const {
diff --git a/src/librbd/api/Migration.cc b/src/librbd/api/Migration.cc
index 8561ba07500..32c13df3786 100644
--- a/src/librbd/api/Migration.cc
+++ b/src/librbd/api/Migration.cc
@@ -235,15 +235,10 @@ int open_source_image(librados::IoCtx& io_ctx, const std::string &image_name,
return r;
}
- // TODO support namespaces
- if (io_ctx.get_id() == migration_spec.pool_id) {
- src_io_ctx.dup(io_ctx);
- } else {
- r = util::create_ioctx(io_ctx, "source image", migration_spec.pool_id,
- {}, &src_io_ctx);
- if (r < 0) {
- return r;
- }
+ r = util::create_ioctx(io_ctx, "source image", migration_spec.pool_id,
+ migration_spec.pool_namespace, &src_io_ctx);
+ if (r < 0) {
+ return r;
}
src_image_name = migration_spec.image_name;
@@ -306,15 +301,11 @@ int open_source_image(librados::IoCtx& io_ctx, const std::string &image_name,
ldout(cct, 20) << "migration spec: " << migration_spec << dendl;
}
- // TODO support namespaces
- if (image_ctx->md_ctx.get_id() == migration_spec.pool_id) {
- dst_io_ctx->dup(io_ctx);
- } else {
- r = util::create_ioctx(image_ctx->md_ctx, "source image",
- migration_spec.pool_id, {}, dst_io_ctx);
- if (r < 0) {
- return r;
- }
+ r = util::create_ioctx(image_ctx->md_ctx, "source image",
+ migration_spec.pool_id, migration_spec.pool_namespace,
+ dst_io_ctx);
+ if (r < 0) {
+ return r;
}
*src_image_ctx = image_ctx;
@@ -635,13 +626,14 @@ Migration<I>::Migration(I *src_image_ctx, librados::IoCtx& dst_io_ctx,
m_dst_header_oid(util::header_name(m_dst_image_id)), m_image_options(opts),
m_flatten(flatten), m_mirroring(mirroring), m_prog_ctx(prog_ctx),
m_src_migration_spec(cls::rbd::MIGRATION_HEADER_TYPE_SRC,
- m_dst_io_ctx.get_id(), m_dst_image_name,
- m_dst_image_id, {}, 0, flatten, mirroring, state,
- state_description),
+ m_dst_io_ctx.get_id(), m_dst_io_ctx.get_namespace(),
+ m_dst_image_name, m_dst_image_id, {}, 0, flatten,
+ mirroring, state, state_description),
m_dst_migration_spec(cls::rbd::MIGRATION_HEADER_TYPE_DST,
- src_image_ctx->md_ctx.get_id(), m_src_image_ctx->name,
- m_src_image_ctx->id, {}, 0, flatten, mirroring, state,
- state_description) {
+ src_image_ctx->md_ctx.get_id(),
+ src_image_ctx->md_ctx.get_namespace(),
+ m_src_image_ctx->name, m_src_image_ctx->id, {}, 0,
+ flatten, mirroring, state, state_description) {
m_src_io_ctx.dup(src_image_ctx->md_ctx);
}
@@ -906,9 +898,11 @@ int Migration<I>::status(image_migration_status_t *status) {
ldout(m_cct, 10) << dendl;
status->source_pool_id = m_dst_migration_spec.pool_id;
+ status->source_pool_namespace = m_dst_migration_spec.pool_namespace;
status->source_image_name = m_dst_migration_spec.image_name;
status->source_image_id = m_dst_migration_spec.image_id;
status->dest_pool_id = m_src_migration_spec.pool_id;
+ status->dest_pool_namespace = m_src_migration_spec.pool_namespace;
status->dest_image_name = m_src_migration_spec.image_name;
status->dest_image_id = m_src_migration_spec.image_id;
@@ -1232,9 +1226,10 @@ int Migration<I>::create_dst_image() {
}
m_dst_migration_spec = {cls::rbd::MIGRATION_HEADER_TYPE_DST,
- m_src_io_ctx.get_id(), m_src_image_name,
- m_src_image_id, snap_seqs, size, m_flatten,
- m_mirroring, cls::rbd::MIGRATION_STATE_PREPARING, ""};
+ m_src_io_ctx.get_id(), m_src_io_ctx.get_namespace(),
+ m_src_image_name, m_src_image_id, snap_seqs, size,
+ m_flatten, m_mirroring,
+ cls::rbd::MIGRATION_STATE_PREPARING, ""};
r = cls_client::migration_set(&m_dst_io_ctx, m_dst_header_oid,
m_dst_migration_spec);
diff --git a/src/librbd/image/RefreshRequest.cc b/src/librbd/image/RefreshRequest.cc
index 082cdd30550..ec290a957ec 100644
--- a/src/librbd/image/RefreshRequest.cc
+++ b/src/librbd/image/RefreshRequest.cc
@@ -1455,6 +1455,7 @@ bool RefreshRequest<I>::get_migration_info(ParentImageInfo *parent_md,
}
parent_md->spec.pool_id = m_migration_spec.pool_id;
+ parent_md->spec.pool_namespace = m_migration_spec.pool_namespace;
parent_md->spec.image_id = m_migration_spec.image_id;
parent_md->spec.snap_id = CEPH_NOSNAP;
parent_md->overlap = std::min(m_size, m_migration_spec.overlap);
@@ -1484,9 +1485,9 @@ bool RefreshRequest<I>::get_migration_info(ParentImageInfo *parent_md,
}
}
- *migration_info = {m_migration_spec.pool_id, m_migration_spec.image_name,
- m_migration_spec.image_id, {}, overlap,
- m_migration_spec.flatten};
+ *migration_info = {m_migration_spec.pool_id, m_migration_spec.pool_namespace,
+ m_migration_spec.image_name, m_migration_spec.image_id, {},
+ overlap, m_migration_spec.flatten};
deep_copy::util::compute_snap_map(0, CEPH_NOSNAP, snap_seqs,
&migration_info->snap_map);
diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc
index 6e409babc29..7db9b78a5b6 100644
--- a/src/librbd/librbd.cc
+++ b/src/librbd/librbd.cc
@@ -3300,9 +3300,13 @@ extern "C" int rbd_migration_status(rados_ioctx_t p, const char *image_name,
int r = librbd::api::Migration<>::status(io_ctx, image_name, &cpp_status);
if (r >= 0) {
status->source_pool_id = cpp_status.source_pool_id;
+ status->source_pool_namespace =
+ strdup(cpp_status.source_pool_namespace.c_str());
status->source_image_name = strdup(cpp_status.source_image_name.c_str());
status->source_image_id = strdup(cpp_status.source_image_id.c_str());
status->dest_pool_id = cpp_status.dest_pool_id;
+ status->dest_pool_namespace =
+ strdup(cpp_status.dest_pool_namespace.c_str());
status->dest_image_name = strdup(cpp_status.dest_image_name.c_str());
status->dest_image_id = strdup(cpp_status.dest_image_id.c_str());
status->state = cpp_status.state;
@@ -3315,8 +3319,10 @@ extern "C" int rbd_migration_status(rados_ioctx_t p, const char *image_name,
extern "C" void rbd_migration_status_cleanup(rbd_image_migration_status_t *s)
{
+ free(s->source_pool_namespace);
free(s->source_image_name);
free(s->source_image_id);
+ free(s->dest_pool_namespace);
free(s->dest_image_name);
free(s->dest_image_id);
free(s->state_description);
diff --git a/src/mds/MDSDaemon.cc b/src/mds/MDSDaemon.cc
index 1f2fb2db1b4..0459ec564eb 100644
--- a/src/mds/MDSDaemon.cc
+++ b/src/mds/MDSDaemon.cc
@@ -245,7 +245,7 @@ void MDSDaemon::set_up_admin_socket()
"show cache status");
ceph_assert(r == 0);
r = admin_socket->register_command("cache drop",
- "cache drop name=timeout,type=CephInt,range=1",
+ "cache drop name=timeout,type=CephInt,range=0,req=false",
asok_hook,
"drop cache");
ceph_assert(r == 0);
@@ -663,7 +663,7 @@ const std::vector<MDSDaemon::MDSCommand>& MDSDaemon::get_commands()
MDSCommand("heap "
"name=heapcmd,type=CephChoices,strings=dump|start_profiler|stop_profiler|release|stats",
"show heap usage info (available only if compiled with tcmalloc)"),
- MDSCommand("cache drop name=timeout,type=CephInt,range=1", "trim cache and optionally request client to release all caps and flush the journal"),
+ MDSCommand("cache drop name=timeout,type=CephInt,range=0,req=false", "trim cache and optionally request client to release all caps and flush the journal"),
};
return commands;
};
diff --git a/src/mds/MDSRank.cc b/src/mds/MDSRank.cc
index 728b3301cec..faa1a92464d 100644
--- a/src/mds/MDSRank.cc
+++ b/src/mds/MDSRank.cc
@@ -276,6 +276,10 @@ private:
}
void start_timer() {
+ if (!timeout) {
+ return;
+ }
+
timer_task = new FunctionContext([this](int _) {
timer_task = nullptr;
complete(-ETIMEDOUT);
@@ -2486,7 +2490,7 @@ bool MDSRankDispatcher::handle_asok_command(std::string_view command,
} else if (command == "cache drop") {
int64_t timeout;
if (!cmd_getval(g_ceph_context, cmdmap, "timeout", timeout)) {
- return false;
+ timeout = 0;
}
C_SaferCond cond;
@@ -3368,7 +3372,7 @@ bool MDSRankDispatcher::handle_command(
} else if (prefix == "cache drop") {
int64_t timeout;
if (!cmd_getval(g_ceph_context, cmdmap, "timeout", timeout)) {
- return false;
+ timeout = 0;
}
JSONFormatter *f = new JSONFormatter(true);
diff --git a/src/pybind/mgr/dashboard/controllers/__init__.py b/src/pybind/mgr/dashboard/controllers/__init__.py
index 5426ee47067..4aaf84ea72a 100644
--- a/src/pybind/mgr/dashboard/controllers/__init__.py
+++ b/src/pybind/mgr/dashboard/controllers/__init__.py
@@ -21,11 +21,8 @@ import cherrypy
from .. import logger
from ..security import Scope, Permission
-from ..settings import Settings
-from ..tools import wraps, getargspec, TaskManager
-from ..exceptions import ViewCacheNoDataException, DashboardException, \
- ScopeNotValid, PermissionNotValid
-from ..services.exception import serialize_dashboard_exception
+from ..tools import wraps, getargspec, TaskManager, get_request_body_params
+from ..exceptions import ScopeNotValid, PermissionNotValid
from ..services.auth import AuthManager, JwtManager
@@ -520,7 +517,7 @@ class BaseController(object):
return result
@staticmethod
- def _request_wrapper(func, method, json_response):
+ def _request_wrapper(func, method, json_response): # pylint: disable=unused-argument
@wraps(func)
def inner(*args, **kwargs):
for key, value in kwargs.items():
@@ -529,27 +526,11 @@ class BaseController(object):
or isinstance(value, str):
kwargs[key] = unquote(value)
- if method in ['GET', 'DELETE']:
- ret = func(*args, **kwargs)
-
- elif cherrypy.request.headers.get('Content-Type', '') == \
- 'application/x-www-form-urlencoded':
- ret = func(*args, **kwargs)
-
- else:
- content_length = int(cherrypy.request.headers['Content-Length'])
- body = cherrypy.request.body.read(content_length)
- if not body:
- ret = func(*args, **kwargs)
- else:
- try:
- data = json.loads(body.decode('utf-8'))
- except Exception as e:
- raise cherrypy.HTTPError(400, 'Failed to decode JSON: {}'
- .format(str(e)))
- kwargs.update(data.items())
- ret = func(*args, **kwargs)
+ # Process method arguments.
+ params = get_request_body_params(cherrypy.request)
+ kwargs.update(params)
+ ret = func(*args, **kwargs)
if isinstance(ret, bytes):
ret = ret.decode('utf-8')
if json_response:
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts
index 2814989c12d..71723b5cbc7 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts
@@ -35,6 +35,36 @@ describe('OsdListComponent', () => {
}
};
+ const getTableAction = (name) => component.tableActions.find((action) => action.name === name);
+
+ const setFakeSelection = () => {
+ // Default data and selection
+ const selection = [{ id: 1 }];
+ const data = [{ id: 1 }];
+
+ // Table data and selection
+ component.selection = new CdTableSelection();
+ component.selection.selected = selection;
+ component.selection.update();
+ component.osds = data;
+ };
+
+ const openActionModal = (actionName) => {
+ setFakeSelection();
+ getTableAction(actionName).click();
+ };
+
+ /**
+ * The following modals are called after the information about their
+ * safety to destroy/remove/mark them lost has been retrieved, hence
+ * we will have to fake its request to be able to open those modals.
+ */
+ const mockSafeToDestroy = () => {
+ spyOn(TestBed.get(OsdService), 'safeToDestroy').and.callFake(() =>
+ of({ 'safe-to-destroy': true })
+ );
+ };
+
configureTestBed({
imports: [
HttpClientTestingModule,
@@ -59,18 +89,6 @@ describe('OsdListComponent', () => {
modalServiceShowSpy = spyOn(TestBed.get(BsModalService), 'show').and.stub();
});
- const setFakeSelection = () => {
- // Default data and selection
- const selection = [{ id: 1 }];
- const data = [{ id: 1 }];
-
- // Table data and selection
- component.selection = new CdTableSelection();
- component.selection.selected = selection;
- component.selection.update();
- component.osds = data;
- };
-
it('should create', () => {
fixture.detectChanges();
expect(component).toBeTruthy();
@@ -142,72 +160,70 @@ describe('OsdListComponent', () => {
describe('tests if all modals are opened correctly', () => {
/**
* Helper function to check if a function opens a modal
- * @param fn
+ *
* @param modalClass - The expected class of the modal
*/
- const expectOpensModal = (fn, modalClass): void => {
- setFakeSelection();
- fn();
+ const expectOpensModal = (actionName: string, modalClass): void => {
+ openActionModal(actionName);
expect(modalServiceShowSpy.calls.any()).toBe(true, 'modalService.show called');
- expect(modalServiceShowSpy.calls.first()).toBeTruthy();
expect(modalServiceShowSpy.calls.first().args[0]).toBe(modalClass);
modalServiceShowSpy.calls.reset();
};
- it('opens the appropriate modal', () => {
- expectOpensModal(() => component.reweight(), OsdReweightModalComponent);
- expectOpensModal(() => component.markOut(), ConfirmationModalComponent);
- expectOpensModal(() => component.markIn(), ConfirmationModalComponent);
- expectOpensModal(() => component.markDown(), ConfirmationModalComponent);
-
- // The following modals are called after the information about their
- // safety to destroy/remove/mark them lost has been retrieved, hence
- // we will have to fake its request to be able to open those modals.
- spyOn(TestBed.get(OsdService), 'safeToDestroy').and.callFake(() =>
- of({ 'safe-to-destroy': true })
- );
+ it('opens the reweight modal', () => {
+ expectOpensModal('Reweight', OsdReweightModalComponent);
+ });
- expectOpensModal(() => component.markLost(), CriticalConfirmationModalComponent);
- expectOpensModal(() => component.remove(), CriticalConfirmationModalComponent);
- expectOpensModal(() => component.destroy(), CriticalConfirmationModalComponent);
+ it('opens all confirmation modals', () => {
+ const modalClass = ConfirmationModalComponent;
+ expectOpensModal('Mark Out', modalClass);
+ expectOpensModal('Mark In', modalClass);
+ expectOpensModal('Mark Down', modalClass);
+ });
+
+ it('opens all critical confirmation modals', () => {
+ const modalClass = CriticalConfirmationModalComponent;
+ mockSafeToDestroy();
+ expectOpensModal('Mark Lost', modalClass);
+ expectOpensModal('Remove', modalClass);
+ expectOpensModal('Destroy', modalClass);
});
});
describe('tests if the correct methods are called on confirmation', () => {
- const expectOsdServiceMethodCalled = (fn: Function, osdServiceMethodName: string): void => {
- setFakeSelection();
+ const expectOsdServiceMethodCalled = (
+ actionName: string,
+ osdServiceMethodName: string
+ ): void => {
const osdServiceSpy = spyOn(TestBed.get(OsdService), osdServiceMethodName).and.callFake(
() => EMPTY
);
-
- modalServiceShowSpy.calls.reset();
- fn(); // calls show on BsModalService
- // Calls onSubmit given to `bsModalService.show()`
+ openActionModal(actionName);
const initialState = modalServiceShowSpy.calls.first().args[1].initialState;
- const action = initialState.onSubmit || initialState.submitAction;
- action.call(component);
+ const submit = initialState.onSubmit || initialState.submitAction;
+ submit.call(component);
expect(osdServiceSpy.calls.count()).toBe(1);
expect(osdServiceSpy.calls.first().args[0]).toBe(1);
- modalServiceShowSpy.calls.reset();
+
+ // Reset spies to be able to recreate them
osdServiceSpy.calls.reset();
+ modalServiceShowSpy.calls.reset();
};
- it('calls the corresponding service methods', () => {
- // Purposely `reweight`
- expectOsdServiceMethodCalled(() => component.markOut(), 'markOut');
- expectOsdServiceMethodCalled(() => component.markIn(), 'markIn');
- expectOsdServiceMethodCalled(() => component.markDown(), 'markDown');
-
- spyOn(TestBed.get(OsdService), 'safeToDestroy').and.callFake(() =>
- of({ 'safe-to-destroy': true })
- );
+ it('calls the corresponding service methods in confirmation modals', () => {
+ expectOsdServiceMethodCalled('Mark Out', 'markOut');
+ expectOsdServiceMethodCalled('Mark In', 'markIn');
+ expectOsdServiceMethodCalled('Mark Down', 'markDown');
+ });
- expectOsdServiceMethodCalled(() => component.markLost(), 'markLost');
- expectOsdServiceMethodCalled(() => component.remove(), 'remove');
- expectOsdServiceMethodCalled(() => component.destroy(), 'destroy');
+ it('calls the corresponding service methods in critical confirmation modals', () => {
+ mockSafeToDestroy();
+ expectOsdServiceMethodCalled('Mark Lost', 'markLost');
+ expectOsdServiceMethodCalled('Remove', 'remove');
+ expectOsdServiceMethodCalled('Destroy', 'destroy');
});
});
});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts
index bbd94075bc7..bfa255662a4 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts
@@ -83,42 +83,55 @@ export class OsdListComponent implements OnInit {
{
name: 'Mark Out',
permission: 'update',
- click: () => this.markOut(),
+ click: () => this.showConfirmationModal('out', this.osdService.markOut),
disable: () => this.isNotSelectedOrInState('out'),
icon: 'fa-arrow-left'
},
{
name: 'Mark In',
permission: 'update',
- click: () => this.markIn(),
+ click: () => this.showConfirmationModal('in', this.osdService.markIn),
disable: () => this.isNotSelectedOrInState('in'),
icon: 'fa-arrow-right'
},
{
name: 'Mark Down',
permission: 'update',
- click: () => this.markDown(),
+ click: () => this.showConfirmationModal('down', this.osdService.markDown),
disable: () => this.isNotSelectedOrInState('down'),
icon: 'fa-arrow-down'
},
{
- name: 'Mark lost',
+ name: 'Mark Lost',
permission: 'delete',
- click: () => this.markLost(),
+ click: () =>
+ this.showCriticalConfirmationModal(
+ 'Mark',
+ 'OSD lost',
+ 'marked lost',
+ this.osdService.markLost
+ ),
disable: () => this.isNotSelectedOrInState('up'),
icon: 'fa-unlink'
},
{
name: 'Remove',
permission: 'delete',
- click: () => this.remove(),
+ click: () =>
+ this.showCriticalConfirmationModal('Remove', 'OSD', 'removed', this.osdService.remove),
disable: () => this.isNotSelectedOrInState('up'),
icon: 'fa-remove'
},
{
name: 'Destroy',
permission: 'delete',
- click: () => this.destroy(),
+ click: () =>
+ this.showCriticalConfirmationModal(
+ 'destroy',
+ 'OSD',
+ 'destroyed',
+ this.osdService.destroy
+ ),
disable: () => this.isNotSelectedOrInState('up'),
icon: 'fa-eraser'
}
@@ -238,18 +251,6 @@ export class OsdListComponent implements OnInit {
});
}
- markOut() {
- this.showConfirmationModal('out', this.osdService.markOut);
- }
-
- markIn() {
- this.showConfirmationModal('in', this.osdService.markIn);
- }
-
- markDown() {
- this.showConfirmationModal('down', this.osdService.markDown);
- }
-
reweight() {
const selectedOsd = this.osds.filter((o) => o.id === this.selection.first().id).pop();
this.modalService.show(OsdReweightModalComponent, {
@@ -285,16 +286,4 @@ export class OsdListComponent implements OnInit {
});
});
}
-
- markLost() {
- this.showCriticalConfirmationModal('Mark', 'OSD lost', 'marked lost', this.osdService.markLost);
- }
-
- remove() {
- this.showCriticalConfirmationModal('Remove', 'OSD', 'removed', this.osdService.remove);
- }
-
- destroy() {
- this.showCriticalConfirmationModal('destroy', 'OSD', 'destroyed', this.osdService.destroy);
- }
}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts
index 1eb9c6ab496..1412fbea588 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts
@@ -163,28 +163,27 @@ export class PoolFormComponent implements OnInit {
}
private initEditFormData(pool: Pool) {
- const transform = {
- name: 'pool_name',
- poolType: 'type',
- crushRule: (p) =>
- this.info['crush_rules_' + p.type].find(
- (rule: CrushRule) => rule.rule_name === p.crush_rule
- ),
- size: 'size',
- erasureProfile: (p) => this.ecProfiles.find((ecp) => ecp.name === p.erasure_code_profile),
- pgNum: 'pg_num',
- ecOverwrites: (p) => p.flags_names.includes('ec_overwrites'),
- mode: 'options.compression_mode',
- algorithm: 'options.compression_algorithm',
- minBlobSize: (p) => this.dimlessBinaryPipe.transform(p.options.compression_min_blob_size),
- maxBlobSize: (p) => this.dimlessBinaryPipe.transform(p.options.compression_max_blob_size),
- ratio: 'options.compression_required_ratio'
+ const dataMap = {
+ name: pool.pool_name,
+ poolType: pool.type,
+ crushRule: this.info['crush_rules_' + pool.type].find(
+ (rule: CrushRule) => rule.rule_name === pool.crush_rule
+ ),
+ size: pool.size,
+ erasureProfile: this.ecProfiles.find((ecp) => ecp.name === pool.erasure_code_profile),
+ pgNum: pool.pg_num,
+ ecOverwrites: pool.flags_names.includes('ec_overwrites'),
+ mode: pool.options.compression_mode,
+ algorithm: pool.options.compression_algorithm,
+ minBlobSize: this.dimlessBinaryPipe.transform(pool.options.compression_min_blob_size),
+ maxBlobSize: this.dimlessBinaryPipe.transform(pool.options.compression_max_blob_size),
+ ratio: pool.options.compression_required_ratio
};
- Object.keys(transform).forEach((key) => {
- const attrib = transform[key];
- const value = _.isFunction(attrib) ? attrib(pool) : _.get(pool, attrib);
+
+ Object.keys(dataMap).forEach((controlName: string) => {
+ const value = dataMap[controlName];
if (!_.isUndefined(value) && value !== '') {
- this.form.silentSet(key, value);
+ this.form.silentSet(controlName, value);
}
});
this.data.applications.selected = pool.application_metadata;
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.ts
index 666ada886bc..67fb868acb4 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.ts
@@ -27,8 +27,9 @@ export class Rgw501Component implements OnInit, OnDestroy {
}
const releaseName = this.cephReleaseNamePipe.transform(summary.version);
- this.docsUrl = `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/
- #enabling-the-object-gateway-management-frontend`;
+ this.docsUrl =
+ `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/` +
+ `#enabling-the-object-gateway-management-frontend`;
setTimeout(() => {
subs.unsubscribe();
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.ts
index 47b80a08a02..00fd332981a 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.ts
@@ -3,9 +3,9 @@ import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { SafeUrl } from '@angular/platform-browser';
-import { SettingsService } from '../../../shared/api/settings.service';
-import { CephReleaseNamePipe } from '../../../shared/pipes/ceph-release-name.pipe';
-import { SummaryService } from '../../../shared/services/summary.service';
+import { SettingsService } from '../../api/settings.service';
+import { CephReleaseNamePipe } from '../../pipes/ceph-release-name.pipe';
+import { SummaryService } from '../../services/summary.service';
@Component({
selector: 'cd-grafana',
@@ -55,7 +55,9 @@ export class GrafanaComponent implements OnInit, OnChanges {
}
const releaseName = this.cephReleaseNamePipe.transform(summary.version);
- this.docsUrl = `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/`;
+ this.docsUrl =
+ `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/` +
+ `#enabling-the-embedding-of-grafana-dashboards`;
setTimeout(() => {
subs.unsubscribe();
diff --git a/src/pybind/mgr/dashboard/module.py b/src/pybind/mgr/dashboard/module.py
index 801725386a6..c08f2b4f05e 100644
--- a/src/pybind/mgr/dashboard/module.py
+++ b/src/pybind/mgr/dashboard/module.py
@@ -151,6 +151,8 @@ class CherryPyConfig(object):
'application/json',
'application/javascript',
],
+ 'tools.json_in.on': True,
+ 'tools.json_in.force': False
}
if ssl:
diff --git a/src/pybind/mgr/dashboard/settings.py b/src/pybind/mgr/dashboard/settings.py
index 953e918234b..ccde39ffd31 100644
--- a/src/pybind/mgr/dashboard/settings.py
+++ b/src/pybind/mgr/dashboard/settings.py
@@ -21,6 +21,10 @@ class Options(object):
ENABLE_BROWSABLE_API = (True, bool)
REST_REQUESTS_TIMEOUT = (45, int)
+ # API auditing
+ AUDIT_API_ENABLED = (False, bool)
+ AUDIT_API_LOG_PAYLOAD = (True, bool)
+
# RGW settings
RGW_API_HOST = ('', str)
RGW_API_PORT = (80, int)
diff --git a/src/pybind/mgr/dashboard/tests/helper.py b/src/pybind/mgr/dashboard/tests/helper.py
index 1a8ea7a381b..2efeba816bb 100644
--- a/src/pybind/mgr/dashboard/tests/helper.py
+++ b/src/pybind/mgr/dashboard/tests/helper.py
@@ -40,7 +40,11 @@ class ControllerTestCase(helper.CPWebCase):
cherrypy.tools.authenticate = AuthManagerTool()
cherrypy.tools.dashboard_exception_handler = HandlerWrapperTool(dashboard_exception_handler,
priority=31)
- cherrypy.config.update({'error_page.default': json_error_page})
+ cherrypy.config.update({
+ 'error_page.default': json_error_page,
+ 'tools.json_in.on': True,
+ 'tools.json_in.force': False
+ })
super(ControllerTestCase, self).__init__(*args, **kwargs)
def _request(self, url, method, data=None):
diff --git a/src/pybind/mgr/dashboard/tests/test_api_auditing.py b/src/pybind/mgr/dashboard/tests/test_api_auditing.py
new file mode 100644
index 00000000000..d22410e847b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_api_auditing.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import re
+import json
+import cherrypy
+import mock
+
+from .helper import ControllerTestCase
+from ..controllers import RESTController, Controller
+from ..tools import RequestLoggingTool
+from .. import mgr
+
+
+# pylint: disable=W0613
+@Controller('/foo', secure=False)
+class FooResource(RESTController):
+ def create(self, password):
+ pass
+
+ def get(self, key):
+ pass
+
+ def delete(self, key):
+ pass
+
+ def set(self, key, password, secret_key=None):
+ pass
+
+
+class ApiAuditingTest(ControllerTestCase):
+ settings = {}
+
+ def __init__(self, *args, **kwargs):
+ cherrypy.tools.request_logging = RequestLoggingTool()
+ cherrypy.config.update({'tools.request_logging.on': True})
+ super(ApiAuditingTest, self).__init__(*args, **kwargs)
+
+ @classmethod
+ def mock_set_config(cls, key, val):
+ cls.settings[key] = val
+
+ @classmethod
+ def mock_get_config(cls, key, default=None):
+ return cls.settings.get(key, default)
+
+ @classmethod
+ def setUpClass(cls):
+ mgr.get_config.side_effect = cls.mock_get_config
+ mgr.set_config.side_effect = cls.mock_set_config
+
+ @classmethod
+ def setup_server(cls):
+ cls.setup_controllers([FooResource])
+
+ def setUp(self):
+ mgr.cluster_log = mock.Mock()
+ mgr.set_config('AUDIT_API_ENABLED', True)
+ mgr.set_config('AUDIT_API_LOG_PAYLOAD', True)
+
+ def _validate_cluster_log_msg(self, path, method, user, params):
+ channel, _, msg = mgr.cluster_log.call_args_list[0][0]
+ self.assertEqual(channel, 'audit')
+ pattern = r'^\[DASHBOARD\] from=\'(.+)\' path=\'(.+)\' ' \
+ 'method=\'(.+)\' user=\'(.+)\' params=\'(.+)\'$'
+ m = re.match(pattern, msg)
+ self.assertEqual(m.group(2), path)
+ self.assertEqual(m.group(3), method)
+ self.assertEqual(m.group(4), user)
+ self.assertDictEqual(json.loads(m.group(5)), params)
+
+ def test_no_audit(self):
+ mgr.set_config('AUDIT_API_ENABLED', False)
+ self._delete('/foo/test1')
+ mgr.cluster_log.assert_not_called()
+
+ def test_no_payload(self):
+ mgr.set_config('AUDIT_API_LOG_PAYLOAD', False)
+ self._delete('/foo/test1')
+ _, _, msg = mgr.cluster_log.call_args_list[0][0]
+ self.assertNotIn('params=', msg)
+
+ def test_no_audit_get(self):
+ self._get('/foo/test1')
+ mgr.cluster_log.assert_not_called()
+
+ def test_audit_put(self):
+ self._put('/foo/test1', {'password': 'y', 'secret_key': 1234})
+ mgr.cluster_log.assert_called_once()
+ self._validate_cluster_log_msg('/foo/test1', 'PUT', 'None',
+ {'key': 'test1',
+ 'password': '***',
+ 'secret_key': '***'})
+
+ def test_audit_post(self):
+ with mock.patch('dashboard.services.auth.JwtManager.get_username',
+ return_value='hugo'):
+ self._post('/foo?password=1234')
+ mgr.cluster_log.assert_called_once()
+ self._validate_cluster_log_msg('/foo', 'POST', 'hugo',
+ {'password': '***'})
+
+ def test_audit_delete(self):
+ self._delete('/foo/test1')
+ mgr.cluster_log.assert_called_once()
+ self._validate_cluster_log_msg('/foo/test1', 'DELETE',
+ 'None', {'key': 'test1'})
diff --git a/src/pybind/mgr/dashboard/tests/test_tools.py b/src/pybind/mgr/dashboard/tests/test_tools.py
index bd27822931e..7cc2b0c6aa1 100644
--- a/src/pybind/mgr/dashboard/tests/test_tools.py
+++ b/src/pybind/mgr/dashboard/tests/test_tools.py
@@ -11,7 +11,8 @@ from ..services.exception import handle_rados_error
from .helper import ControllerTestCase
from ..controllers import RESTController, ApiController, Controller, \
BaseController, Proxy
-from ..tools import is_valid_ipv6_address, dict_contains_path
+from ..tools import is_valid_ipv6_address, dict_contains_path, \
+ RequestLoggingTool
# pylint: disable=W0613
@@ -146,6 +147,29 @@ class RESTControllerTest(ControllerTestCase):
GenerateControllerRoutesController
+class RequestLoggingToolTest(ControllerTestCase):
+
+ def __init__(self, *args, **kwargs):
+ cherrypy.tools.request_logging = RequestLoggingTool()
+ cherrypy.config.update({'tools.request_logging.on': True})
+ super(RequestLoggingToolTest, self).__init__(*args, **kwargs)
+
+ @classmethod
+ def setup_server(cls):
+ cls.setup_controllers([FooResource])
+
+ def test_is_logged(self):
+ with patch('logging.Logger.debug') as mock_logger_debug:
+ self._put('/foo/0', {'newdata': 'xyz'})
+ self.assertStatus(200)
+ call_args_list = mock_logger_debug.call_args_list
+ _, host, _, method, user, path = call_args_list[0][0]
+ self.assertEqual(host, '127.0.0.1')
+ self.assertEqual(method, 'PUT')
+ self.assertIsNone(user)
+ self.assertEqual(path, '/foo/0')
+
+
class TestFunctions(unittest.TestCase):
def test_is_valid_ipv6_address(self):
diff --git a/src/pybind/mgr/dashboard/tools.py b/src/pybind/mgr/dashboard/tools.py
index 662fc5cd955..ee8de3b9658 100644
--- a/src/pybind/mgr/dashboard/tools.py
+++ b/src/pybind/mgr/dashboard/tools.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import
import sys
import inspect
+import json
import functools
import collections
@@ -15,8 +16,9 @@ import socket
from six.moves import urllib
import cherrypy
-from . import logger
+from . import logger, mgr
from .exceptions import ViewCacheNoDataException
+from .settings import Settings
from .services.auth import JwtManager
@@ -35,12 +37,31 @@ class RequestLoggingTool(cherrypy.Tool):
def request_begin(self):
req = cherrypy.request
user = JwtManager.get_username()
- if user:
- logger.debug("[%s:%s] [%s] [%s] %s", req.remote.ip,
- req.remote.port, req.method, user, req.path_info)
- else:
- logger.debug("[%s:%s] [%s] %s", req.remote.ip,
- req.remote.port, req.method, req.path_info)
+ # Log the request.
+ logger.debug('[%s:%s] [%s] [%s] %s', req.remote.ip, req.remote.port,
+ req.method, user, req.path_info)
+ # Audit the request.
+ if Settings.AUDIT_API_ENABLED and req.method not in ['GET']:
+ url = build_url(req.remote.ip, scheme=req.scheme,
+ port=req.remote.port)
+ msg = '[DASHBOARD] from=\'{}\' path=\'{}\' method=\'{}\' ' \
+ 'user=\'{}\''.format(url, req.path_info, req.method, user)
+ if Settings.AUDIT_API_LOG_PAYLOAD:
+ params = req.params if req.params else {}
+ params.update(get_request_body_params(req))
+ # Hide sensitive data like passwords, secret keys, ...
+ # Extend the list of patterns to search for if necessary.
+ # Currently parameters like this are processed:
+ # - secret_key
+ # - user_password
+ # - new_passwd_to_login
+ keys = []
+ for key in ['password', 'passwd', 'secret']:
+ keys.extend([x for x in params.keys() if key in x])
+ for key in keys:
+ params[key] = '***'
+ msg = '{} params=\'{}\''.format(msg, json.dumps(params))
+ mgr.cluster_log('audit', mgr.CLUSTER_LOG_PRIO_INFO, msg)
def request_error(self):
self._request_log(logger.error)
@@ -718,3 +739,24 @@ def str_to_bool(val):
if isinstance(val, bool):
return val
return bool(strtobool(val))
+
+
+def get_request_body_params(request):
+ """
+ Helper function to get parameters from the request body.
+ :param request The CherryPy request object.
+ :type request: cherrypy.Request
+ :return: A dictionary containing the parameters.
+ :rtype: dict
+ """
+ params = {}
+ if request.method not in request.methods_with_bodies:
+ return params
+
+ content_type = request.headers.get('Content-Type', '')
+ if content_type in ['application/json', 'text/javascript']:
+ if not hasattr(request, 'json'):
+ raise cherrypy.HTTPError(400, 'Expected JSON body')
+ params.update(request.json.items())
+
+ return params
diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx
index b300edd0d1a..871345dfe2f 100644
--- a/src/pybind/rbd/rbd.pyx
+++ b/src/pybind/rbd/rbd.pyx
@@ -208,9 +208,11 @@ cdef extern from "rbd/librbd.h" nogil:
ctypedef struct rbd_image_migration_status_t:
int64_t source_pool_id
+ char *source_pool_namespace
char *source_image_name
char *source_image_id
int64_t dest_pool_id
+ char *dest_pool_namespace
char *dest_image_name
char *dest_image_id
rbd_image_migration_state_t state
@@ -1385,12 +1387,16 @@ class RBD(object):
* ``source_pool_id`` (int) - source image pool id
+ * ``source_pool_namespace`` (str) - source image pool namespace
+
* ``source_image_name`` (str) - source image name
* ``source_image_id`` (str) - source image id
* ``dest_pool_id`` (int) - destination image pool id
+ * ``dest_pool_namespace`` (str) - destination image pool namespace
+
* ``dest_image_name`` (str) - destination image name
* ``dest_image_id`` (str) - destination image id
@@ -1413,14 +1419,16 @@ class RBD(object):
raise make_ex(ret, 'error getting migration status')
status = {
- 'source_pool_id' : c_status.source_pool_id,
- 'source_image_name' : decode_cstr(c_status.source_image_name),
- 'source_image_id' : decode_cstr(c_status.source_image_id),
- 'dest_pool_id' : c_status.source_pool_id,
- 'dest_image_name' : decode_cstr(c_status.dest_image_name),
- 'dest_image_id' : decode_cstr(c_status.dest_image_id),
- 'state' : c_status.state,
- 'state_description' : decode_cstr(c_status.state_description)
+ 'source_pool_id' : c_status.source_pool_id,
+ 'source_pool_namespace' : decode_cstr(c_status.source_pool_namespace),
+ 'source_image_name' : decode_cstr(c_status.source_image_name),
+ 'source_image_id' : decode_cstr(c_status.source_image_id),
+ 'dest_pool_id' : c_status.source_pool_id,
+ 'dest_pool_namespace' : decode_cstr(c_status.dest_pool_namespace),
+ 'dest_image_name' : decode_cstr(c_status.dest_image_name),
+ 'dest_image_id' : decode_cstr(c_status.dest_image_id),
+ 'state' : c_status.state,
+ 'state_description' : decode_cstr(c_status.state_description)
}
rbd_migration_status_cleanup(&c_status)
diff --git a/src/rbd_fuse/CMakeLists.txt b/src/rbd_fuse/CMakeLists.txt
index 618992b776a..e0bd3e2497d 100644
--- a/src/rbd_fuse/CMakeLists.txt
+++ b/src/rbd_fuse/CMakeLists.txt
@@ -1,5 +1,5 @@
add_executable(rbd-fuse
rbd-fuse.cc)
target_link_libraries(rbd-fuse
- ceph-common librbd librados ${FUSE_LIBRARIES})
+ ceph-common librbd librados global ${FUSE_LIBRARIES})
install(TARGETS rbd-fuse DESTINATION bin)
diff --git a/src/rbd_fuse/rbd-fuse.cc b/src/rbd_fuse/rbd-fuse.cc
index d6d44e051f9..f40556a1972 100644
--- a/src/rbd_fuse/rbd-fuse.cc
+++ b/src/rbd_fuse/rbd-fuse.cc
@@ -28,9 +28,14 @@
#include "include/compat.h"
#include "include/rbd/librbd.h"
-
#include "include/ceph_assert.h"
+#include "common/ceph_argparse.h"
+#include "common/ceph_context.h"
+
+#include "global/global_init.h"
+#include "global/global_context.h"
+
static int gotrados = 0;
char *pool_name;
char *mount_image_name;
@@ -45,7 +50,6 @@ struct rbd_stat {
};
struct rbd_options {
- char *ceph_config;
char *pool_name;
char *image_name;
};
@@ -68,8 +72,7 @@ struct rbd_openimage {
#define MAX_RBD_IMAGES 128
struct rbd_openimage opentbl[MAX_RBD_IMAGES];
-struct rbd_options rbd_options = {(char*) "/etc/ceph/ceph.conf", (char*) "rbd",
- NULL};
+struct rbd_options rbd_options = {(char*) "rbd", NULL};
#define rbdsize(fd) opentbl[fd].rbd_stat.rbd_info.size
#define rbdblksize(fd) opentbl[fd].rbd_stat.rbd_info.obj_size
@@ -759,8 +762,6 @@ const static struct fuse_operations rbdfs_oper = {
enum {
KEY_HELP,
KEY_VERSION,
- KEY_CEPH_CONFIG,
- KEY_CEPH_CONFIG_LONG,
KEY_RADOS_POOLNAME,
KEY_RADOS_POOLNAME_LONG,
KEY_RBD_IMAGENAME,
@@ -772,15 +773,13 @@ static struct fuse_opt rbdfs_opts[] = {
FUSE_OPT_KEY("--help", KEY_HELP),
FUSE_OPT_KEY("-V", KEY_VERSION),
FUSE_OPT_KEY("--version", KEY_VERSION),
- {"-c %s", offsetof(struct rbd_options, ceph_config), KEY_CEPH_CONFIG},
- {"--configfile=%s", offsetof(struct rbd_options, ceph_config),
- KEY_CEPH_CONFIG_LONG},
{"-p %s", offsetof(struct rbd_options, pool_name), KEY_RADOS_POOLNAME},
{"--poolname=%s", offsetof(struct rbd_options, pool_name),
KEY_RADOS_POOLNAME_LONG},
{"-r %s", offsetof(struct rbd_options, image_name), KEY_RBD_IMAGENAME},
{"--image=%s", offsetof(struct rbd_options, image_name),
KEY_RBD_IMAGENAME_LONG},
+ FUSE_OPT_END
};
static void usage(const char *progname)
@@ -791,7 +790,7 @@ static void usage(const char *progname)
"General options:\n"
" -h --help print help\n"
" -V --version print version\n"
-" -c --configfile ceph configuration file [/etc/ceph/ceph.conf]\n"
+" -c --conf ceph configuration file [/etc/ceph/ceph.conf]\n"
" -p --poolname rados pool name [rbd]\n"
" -r --image RBD image name\n"
"\n", progname);
@@ -813,15 +812,6 @@ static int rbdfs_opt_proc(void *data, const char *arg, int key,
exit(0);
}
- if (key == KEY_CEPH_CONFIG) {
- if (rbd_options.ceph_config != NULL) {
- free(rbd_options.ceph_config);
- rbd_options.ceph_config = NULL;
- }
- rbd_options.ceph_config = strdup(arg+2);
- return 0;
- }
-
if (key == KEY_RADOS_POOLNAME) {
if (rbd_options.pool_name != NULL) {
free(rbd_options.pool_name);
@@ -854,36 +844,63 @@ int
connect_to_cluster(rados_t *pcluster)
{
int r;
+ global_init_postfork_start(g_ceph_context);
+ common_init_finish(g_ceph_context);
+ global_init_postfork_finish(g_ceph_context);
- r = rados_create(pcluster, NULL);
+ r = rados_create_with_context(pcluster, g_ceph_context);
if (r < 0) {
simple_err("Could not create cluster handle", r);
return r;
}
- rados_conf_parse_env(*pcluster, NULL);
- r = rados_conf_read_file(*pcluster, rbd_options.ceph_config);
- if (r < 0) {
- simple_err("Error reading Ceph config file", r);
- goto failed_shutdown;
- }
+
r = rados_connect(*pcluster);
if (r < 0) {
simple_err("Error connecting to cluster", r);
- goto failed_shutdown;
+ rados_shutdown(*pcluster);
+ return r;
}
return 0;
-
-failed_shutdown:
- rados_shutdown(*pcluster);
- return r;
}
-int main(int argc, char *argv[])
+int main(int argc, const char *argv[])
{
- struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ // librados will filter out -f/-d options from command-line
+ std::map<std::string, bool> filter_args = {
+ {"-f", false},
+ {"-d", false}};
+
+ std::vector<const char*> arg_vector;
+ for (auto idx = 0; idx < argc; ++idx) {
+ auto it = filter_args.find(argv[idx]);
+ if (it != filter_args.end()) {
+ it->second = true;
+ }
+ arg_vector.push_back(argv[idx]);
+ }
+
+ auto cct = global_init(NULL, arg_vector, CEPH_ENTITY_TYPE_CLIENT,
+ CODE_ENVIRONMENT_DAEMON,
+ CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS);
+ g_ceph_context->_conf.set_val_or_die("pid_file", "");
+ g_ceph_context->_conf.set_val_or_die("daemonize", "true");
+
+ if (global_init_prefork(g_ceph_context) < 0) {
+ fprintf(stderr, "Failed to initialize librados\n");
+ exit(1);
+ }
+
+ for (auto& it : filter_args) {
+ if (it.second) {
+ arg_vector.push_back(it.first.c_str());
+ }
+ }
- if (fuse_opt_parse(&args, &rbd_options, rbdfs_opts, rbdfs_opt_proc) == -1) {
+ struct fuse_args args = FUSE_ARGS_INIT((int)arg_vector.size(),
+ (char**)&arg_vector.front());
+ if (fuse_opt_parse(&args, &rbd_options, rbdfs_opts,
+ rbdfs_opt_proc) == -1) {
exit(1);
}
diff --git a/src/rbd_replay/CMakeLists.txt b/src/rbd_replay/CMakeLists.txt
index e9d3804c5f5..5ffae423be4 100644
--- a/src/rbd_replay/CMakeLists.txt
+++ b/src/rbd_replay/CMakeLists.txt
@@ -10,7 +10,7 @@ set(librbd_replay_srcs
rbd_loc.cc
Replayer.cc)
add_library(rbd_replay STATIC ${librbd_replay_srcs})
-target_link_libraries(rbd_replay PRIVATE librbd librados global)
+target_link_libraries(rbd_replay PRIVATE librbd librados-cxx global)
add_executable(rbd-replay
rbd-replay.cc)
diff --git a/src/rgw/CMakeLists.txt b/src/rgw/CMakeLists.txt
index 4d488a0eba3..939282733c2 100644
--- a/src/rgw/CMakeLists.txt
+++ b/src/rgw/CMakeLists.txt
@@ -169,7 +169,7 @@ add_dependencies(rgw_a civetweb_h)
target_include_directories(rgw_a SYSTEM PUBLIC "../rapidjson/include")
target_link_libraries(rgw_a PRIVATE
- librados cls_otp_client cls_lock_client cls_rgw_client cls_refcount_client
+ librados-cxx cls_otp_client cls_lock_client cls_rgw_client cls_refcount_client
cls_log_client cls_timeindex_client cls_version_client
cls_user_client ceph-common common_utf8 global
${CURL_LIBRARIES}
@@ -296,7 +296,7 @@ add_library(rgw_admin_user SHARED
add_dependencies(rgw_admin_user civetweb_h)
target_link_libraries(rgw_admin_user PRIVATE
- librados
+ librados-cxx
cls_rgw_client
cls_otp_client
cls_lock_client
diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc
index 15eb5c2d36f..29e0f6479c0 100644
--- a/src/rgw/rgw_admin.cc
+++ b/src/rgw/rgw_admin.cc
@@ -5763,7 +5763,7 @@ next:
for (int i = 0; i < max_shards; i++) {
RGWRados::BucketShard bs(store);
int shard_id = (bucket_info.num_shards > 0 ? i : -1);
- int ret = bs.init(bucket, shard_id);
+ int ret = bs.init(bucket, shard_id, nullptr /* no RGWBucketInfo */);
marker.clear();
if (ret < 0) {
@@ -5824,7 +5824,7 @@ next:
for (int i = 0; i < max_shards; i++) {
RGWRados::BucketShard bs(store);
int shard_id = (bucket_info.num_shards > 0 ? i : -1);
- int ret = bs.init(bucket, shard_id);
+ int ret = bs.init(bucket, shard_id, nullptr /* no RGWBucketInfo */);
if (ret < 0) {
cerr << "ERROR: bs.init(bucket=" << bucket << ", shard=" << shard_id << "): " << cpp_strerror(-ret) << std::endl;
return -ret;
@@ -6020,7 +6020,7 @@ next:
return ret;
}
- RGWBucketReshard br(store, bucket_info, attrs);
+ RGWBucketReshard br(store, bucket_info, attrs, nullptr /* no callback */);
#define DEFAULT_RESHARD_MAX_ENTRIES 1000
if (max_entries < 1) {
@@ -6106,7 +6106,6 @@ next:
return 0;
}
-
if (opt_cmd == OPT_RESHARD_STATUS) {
if (bucket_name.empty()) {
cerr << "ERROR: bucket not specified" << std::endl;
@@ -6122,11 +6121,12 @@ next:
return -ret;
}
- RGWBucketReshard br(store, bucket_info, attrs);
+ RGWBucketReshard br(store, bucket_info, attrs, nullptr /* no callback */);
list<cls_rgw_bucket_instance_entry> status;
int r = br.get_status(&status);
if (r < 0) {
- cerr << "ERROR: could not get resharding status for bucket " << bucket_name << std::endl;
+ cerr << "ERROR: could not get resharding status for bucket " <<
+ bucket_name << std::endl;
return -r;
}
@@ -6159,7 +6159,7 @@ next:
return -ret;
}
- RGWBucketReshard br(store, bucket_info, attrs);
+ RGWBucketReshard br(store, bucket_info, attrs, nullptr /* no callback */);
int ret = br.cancel();
if (ret < 0) {
if (ret == -EBUSY) {
diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc
index fc44adeac66..006b1d62493 100644
--- a/src/rgw/rgw_bucket.cc
+++ b/src/rgw/rgw_bucket.cc
@@ -1420,6 +1420,7 @@ static int bucket_stats(RGWRados *store, const std::string& tenant_name, std::st
formatter->open_object_section("stats");
formatter->dump_string("bucket", bucket.name);
+ formatter->dump_string("tenant", bucket.tenant);
formatter->dump_string("zonegroup", bucket_info.zonegroup);
formatter->dump_string("placement_rule", bucket_info.placement_rule);
::encode_json("explicit_placement", bucket.explicit_placement, formatter);
diff --git a/src/rgw/rgw_cr_rados.cc b/src/rgw/rgw_cr_rados.cc
index a29630677a7..19caececeba 100644
--- a/src/rgw/rgw_cr_rados.cc
+++ b/src/rgw/rgw_cr_rados.cc
@@ -170,7 +170,7 @@ int RGWAsyncLockSystemObj::_send_request()
utime_t duration(duration_secs, 0);
l.set_duration(duration);
l.set_cookie(cookie);
- l.set_renew(true);
+ l.set_may_renew(true);
return l.lock_exclusive(&ref.ioctx, ref.oid);
}
diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc
index 770a84334d1..780863afdab 100644
--- a/src/rgw/rgw_rados.cc
+++ b/src/rgw/rgw_rados.cc
@@ -3164,21 +3164,22 @@ int RGWIndexCompletionThread::process()
ldout(store->ctx(), 20) << __func__ << "(): handling completion for key=" << c->key << dendl;
RGWRados::BucketShard bs(store);
+ RGWBucketInfo bucket_info;
- int r = bs.init(c->obj.bucket, c->obj);
+ int r = bs.init(c->obj.bucket, c->obj, &bucket_info);
if (r < 0) {
ldout(cct, 0) << "ERROR: " << __func__ << "(): failed to initialize BucketShard, obj=" << c->obj << " r=" << r << dendl;
/* not much to do */
continue;
}
- r = store->guard_reshard(&bs, c->obj, [&](RGWRados::BucketShard *bs) -> int {
- librados::ObjectWriteOperation o;
- cls_rgw_guard_bucket_resharding(o, -ERR_BUSY_RESHARDING);
- cls_rgw_bucket_complete_op(o, c->op, c->tag, c->ver, c->key, c->dir_meta, &c->remove_objs,
- c->log_op, c->bilog_op, &c->zones_trace);
-
- return bs->index_ctx.operate(bs->bucket_obj, &o);
+ r = store->guard_reshard(&bs, c->obj, bucket_info,
+ [&](RGWRados::BucketShard *bs) -> int {
+ librados::ObjectWriteOperation o;
+ cls_rgw_guard_bucket_resharding(o, -ERR_BUSY_RESHARDING);
+ cls_rgw_bucket_complete_op(o, c->op, c->tag, c->ver, c->key, c->dir_meta, &c->remove_objs,
+ c->log_op, c->bilog_op, &c->zones_trace);
+ return bs->index_ctx.operate(bs->bucket_obj, &o);
});
if (r < 0) {
ldout(cct, 0) << "ERROR: " << __func__ << "(): bucket index completion failed, obj=" << c->obj << " r=" << r << dendl;
@@ -5225,7 +5226,7 @@ int RGWRados::lock_exclusive(rgw_pool& pool, const string& oid, timespan& durati
l.set_duration(ut);
l.set_cookie(owner_id);
l.set_tag(zone_id);
- l.set_renew(true);
+ l.set_may_renew(true);
return l.lock_exclusive(&io_ctx, oid);
}
@@ -6416,19 +6417,24 @@ int RGWRados::fix_tail_obj_locator(const RGWBucketInfo& bucket_info, rgw_obj_key
return 0;
}
-int RGWRados::BucketShard::init(const rgw_bucket& _bucket, const rgw_obj& obj)
+int RGWRados::BucketShard::init(const rgw_bucket& _bucket,
+ const rgw_obj& obj,
+ RGWBucketInfo* bucket_info_out)
{
bucket = _bucket;
RGWObjectCtx obj_ctx(store);
RGWBucketInfo bucket_info;
- int ret = store->get_bucket_instance_info(obj_ctx, bucket, bucket_info, NULL, NULL);
+ RGWBucketInfo* bucket_info_p =
+ bucket_info_out ? bucket_info_out : &bucket_info;
+
+ int ret = store->get_bucket_instance_info(obj_ctx, bucket, *bucket_info_p, NULL, NULL);
if (ret < 0) {
return ret;
}
- ret = store->open_bucket_index_shard(bucket_info, index_ctx, obj.get_hash_object(), &bucket_obj, &shard_id);
+ ret = store->open_bucket_index_shard(*bucket_info_p, index_ctx, obj.get_hash_object(), &bucket_obj, &shard_id);
if (ret < 0) {
ldout(store->ctx(), 0) << "ERROR: open_bucket_index_shard() returned ret=" << ret << dendl;
return ret;
@@ -6438,7 +6444,9 @@ int RGWRados::BucketShard::init(const rgw_bucket& _bucket, const rgw_obj& obj)
return 0;
}
-int RGWRados::BucketShard::init(const rgw_bucket& _bucket, int sid)
+int RGWRados::BucketShard::init(const rgw_bucket& _bucket,
+ int sid,
+ RGWBucketInfo* bucket_info_out)
{
bucket = _bucket;
shard_id = sid;
@@ -6446,12 +6454,14 @@ int RGWRados::BucketShard::init(const rgw_bucket& _bucket, int sid)
RGWObjectCtx obj_ctx(store);
RGWBucketInfo bucket_info;
- int ret = store->get_bucket_instance_info(obj_ctx, bucket, bucket_info, NULL, NULL);
+ RGWBucketInfo* bucket_info_p =
+ bucket_info_out ? bucket_info_out : &bucket_info;
+ int ret = store->get_bucket_instance_info(obj_ctx, bucket, *bucket_info_p, NULL, NULL);
if (ret < 0) {
return ret;
}
- ret = store->open_bucket_index_shard(bucket_info, index_ctx, shard_id, &bucket_obj);
+ ret = store->open_bucket_index_shard(*bucket_info_p, index_ctx, shard_id, &bucket_obj);
if (ret < 0) {
ldout(store->ctx(), 0) << "ERROR: open_bucket_index_shard() returned ret=" << ret << dendl;
return ret;
@@ -8552,7 +8562,7 @@ int RGWRados::bucket_rebuild_index(RGWBucketInfo& bucket_info)
return CLSRGWIssueBucketRebuild(index_ctx, bucket_objs, cct->_conf->rgw_bucket_index_max_aio)();
}
-int RGWRados::bucket_set_reshard(RGWBucketInfo& bucket_info, const cls_rgw_bucket_instance_entry& entry)
+int RGWRados::bucket_set_reshard(const RGWBucketInfo& bucket_info, const cls_rgw_bucket_instance_entry& entry)
{
librados::IoCtx index_ctx;
map<int, string> bucket_objs;
@@ -9825,7 +9835,7 @@ int RGWRados::Bucket::UpdateIndex::guard_reshard(BucketShard **pbs, std::functio
}
ldout(store->ctx(), 0) << "NOTICE: resharding operation on bucket index detected, blocking" << dendl;
string new_bucket_id;
- r = store->block_while_resharding(bs, &new_bucket_id);
+ r = store->block_while_resharding(bs, &new_bucket_id, target->bucket_info);
if (r == -ERR_BUSY_RESHARDING) {
continue;
}
@@ -9877,9 +9887,9 @@ int RGWRados::Bucket::UpdateIndex::prepare(RGWModifyOp op, const string *write_t
}
}
- int r = guard_reshard(nullptr, [&](BucketShard *bs) -> int {
- return store->cls_obj_prepare_op(*bs, op, optag, obj, bilog_flags, zones_trace);
- });
+ int r = guard_reshard(nullptr, [&](BucketShard *bs) -> int {
+ return store->cls_obj_prepare_op(*bs, op, optag, obj, bilog_flags, zones_trace);
+ });
if (r < 0) {
return r;
@@ -9978,9 +9988,9 @@ int RGWRados::Bucket::UpdateIndex::cancel()
RGWRados *store = target->get_store();
BucketShard *bs;
- int ret = guard_reshard(&bs, [&](BucketShard *bs) -> int {
- return store->cls_obj_complete_cancel(*bs, optag, obj, bilog_flags, zones_trace);
- });
+ int ret = guard_reshard(&bs, [&](BucketShard *bs) -> int {
+ return store->cls_obj_complete_cancel(*bs, optag, obj, bilog_flags, zones_trace);
+ });
/*
* need to update data log anyhow, so that whoever follows needs to update its internal markers
@@ -10774,14 +10784,17 @@ int RGWRados::olh_init_modification(const RGWBucketInfo& bucket_info, RGWObjStat
return ret;
}
-int RGWRados::guard_reshard(BucketShard *bs, const rgw_obj& obj_instance, std::function<int(BucketShard *)> call)
+int RGWRados::guard_reshard(BucketShard *bs,
+ const rgw_obj& obj_instance,
+ const RGWBucketInfo& bucket_info,
+ std::function<int(BucketShard *)> call)
{
rgw_obj obj;
const rgw_obj *pobj = &obj_instance;
int r;
for (int i = 0; i < NUM_RESHARD_RETRIES; ++i) {
- r = bs->init(pobj->bucket, *pobj);
+ r = bs->init(pobj->bucket, *pobj, nullptr /* no RGWBucketInfo */);
if (r < 0) {
ldout(cct, 5) << "bs.init() returned ret=" << r << dendl;
return r;
@@ -10792,7 +10805,7 @@ int RGWRados::guard_reshard(BucketShard *bs, const rgw_obj& obj_instance, std::f
}
ldout(cct, 0) << "NOTICE: resharding operation on bucket index detected, blocking" << dendl;
string new_bucket_id;
- r = block_while_resharding(bs, &new_bucket_id);
+ r = block_while_resharding(bs, &new_bucket_id, bucket_info);
if (r == -ERR_BUSY_RESHARDING) {
continue;
}
@@ -10814,11 +10827,13 @@ int RGWRados::guard_reshard(BucketShard *bs, const rgw_obj& obj_instance, std::f
return 0;
}
-int RGWRados::block_while_resharding(RGWRados::BucketShard *bs, string *new_bucket_id)
+int RGWRados::block_while_resharding(RGWRados::BucketShard *bs,
+ string *new_bucket_id,
+ const RGWBucketInfo& bucket_info)
{
std::shared_ptr<RGWReshardWait> waiter = reshard_wait;
- return waiter->block_while_resharding(bs, new_bucket_id);
+ return waiter->block_while_resharding(bs, new_bucket_id, bucket_info);
}
int RGWRados::bucket_index_link_olh(const RGWBucketInfo& bucket_info, RGWObjState& olh_state, const rgw_obj& obj_instance,
@@ -10844,13 +10859,14 @@ int RGWRados::bucket_index_link_olh(const RGWBucketInfo& bucket_info, RGWObjStat
BucketShard bs(this);
cls_rgw_obj_key key(obj_instance.key.get_index_key_name(), obj_instance.key.instance);
- r = guard_reshard(&bs, obj_instance, [&](BucketShard *bs) -> int {
- librados::ObjectWriteOperation op;
- cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
- return cls_rgw_bucket_link_olh(bs->index_ctx, op,
- bs->bucket_obj, key, olh_state.olh_tag, delete_marker, op_tag, meta, olh_epoch,
- unmod_since, high_precision_time,
- get_zone().log_data, zones_trace);
+ r = guard_reshard(&bs, obj_instance, bucket_info,
+ [&](BucketShard *bs) -> int {
+ librados::ObjectWriteOperation op;
+ cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
+ return cls_rgw_bucket_link_olh(bs->index_ctx, op,
+ bs->bucket_obj, key, olh_state.olh_tag, delete_marker, op_tag, meta, olh_epoch,
+ unmod_since, high_precision_time,
+ get_zone().log_data, zones_trace);
});
if (r < 0) {
ldout(cct, 20) << "cls_rgw_bucket_link_olh() returned r=" << r << dendl;
@@ -10888,11 +10904,12 @@ int RGWRados::bucket_index_unlink_instance(const RGWBucketInfo& bucket_info, con
BucketShard bs(this);
cls_rgw_obj_key key(obj_instance.key.get_index_key_name(), obj_instance.key.instance);
- r = guard_reshard(&bs, obj_instance, [&](BucketShard *bs) -> int {
- librados::ObjectWriteOperation op;
- cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
- return cls_rgw_bucket_unlink_instance(bs->index_ctx, op, bs->bucket_obj, key, op_tag,
- olh_tag, olh_epoch, get_zone().log_data, zones_trace);
+ r = guard_reshard(&bs, obj_instance, bucket_info,
+ [&](BucketShard *bs) -> int {
+ librados::ObjectWriteOperation op;
+ cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
+ return cls_rgw_bucket_unlink_instance(bs->index_ctx, op, bs->bucket_obj, key, op_tag,
+ olh_tag, olh_epoch, get_zone().log_data, zones_trace);
});
if (r < 0) {
ldout(cct, 20) << "cls_rgw_bucket_link_olh() returned r=" << r << dendl;
@@ -10914,7 +10931,8 @@ int RGWRados::bucket_index_read_olh_log(const RGWBucketInfo& bucket_info, RGWObj
}
BucketShard bs(this);
- int ret = bs.init(obj_instance.bucket, obj_instance);
+ int ret =
+ bs.init(obj_instance.bucket, obj_instance, nullptr /* no RGWBucketInfo */);
if (ret < 0) {
ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
return ret;
@@ -10924,12 +10942,13 @@ int RGWRados::bucket_index_read_olh_log(const RGWBucketInfo& bucket_info, RGWObj
cls_rgw_obj_key key(obj_instance.key.get_index_key_name(), string());
- ret = guard_reshard(&bs, obj_instance, [&](BucketShard *bs) -> int {
- ObjectReadOperation op;
- cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
- return cls_rgw_get_olh_log(bs->index_ctx, bs->bucket_obj, op,
- key, ver_marker, olh_tag, log, is_truncated);
- });
+ ret = guard_reshard(&bs, obj_instance, bucket_info,
+ [&](BucketShard *bs) -> int {
+ ObjectReadOperation op;
+ cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
+ return cls_rgw_get_olh_log(bs->index_ctx, bs->bucket_obj, op,
+ key, ver_marker, olh_tag, log, is_truncated);
+ });
if (ret < 0) {
ldout(cct, 20) << "cls_rgw_get_olh_log() returned r=" << r << dendl;
return ret;
@@ -10947,7 +10966,8 @@ int RGWRados::bucket_index_trim_olh_log(const RGWBucketInfo& bucket_info, RGWObj
}
BucketShard bs(this);
- int ret = bs.init(obj_instance.bucket, obj_instance);
+ int ret =
+ bs.init(obj_instance.bucket, obj_instance, nullptr /* no RGWBucketInfo */);
if (ret < 0) {
ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
return ret;
@@ -10957,11 +10977,12 @@ int RGWRados::bucket_index_trim_olh_log(const RGWBucketInfo& bucket_info, RGWObj
cls_rgw_obj_key key(obj_instance.key.get_index_key_name(), string());
- ret = guard_reshard(&bs, obj_instance, [&](BucketShard *pbs) -> int {
- ObjectWriteOperation op;
- cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
- cls_rgw_trim_olh_log(op, key, ver, olh_tag);
- return pbs->index_ctx.operate(pbs->bucket_obj, &op);
+ ret = guard_reshard(&bs, obj_instance, bucket_info,
+ [&](BucketShard *pbs) -> int {
+ ObjectWriteOperation op;
+ cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
+ cls_rgw_trim_olh_log(op, key, ver, olh_tag);
+ return pbs->index_ctx.operate(pbs->bucket_obj, &op);
});
if (ret < 0) {
ldout(cct, 20) << "cls_rgw_trim_olh_log() returned r=" << ret << dendl;
@@ -10985,10 +11006,11 @@ int RGWRados::bucket_index_clear_olh(const RGWBucketInfo& bucket_info, RGWObjSta
cls_rgw_obj_key key(obj_instance.key.get_index_key_name(), string());
- int ret = guard_reshard(&bs, obj_instance, [&](BucketShard *pbs) -> int {
- ObjectWriteOperation op;
- cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
- return cls_rgw_clear_olh(pbs->index_ctx, op, pbs->bucket_obj, key, olh_tag);
+ int ret = guard_reshard(&bs, obj_instance, bucket_info,
+ [&](BucketShard *pbs) -> int {
+ ObjectWriteOperation op;
+ cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
+ return cls_rgw_clear_olh(pbs->index_ctx, op, pbs->bucket_obj, key, olh_tag);
});
if (ret < 0) {
ldout(cct, 5) << "cls_rgw_clear_olh() returned ret=" << ret << dendl;
@@ -12571,7 +12593,7 @@ int RGWRados::bi_get_instance(const RGWBucketInfo& bucket_info, rgw_obj& obj, rg
int RGWRados::bi_get(rgw_bucket& bucket, rgw_obj& obj, BIIndexType index_type, rgw_cls_bi_entry *entry)
{
BucketShard bs(this);
- int ret = bs.init(bucket, obj);
+ int ret = bs.init(bucket, obj, nullptr /* no RGWBucketInfo */);
if (ret < 0) {
ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
return ret;
@@ -12603,7 +12625,7 @@ int RGWRados::bi_put(BucketShard& bs, rgw_cls_bi_entry& entry)
int RGWRados::bi_put(rgw_bucket& bucket, rgw_obj& obj, rgw_cls_bi_entry& entry)
{
BucketShard bs(this);
- int ret = bs.init(bucket, obj);
+ int ret = bs.init(bucket, obj, nullptr /* no RGWBucketInfo */);
if (ret < 0) {
ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
return ret;
@@ -12616,7 +12638,7 @@ int RGWRados::bi_list(rgw_bucket& bucket, const string& obj_name, const string&
{
rgw_obj obj(bucket, obj_name);
BucketShard bs(this);
- int ret = bs.init(bucket, obj);
+ int ret = bs.init(bucket, obj, nullptr /* no RGWBucketInfo */);
if (ret < 0) {
ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
return ret;
@@ -12658,7 +12680,7 @@ int RGWRados::bi_remove(BucketShard& bs)
int RGWRados::bi_list(rgw_bucket& bucket, int shard_id, const string& filter_obj, const string& marker, uint32_t max, list<rgw_cls_bi_entry> *entries, bool *is_truncated)
{
BucketShard bs(this);
- int ret = bs.init(bucket, shard_id);
+ int ret = bs.init(bucket, shard_id, nullptr /* no RGWBucketInfo */);
if (ret < 0) {
ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
return ret;
diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h
index ccf067d197f..d48d9567837 100644
--- a/src/rgw/rgw_rados.h
+++ b/src/rgw/rgw_rados.h
@@ -2118,6 +2118,7 @@ class RGWRados : public AdminSocketHook
friend class RGWDataSyncProcessorThread;
friend class RGWReshard;
friend class RGWBucketReshard;
+ friend class RGWBucketReshardLock;
friend class BucketIndexLockGuard;
friend class RGWCompleteMultipart;
@@ -2619,8 +2620,8 @@ public:
string bucket_obj;
explicit BucketShard(RGWRados *_store) : store(_store), shard_id(-1) {}
- int init(const rgw_bucket& _bucket, const rgw_obj& obj);
- int init(const rgw_bucket& _bucket, int sid);
+ int init(const rgw_bucket& _bucket, const rgw_obj& obj, RGWBucketInfo* out);
+ int init(const rgw_bucket& _bucket, int sid, RGWBucketInfo* out);
int init(const RGWBucketInfo& bucket_info, int sid);
};
@@ -2660,7 +2661,8 @@ public:
int get_bucket_shard(BucketShard **pbs) {
if (!bs_initialized) {
- int r = bs.init(bucket_info.bucket, obj);
+ int r =
+ bs.init(bucket_info.bucket, obj, nullptr /* no RGWBucketInfo */);
if (r < 0) {
return r;
}
@@ -2859,7 +2861,8 @@ public:
rgw_zone_set *zones_trace{nullptr};
int init_bs() {
- int r = bs.init(target->get_bucket(), obj);
+ int r =
+ bs.init(target->get_bucket(), obj, nullptr /* no RGWBucketInfo */);
if (r < 0) {
return r;
}
@@ -3254,8 +3257,13 @@ public:
int obj_operate(const RGWBucketInfo& bucket_info, const rgw_obj& obj, librados::ObjectWriteOperation *op);
int obj_operate(const RGWBucketInfo& bucket_info, const rgw_obj& obj, librados::ObjectReadOperation *op);
- int guard_reshard(BucketShard *bs, const rgw_obj& obj_instance, std::function<int(BucketShard *)> call);
- int block_while_resharding(RGWRados::BucketShard *bs, string *new_bucket_id);
+ int guard_reshard(BucketShard *bs,
+ const rgw_obj& obj_instance,
+ const RGWBucketInfo& bucket_info,
+ std::function<int(BucketShard *)> call);
+ int block_while_resharding(RGWRados::BucketShard *bs,
+ string *new_bucket_id,
+ const RGWBucketInfo& bucket_info);
void bucket_index_guard_olh_op(RGWObjState& olh_state, librados::ObjectOperation& op);
int olh_init_modification(const RGWBucketInfo& bucket_info, RGWObjState& state, const rgw_obj& olh_obj, string *op_tag);
@@ -3528,7 +3536,7 @@ public:
map<RGWObjCategory, RGWStorageStats> *existing_stats,
map<RGWObjCategory, RGWStorageStats> *calculated_stats);
int bucket_rebuild_index(RGWBucketInfo& bucket_info);
- int bucket_set_reshard(RGWBucketInfo& bucket_info, const cls_rgw_bucket_instance_entry& entry);
+ int bucket_set_reshard(const RGWBucketInfo& bucket_info, const cls_rgw_bucket_instance_entry& entry);
int remove_objs_from_index(RGWBucketInfo& bucket_info, list<rgw_obj_index_key>& oid_list);
int move_rados_obj(librados::IoCtx& src_ioctx,
const string& src_oid, const string& src_locator,
diff --git a/src/rgw/rgw_reshard.cc b/src/rgw/rgw_reshard.cc
index c95ab7e4728..a9f7d900e8b 100644
--- a/src/rgw/rgw_reshard.cc
+++ b/src/rgw/rgw_reshard.cc
@@ -1,6 +1,8 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include <limits>
+
#include "rgw_rados.h"
#include "rgw_bucket.h"
#include "rgw_reshard.h"
@@ -22,6 +24,7 @@ const string bucket_instance_lock_name = "bucket_instance_lock";
#define RESHARD_SHARD_WINDOW 64
#define RESHARD_MAX_AIO 128
+
class BucketReshardShard {
RGWRados *store;
const RGWBucketInfo& bucket_info;
@@ -65,10 +68,12 @@ class BucketReshardShard {
public:
BucketReshardShard(RGWRados *_store, const RGWBucketInfo& _bucket_info,
int _num_shard,
- deque<librados::AioCompletion *>& _completions) : store(_store), bucket_info(_bucket_info), bs(store),
- aio_completions(_completions) {
+ deque<librados::AioCompletion *>& _completions) :
+ store(_store), bucket_info(_bucket_info), bs(store),
+ aio_completions(_completions)
+ {
num_shard = (bucket_info.num_shards > 0 ? _num_shard : -1);
- bs.init(bucket_info.bucket, num_shard);
+ bs.init(bucket_info.bucket, num_shard, nullptr /* no RGWBucketInfo */);
}
int get_num_shard() {
@@ -91,8 +96,10 @@ public:
return ret;
}
}
+
return 0;
}
+
int flush() {
if (entries.size() == 0) {
return 0;
@@ -156,14 +163,20 @@ public:
}
}
+ /*
+ * did_flush is set if not nullptr and a flush occurred; otherwise not altered
+ */
int add_entry(int shard_index,
rgw_cls_bi_entry& entry, bool account, uint8_t category,
const rgw_bucket_category_stats& entry_stats) {
- int ret = target_shards[shard_index]->add_entry(entry, account, category, entry_stats);
+ int ret = target_shards[shard_index]->add_entry(entry, account, category,
+ entry_stats);
if (ret < 0) {
- derr << "ERROR: target_shards.add_entry(" << entry.idx << ") returned error: " << cpp_strerror(-ret) << dendl;
+ derr << "ERROR: target_shards.add_entry(" << entry.idx <<
+ ") returned error: " << cpp_strerror(-ret) << dendl;
return ret;
}
+
return 0;
}
@@ -189,41 +202,20 @@ public:
}
};
-RGWBucketReshard::RGWBucketReshard(RGWRados *_store, const RGWBucketInfo& _bucket_info, const map<string, bufferlist>& _bucket_attrs) :
- store(_store), bucket_info(_bucket_info), bucket_attrs(_bucket_attrs),
- reshard_lock(reshard_lock_name) {
- const rgw_bucket& b = bucket_info.bucket;
- reshard_oid = b.tenant + (b.tenant.empty() ? "" : ":") + b.name + ":" + b.bucket_id;
-
- utime_t lock_duration(store->ctx()->_conf->rgw_reshard_bucket_lock_duration, 0);
-#define COOKIE_LEN 16
- char cookie_buf[COOKIE_LEN + 1];
- gen_rand_alphanumeric(store->ctx(), cookie_buf, sizeof(cookie_buf) - 1);
- cookie_buf[COOKIE_LEN] = '\0';
-
- reshard_lock.set_cookie(cookie_buf);
- reshard_lock.set_duration(lock_duration);
-}
-
-int RGWBucketReshard::lock_bucket()
-{
- int ret = reshard_lock.lock_exclusive(&store->reshard_pool_ctx, reshard_oid);
- if (ret < 0) {
- ldout(store->ctx(), 0) << "RGWReshard::add failed to acquire lock on " << reshard_oid << " ret=" << ret << dendl;
- return ret;
- }
- return 0;
-}
-
-void RGWBucketReshard::unlock_bucket()
-{
- int ret = reshard_lock.unlock(&store->reshard_pool_ctx, reshard_oid);
- if (ret < 0) {
- ldout(store->ctx(), 0) << "WARNING: RGWReshard::add failed to drop lock on " << reshard_oid << " ret=" << ret << dendl;
- }
-}
-
-int RGWBucketReshard::set_resharding_status(const string& new_instance_id, int32_t num_shards, cls_rgw_reshard_status status)
+RGWBucketReshard::RGWBucketReshard(RGWRados *_store,
+ const RGWBucketInfo& _bucket_info,
+ const map<string, bufferlist>& _bucket_attrs,
+ RGWBucketReshardLock* _outer_reshard_lock) :
+ store(_store), bucket_info(_bucket_info), bucket_attrs(_bucket_attrs),
+ reshard_lock(store, bucket_info, true),
+ outer_reshard_lock(_outer_reshard_lock)
+{ }
+
+int RGWBucketReshard::set_resharding_status(RGWRados* store,
+ const RGWBucketInfo& bucket_info,
+ const string& new_instance_id,
+ int32_t num_shards,
+ cls_rgw_reshard_status status)
{
if (new_instance_id.empty()) {
ldout(store->ctx(), 0) << __func__ << " missing new bucket instance id" << dendl;
@@ -242,16 +234,48 @@ int RGWBucketReshard::set_resharding_status(const string& new_instance_id, int32
return 0;
}
-int RGWBucketReshard::clear_resharding()
+// reshard lock assumes lock is held
+int RGWBucketReshard::clear_resharding(RGWRados* store,
+ const RGWBucketInfo& bucket_info)
{
- cls_rgw_bucket_instance_entry instance_entry;
+ int ret = clear_index_shard_reshard_status(store, bucket_info);
+ if (ret < 0) {
+ ldout(store->ctx(), 0) << "RGWBucketReshard::" << __func__ <<
+ " ERROR: error clearing reshard status from index shard " <<
+ cpp_strerror(-ret) << dendl;
+ return ret;
+ }
- int ret = store->bucket_set_reshard(bucket_info, instance_entry);
+ cls_rgw_bucket_instance_entry instance_entry;
+ ret = store->bucket_set_reshard(bucket_info, instance_entry);
if (ret < 0) {
- ldout(store->ctx(), 0) << "RGWReshard::" << __func__ << " ERROR: error setting bucket resharding flag on bucket index: "
- << cpp_strerror(-ret) << dendl;
+ ldout(store->ctx(), 0) << "RGWReshard::" << __func__ <<
+ " ERROR: error setting bucket resharding flag on bucket index: " <<
+ cpp_strerror(-ret) << dendl;
return ret;
}
+
+ return 0;
+}
+
+int RGWBucketReshard::clear_index_shard_reshard_status(RGWRados* store,
+ const RGWBucketInfo& bucket_info)
+{
+ uint32_t num_shards = bucket_info.num_shards;
+
+ if (num_shards < std::numeric_limits<uint32_t>::max()) {
+ int ret = set_resharding_status(store, bucket_info,
+ bucket_info.bucket.bucket_id,
+ (num_shards < 1 ? 1 : num_shards),
+ CLS_RGW_RESHARD_NONE);
+ if (ret < 0) {
+ ldout(store->ctx(), 0) << "RGWBucketReshard::" << __func__ <<
+ " ERROR: error clearing reshard status from index shard " <<
+ cpp_strerror(-ret) << dendl;
+ return ret;
+ }
+ }
+
return 0;
}
@@ -295,15 +319,15 @@ int RGWBucketReshard::create_new_bucket_instance(int new_num_shards,
int RGWBucketReshard::cancel()
{
- int ret = lock_bucket();
+ int ret = reshard_lock.lock();
if (ret < 0) {
return ret;
}
ret = clear_resharding();
- unlock_bucket();
- return 0;
+ reshard_lock.unlock();
+ return ret;
}
class BucketInfoReshardUpdate
@@ -325,16 +349,27 @@ class BucketInfoReshardUpdate
}
public:
- BucketInfoReshardUpdate(RGWRados *_store, RGWBucketInfo& _bucket_info,
- map<string, bufferlist>& _bucket_attrs, const string& new_bucket_id) : store(_store),
- bucket_info(_bucket_info),
- bucket_attrs(_bucket_attrs) {
+ BucketInfoReshardUpdate(RGWRados *_store,
+ RGWBucketInfo& _bucket_info,
+ map<string, bufferlist>& _bucket_attrs,
+ const string& new_bucket_id) :
+ store(_store),
+ bucket_info(_bucket_info),
+ bucket_attrs(_bucket_attrs)
+ {
bucket_info.new_bucket_instance_id = new_bucket_id;
}
+
~BucketInfoReshardUpdate() {
if (in_progress) {
+ int ret =
+ RGWBucketReshard::clear_index_shard_reshard_status(store, bucket_info);
+ if (ret < 0) {
+ lderr(store->ctx()) << "Error: " << __func__ <<
+ " clear_index_shard_status returned " << ret << dendl;
+ }
bucket_info.new_bucket_instance_id.clear();
- set_status(CLS_RGW_RESHARD_NONE);
+ set_status(CLS_RGW_RESHARD_NONE); // saves new_bucket_instance as well
}
}
@@ -357,13 +392,84 @@ public:
}
};
-int RGWBucketReshard::do_reshard(
- int num_shards,
- RGWBucketInfo& new_bucket_info,
- int max_entries,
- bool verbose,
- ostream *out,
- Formatter *formatter)
+
+RGWBucketReshardLock::RGWBucketReshardLock(RGWRados* _store,
+ const std::string& reshard_lock_oid,
+ bool _ephemeral) :
+ store(_store),
+ lock_oid(reshard_lock_oid),
+ ephemeral(_ephemeral),
+ internal_lock(reshard_lock_name)
+{
+ const int lock_dur_secs = store->ctx()->_conf->rgw_reshard_bucket_lock_duration;
+ duration = std::chrono::seconds(lock_dur_secs);
+
+#define COOKIE_LEN 16
+ char cookie_buf[COOKIE_LEN + 1];
+ gen_rand_alphanumeric(store->ctx(), cookie_buf, sizeof(cookie_buf) - 1);
+ cookie_buf[COOKIE_LEN] = '\0';
+
+ internal_lock.set_cookie(cookie_buf);
+ internal_lock.set_duration(duration);
+}
+
+int RGWBucketReshardLock::lock() {
+ internal_lock.set_must_renew(false);
+ int ret;
+ if (ephemeral) {
+ ret = internal_lock.lock_exclusive_ephemeral(&store->reshard_pool_ctx,
+ lock_oid);
+ } else {
+ ret = internal_lock.lock_exclusive(&store->reshard_pool_ctx, lock_oid);
+ }
+ if (ret < 0) {
+ ldout(store->ctx(), 0) << "RGWReshardLock::" << __func__ <<
+ " failed to acquire lock on " << lock_oid << " ret=" << ret << dendl;
+ return ret;
+ }
+ reset_time(Clock::now());
+
+ return 0;
+}
+
+void RGWBucketReshardLock::unlock() {
+ int ret = internal_lock.unlock(&store->reshard_pool_ctx, lock_oid);
+ if (ret < 0) {
+ ldout(store->ctx(), 0) << "WARNING: RGWBucketReshardLock::" << __func__ <<
+ " failed to drop lock on " << lock_oid << " ret=" << ret << dendl;
+ }
+}
+
+int RGWBucketReshardLock::renew(const Clock::time_point& now) {
+ internal_lock.set_must_renew(true);
+ int ret;
+ if (ephemeral) {
+ ret = internal_lock.lock_exclusive_ephemeral(&store->reshard_pool_ctx,
+ lock_oid);
+ } else {
+ ret = internal_lock.lock_exclusive(&store->reshard_pool_ctx, lock_oid);
+ }
+ if (ret < 0) { /* expired or already locked by another processor */
+ ldout(store->ctx(), 5) << __func__ << "(): failed to renew lock on " <<
+ lock_oid << " with " << cpp_strerror(-ret) << dendl;
+ return ret;
+ }
+ internal_lock.set_must_renew(false);
+
+ reset_time(now);
+ ldout(store->ctx(), 20) << __func__ << "(): successfully renewed lock on " <<
+ lock_oid << dendl;
+
+ return 0;
+}
+
+
+int RGWBucketReshard::do_reshard(int num_shards,
+ RGWBucketInfo& new_bucket_info,
+ int max_entries,
+ bool verbose,
+ ostream *out,
+ Formatter *formatter)
{
rgw_bucket& bucket = bucket_info.bucket;
@@ -386,6 +492,8 @@ int RGWBucketReshard::do_reshard(
return -EINVAL;
}
+ // NB: destructor cleans up sharding state if reshard does not
+ // complete successfully
BucketInfoReshardUpdate bucket_info_updater(store, bucket_info, bucket_attrs, new_bucket_info.bucket.bucket_id);
ret = bucket_info_updater.start();
@@ -420,7 +528,7 @@ int RGWBucketReshard::do_reshard(
ret = store->bi_list(bucket, i, string(), marker, max_entries, &entries, &is_truncated);
if (ret < 0 && ret != -ENOENT) {
derr << "ERROR: bi_list(): " << cpp_strerror(-ret) << dendl;
- return -ret;
+ return ret;
}
list<rgw_cls_bi_entry>::iterator iter;
@@ -452,22 +560,41 @@ int RGWBucketReshard::do_reshard(
int shard_index = (target_shard_id > 0 ? target_shard_id : 0);
- ret = target_shards_mgr.add_entry(shard_index, entry, account, category, stats);
+ ret = target_shards_mgr.add_entry(shard_index, entry, account,
+ category, stats);
if (ret < 0) {
return ret;
}
+
+ Clock::time_point now = Clock::now();
+ if (reshard_lock.should_renew(now)) {
+ // assume outer locks have timespans at least the size of ours, so
+ // can call inside conditional
+ if (outer_reshard_lock) {
+ ret = outer_reshard_lock->renew(now);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+ ret = reshard_lock.renew(now);
+ if (ret < 0) {
+ lderr(store->ctx()) << "Error renewing bucket lock: " << ret << dendl;
+ return ret;
+ }
+ }
+
if (verbose) {
formatter->close_section();
if (out) {
formatter->flush(*out);
- formatter->flush(*out);
}
} else if (out && !(total_entries % 1000)) {
(*out) << " " << total_entries;
}
- }
+ } // entries loop
}
}
+
if (verbose) {
formatter->close_section();
if (out) {
@@ -480,13 +607,13 @@ int RGWBucketReshard::do_reshard(
ret = target_shards_mgr.finish();
if (ret < 0) {
lderr(store->ctx()) << "ERROR: failed to reshard" << dendl;
- return EIO;
+ return -EIO;
}
ret = rgw_link_bucket(store, new_bucket_info.owner, new_bucket_info.bucket, bucket_info.creation_time);
if (ret < 0) {
lderr(store->ctx()) << "failed to link new bucket instance (bucket_id=" << new_bucket_info.bucket.bucket_id << ": " << cpp_strerror(-ret) << ")" << dendl;
- return -ret;
+ return ret;
}
ret = bucket_info_updater.complete();
@@ -494,8 +621,9 @@ int RGWBucketReshard::do_reshard(
ldout(store->ctx(), 0) << __func__ << ": failed to update bucket info ret=" << ret << dendl;
/* don't error out, reshard process succeeded */
}
+
return 0;
-}
+} // RGWBucketReshard::do_reshard
int RGWBucketReshard::get_status(list<cls_rgw_bucket_instance_entry> *status)
{
@@ -522,11 +650,12 @@ int RGWBucketReshard::get_status(list<cls_rgw_bucket_instance_entry> *status)
return 0;
}
-int RGWBucketReshard::execute(int num_shards, int max_op_entries,
- bool verbose, ostream *out, Formatter *formatter, RGWReshard* reshard_log)
+int RGWBucketReshard::execute(int num_shards, int max_op_entries,
+ bool verbose, ostream *out, Formatter *formatter,
+ RGWReshard* reshard_log)
{
- int ret = lock_bucket();
+ int ret = reshard_lock.lock();
if (ret < 0) {
return ret;
}
@@ -534,21 +663,22 @@ int RGWBucketReshard::execute(int num_shards, int max_op_entries,
RGWBucketInfo new_bucket_info;
ret = create_new_bucket_instance(num_shards, new_bucket_info);
if (ret < 0) {
- unlock_bucket();
+ reshard_lock.unlock();
return ret;
}
if (reshard_log) {
ret = reshard_log->update(bucket_info, new_bucket_info);
if (ret < 0) {
- unlock_bucket();
+ reshard_lock.unlock();
return ret;
}
}
- ret = set_resharding_status(new_bucket_info.bucket.bucket_id, num_shards, CLS_RGW_RESHARD_IN_PROGRESS);
+ ret = set_resharding_status(new_bucket_info.bucket.bucket_id,
+ num_shards, CLS_RGW_RESHARD_IN_PROGRESS);
if (ret < 0) {
- unlock_bucket();
+ reshard_lock.unlock();
return ret;
}
@@ -558,25 +688,27 @@ int RGWBucketReshard::execute(int num_shards, int max_op_entries,
verbose, out, formatter);
if (ret < 0) {
- unlock_bucket();
+ reshard_lock.unlock();
return ret;
}
- ret = set_resharding_status(new_bucket_info.bucket.bucket_id, num_shards, CLS_RGW_RESHARD_DONE);
+ ret = set_resharding_status(new_bucket_info.bucket.bucket_id, num_shards,
+ CLS_RGW_RESHARD_DONE);
if (ret < 0) {
- unlock_bucket();
+ reshard_lock.unlock();
return ret;
}
- unlock_bucket();
+ reshard_lock.unlock();
return 0;
}
RGWReshard::RGWReshard(RGWRados* _store, bool _verbose, ostream *_out,
- Formatter *_formatter) : store(_store), instance_lock(bucket_instance_lock_name),
- verbose(_verbose), out(_out), formatter(_formatter)
+ Formatter *_formatter) :
+ store(_store), instance_lock(bucket_instance_lock_name),
+ verbose(_verbose), out(_out), formatter(_formatter)
{
num_logshards = store->ctx()->_conf->rgw_reshard_num_logs;
}
@@ -731,12 +863,14 @@ int RGWReshardWait::do_wait()
return 0;
}
-int RGWReshardWait::block_while_resharding(RGWRados::BucketShard *bs, string *new_bucket_id)
+int RGWReshardWait::block_while_resharding(RGWRados::BucketShard *bs,
+ string *new_bucket_id,
+ const RGWBucketInfo& bucket_info)
{
int ret = 0;
cls_rgw_bucket_instance_entry entry;
- for (int i=0; i < num_retries;i++) {
+ for (int i=0; i < num_retries; i++) {
ret = cls_rgw_get_bucket_resharding(bs->index_ctx, bs->bucket_obj, &entry);
if (ret < 0) {
ldout(store->ctx(), 0) << __func__ << " ERROR: failed to get bucket resharding :" <<
@@ -748,12 +882,48 @@ int RGWReshardWait::block_while_resharding(RGWRados::BucketShard *bs, string *ne
return 0;
}
ldout(store->ctx(), 20) << "NOTICE: reshard still in progress; " << (i < num_retries - 1 ? "retrying" : "too many retries") << dendl;
- /* needed to unlock as clear resharding uses the same lock */
if (i == num_retries - 1) {
break;
}
+ // If bucket is erroneously marked as resharding (e.g., crash or
+ // other error) then fix it. If we can take the bucket reshard
+ // lock then it means no other resharding should be taking place,
+ // and we're free to clear the flags.
+ {
+ // since we expect to do this rarely, we'll do our work in a
+ // block and erase our work after each try
+
+ RGWObjectCtx obj_ctx(bs->store);
+ const rgw_bucket& b = bs->bucket;
+ std::string bucket_id = b.get_key();
+ RGWBucketReshardLock reshard_lock(bs->store, bucket_info, true);
+ ret = reshard_lock.lock();
+ if (ret < 0) {
+ ldout(store->ctx(), 20) << __func__ <<
+ " INFO: failed to take reshard lock for bucket " <<
+ bucket_id << "; expected if resharding underway" << dendl;
+ } else {
+ ldout(store->ctx(), 10) << __func__ <<
+ " INFO: was able to take reshard lock for bucket " <<
+ bucket_id << dendl;
+ ret = RGWBucketReshard::clear_resharding(bs->store, bucket_info);
+ if (ret < 0) {
+ reshard_lock.unlock();
+ ldout(store->ctx(), 0) << __func__ <<
+ " ERROR: failed to clear resharding flags for bucket " <<
+ bucket_id << dendl;
+ } else {
+ reshard_lock.unlock();
+ ldout(store->ctx(), 5) << __func__ <<
+ " INFO: apparently successfully cleared resharding flags for "
+ "bucket " << bucket_id << dendl;
+ continue; // if we apparently succeed immediately test again
+ } // if clear resharding succeeded
+ } // if taking of lock succeeded
+ } // block to encapsulate recovery from incomplete reshard
+
ret = do_wait();
if (ret < 0) {
ldout(store->ctx(), 0) << __func__ << " ERROR: bucket is still resharding, please retry" << dendl;
@@ -770,92 +940,86 @@ int RGWReshard::process_single_logshard(int logshard_num)
bool truncated = true;
CephContext *cct = store->ctx();
- int max_entries = 1000;
- int max_secs = 60;
-
- rados::cls::lock::Lock l(reshard_lock_name);
-
- utime_t time(max_secs, 0);
- l.set_duration(time);
-
- char cookie_buf[COOKIE_LEN + 1];
- gen_rand_alphanumeric(store->ctx(), cookie_buf, sizeof(cookie_buf) - 1);
- cookie_buf[COOKIE_LEN] = '\0';
-
- l.set_cookie(cookie_buf);
+ constexpr uint32_t max_entries = 1000;
string logshard_oid;
get_logshard_oid(logshard_num, &logshard_oid);
- int ret = l.lock_exclusive(&store->reshard_pool_ctx, logshard_oid);
+ RGWBucketReshardLock logshard_lock(store, logshard_oid, false);
+
+ int ret = logshard_lock.lock();
if (ret == -EBUSY) { /* already locked by another processor */
- ldout(store->ctx(), 5) << __func__ << "(): failed to acquire lock on " << logshard_oid << dendl;
+ ldout(store->ctx(), 5) << __func__ << "(): failed to acquire lock on " <<
+ logshard_oid << dendl;
return ret;
}
- utime_t lock_start_time = ceph_clock_now();
-
do {
std::list<cls_rgw_reshard_entry> entries;
ret = list(logshard_num, marker, max_entries, entries, &truncated);
if (ret < 0) {
- ldout(cct, 10) << "cannot list all reshards in logshard oid=" << logshard_oid << dendl;
+ ldout(cct, 10) << "cannot list all reshards in logshard oid=" <<
+ logshard_oid << dendl;
continue;
}
- for(auto& entry: entries) {
+ for(auto& entry: entries) { // logshard entries
if(entry.new_instance_id.empty()) {
- ldout(store->ctx(), 20) << __func__ << " resharding " << entry.bucket_name << dendl;
+ ldout(store->ctx(), 20) << __func__ << " resharding " <<
+ entry.bucket_name << dendl;
RGWObjectCtx obj_ctx(store);
rgw_bucket bucket;
RGWBucketInfo bucket_info;
map<string, bufferlist> attrs;
- ret = store->get_bucket_info(obj_ctx, entry.tenant, entry.bucket_name, bucket_info, nullptr,
- &attrs);
+ ret = store->get_bucket_info(obj_ctx, entry.tenant, entry.bucket_name,
+ bucket_info, nullptr, &attrs);
if (ret < 0) {
- ldout(cct, 0) << __func__ << ": Error in get_bucket_info: " << cpp_strerror(-ret) << dendl;
+ ldout(cct, 0) << __func__ << ": Error in get_bucket_info: " <<
+ cpp_strerror(-ret) << dendl;
return -ret;
}
- RGWBucketReshard br(store, bucket_info, attrs);
+ RGWBucketReshard br(store, bucket_info, attrs, nullptr);
Formatter* formatter = new JSONFormatter(false);
auto formatter_ptr = std::unique_ptr<Formatter>(formatter);
- ret = br.execute(entry.new_num_shards, max_entries, true,nullptr, formatter, this);
+ ret = br.execute(entry.new_num_shards, max_entries, true, nullptr,
+ formatter, this);
if (ret < 0) {
- ldout (store->ctx(), 0) << __func__ << "ERROR in reshard_bucket " << entry.bucket_name << ":" <<
+ ldout (store->ctx(), 0) << __func__ <<
+ "ERROR in reshard_bucket " << entry.bucket_name << ":" <<
cpp_strerror(-ret)<< dendl;
return ret;
}
- ldout (store->ctx(), 20) << " removing entry" << entry.bucket_name<< dendl;
+ ldout (store->ctx(), 20) << " removing entry" << entry.bucket_name <<
+ dendl;
ret = remove(entry);
if (ret < 0) {
- ldout(cct, 0)<< __func__ << ":Error removing bucket " << entry.bucket_name << " for resharding queue: "
- << cpp_strerror(-ret) << dendl;
+ ldout(cct, 0)<< __func__ << ":Error removing bucket " <<
+ entry.bucket_name << " for resharding queue: " <<
+ cpp_strerror(-ret) << dendl;
return ret;
}
}
- utime_t now = ceph_clock_now();
-
- if (now > lock_start_time + max_secs / 2) { /* do you need to renew lock? */
- l.set_renew(true);
- ret = l.lock_exclusive(&store->reshard_pool_ctx, logshard_oid);
- if (ret == -EBUSY) { /* already locked by another processor */
- ldout(store->ctx(), 5) << __func__ << "(): failed to acquire lock on " << logshard_oid << dendl;
- return ret;
- }
- lock_start_time = now;
+
+ Clock::time_point now = Clock::now();
+ if (logshard_lock.should_renew(now)) {
+ ret = logshard_lock.renew(now);
+ if (ret < 0) {
+ return ret;
+ }
}
+
entry.get_key(&marker);
}
} while (truncated);
- l.unlock(&store->reshard_pool_ctx, logshard_oid);
+ logshard_lock.unlock();
return 0;
}
diff --git a/src/rgw/rgw_reshard.h b/src/rgw/rgw_reshard.h
index c6e56e14fca..e1ad4a9738e 100644
--- a/src/rgw/rgw_reshard.h
+++ b/src/rgw/rgw_reshard.h
@@ -5,31 +5,72 @@
#define RGW_RESHARD_H
#include <vector>
+#include <functional>
+
#include "include/rados/librados.hpp"
+#include "common/ceph_time.h"
#include "cls/rgw/cls_rgw_types.h"
#include "cls/lock/cls_lock_client.h"
#include "rgw_bucket.h"
+
class CephContext;
class RGWRados;
+class RGWBucketReshardLock {
+ using Clock = ceph::coarse_mono_clock;
+
+ RGWRados* store;
+ const std::string lock_oid;
+ const bool ephemeral;
+ rados::cls::lock::Lock internal_lock;
+ std::chrono::seconds duration;
+
+ Clock::time_point start_time;
+ Clock::time_point renew_thresh;
+
+ void reset_time(const Clock::time_point& now) {
+ start_time = now;
+ renew_thresh = start_time + duration / 2;
+ }
+
+public:
+ RGWBucketReshardLock(RGWRados* _store,
+ const std::string& reshard_lock_oid,
+ bool _ephemeral);
+ RGWBucketReshardLock(RGWRados* _store,
+ const RGWBucketInfo& bucket_info,
+ bool _ephemeral) :
+ RGWBucketReshardLock(_store, bucket_info.bucket.get_key(':'), _ephemeral)
+ {}
+
+ int lock();
+ void unlock();
+ int renew(const Clock::time_point&);
+
+ bool should_renew(const Clock::time_point& now) const {
+ return now >= renew_thresh;
+ }
+}; // class RGWBucketReshardLock
class RGWBucketReshard {
+public:
+
friend class RGWReshard;
+ using Clock = ceph::coarse_mono_clock;
+
+private:
+
RGWRados *store;
RGWBucketInfo bucket_info;
std::map<string, bufferlist> bucket_attrs;
- string reshard_oid;
- rados::cls::lock::Lock reshard_lock;
-
- int lock_bucket();
- void unlock_bucket();
- int set_resharding_status(const string& new_instance_id, int32_t num_shards, cls_rgw_reshard_status status);
- int clear_resharding();
+ RGWBucketReshardLock reshard_lock;
+ RGWBucketReshardLock* outer_reshard_lock;
- int create_new_bucket_instance(int new_num_shards, RGWBucketInfo& new_bucket_info);
+ int create_new_bucket_instance(int new_num_shards,
+ RGWBucketInfo& new_bucket_info);
int do_reshard(int num_shards,
RGWBucketInfo& new_bucket_info,
int max_entries,
@@ -37,19 +78,46 @@ class RGWBucketReshard {
ostream *os,
Formatter *formatter);
public:
- RGWBucketReshard(RGWRados *_store, const RGWBucketInfo& _bucket_info,
- const std::map<string, bufferlist>& _bucket_attrs);
+ // pass nullptr for the final parameter if no outer reshard lock to
+ // manage
+ RGWBucketReshard(RGWRados *_store, const RGWBucketInfo& _bucket_info,
+ const std::map<string, bufferlist>& _bucket_attrs,
+ RGWBucketReshardLock* _outer_reshard_lock);
int execute(int num_shards, int max_op_entries,
bool verbose = false, ostream *out = nullptr,
Formatter *formatter = nullptr,
RGWReshard *reshard_log = nullptr);
- int abort();
int get_status(std::list<cls_rgw_bucket_instance_entry> *status);
int cancel();
-};
+ static int clear_resharding(RGWRados* store,
+ const RGWBucketInfo& bucket_info);
+ int clear_resharding() {
+ return clear_resharding(store, bucket_info);
+ }
+ static int clear_index_shard_reshard_status(RGWRados* store,
+ const RGWBucketInfo& bucket_info);
+ int clear_index_shard_reshard_status() {
+ return clear_index_shard_reshard_status(store, bucket_info);
+ }
+ static int set_resharding_status(RGWRados* store,
+ const RGWBucketInfo& bucket_info,
+ const string& new_instance_id,
+ int32_t num_shards,
+ cls_rgw_reshard_status status);
+ int set_resharding_status(const string& new_instance_id,
+ int32_t num_shards,
+ cls_rgw_reshard_status status) {
+ return set_resharding_status(store, bucket_info,
+ new_instance_id, num_shards, status);
+ }
+}; // RGWBucketReshard
class RGWReshard {
+public:
+ using Clock = ceph::coarse_mono_clock;
+
+private:
RGWRados *store;
string lock_name;
rados::cls::lock::Lock instance_lock;
@@ -116,7 +184,9 @@ public:
~RGWReshardWait() {
ceph_assert(going_down);
}
- int block_while_resharding(RGWRados::BucketShard *bs, string *new_bucket_id);
+ int block_while_resharding(RGWRados::BucketShard *bs,
+ string *new_bucket_id,
+ const RGWBucketInfo& bucket_info);
void stop() {
Mutex::Locker l(lock);
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index 43243785864..f9eb45b5bd8 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -130,7 +130,7 @@ target_link_libraries(ceph_bench_log global pthread rt ${BLKID_LIBRARIES} ${CMAK
add_executable(ceph_test_mutate
test_mutate.cc
)
-target_link_libraries(ceph_test_mutate global librados ${BLKID_LIBRARIES}
+target_link_libraries(ceph_test_mutate global librados-cxx ${BLKID_LIBRARIES}
${CMAKE_DL_LIBS})
# test_trans
@@ -150,7 +150,7 @@ add_executable(ceph_omapbench
${omapbench_srcs}
)
target_link_libraries(ceph_omapbench
- librados
+ librados-cxx
Boost::program_options
global
${BLKID_LIBRARIES}
@@ -164,7 +164,7 @@ if(WITH_KVS)
${CMAKE_SOURCE_DIR}/src/key_value_store/kv_flat_btree_async.cc
)
add_executable(ceph_kvstorebench ${kvstorebench_srcs})
- target_link_libraries(ceph_kvstorebench librados global ${BLKID_LIBRARIES} ${CMAKE_DL_LIBS})
+ target_link_libraries(ceph_kvstorebench librados-cxx global ${BLKID_LIBRARIES} ${CMAKE_DL_LIBS})
install(TARGETS ceph_kvstorebench DESTINATION bin)
endif(WITH_KVS)
@@ -356,7 +356,7 @@ endif(${WITH_RADOSGW})
add_executable(ceph_multi_stress_watch
multi_stress_watch.cc
)
-target_link_libraries(ceph_multi_stress_watch librados global radostest
+target_link_libraries(ceph_multi_stress_watch librados-cxx global radostest-cxx
${BLKID_LIBRARIES} ${CMAKE_DL_LIBS})
#ceph_perf_local
@@ -418,9 +418,9 @@ add_executable(ceph_test_stress_watch
test_stress_watch.cc
)
target_link_libraries(ceph_test_stress_watch
- librados
+ librados-cxx
${UNITTEST_LIBS}
- radostest
+ radostest-cxx
${EXTRALIBS}
${BLKID_LIBRARIES}
${CMAKE_DL_LIBS}
diff --git a/src/test/cls_hello/CMakeLists.txt b/src/test/cls_hello/CMakeLists.txt
index 4ed22132f26..1363d746b6a 100644
--- a/src/test/cls_hello/CMakeLists.txt
+++ b/src/test/cls_hello/CMakeLists.txt
@@ -2,12 +2,12 @@ add_executable(ceph_test_cls_hello
test_cls_hello.cc
)
target_link_libraries(ceph_test_cls_hello
- librados
+ librados-cxx
global
${EXTRALIBS}
${BLKID_LIBRARIES}
${CMAKE_DL_LIBS}
- radostest
+ radostest-cxx
${UNITTEST_LIBS}
)
install(TARGETS
diff --git a/src/test/cls_hello/test_cls_hello.cc b/src/test/cls_hello/test_cls_hello.cc
index 55386a86fb2..7cf30125f0b 100644
--- a/src/test/cls_hello/test_cls_hello.cc
+++ b/src/test/cls_hello/test_cls_hello.cc
@@ -17,7 +17,7 @@
#include "include/rados/librados.hpp"
#include "include/encoding.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
using namespace librados;
diff --git a/src/test/cls_journal/CMakeLists.txt b/src/test/cls_journal/CMakeLists.txt
index 3f2cad9c01f..08d47655a79 100644
--- a/src/test/cls_journal/CMakeLists.txt
+++ b/src/test/cls_journal/CMakeLists.txt
@@ -4,13 +4,13 @@ add_executable(ceph_test_cls_journal
$<TARGET_OBJECTS:common_texttable_obj>)
target_link_libraries(ceph_test_cls_journal
cls_journal_client
- librados
+ librados-cxx
global
${UNITTEST_LIBS}
${CMAKE_DL_LIBS}
${CRYPTO_LIBS}
${EXTRALIBS}
- radostest)
+ radostest-cxx)
install(TARGETS
ceph_test_cls_journal
DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/test/cls_journal/test_cls_journal.cc b/src/test/cls_journal/test_cls_journal.cc
index 9df173d6202..2082bbc2935 100644
--- a/src/test/cls_journal/test_cls_journal.cc
+++ b/src/test/cls_journal/test_cls_journal.cc
@@ -4,7 +4,7 @@
#include "cls/journal/cls_journal_client.h"
#include "include/stringify.h"
#include "common/Cond.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
#include <errno.h>
#include <set>
diff --git a/src/test/cls_lock/CMakeLists.txt b/src/test/cls_lock/CMakeLists.txt
index 49214e17e68..53f36725c56 100644
--- a/src/test/cls_lock/CMakeLists.txt
+++ b/src/test/cls_lock/CMakeLists.txt
@@ -3,14 +3,14 @@ add_executable(ceph_test_cls_lock
)
target_link_libraries(ceph_test_cls_lock
cls_lock_client
- librados
+ librados-cxx
global
${UNITTEST_LIBS}
${BLKID_LIBRARIES}
${CMAKE_DL_LIBS}
${CRYPTO_LIBS}
${EXTRALIBS}
- radostest
+ radostest-cxx
)
install(TARGETS
ceph_test_cls_lock
diff --git a/src/test/cls_lock/test_cls_lock.cc b/src/test/cls_lock/test_cls_lock.cc
index 0aeed8245e7..c9bc2dd4b89 100644
--- a/src/test/cls_lock/test_cls_lock.cc
+++ b/src/test/cls_lock/test_cls_lock.cc
@@ -20,7 +20,7 @@
#include "msg/msg_types.h"
#include "include/rados/librados.hpp"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
using namespace librados;
@@ -94,10 +94,10 @@ TEST(ClsLock, TestMultiLocking) {
ASSERT_EQ(-EEXIST, l.lock_exclusive(&ioctx, oid));
/* test idempotency */
- l.set_renew(true);
+ l.set_may_renew(true);
ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
- l.set_renew(false);
+ l.set_may_renew(false);
/* test second client */
Lock l2(lock_name);
@@ -204,7 +204,7 @@ TEST(ClsLock, TestMeta) {
/* check new tag */
string new_tag = "new_tag";
l.set_tag(new_tag);
- l.set_renew(true);
+ l.set_may_renew(true);
ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
lock_info(&ioctx, oid, lock_name, lockers, NULL, &new_tag);
ASSERT_EQ(1, (int)lockers.size());
@@ -391,3 +391,175 @@ TEST(ClsLock, TestSetCookie) {
ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
}
+
+TEST(ClsLock, TestRenew) {
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ bufferlist bl;
+
+ string oid1 = "foo1";
+ string lock_name1 = "mylock1";
+
+ ASSERT_EQ(0, ioctx.write(oid1, bl, bl.length(), 0));
+
+ Lock l1(lock_name1);
+ utime_t lock_duration1(5, 0);
+ l1.set_duration(lock_duration1);
+
+ ASSERT_EQ(0, l1.lock_exclusive(&ioctx, oid1));
+ l1.set_may_renew(true);
+ sleep(2);
+ ASSERT_EQ(0, l1.lock_exclusive(&ioctx, oid1));
+ sleep(7);
+ ASSERT_EQ(0, l1.lock_exclusive(&ioctx, oid1)) <<
+ "when a cls_lock is set to may_renew, a relock after expiration "
+ "should still work";
+ ASSERT_EQ(0, l1.unlock(&ioctx, oid1));
+
+ // ***********************************************
+
+ string oid2 = "foo2";
+ string lock_name2 = "mylock2";
+
+ ASSERT_EQ(0, ioctx.write(oid2, bl, bl.length(), 0));
+
+ Lock l2(lock_name2);
+ utime_t lock_duration2(5, 0);
+ l2.set_duration(lock_duration2);
+
+ ASSERT_EQ(0, l2.lock_exclusive(&ioctx, oid2));
+ l2.set_must_renew(true);
+ sleep(2);
+ ASSERT_EQ(0, l2.lock_exclusive(&ioctx, oid2));
+ sleep(7);
+ ASSERT_EQ(-ENOENT, l2.lock_exclusive(&ioctx, oid2)) <<
+ "when a cls_lock is set to must_renew, a relock after expiration "
+ "should fail";
+ ASSERT_EQ(-ENOENT, l2.unlock(&ioctx, oid2));
+
+ // ***********************************************
+
+ string oid3 = "foo3";
+ string lock_name3 = "mylock3";
+
+ ASSERT_EQ(0, ioctx.write(oid3, bl, bl.length(), 0));
+
+ Lock l3(lock_name3);
+ l3.set_duration(utime_t(5, 0));
+ l3.set_must_renew(true);
+
+ ASSERT_EQ(-ENOENT, l3.lock_exclusive(&ioctx, oid3)) <<
+ "unable to create a lock with must_renew";
+
+ ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
+}
+
+TEST(ClsLock, TestExclusiveEphemeralBasic) {
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ bufferlist bl;
+
+ string oid1 = "foo1";
+ string oid2 = "foo2";
+ string lock_name1 = "mylock1";
+ string lock_name2 = "mylock2";
+
+ Lock l1(lock_name1);
+ l1.set_duration(utime_t(5, 0));
+
+ uint64_t size;
+ time_t mod_time;
+
+ l1.set_may_renew(true);
+ ASSERT_EQ(0, l1.lock_exclusive_ephemeral(&ioctx, oid1));
+ ASSERT_EQ(0, ioctx.stat(oid1, &size, &mod_time));
+ sleep(2);
+ ASSERT_EQ(0, l1.unlock(&ioctx, oid1));
+ ASSERT_EQ(-ENOENT, ioctx.stat(oid1, &size, &mod_time));
+
+ // ***********************************************
+
+ Lock l2(lock_name2);
+ utime_t lock_duration2(5, 0);
+ l2.set_duration(utime_t(5, 0));
+
+ ASSERT_EQ(0, l2.lock_exclusive(&ioctx, oid2));
+ ASSERT_EQ(0, ioctx.stat(oid2, &size, &mod_time));
+ sleep(2);
+ ASSERT_EQ(0, l2.unlock(&ioctx, oid2));
+ ASSERT_EQ(0, ioctx.stat(oid2, &size, &mod_time));
+
+ ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
+}
+
+
+TEST(ClsLock, TestExclusiveEphemeralStealEphemeral) {
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ bufferlist bl;
+
+ string oid1 = "foo1";
+ string lock_name1 = "mylock1";
+
+ Lock l1(lock_name1);
+ l1.set_duration(utime_t(3, 0));
+
+ ASSERT_EQ(0, l1.lock_exclusive_ephemeral(&ioctx, oid1));
+ sleep(4);
+
+ // l1 is expired, l2 can take; l2 is also exclusive_ephemeral
+ Lock l2(lock_name1);
+ l2.set_duration(utime_t(3, 0));
+ ASSERT_EQ(0, l2.lock_exclusive_ephemeral(&ioctx, oid1));
+ sleep(1);
+ ASSERT_EQ(0, l2.unlock(&ioctx, oid1));
+
+ // l2 cannot unlock its expired lock
+ ASSERT_EQ(-ENOENT, l1.unlock(&ioctx, oid1));
+
+ ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
+}
+
+
+TEST(ClsLock, TestExclusiveEphemeralStealExclusive) {
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ bufferlist bl;
+
+ string oid1 = "foo1";
+ string lock_name1 = "mylock1";
+
+ Lock l1(lock_name1);
+ l1.set_duration(utime_t(3, 0));
+
+ ASSERT_EQ(0, l1.lock_exclusive_ephemeral(&ioctx, oid1));
+ sleep(4);
+
+ // l1 is expired, l2 can take; l2 is exclusive (but not ephemeral)
+ Lock l2(lock_name1);
+ l2.set_duration(utime_t(3, 0));
+ ASSERT_EQ(0, l2.lock_exclusive(&ioctx, oid1));
+ sleep(1);
+ ASSERT_EQ(0, l2.unlock(&ioctx, oid1));
+
+ // l2 cannot unlock its expired lock
+ ASSERT_EQ(-ENOENT, l1.unlock(&ioctx, oid1));
+
+ ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
+}
diff --git a/src/test/cls_log/CMakeLists.txt b/src/test/cls_log/CMakeLists.txt
index acbd31d6bd9..c27d9843a1c 100644
--- a/src/test/cls_log/CMakeLists.txt
+++ b/src/test/cls_log/CMakeLists.txt
@@ -1,10 +1,10 @@
add_executable(ceph_test_cls_log
test_cls_log.cc)
target_link_libraries(ceph_test_cls_log
- librados
+ librados-cxx
cls_log_client
global
- radostest
+ radostest-cxx
${UNITTEST_LIBS}
${BLKID_LIBRARIES}
${CMAKE_DL_LIBS}
diff --git a/src/test/cls_log/test_cls_log.cc b/src/test/cls_log/test_cls_log.cc
index daf1ceeb9e9..05485035ae0 100644
--- a/src/test/cls_log/test_cls_log.cc
+++ b/src/test/cls_log/test_cls_log.cc
@@ -10,7 +10,7 @@
#include "global/global_context.h"
#include "gtest/gtest.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include <errno.h>
#include <string>
diff --git a/src/test/cls_lua/CMakeLists.txt b/src/test/cls_lua/CMakeLists.txt
index 1bc8c4cce6e..cfb6ba1171b 100644
--- a/src/test/cls_lua/CMakeLists.txt
+++ b/src/test/cls_lua/CMakeLists.txt
@@ -4,13 +4,12 @@ add_executable(ceph_test_cls_lua
target_link_libraries(ceph_test_cls_lua
cls_lua_client
liblua
- librados
+ librados-cxx
global
${UNITTEST_LIBS}
${EXTRALIBS}
${CMAKE_DL_LIBS}
- radostest
-)
+ radostest-cxx)
install(TARGETS
ceph_test_cls_lua
DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/test/cls_lua/test_cls_lua.cc b/src/test/cls_lua/test_cls_lua.cc
index 1cd3a00d2fa..b6727826659 100644
--- a/src/test/cls_lua/test_cls_lua.cc
+++ b/src/test/cls_lua/test_cls_lua.cc
@@ -1,9 +1,9 @@
#include <errno.h>
#include <lua.hpp>
#include "include/types.h"
-#include "include/rados/librados.h"
+#include "include/rados/librados.hpp"
#include "gtest/gtest.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "cls/lua/cls_lua_client.h"
#include "cls/lua/cls_lua.h"
diff --git a/src/test/cls_numops/CMakeLists.txt b/src/test/cls_numops/CMakeLists.txt
index b52d7f9894a..00108991d39 100644
--- a/src/test/cls_numops/CMakeLists.txt
+++ b/src/test/cls_numops/CMakeLists.txt
@@ -2,13 +2,13 @@
add_executable(ceph_test_cls_numops
test_cls_numops.cc)
target_link_libraries(ceph_test_cls_numops
- librados
+ librados-cxx
global
cls_numops_client
${EXTRALIBS}
${BLKID_LIBRARIES}
${CMAKE_DL_LIBS}
- radostest
+ radostest-cxx
${UNITTEST_LIBS}
)
install(TARGETS
diff --git a/src/test/cls_numops/test_cls_numops.cc b/src/test/cls_numops/test_cls_numops.cc
index 844caf993cf..ebb2256208b 100644
--- a/src/test/cls_numops/test_cls_numops.cc
+++ b/src/test/cls_numops/test_cls_numops.cc
@@ -21,7 +21,7 @@
#include "cls/numops/cls_numops_client.h"
#include "gtest/gtest.h"
#include "include/rados/librados.hpp"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
using namespace librados;
diff --git a/src/test/cls_rbd/CMakeLists.txt b/src/test/cls_rbd/CMakeLists.txt
index 77596dd690b..d42deb08848 100644
--- a/src/test/cls_rbd/CMakeLists.txt
+++ b/src/test/cls_rbd/CMakeLists.txt
@@ -5,13 +5,13 @@ add_executable(ceph_test_cls_rbd
target_link_libraries(ceph_test_cls_rbd
cls_rbd_client
cls_lock_client
- librados
+ librados-cxx
global
${UNITTEST_LIBS}
${CMAKE_DL_LIBS}
${CRYPTO_LIBS}
${EXTRALIBS}
- radostest)
+ radostest-cxx)
install(TARGETS
ceph_test_cls_rbd
DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/test/cls_rbd/test_cls_rbd.cc b/src/test/cls_rbd/test_cls_rbd.cc
index 99a0a55b981..1783866dc94 100644
--- a/src/test/cls_rbd/test_cls_rbd.cc
+++ b/src/test/cls_rbd/test_cls_rbd.cc
@@ -17,7 +17,7 @@
#include "librbd/Types.h"
#include "gtest/gtest.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include <errno.h>
#include <string>
@@ -2810,7 +2810,8 @@ TEST_F(TestClsRbd, migration)
ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
cls::rbd::MigrationSpec migration_spec(cls::rbd::MIGRATION_HEADER_TYPE_DST, 1,
- "name", "id", {}, 0, false, false,
+ "name", "ns", "id", {}, 0, false,
+ false,
cls::rbd::MIGRATION_STATE_PREPARING,
"123");
cls::rbd::MigrationSpec read_migration_spec;
@@ -2879,7 +2880,8 @@ TEST_F(TestClsRbd, migration_v1)
ASSERT_EQ(0, ioctx.write(oid, header, header.length(), 0));
cls::rbd::MigrationSpec migration_spec(cls::rbd::MIGRATION_HEADER_TYPE_DST, 1,
- "name", "id", {}, 0, false, false,
+ "name", "ns", "id", {}, 0, false,
+ false,
cls::rbd::MIGRATION_STATE_PREPARING,
"123");
cls::rbd::MigrationSpec read_migration_spec;
diff --git a/src/test/cls_refcount/CMakeLists.txt b/src/test/cls_refcount/CMakeLists.txt
index 9983828456f..e9aaeaa6a25 100644
--- a/src/test/cls_refcount/CMakeLists.txt
+++ b/src/test/cls_refcount/CMakeLists.txt
@@ -3,7 +3,7 @@ add_executable(ceph_test_cls_refcount
test_cls_refcount.cc
)
target_link_libraries(ceph_test_cls_refcount
- librados
+ librados-cxx
cls_refcount_client
global
${UNITTEST_LIBS}
@@ -11,7 +11,7 @@ target_link_libraries(ceph_test_cls_refcount
${CMAKE_DL_LIBS}
${CRYPTO_LIBS}
${EXTRALIBS}
- radostest
+ radostest-cxx
)
install(TARGETS
ceph_test_cls_refcount
diff --git a/src/test/cls_refcount/test_cls_refcount.cc b/src/test/cls_refcount/test_cls_refcount.cc
index 73ba1db13b3..b481ca0f240 100644
--- a/src/test/cls_refcount/test_cls_refcount.cc
+++ b/src/test/cls_refcount/test_cls_refcount.cc
@@ -5,7 +5,7 @@
#include "cls/refcount/cls_refcount_client.h"
#include "gtest/gtest.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include <errno.h>
#include <string>
diff --git a/src/test/cls_rgw/CMakeLists.txt b/src/test/cls_rgw/CMakeLists.txt
index ca53e9dfc7d..79409db53b7 100644
--- a/src/test/cls_rgw/CMakeLists.txt
+++ b/src/test/cls_rgw/CMakeLists.txt
@@ -4,13 +4,13 @@ if(${WITH_RADOSGW})
)
target_link_libraries(ceph_test_cls_rgw
cls_rgw_client
- librados
+ librados-cxx
global
${UNITTEST_LIBS}
${EXTRALIBS}
${BLKID_LIBRARIES}
${CMAKE_DL_LIBS}
- radostest)
+ radostest-cxx)
install(TARGETS
ceph_test_cls_rgw
DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/test/cls_rgw/test_cls_rgw.cc b/src/test/cls_rgw/test_cls_rgw.cc
index d09e867ec75..7e78acf8a1c 100644
--- a/src/test/cls_rgw/test_cls_rgw.cc
+++ b/src/test/cls_rgw/test_cls_rgw.cc
@@ -6,7 +6,7 @@
#include "cls/rgw/cls_rgw_ops.h"
#include "gtest/gtest.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "global/global_context.h"
#include <errno.h>
diff --git a/src/test/cls_sdk/CMakeLists.txt b/src/test/cls_sdk/CMakeLists.txt
index d75971276c2..cd05900d56f 100644
--- a/src/test/cls_sdk/CMakeLists.txt
+++ b/src/test/cls_sdk/CMakeLists.txt
@@ -2,12 +2,12 @@ add_executable(ceph_test_cls_sdk
test_cls_sdk.cc
)
target_link_libraries(ceph_test_cls_sdk
- librados
+ librados-cxx
global
${EXTRALIBS}
${BLKID_LIBRARIES}
${CMAKE_DL_LIBS}
- radostest
+ radostest-cxx
${UNITTEST_LIBS}
)
install(TARGETS
diff --git a/src/test/cls_sdk/test_cls_sdk.cc b/src/test/cls_sdk/test_cls_sdk.cc
index af3452bb5c6..44b32196b3a 100644
--- a/src/test/cls_sdk/test_cls_sdk.cc
+++ b/src/test/cls_sdk/test_cls_sdk.cc
@@ -1,7 +1,7 @@
#include <iostream>
#include <errno.h>
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
using namespace librados;
diff --git a/src/test/cls_version/CMakeLists.txt b/src/test/cls_version/CMakeLists.txt
index 7334ce43624..d8e43878d69 100644
--- a/src/test/cls_version/CMakeLists.txt
+++ b/src/test/cls_version/CMakeLists.txt
@@ -3,7 +3,7 @@ add_executable(ceph_test_cls_version
test_cls_version.cc
)
target_link_libraries(ceph_test_cls_version
- librados
+ librados-cxx
cls_version_client
global
${UNITTEST_LIBS}
@@ -11,6 +11,6 @@ target_link_libraries(ceph_test_cls_version
${CMAKE_DL_LIBS}
${CRYPTO_LIBS}
${EXTRALIBS}
- radostest
+ radostest-cxx
)
diff --git a/src/test/cls_version/test_cls_version.cc b/src/test/cls_version/test_cls_version.cc
index 4c2d59500df..9ecea1f2cd2 100644
--- a/src/test/cls_version/test_cls_version.cc
+++ b/src/test/cls_version/test_cls_version.cc
@@ -1,12 +1,14 @@
// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include "include/rados/librados.hpp"
#include "include/types.h"
+
#include "cls/version/cls_version_types.h"
#include "cls/version/cls_version_client.h"
#include "gtest/gtest.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include <errno.h>
#include <string>
diff --git a/src/test/encoding/readable.sh b/src/test/encoding/readable.sh
index 11937238028..81545852cf5 100755
--- a/src/test/encoding/readable.sh
+++ b/src/test/encoding/readable.sh
@@ -231,5 +231,11 @@ if [ $failed -gt 0 ]; then
echo "FAILED $failed / $numtests tests."
exit 1
fi
+
+if [ $numtests -eq 0 ]; then
+ echo "FAILED: no tests found to run!"
+ exit 1
+fi
+
echo "passed $numtests tests."
diff --git a/src/test/journal/CMakeLists.txt b/src/test/journal/CMakeLists.txt
index 213630e941c..99e0f8ae6e6 100644
--- a/src/test/journal/CMakeLists.txt
+++ b/src/test/journal/CMakeLists.txt
@@ -27,6 +27,6 @@ target_link_libraries(unittest_journal
cls_journal_client
rados_test_stub
librados
- radostest
+ radostest-cxx
global
)
diff --git a/src/test/journal/RadosTestFixture.cc b/src/test/journal/RadosTestFixture.cc
index 1c4ed84075e..61a9967f75f 100644
--- a/src/test/journal/RadosTestFixture.cc
+++ b/src/test/journal/RadosTestFixture.cc
@@ -1,6 +1,7 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include "test/librados/test_cxx.h"
#include "test/journal/RadosTestFixture.h"
#include "cls/journal/cls_journal_client.h"
#include "include/stringify.h"
diff --git a/src/test/librados/CMakeLists.txt b/src/test/librados/CMakeLists.txt
index 33ac156f9d1..1e7ccff92f1 100644
--- a/src/test/librados/CMakeLists.txt
+++ b/src/test/librados/CMakeLists.txt
@@ -1,30 +1,43 @@
# radostest
-add_library(libradostest_obj OBJECT test.cc)
-target_include_directories(libradostest_obj PRIVATE
+add_library(radostest_shared OBJECT test_shared.cc)
+target_include_directories(radostest_shared PRIVATE
$<TARGET_PROPERTY:GTest::GTest,INTERFACE_INCLUDE_DIRECTORIES>)
-set(libradostest_srcs
- test_common.cc
- TestCase.cc)
+
add_library(radostest STATIC
- ${libradostest_srcs}
- $<TARGET_OBJECTS:libradostest_obj>)
-target_link_libraries(radostest
+ test_common.cc
+ TestCase.cc
+ test.cc
+ $<TARGET_OBJECTS:radostest_shared>)
+target_link_libraries(radostest PUBLIC
GTest::GTest
- librados
ceph-common
json_spirit
${EXTRALIBS})
-
+add_library(radostest-cxx STATIC
+ testcase_cxx.cc
+ test_cxx.cc
+ $<TARGET_OBJECTS:radostest_shared>)
+target_link_libraries(radostest-cxx PUBLIC
+ GTest::GTest
+ ceph-common)
add_executable(ceph_test_rados_api_cmd
cmd.cc)
target_link_libraries(ceph_test_rados_api_cmd
librados ${UNITTEST_LIBS} radostest)
+add_executable(ceph_test_rados_api_cmd_pp
+ cmd_cxx.cc)
+target_link_libraries(ceph_test_rados_api_cmd_pp
+ librados-cxx ${UNITTEST_LIBS} radostest-cxx)
add_executable(ceph_test_rados_api_io
io.cc)
target_link_libraries(ceph_test_rados_api_io
librados ${UNITTEST_LIBS} radostest)
+add_executable(ceph_test_rados_api_io_pp
+ io_cxx.cc)
+target_link_libraries(ceph_test_rados_api_io_pp
+ librados-cxx ${UNITTEST_LIBS} radostest-cxx)
add_executable(ceph_test_rados_api_c_write_operations
c_write_operations.cc)
@@ -40,10 +53,14 @@ add_executable(ceph_test_rados_api_aio
aio.cc)
target_link_libraries(ceph_test_rados_api_aio
librados ${UNITTEST_LIBS} radostest)
+add_executable(ceph_test_rados_api_aio_pp
+ aio_cxx.cc)
+target_link_libraries(ceph_test_rados_api_aio_pp
+ librados-cxx ${UNITTEST_LIBS} radostest-cxx)
add_executable(ceph_test_rados_api_asio asio.cc)
target_link_libraries(ceph_test_rados_api_asio global
- librados ${UNITTEST_LIBS})
+ librados-cxx ${UNITTEST_LIBS})
if(WITH_BOOST_CONTEXT)
target_link_libraries(ceph_test_rados_api_asio Boost::coroutine Boost::context)
endif()
@@ -63,60 +80,94 @@ add_executable(ceph_test_rados_api_stat
stat.cc)
target_link_libraries(ceph_test_rados_api_stat
librados ${UNITTEST_LIBS} radostest)
+add_executable(ceph_test_rados_api_stat_pp
+ stat_cxx.cc)
+target_link_libraries(ceph_test_rados_api_stat_pp
+ librados-cxx ${UNITTEST_LIBS} radostest-cxx)
add_executable(ceph_test_rados_api_watch_notify
watch_notify.cc)
target_link_libraries(ceph_test_rados_api_watch_notify
librados ${UNITTEST_LIBS} radostest)
+add_executable(ceph_test_rados_api_watch_notify_pp
+ watch_notify_cxx.cc)
+target_link_libraries(ceph_test_rados_api_watch_notify_pp
+ librados-cxx ${UNITTEST_LIBS} radostest-cxx)
add_executable(ceph_test_rados_api_cls
cls.cc)
target_link_libraries(ceph_test_rados_api_cls
- librados ${UNITTEST_LIBS} radostest)
+ librados-cxx ${UNITTEST_LIBS} radostest-cxx)
add_executable(ceph_test_rados_api_misc
misc.cc
$<TARGET_OBJECTS:unit-main>)
target_link_libraries(ceph_test_rados_api_misc
librados global ${UNITTEST_LIBS} radostest)
+add_executable(ceph_test_rados_api_misc_pp
+ misc_cxx.cc
+ $<TARGET_OBJECTS:unit-main>)
+target_link_libraries(ceph_test_rados_api_misc_pp
+ librados-cxx global ${UNITTEST_LIBS} radostest-cxx)
add_executable(ceph_test_rados_api_lock
lock.cc)
target_link_libraries(ceph_test_rados_api_lock
librados ${UNITTEST_LIBS} radostest)
+add_executable(ceph_test_rados_api_lock_pp
+ lock_cxx.cc)
+target_link_libraries(ceph_test_rados_api_lock_pp
+ librados-cxx ${UNITTEST_LIBS} radostest-cxx)
add_executable(ceph_test_rados_api_service
service.cc)
target_link_libraries(ceph_test_rados_api_service
librados global ${UNITTEST_LIBS} radostest)
+add_executable(ceph_test_rados_api_service_pp
+ service_cxx.cc)
+target_link_libraries(ceph_test_rados_api_service_pp
+ librados-cxx global ${UNITTEST_LIBS} radostest-cxx)
-add_executable(ceph_test_rados_api_tier
- tier.cc
+add_executable(ceph_test_rados_api_tier_pp
+ tier_cxx.cc
$<TARGET_OBJECTS:unit-main>)
-target_link_libraries(ceph_test_rados_api_tier
- librados global ${UNITTEST_LIBS} Boost::system radostest)
+target_link_libraries(ceph_test_rados_api_tier_pp
+ librados-cxx global ${UNITTEST_LIBS} Boost::system radostest-cxx)
add_executable(ceph_test_rados_api_snapshots
snapshots.cc)
target_link_libraries(ceph_test_rados_api_snapshots
librados ${UNITTEST_LIBS} radostest)
+add_executable(ceph_test_rados_api_snapshots_pp
+ snapshots_cxx.cc)
+target_link_libraries(ceph_test_rados_api_snapshots_pp
+ librados-cxx ${UNITTEST_LIBS} radostest-cxx)
install(TARGETS
ceph_test_rados_api_aio
+ ceph_test_rados_api_aio_pp
ceph_test_rados_api_asio
ceph_test_rados_api_c_read_operations
ceph_test_rados_api_c_write_operations
ceph_test_rados_api_cmd
+ ceph_test_rados_api_cmd_pp
ceph_test_rados_api_io
+ ceph_test_rados_api_io_pp
ceph_test_rados_api_list
ceph_test_rados_api_lock
+ ceph_test_rados_api_lock_pp
ceph_test_rados_api_misc
+ ceph_test_rados_api_misc_pp
ceph_test_rados_api_pool
ceph_test_rados_api_service
+ ceph_test_rados_api_service_pp
ceph_test_rados_api_snapshots
+ ceph_test_rados_api_snapshots_pp
ceph_test_rados_api_stat
- ceph_test_rados_api_tier
+ ceph_test_rados_api_stat_pp
+ ceph_test_rados_api_tier_pp
ceph_test_rados_api_watch_notify
+ ceph_test_rados_api_watch_notify_pp
DESTINATION ${CMAKE_INSTALL_BINDIR})
# unittest_librados
diff --git a/src/test/librados/TestCase.cc b/src/test/librados/TestCase.cc
index 37dbd2a923b..1066587b5ec 100644
--- a/src/test/librados/TestCase.cc
+++ b/src/test/librados/TestCase.cc
@@ -6,24 +6,10 @@
#include "test/librados/TestCase.h"
#include "include/scope_guard.h"
-using namespace librados;
std::string RadosTestNS::pool_name;
rados_t RadosTestNS::s_cluster = NULL;
-namespace {
-
-void init_rand() {
- static bool seeded = false;
- if (!seeded) {
- seeded = true;
- int seed = getpid();
- std::cout << "seed " << seed << std::endl;
- srand(seed);
- }
-}
-
-} // anonymous namespace
void RadosTestNS::SetUpTestCase()
{
@@ -74,131 +60,6 @@ void RadosTestNS::cleanup_all_objects(rados_ioctx_t ioctx)
}
}
-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));
- bool requires;
- ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
- ASSERT_FALSE(requires);
-}
-
-void RadosTestPPNS::TearDown()
-{
- if (cleanup)
- cleanup_all_objects(ioctx);
- ioctx.close();
-}
-
-void RadosTestPPNS::cleanup_all_objects(librados::IoCtx ioctx)
-{
- // remove all objects to avoid polluting other tests
- ioctx.snap_set_read(librados::SNAP_HEAD);
- 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));
- bool requires;
- ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
- ASSERT_FALSE(requires);
-}
-
-void RadosTestParamPPNS::TearDown()
-{
- if (cleanup)
- cleanup_all_objects(ioctx);
- ioctx.close();
-}
-
-void RadosTestParamPPNS::cleanup_all_objects(librados::IoCtx ioctx)
-{
- // remove all objects to avoid polluting other tests
- ioctx.snap_set_read(librados::SNAP_HEAD);
- 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;
@@ -231,37 +92,6 @@ void RadosTestECNS::TearDown()
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));
- bool requires;
- ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
- ASSERT_TRUE(requires);
- ASSERT_EQ(0, ioctx.pool_required_alignment2(&alignment));
- ASSERT_NE(0U, alignment);
-}
-
-void RadosTestECPPNS::TearDown()
-{
- if (cleanup)
- cleanup_all_objects(ioctx);
- ioctx.close();
-}
-
std::string RadosTest::pool_name;
rados_t RadosTest::s_cluster = NULL;
@@ -322,179 +152,6 @@ void RadosTest::cleanup_namespace(rados_ioctx_t ioctx, std::string ns)
}
}
-std::string RadosTestPP::pool_name;
-Rados RadosTestPP::s_cluster;
-
-void RadosTestPP::SetUpTestCase()
-{
- init_rand();
-
- pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_pool_pp(pool_name, s_cluster));
-}
-
-void RadosTestPP::TearDownTestCase()
-{
- ASSERT_EQ(0, destroy_one_pool_pp(pool_name, s_cluster));
-}
-
-void RadosTestPP::SetUp()
-{
- ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
- nspace = get_temp_pool_name();
- ioctx.set_namespace(nspace);
- bool requires;
- ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
- ASSERT_FALSE(requires);
-}
-
-void RadosTestPP::TearDown()
-{
- if (cleanup) {
- cleanup_default_namespace(ioctx);
- cleanup_namespace(ioctx, nspace);
- }
- ioctx.close();
-}
-
-void RadosTestPP::cleanup_default_namespace(librados::IoCtx ioctx)
-{
- // remove all objects from the default namespace to avoid polluting
- // other tests
- cleanup_namespace(ioctx, "");
-}
-
-void RadosTestPP::cleanup_namespace(librados::IoCtx ioctx, std::string ns)
-{
- ioctx.snap_set_read(librados::SNAP_HEAD);
- ioctx.set_namespace(ns);
- int tries = 600;
- while (--tries) {
- int got_enoent = 0;
- for (NObjectIterator it = ioctx.nobjects_begin();
- it != ioctx.nobjects_end(); ++it) {
- ioctx.locator_set_key(it->get_locator());
- ObjectWriteOperation op;
- op.remove();
- librados::AioCompletion *completion = s_cluster.aio_create_completion();
- auto sg = make_scope_guard([&] { completion->release(); });
- ASSERT_EQ(0, ioctx.aio_operate(it->get_oid(), completion, &op,
- librados::OPERATION_IGNORE_CACHE));
- completion->wait_for_safe();
- if (completion->get_return_value() == -ENOENT) {
- ++got_enoent;
- std::cout << " got ENOENT removing " << it->get_oid() << std::endl;
- } else {
- ASSERT_EQ(0, completion->get_return_value());
- }
- }
- if (!got_enoent) {
- break;
- }
- std::cout << " got ENOENT on " << got_enoent
- << " objects, waiting a bit for snap"
- << " trimming before retrying " << tries << " more times..."
- << std::endl;
- sleep(1);
- }
- if (tries == 0) {
- std::cout << "failed to clean up" << std::endl;
- ASSERT_TRUE(false);
- }
-}
-
-std::string RadosTestParamPP::pool_name;
-std::string RadosTestParamPP::cache_pool_name;
-Rados RadosTestParamPP::s_cluster;
-
-void RadosTestParamPP::SetUpTestCase()
-{
- pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_pool_pp(pool_name, s_cluster));
-}
-
-void RadosTestParamPP::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 RadosTestParamPP::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));
- nspace = get_temp_pool_name();
- ioctx.set_namespace(nspace);
- bool requires;
- ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
- ASSERT_FALSE(requires);
-}
-
-void RadosTestParamPP::TearDown()
-{
- if (cleanup) {
- cleanup_default_namespace(ioctx);
- cleanup_namespace(ioctx, nspace);
- }
- ioctx.close();
-}
-
-void RadosTestParamPP::cleanup_default_namespace(librados::IoCtx ioctx)
-{
- // remove all objects from the default namespace to avoid polluting
- // other tests
- cleanup_namespace(ioctx, "");
-}
-
-void RadosTestParamPP::cleanup_namespace(librados::IoCtx ioctx, std::string ns)
-{
- ioctx.snap_set_read(librados::SNAP_HEAD);
- ioctx.set_namespace(ns);
- 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()));
- }
-}
-
std::string RadosTestEC::pool_name;
rados_t RadosTestEC::s_cluster = NULL;
@@ -531,38 +188,3 @@ void RadosTestEC::TearDown()
rados_ioctx_destroy(ioctx);
}
-std::string RadosTestECPP::pool_name;
-Rados RadosTestECPP::s_cluster;
-
-void RadosTestECPP::SetUpTestCase()
-{
- pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_ec_pool_pp(pool_name, s_cluster));
-}
-
-void RadosTestECPP::TearDownTestCase()
-{
- ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, s_cluster));
-}
-
-void RadosTestECPP::SetUp()
-{
- ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
- nspace = get_temp_pool_name();
- ioctx.set_namespace(nspace);
- bool requires;
- ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
- ASSERT_TRUE(requires);
- ASSERT_EQ(0, ioctx.pool_required_alignment2(&alignment));
- ASSERT_NE(0U, alignment);
-}
-
-void RadosTestECPP::TearDown()
-{
- if (cleanup) {
- cleanup_default_namespace(ioctx);
- cleanup_namespace(ioctx, nspace);
- }
- ioctx.close();
-}
-
diff --git a/src/test/librados/TestCase.h b/src/test/librados/TestCase.h
index 94f668eac01..15fcfeb73bc 100644
--- a/src/test/librados/TestCase.h
+++ b/src/test/librados/TestCase.h
@@ -5,7 +5,6 @@
#define CEPH_TEST_RADOS_TESTCASE_H
#include "include/rados/librados.h"
-#include "include/rados/librados.hpp"
#include "gtest/gtest.h"
#include <string>
@@ -41,47 +40,6 @@ struct RadosTestNSCleanup : public RadosTestNS {
RadosTestNSCleanup() : RadosTestNS(true) {}
};
-class RadosTestPPNS : public ::testing::Test {
-public:
- RadosTestPPNS(bool c=false) : cluster(s_cluster), cleanup(c) {}
- ~RadosTestPPNS() override {}
-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;
-
- void SetUp() override;
- void TearDown() override;
- librados::Rados &cluster;
- librados::IoCtx ioctx;
- bool cleanup;
-};
-
-struct RadosTestPPNSCleanup : public RadosTestPPNS {
- RadosTestPPNSCleanup() : RadosTestPPNS(true) {}
-};
-
-class RadosTestParamPPNS : public ::testing::TestWithParam<const char*> {
-public:
- RadosTestParamPPNS(bool c=false) : cluster(s_cluster), cleanup(c) {}
- ~RadosTestParamPPNS() override {}
- 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;
-
- void SetUp() override;
- void TearDown() override;
- librados::Rados &cluster;
- librados::IoCtx ioctx;
- bool cleanup;
-};
-
class RadosTestECNS : public RadosTestNS {
public:
RadosTestECNS(bool c=false) : cleanup(c) {}
@@ -104,28 +62,6 @@ struct RadosTestECNSCleanup : public RadosTestECNS {
RadosTestECNSCleanup() : RadosTestECNS(true) {}
};
-class RadosTestECPPNS : public RadosTestPPNS {
-public:
- RadosTestECPPNS(bool c=false) : cluster(s_cluster), cleanup(c) {}
- ~RadosTestECPPNS() override {}
-protected:
- static void SetUpTestCase();
- static void TearDownTestCase();
- static librados::Rados s_cluster;
- static std::string pool_name;
-
- void SetUp() override;
- void TearDown() override;
- librados::Rados &cluster;
- librados::IoCtx ioctx;
- uint64_t alignment = 0;
- bool cleanup;
-};
-
-struct RadosTestECPPNSCleanup : public RadosTestECPPNS {
- RadosTestECPPNSCleanup() : RadosTestECPPNS(true) {}
-};
-
/**
* 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
@@ -154,47 +90,6 @@ protected:
bool cleanup;
};
-class RadosTestPP : public ::testing::Test {
-public:
- RadosTestPP(bool c=false) : cluster(s_cluster), cleanup(c) {}
- ~RadosTestPP() override {}
-protected:
- static void SetUpTestCase();
- static void TearDownTestCase();
- static void cleanup_default_namespace(librados::IoCtx ioctx);
- static void cleanup_namespace(librados::IoCtx ioctx, std::string ns);
- static librados::Rados s_cluster;
- static std::string pool_name;
-
- void SetUp() override;
- void TearDown() override;
- librados::Rados &cluster;
- librados::IoCtx ioctx;
- bool cleanup;
- std::string nspace;
-};
-
-class RadosTestParamPP : public ::testing::TestWithParam<const char*> {
-public:
- RadosTestParamPP(bool c=false) : cluster(s_cluster), cleanup(c) {}
- ~RadosTestParamPP() override {}
- static void SetUpTestCase();
- static void TearDownTestCase();
-protected:
- static void cleanup_default_namespace(librados::IoCtx ioctx);
- static void cleanup_namespace(librados::IoCtx ioctx, std::string ns);
- static librados::Rados s_cluster;
- static std::string pool_name;
- static std::string cache_pool_name;
-
- void SetUp() override;
- void TearDown() override;
- librados::Rados &cluster;
- librados::IoCtx ioctx;
- bool cleanup;
- std::string nspace;
-};
-
class RadosTestEC : public RadosTest {
public:
RadosTestEC(bool c=false) : cleanup(c) {}
@@ -214,25 +109,6 @@ protected:
uint64_t alignment = 0;
};
-class RadosTestECPP : public RadosTestPP {
-public:
- RadosTestECPP(bool c=false) : cluster(s_cluster), cleanup(c) {}
- ~RadosTestECPP() override {}
-protected:
- static void SetUpTestCase();
- static void TearDownTestCase();
- static librados::Rados s_cluster;
- static std::string pool_name;
-
- void SetUp() override;
- void TearDown() override;
- librados::Rados &cluster;
- librados::IoCtx ioctx;
- bool cleanup;
- std::string nspace;
- uint64_t alignment = 0;
-};
-
/**
* Test case without creating a temporary pool in advance.
* This is necessary for scenarios such that we need to
diff --git a/src/test/librados/aio.cc b/src/test/librados/aio.cc
index 2d14e0f9170..503f992c069 100644
--- a/src/test/librados/aio.cc
+++ b/src/test/librados/aio.cc
@@ -1,22 +1,23 @@
-#include "common/errno.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <string>
+#include <sstream>
+#include <utility>
+#include <boost/scoped_ptr.hpp>
+
#include "include/err.h"
#include "include/rados/librados.h"
-#include "test/librados/test.h"
#include "include/types.h"
#include "include/stringify.h"
#include "include/scope_guard.h"
+#include "common/errno.h"
+
#include "gtest/gtest.h"
-#include <errno.h>
-#include <fcntl.h>
-#include <sstream>
-#include <string>
-#include <boost/scoped_ptr.hpp>
-#include <utility>
+
+#include "test.h"
using std::ostringstream;
-using namespace librados;
-using std::pair;
class AioTestData
{
@@ -63,55 +64,6 @@ public:
bool m_init;
};
-class AioTestDataPP
-{
-public:
- AioTestDataPP()
- : m_init(false)
- {
- }
-
- ~AioTestDataPP()
- {
- if (m_init) {
- m_ioctx.close();
- destroy_one_pool_pp(m_pool_name, m_cluster);
- }
- }
-
- std::string init()
- {
- return init({});
- }
-
- std::string init(const std::map<std::string, std::string> &config)
- {
- int ret;
-
- m_pool_name = get_temp_pool_name();
- std::string err = create_one_pool_pp(m_pool_name, m_cluster, config);
- if (!err.empty()) {
- ostringstream oss;
- oss << "create_one_pool(" << m_pool_name << ") failed: error " << err;
- return oss.str();
- }
- ret = m_cluster.ioctx_create(m_pool_name.c_str(), m_ioctx);
- if (ret) {
- destroy_one_pool_pp(m_pool_name, m_cluster);
- ostringstream oss;
- oss << "rados_ioctx_create failed: error " << ret;
- return oss.str();
- }
- m_init = true;
- return "";
- }
-
- Rados m_cluster;
- IoCtx m_ioctx;
- std::string m_pool_name;
- bool m_init;
-};
-
TEST(LibRadosAio, TooBig) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -129,75 +81,6 @@ TEST(LibRadosAio, TooBig) {
rados_aio_release(my_completion);
}
-TEST(LibRadosAio, TooBigPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
-
- bufferlist bl;
- AioCompletion *aio_completion = test_data.m_cluster.aio_create_completion(
- nullptr, NULL, NULL);
- ASSERT_EQ(-E2BIG, test_data.m_ioctx.aio_write("foo", aio_completion, bl, UINT_MAX, 0));
- ASSERT_EQ(-E2BIG, test_data.m_ioctx.aio_append("foo", aio_completion, bl, UINT_MAX));
- // ioctx.aio_write_full no way to overflow bl.length()
- delete aio_completion;
-}
-
-TEST(LibRadosAio, PoolQuotaPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- string p = get_temp_pool_name();
- ASSERT_EQ(0, test_data.m_cluster.pool_create(p.c_str()));
- IoCtx ioctx;
- ASSERT_EQ(0, test_data.m_cluster.ioctx_create(p.c_str(), ioctx));
- ioctx.application_enable("rados", true);
-
- bufferlist inbl;
- ASSERT_EQ(0, test_data.m_cluster.mon_command(
- "{\"prefix\": \"osd pool set-quota\", \"pool\": \"" + p +
- "\", \"field\": \"max_bytes\", \"val\": \"4096\"}",
- inbl, NULL, NULL));
-
- bufferlist bl;
- bufferptr z(4096);
- bl.append(z);
- int n;
- for (n = 0; n < 1024; ++n) {
- ObjectWriteOperation op;
- op.write_full(bl);
- librados::AioCompletion *completion =
- test_data.m_cluster.aio_create_completion();
- ASSERT_EQ(0, ioctx.aio_operate(
- "foo" + stringify(n), completion, &op,
- librados::OPERATION_FULL_TRY));
- completion->wait_for_safe();
- int r = completion->get_return_value();
- completion->release();
- if (r == -EDQUOT)
- break;
- ASSERT_EQ(0, r);
- sleep(1);
- }
- ASSERT_LT(n, 1024);
-
- // make sure we have latest map that marked the pool full
- test_data.m_cluster.wait_for_latest_osdmap();
-
- // make sure we block without FULL_TRY
- {
- ObjectWriteOperation op;
- op.write_full(bl);
- librados::AioCompletion *completion =
- test_data.m_cluster.aio_create_completion();
- ASSERT_EQ(0, ioctx.aio_operate("bar", completion, &op, 0));
- sleep(5);
- ASSERT_FALSE(completion->is_safe());
- completion->release();
- }
-
- ioctx.close();
- ASSERT_EQ(0, test_data.m_cluster.pool_delete(p.c_str()));
-}
-
TEST(LibRadosAio, SimpleWrite) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -229,45 +112,6 @@ TEST(LibRadosAio, SimpleWrite) {
ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
}
-TEST(LibRadosAio, SimpleWritePP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
- my_completion, bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- delete my_completion;
- }
-
- {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- test_data.m_ioctx.set_namespace("nspace");
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
- my_completion, bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- delete my_completion;
- }
-}
-
TEST(LibRadosAio, WaitForSafe) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -284,25 +128,6 @@ TEST(LibRadosAio, WaitForSafe) {
rados_aio_release(my_completion);
}
-TEST(LibRadosAio, WaitForSafePP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
- my_completion, bl1, sizeof(buf), 0));
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_safe());
- ASSERT_EQ(0, my_completion->get_return_value());
- delete my_completion;
-}
-
TEST(LibRadosAio, RoundTrip) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -426,167 +251,6 @@ TEST(LibRadosAio, RoundTrip3) {
ASSERT_EQ(bl.crc32c(-1), checksum[1]);
}
-TEST(LibRadosAio, RoundTripPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
- my_completion2, &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
-}
-
-TEST(LibRadosAio, RoundTripPP2) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
- my_completion2, &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_safe());
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
-}
-
-//using ObjectWriteOperation/ObjectReadOperation with iohint
-TEST(LibRadosAio, RoundTripPP3)
-{
- Rados cluster;
- std::string pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
- IoCtx ioctx;
- cluster.ioctx_create(pool_name.c_str(), ioctx);
-
- boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- op.write(0, bl);
- op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ioctx.aio_operate("test_obj", my_completion1.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion1->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion1->get_return_value());
-
- boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
- bl.clear();
- ObjectReadOperation op1;
- op1.read(0, sizeof(buf), &bl, NULL);
- op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
- bufferlist init_value_bl;
- encode(static_cast<int32_t>(-1), init_value_bl);
- bufferlist csum_bl;
- op1.checksum(LIBRADOS_CHECKSUM_TYPE_CRC32C, init_value_bl,
- 0, 0, 0, &csum_bl, nullptr);
- ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
-
- ASSERT_EQ(8U, csum_bl.length());
- auto csum_bl_it = csum_bl.cbegin();
- uint32_t csum_count;
- uint32_t csum;
- decode(csum_count, csum_bl_it);
- ASSERT_EQ(1U, csum_count);
- decode(csum, csum_bl_it);
- ASSERT_EQ(bl.crc32c(-1), csum);
- ioctx.remove("test_obj");
- destroy_one_pool_pp(pool_name, cluster);
-}
-
-TEST(LibRadosAio, RoundTripSparseReadPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- std::map<uint64_t, uint64_t> extents;
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_sparse_read("foo",
- my_completion2, &extents, &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- assert_eq_sparse(bl1, extents, bl2);
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAio, RoundTripAppend) {
AioTestData test_data;
rados_completion_t my_completion, my_completion2, my_completion3;
@@ -631,57 +295,6 @@ TEST(LibRadosAio, RoundTripAppend) {
rados_aio_release(my_completion3);
}
-TEST(LibRadosAio, RoundTripAppendPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion,
- bl1, sizeof(buf)));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- char buf2[128];
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion2,
- bl2, sizeof(buf2)));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- bufferlist bl3;
- AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion3, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
- my_completion3, &bl3, 2 * sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ((int)(sizeof(buf) * 2), my_completion3->get_return_value());
- ASSERT_EQ(sizeof(buf) * 2, bl3.length());
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf), buf2, sizeof(buf2)));
- delete my_completion;
- delete my_completion2;
- delete my_completion3;
-}
-
TEST(LibRadosAio, RemoveTest) {
char buf[128];
char buf2[sizeof(buf)];
@@ -703,27 +316,6 @@ TEST(LibRadosAio, RemoveTest) {
rados_aio_release(my_completion);
}
-TEST(LibRadosAioPP, RemoveTestPP) {
- char buf[128];
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
- boost::scoped_ptr<AioCompletion> my_completion
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion.get()));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- ASSERT_EQ(-ENOENT, test_data.m_ioctx.read("foo", bl2, sizeof(buf), 0));
-}
-
TEST(LibRadosAio, XattrsRoundTrip) {
char buf[128];
char attr1[] = "attr1";
@@ -770,59 +362,6 @@ TEST(LibRadosAio, XattrsRoundTrip) {
ASSERT_EQ(0, memcmp(attr1_buf, buf, sizeof(attr1_buf)));
}
-TEST(LibRadosAioPP, XattrsRoundTripPP) {
- char buf[128];
- char attr1[] = "attr1";
- char attr1_buf[] = "foo bar baz";
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
- bufferlist bl2;
- // async getxattr
- boost::scoped_ptr<AioCompletion> my_completion
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr("foo", my_completion.get(), attr1, bl2));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(-ENODATA, my_completion->get_return_value());
- // append
- bufferlist bl3;
- bl3.append(attr1_buf, sizeof(attr1_buf));
- // async setxattr
- AioTestDataPP test_data2;
- ASSERT_EQ("", test_data2.init());
- boost::scoped_ptr<AioCompletion> my_completion2
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr("foo", my_completion2.get(), attr1, bl3));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- // async getxattr
- bufferlist bl4;
- AioTestDataPP test_data3;
- ASSERT_EQ("", test_data3.init());
- boost::scoped_ptr<AioCompletion> my_completion3
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr("foo", my_completion3.get(), attr1, bl4));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(attr1_buf), my_completion3->get_return_value());
- // check content of attribute
- ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
-}
-
TEST(LibRadosAio, RmXattr) {
char buf[128];
char attr1[] = "attr1";
@@ -897,91 +436,6 @@ TEST(LibRadosAio, RmXattr) {
rados_aio_release(my_completion5);
}
-TEST(LibRadosAioPP, RmXattrPP) {
- char buf[128];
- char attr1[] = "attr1";
- char attr1_buf[] = "foo bar baz";
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
- // async setxattr
- bufferlist bl2;
- bl2.append(attr1_buf, sizeof(attr1_buf));
- boost::scoped_ptr<AioCompletion> my_completion
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr("foo", my_completion.get(), attr1, bl2));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- // async rmxattr
- AioTestDataPP test_data2;
- ASSERT_EQ("", test_data2.init());
- boost::scoped_ptr<AioCompletion> my_completion2
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- ASSERT_EQ(0, test_data.m_ioctx.aio_rmxattr("foo", my_completion2.get(), attr1));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- // async getxattr
- AioTestDataPP test_data3;
- ASSERT_EQ("", test_data3.init());
- boost::scoped_ptr<AioCompletion> my_completion3
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- bufferlist bl3;
- ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr("foo", my_completion3.get(), attr1, bl3));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ(-ENODATA, my_completion3->get_return_value());
- // Test rmxattr on a removed object
- char buf2[128];
- char attr2[] = "attr2";
- char attr2_buf[] = "foo bar baz";
- memset(buf2, 0xbb, sizeof(buf2));
- bufferlist bl21;
- bl21.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
- bufferlist bl22;
- bl22.append(attr2_buf, sizeof(attr2_buf));
- // async setxattr
- AioTestDataPP test_data4;
- ASSERT_EQ("", test_data4.init());
- boost::scoped_ptr<AioCompletion> my_completion4
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr("foo_rmxattr", my_completion4.get(), attr2, bl22));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion4->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion4->get_return_value());
- // remove object
- ASSERT_EQ(0, test_data.m_ioctx.remove("foo_rmxattr"));
- // async rmxattr on non existing object
- AioTestDataPP test_data5;
- ASSERT_EQ("", test_data5.init());
- boost::scoped_ptr<AioCompletion> my_completion5
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- ASSERT_EQ(0, test_data.m_ioctx.aio_rmxattr("foo_rmxattr", my_completion5.get(), attr2));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion5->wait_for_complete());
- }
- ASSERT_EQ(-ENOENT, my_completion5->get_return_value());
-}
-
TEST(LibRadosAio, XattrIter) {
AioTestData test_data;
ASSERT_EQ("", test_data.init());
@@ -1000,7 +454,7 @@ TEST(LibRadosAio, XattrIter) {
ASSERT_EQ(0, rados_setxattr(test_data.m_ioctx, "foo", attr2, attr2_buf, sizeof(attr2_buf)));
// call async version of getxattrs and wait for completion
rados_completion_t my_completion;
- ASSERT_EQ(0, rados_aio_create_completion(nullptr,
+ ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
nullptr, nullptr, &my_completion));
rados_xattrs_iter_t iter;
ASSERT_EQ(0, rados_aio_getxattrs(test_data.m_ioctx, "foo", my_completion, &iter));
@@ -1035,53 +489,6 @@ TEST(LibRadosAio, XattrIter) {
rados_getxattrs_end(iter);
}
-TEST(LibRadosIoPP, XattrListPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- // create an object with 2 attributes
- char buf[128];
- char attr1[] = "attr1";
- char attr1_buf[] = "foo bar baz";
- char attr2[] = "attr2";
- char attr2_buf[256];
- for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
- attr2_buf[j] = j % 0xff;
- }
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
- bufferlist bl2;
- bl2.append(attr1_buf, sizeof(attr1_buf));
- ASSERT_EQ(0, test_data.m_ioctx.setxattr("foo", attr1, bl2));
- bufferlist bl3;
- bl3.append(attr2_buf, sizeof(attr2_buf));
- ASSERT_EQ(0, test_data.m_ioctx.setxattr("foo", attr2, bl3));
- // call async version of getxattrs
- boost::scoped_ptr<AioCompletion> my_completion
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- std::map<std::string, bufferlist> attrset;
- ASSERT_EQ(0, test_data.m_ioctx.aio_getxattrs("foo", my_completion.get(), attrset));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
- i != attrset.end(); ++i) {
- if (i->first == string(attr1)) {
- ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
- }
- else if (i->first == string(attr2)) {
- ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
- }
- else {
- ASSERT_EQ(0, 1);
- }
- }
-}
-
TEST(LibRadosAio, IsComplete) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -1121,48 +528,6 @@ TEST(LibRadosAio, IsComplete) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAio, IsCompletePP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
- &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
-
- // Busy-wait until the AIO completes.
- // Normally we wouldn't do this, but we want to test is_complete.
- while (true) {
- int is_complete = my_completion2->is_complete();
- if (is_complete)
- break;
- }
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAio, IsSafe) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -1202,48 +567,6 @@ TEST(LibRadosAio, IsSafe) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAio, IsSafePP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
-
- // Busy-wait until the AIO completes.
- // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
- while (true) {
- int is_safe = my_completion->is_safe();
- if (is_safe)
- break;
- }
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- bufferlist bl2;
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
- &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAio, ReturnValue) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -1262,24 +585,6 @@ TEST(LibRadosAio, ReturnValue) {
rados_aio_release(my_completion);
}
-TEST(LibRadosAio, ReturnValuePP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- bufferlist bl1;
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("nonexistent",
- my_completion, &bl1, 128, 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(-ENOENT, my_completion->get_return_value());
- delete my_completion;
-}
-
TEST(LibRadosAio, Flush) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -1309,38 +614,6 @@ TEST(LibRadosAio, Flush) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAio, FlushPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xee, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- ASSERT_EQ(0, test_data.m_ioctx.aio_flush());
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
- &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAio, FlushAsync) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -1382,50 +655,6 @@ TEST(LibRadosAio, FlushAsync) {
rados_aio_release(flush_completion);
}
-TEST(LibRadosAio, FlushAsyncPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *flush_completion =
- test_data.m_cluster.aio_create_completion(NULL, NULL, NULL);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xee, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- ASSERT_EQ(0, test_data.m_ioctx.aio_flush_async(flush_completion));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, flush_completion->wait_for_complete());
- ASSERT_EQ(0, flush_completion->wait_for_safe());
- }
- ASSERT_EQ(1, my_completion->is_complete());
- ASSERT_EQ(1, my_completion->is_safe());
- ASSERT_EQ(1, flush_completion->is_complete());
- ASSERT_EQ(1, flush_completion->is_safe());
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
- &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
- delete flush_completion;
-}
-
TEST(LibRadosAio, RoundTripWriteFull) {
AioTestData test_data;
rados_completion_t my_completion, my_completion2, my_completion3;
@@ -1469,97 +698,6 @@ TEST(LibRadosAio, RoundTripWriteFull) {
rados_aio_release(my_completion3);
}
-TEST(LibRadosAio, RoundTripWriteFullPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- char buf2[64];
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_write_full("foo", my_completion2, bl2));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- bufferlist bl3;
- AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion3, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
- &bl3, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf2), my_completion3->get_return_value());
- ASSERT_EQ(sizeof(buf2), bl3.length());
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
- delete my_completion;
- delete my_completion2;
- delete my_completion3;
-}
-
-//using ObjectWriteOperation/ObjectReadOperation with iohint
-TEST(LibRadosAio, RoundTripWriteFullPP2)
-{
- Rados cluster;
- std::string pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
- IoCtx ioctx;
- cluster.ioctx_create(pool_name.c_str(), ioctx);
-
- boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf);
-
- op.write_full(bl);
- op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ioctx.aio_operate("test_obj", my_completion1.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion1->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion1->get_return_value());
-
- boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
- bl.clear();
- ObjectReadOperation op1;
- op1.read(0, sizeof(buf), &bl, NULL);
- op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
- ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
-
- ioctx.remove("test_obj");
- destroy_one_pool_pp(pool_name, cluster);
-}
-
TEST(LibRadosAio, RoundTripWriteSame) {
AioTestData test_data;
rados_completion_t my_completion, my_completion2, my_completion3;
@@ -1606,110 +744,6 @@ TEST(LibRadosAio, RoundTripWriteSame) {
rados_aio_release(my_completion3);
}
-TEST(LibRadosAio, RoundTripWriteSamePP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char full[128];
- memset(full, 0xcc, sizeof(full));
- bufferlist bl1;
- bl1.append(full, sizeof(full));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(full), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- /* write the same buf four times */
- char buf[32];
- size_t ws_write_len = sizeof(full);
- memset(buf, 0xdd, sizeof(buf));
- bufferlist bl2;
- bl2.append(buf, sizeof(buf));
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_writesame("foo", my_completion2, bl2,
- ws_write_len, 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- bufferlist bl3;
- AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion3, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
- &bl3, sizeof(full), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(full), my_completion3->get_return_value());
- ASSERT_EQ(sizeof(full), bl3.length());
- for (char *cmp = bl3.c_str(); cmp < bl3.c_str() + bl3.length();
- cmp += sizeof(buf)) {
- ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
- }
- delete my_completion;
- delete my_completion2;
- delete my_completion3;
-}
-
-TEST(LibRadosAio, RoundTripWriteSamePP2)
-{
- Rados cluster;
- std::string pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
- IoCtx ioctx;
- cluster.ioctx_create(pool_name.c_str(), ioctx);
-
- boost::scoped_ptr<AioCompletion>
- wr_cmpl(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- op.writesame(0, sizeof(buf) * 4, bl);
- op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ioctx.aio_operate("test_obj", wr_cmpl.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, wr_cmpl->wait_for_complete());
- }
- EXPECT_EQ(0, wr_cmpl->get_return_value());
-
- boost::scoped_ptr<AioCompletion>
- rd_cmpl(cluster.aio_create_completion(0, 0, 0));
- char *cmp;
- char full[sizeof(buf) * 4];
- memset(full, 0, sizeof(full));
- bufferlist fl;
- fl.append(full, sizeof(full));
- ObjectReadOperation op1;
- op1.read(0, sizeof(full), &fl, NULL);
- op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ioctx.aio_operate("test_obj", rd_cmpl.get(), &op1, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, rd_cmpl->wait_for_complete());
- }
- EXPECT_EQ(0, rd_cmpl->get_return_value());
- for (cmp = fl.c_str(); cmp < fl.c_str() + fl.length(); cmp += sizeof(buf)) {
- ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
- }
-
- ioctx.remove("test_obj");
- destroy_one_pool_pp(pool_name, cluster);
-}
-
TEST(LibRadosAio, SimpleStat) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -1742,41 +776,6 @@ TEST(LibRadosAio, SimpleStat) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAio, SimpleStatPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- uint64_t psize;
- time_t pmtime;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
- &psize, &pmtime));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), psize);
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAio, SimpleStatNS) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -1837,41 +836,6 @@ TEST(LibRadosAio, SimpleStatNS) {
rados_aio_release(my_completion3);
}
-TEST(LibRadosAio, SimpleStatPPNS) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- uint64_t psize;
- time_t pmtime;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
- &psize, &pmtime));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), psize);
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAio, StatRemove) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -1927,65 +891,6 @@ TEST(LibRadosAio, StatRemove) {
rados_aio_release(my_completion4);
}
-TEST(LibRadosAio, StatRemovePP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- uint64_t psize;
- time_t pmtime;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
- &psize, &pmtime));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), psize);
- uint64_t psize2;
- time_t pmtime2;
- AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion3, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion3));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion3->get_return_value());
-
- AioCompletion *my_completion4 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion4, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion4,
- &psize2, &pmtime2));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion4->wait_for_complete());
- }
- ASSERT_EQ(-ENOENT, my_completion4->get_return_value());
- delete my_completion;
- delete my_completion2;
- delete my_completion3;
- delete my_completion4;
-}
-
TEST(LibRadosAio, ExecuteClass) {
AioTestData test_data;
rados_completion_t my_completion;
@@ -2016,245 +921,10 @@ TEST(LibRadosAio, ExecuteClass) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAio, ExecuteClassPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- bufferlist in, out;
- ASSERT_EQ(0, test_data.m_ioctx.aio_exec("foo", my_completion2,
- "hello", "say_hello", in, &out));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
- delete my_completion;
- delete my_completion2;
-}
-
using std::string;
using std::map;
using std::set;
-TEST(LibRadosAio, OmapPP) {
- Rados cluster;
- std::string pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
- IoCtx ioctx;
- cluster.ioctx_create(pool_name.c_str(), ioctx);
-
- string header_str = "baz";
- bufferptr bp(header_str.c_str(), header_str.size() + 1);
- bufferlist header_to_set;
- header_to_set.push_back(bp);
- map<string, bufferlist> to_set;
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- to_set["foo"] = header_to_set;
- to_set["foo2"] = header_to_set;
- to_set["qfoo3"] = header_to_set;
- op.omap_set(to_set);
-
- op.omap_set_header(header_to_set);
-
- ioctx.aio_operate("test_obj", my_completion.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion->get_return_value());
- }
-
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectReadOperation op;
- map<string, pair<bufferlist, int> > assertions;
- bufferlist val;
- val.append(string("bar"));
- assertions["foo"] = pair<bufferlist, int>(val, CEPH_OSD_CMPXATTR_OP_EQ);
-
- int r;
- op.omap_cmp(assertions, &r);
-
- ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(-ECANCELED, my_completion->get_return_value());
- ASSERT_EQ(-ECANCELED, r);
- }
-
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectReadOperation op;
-
- set<string> set_got;
- map<string, bufferlist> map_got;
-
- set<string> to_get;
- map<string, bufferlist> got3;
-
- map<string, bufferlist> got4;
-
- bufferlist header;
-
- op.omap_get_keys2("", 1, &set_got, nullptr, 0);
- op.omap_get_vals2("foo", 1, &map_got, nullptr, 0);
-
- to_get.insert("foo");
- to_get.insert("qfoo3");
- op.omap_get_vals_by_keys(to_get, &got3, 0);
-
- op.omap_get_header(&header, 0);
-
- op.omap_get_vals2("foo2", "q", 1, &got4, nullptr, 0);
-
- ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion->get_return_value());
-
- ASSERT_EQ(header.length(), header_to_set.length());
- ASSERT_EQ(set_got.size(), (unsigned)1);
- ASSERT_EQ(*set_got.begin(), "foo");
- ASSERT_EQ(map_got.size(), (unsigned)1);
- ASSERT_EQ(map_got.begin()->first, "foo2");
- ASSERT_EQ(got3.size(), (unsigned)2);
- ASSERT_EQ(got3.begin()->first, "foo");
- ASSERT_EQ(got3.rbegin()->first, "qfoo3");
- ASSERT_EQ(got4.size(), (unsigned)1);
- ASSERT_EQ(got4.begin()->first, "qfoo3");
- }
-
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- set<string> to_remove;
- to_remove.insert("foo2");
- op.omap_rm_keys(to_remove);
- ioctx.aio_operate("test_obj", my_completion.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion->get_return_value());
- }
-
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectReadOperation op;
-
- set<string> set_got;
- op.omap_get_keys2("", -1, &set_got, nullptr, 0);
- ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion->get_return_value());
- ASSERT_EQ(set_got.size(), (unsigned)2);
- }
-
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- op.omap_clear();
- ioctx.aio_operate("test_obj", my_completion.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion->get_return_value());
- }
-
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectReadOperation op;
-
- set<string> set_got;
- op.omap_get_keys2("", -1, &set_got, nullptr, 0);
- ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion->get_return_value());
- ASSERT_EQ(set_got.size(), (unsigned)0);
- }
-
- // omap_clear clears header *and* keys
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- bufferlist bl;
- bl.append("some data");
- map<string,bufferlist> to_set;
- to_set["foo"] = bl;
- to_set["foo2"] = bl;
- to_set["qfoo3"] = bl;
- op.omap_set(to_set);
- op.omap_set_header(bl);
- ioctx.aio_operate("foo3", my_completion.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion->get_return_value());
- }
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- op.omap_clear();
- ioctx.aio_operate("foo3", my_completion.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion->get_return_value());
- }
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectReadOperation op;
- set<string> set_got;
- bufferlist hdr;
- op.omap_get_keys2("", -1, &set_got, nullptr, 0);
- op.omap_get_header(&hdr, NULL);
- ioctx.aio_operate("foo3", my_completion.get(), &op, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion->get_return_value());
- ASSERT_EQ(set_got.size(), (unsigned)0);
- ASSERT_EQ(hdr.length(), 0u);
- }
-
- ioctx.remove("test_obj");
- destroy_one_pool_pp(pool_name, cluster);
-}
-
TEST(LibRadosAio, MultiWrite) {
AioTestData test_data;
rados_completion_t my_completion, my_completion2, my_completion3;
@@ -2301,59 +971,6 @@ TEST(LibRadosAio, MultiWrite) {
rados_aio_release(my_completion3);
}
-TEST(LibRadosAio, MultiWritePP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
-
- char buf2[64];
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion2,
- bl2, sizeof(buf2), sizeof(buf)));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
-
- bufferlist bl3;
- AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion3, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
- &bl3, (sizeof(buf) + sizeof(buf2) * 3), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ((int)(sizeof(buf) + sizeof(buf2)), my_completion3->get_return_value());
- ASSERT_EQ(sizeof(buf) + sizeof(buf2), bl3.length());
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf), buf2, sizeof(buf2)));
- delete my_completion;
- delete my_completion2;
- delete my_completion3;
-}
-
TEST(LibRadosAio, AioUnlock) {
AioTestData test_data;
ASSERT_EQ("", test_data.init());
@@ -2370,23 +987,6 @@ TEST(LibRadosAio, AioUnlock) {
ASSERT_EQ(0, rados_lock_exclusive(test_data.m_ioctx, "foo", "TestLock", "Cookie", "", NULL, 0));
}
-TEST(LibRadosAio, AioUnlockPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- ASSERT_EQ(0, test_data.m_ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
- boost::scoped_ptr<AioCompletion> my_completion
- (test_data.m_cluster.aio_create_completion
- (nullptr, nullptr, nullptr));
- ASSERT_EQ(0, test_data.m_ioctx.aio_unlock("foo", "TestLock", "Cookie", my_completion.get()));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- ASSERT_EQ(0, test_data.m_ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
-}
-
// EC test cases
class AioTestDataEC
{
@@ -2433,49 +1033,6 @@ public:
bool m_init;
};
-class AioTestDataECPP
-{
-public:
- AioTestDataECPP()
- : m_init(false)
- {
- }
-
- ~AioTestDataECPP()
- {
- if (m_init) {
- m_ioctx.close();
- destroy_one_ec_pool_pp(m_pool_name, m_cluster);
- }
- }
-
- std::string init()
- {
- int ret;
- m_pool_name = get_temp_pool_name();
- std::string err = create_one_ec_pool_pp(m_pool_name, m_cluster);
- if (!err.empty()) {
- ostringstream oss;
- oss << "create_one_ec_pool(" << m_pool_name << ") failed: error " << err;
- return oss.str();
- }
- ret = m_cluster.ioctx_create(m_pool_name.c_str(), m_ioctx);
- if (ret) {
- destroy_one_ec_pool_pp(m_pool_name, m_cluster);
- ostringstream oss;
- oss << "rados_ioctx_create failed: error " << ret;
- return oss.str();
- }
- m_init = true;
- return "";
- }
-
- Rados m_cluster;
- IoCtx m_ioctx;
- std::string m_pool_name;
- bool m_init;
-};
-
TEST(LibRadosAioEC, SimpleWrite) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -2507,45 +1064,6 @@ TEST(LibRadosAioEC, SimpleWrite) {
ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
}
-TEST(LibRadosAioEC, SimpleWritePP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
- my_completion, bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- delete my_completion;
- }
-
- {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- test_data.m_ioctx.set_namespace("nspace");
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
- my_completion, bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- delete my_completion;
- }
-}
-
TEST(LibRadosAioEC, WaitForSafe) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -2562,25 +1080,6 @@ TEST(LibRadosAioEC, WaitForSafe) {
rados_aio_release(my_completion);
}
-TEST(LibRadosAioEC, WaitForSafePP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
- my_completion, bl1, sizeof(buf), 0));
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_safe());
- ASSERT_EQ(0, my_completion->get_return_value());
- delete my_completion;
-}
-
TEST(LibRadosAioEC, RoundTrip) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -2645,155 +1144,6 @@ TEST(LibRadosAioEC, RoundTrip2) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAioEC, RoundTripPP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
- my_completion2, &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
-}
-
-TEST(LibRadosAioEC, RoundTripPP2) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
- my_completion2, &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_safe());
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
-}
-
-//using ObjectWriteOperation/ObjectReadOperation with iohint
-TEST(LibRadosAioEC, RoundTripPP3)
-{
- Rados cluster;
- std::string pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
- IoCtx ioctx;
- cluster.ioctx_create(pool_name.c_str(), ioctx);
-
- boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf);
-
- op.write(0, bl);
- op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ioctx.aio_operate("test_obj", my_completion1.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion1->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion1->get_return_value());
-
- boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
- bl.clear();
- ObjectReadOperation op1;
- op1.read(0, sizeof(buf), &bl, NULL);
- op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
- ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
-
- ioctx.remove("test_obj");
- destroy_one_pool_pp(pool_name, cluster);
-}
-
-TEST(LibRadosAioEC, RoundTripSparseReadPP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
-
- map<uint64_t, uint64_t> extents;
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_sparse_read("foo",
- my_completion2, &extents, &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- assert_eq_sparse(bl1, extents, bl2);
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAioEC, RoundTripAppend) {
AioTestDataEC test_data;
rados_completion_t my_completion, my_completion2, my_completion3, my_completion4;
@@ -2864,81 +1214,6 @@ TEST(LibRadosAioEC, RoundTripAppend) {
delete[] buf3;
}
-TEST(LibRadosAioEC, RoundTripAppendPP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- bool requires;
- ASSERT_EQ(0, test_data.m_ioctx.pool_requires_alignment2(&requires));
- ASSERT_TRUE(requires);
- uint64_t alignment;
- ASSERT_EQ(0, test_data.m_ioctx.pool_required_alignment2(&alignment));
- ASSERT_NE((unsigned)0, alignment);
- int bsize = alignment;
- char *buf = (char *)new char[bsize];
- memset(buf, 0xcc, bsize);
- bufferlist bl1;
- bl1.append(buf, bsize);
- ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion,
- bl1, bsize));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
-
- int hbsize = bsize / 2;
- char *buf2 = (char *)new char[hbsize];
- memset(buf2, 0xdd, hbsize);
- bufferlist bl2;
- bl2.append(buf2, hbsize);
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion2,
- bl2, hbsize));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
-
- AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion3, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion3,
- bl2, hbsize));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- EXPECT_EQ(-EOPNOTSUPP, my_completion3->get_return_value());
-
- bufferlist bl3;
- AioCompletion *my_completion4 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion4, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
- my_completion4, &bl3, bsize * 3, 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion4->wait_for_complete());
- }
- int tbsize = bsize + hbsize;
- ASSERT_EQ(tbsize, my_completion4->get_return_value());
- ASSERT_EQ((unsigned)tbsize, bl3.length());
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
- ASSERT_EQ(0, memcmp(bl3.c_str() + bsize, buf2, hbsize));
- delete my_completion;
- delete my_completion2;
- delete my_completion3;
- delete[] buf;
- delete[] buf2;
-}
-
TEST(LibRadosAioEC, IsComplete) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -2978,48 +1253,6 @@ TEST(LibRadosAioEC, IsComplete) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAioEC, IsCompletePP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
- &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
-
- // Busy-wait until the AIO completes.
- // Normally we wouldn't do this, but we want to test is_complete.
- while (true) {
- int is_complete = my_completion2->is_complete();
- if (is_complete)
- break;
- }
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAioEC, IsSafe) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -3059,48 +1292,6 @@ TEST(LibRadosAioEC, IsSafe) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAioEC, IsSafePP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
-
- // Busy-wait until the AIO completes.
- // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
- while (true) {
- int is_safe = my_completion->is_safe();
- if (is_safe)
- break;
- }
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- bufferlist bl2;
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
- &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAioEC, ReturnValue) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -3119,24 +1310,6 @@ TEST(LibRadosAioEC, ReturnValue) {
rados_aio_release(my_completion);
}
-TEST(LibRadosAioEC, ReturnValuePP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- bufferlist bl1;
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("nonexistent",
- my_completion, &bl1, 128, 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(-ENOENT, my_completion->get_return_value());
- delete my_completion;
-}
-
TEST(LibRadosAioEC, Flush) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -3166,38 +1339,6 @@ TEST(LibRadosAioEC, Flush) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAioEC, FlushPP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xee, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- ASSERT_EQ(0, test_data.m_ioctx.aio_flush());
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
- &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAioEC, FlushAsync) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -3239,50 +1380,6 @@ TEST(LibRadosAioEC, FlushAsync) {
rados_aio_release(flush_completion);
}
-TEST(LibRadosAioEC, FlushAsyncPP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *flush_completion =
- test_data.m_cluster.aio_create_completion(NULL, NULL, NULL);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xee, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- ASSERT_EQ(0, test_data.m_ioctx.aio_flush_async(flush_completion));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, flush_completion->wait_for_complete());
- ASSERT_EQ(0, flush_completion->wait_for_safe());
- }
- ASSERT_EQ(1, my_completion->is_complete());
- ASSERT_EQ(1, my_completion->is_safe());
- ASSERT_EQ(1, flush_completion->is_complete());
- ASSERT_EQ(1, flush_completion->is_safe());
- ASSERT_EQ(0, my_completion->get_return_value());
- bufferlist bl2;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
- &bl2, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), bl2.length());
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
- delete my_completion;
- delete my_completion2;
- delete flush_completion;
-}
-
TEST(LibRadosAioEC, RoundTripWriteFull) {
AioTestDataEC test_data;
rados_completion_t my_completion, my_completion2, my_completion3;
@@ -3326,97 +1423,6 @@ TEST(LibRadosAioEC, RoundTripWriteFull) {
rados_aio_release(my_completion3);
}
-TEST(LibRadosAioEC, RoundTripWriteFullPP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- char buf2[64];
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_write_full("foo", my_completion2, bl2));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- bufferlist bl3;
- AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion3, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
- &bl3, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf2), my_completion3->get_return_value());
- ASSERT_EQ(sizeof(buf2), bl3.length());
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
- delete my_completion;
- delete my_completion2;
- delete my_completion3;
-}
-
-//using ObjectWriteOperation/ObjectReadOperation with iohint
-TEST(LibRadosAioEC, RoundTripWriteFullPP2)
-{
- Rados cluster;
- std::string pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
- IoCtx ioctx;
- cluster.ioctx_create(pool_name.c_str(), ioctx);
-
- boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf);
-
- op.write_full(bl);
- op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
- ioctx.aio_operate("test_obj", my_completion1.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion1->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion1->get_return_value());
-
- boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
- bl.clear();
- ObjectReadOperation op1;
- op1.read(0, sizeof(buf), &bl, NULL);
- op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
- ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- EXPECT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
-
- ioctx.remove("test_obj");
- destroy_one_pool_pp(pool_name, cluster);
-}
-
TEST(LibRadosAioEC, SimpleStat) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -3449,40 +1455,6 @@ TEST(LibRadosAioEC, SimpleStat) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAioEC, SimpleStatPP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- uint64_t psize;
- time_t pmtime;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
- &psize, &pmtime));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), psize);
- delete my_completion;
- delete my_completion2;
-}
TEST(LibRadosAioEC, SimpleStatNS) {
AioTestDataEC test_data;
@@ -3544,41 +1516,6 @@ TEST(LibRadosAioEC, SimpleStatNS) {
rados_aio_release(my_completion3);
}
-TEST(LibRadosAioEC, SimpleStatPPNS) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- uint64_t psize;
- time_t pmtime;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
- &psize, &pmtime));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), psize);
- delete my_completion;
- delete my_completion2;
-}
-
TEST(LibRadosAioEC, StatRemove) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -3634,65 +1571,6 @@ TEST(LibRadosAioEC, StatRemove) {
rados_aio_release(my_completion4);
}
-TEST(LibRadosAioEC, StatRemovePP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- uint64_t psize;
- time_t pmtime;
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
- &psize, &pmtime));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(sizeof(buf), psize);
- uint64_t psize2;
- time_t pmtime2;
- AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion3, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion3));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion3->get_return_value());
-
- AioCompletion *my_completion4 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion4, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion4,
- &psize2, &pmtime2));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion4->wait_for_complete());
- }
- ASSERT_EQ(-ENOENT, my_completion4->get_return_value());
- delete my_completion;
- delete my_completion2;
- delete my_completion3;
- delete my_completion4;
-}
-
TEST(LibRadosAioEC, ExecuteClass) {
AioTestDataEC test_data;
rados_completion_t my_completion;
@@ -3724,73 +1602,6 @@ TEST(LibRadosAioEC, ExecuteClass) {
rados_aio_release(my_completion2);
}
-TEST(LibRadosAioEC, ExecuteClassPP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- bufferlist in, out;
- ASSERT_EQ(0, test_data.m_ioctx.aio_exec("foo", my_completion2,
- "hello", "say_hello", in, &out));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
- ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
- delete my_completion;
- delete my_completion2;
-}
-
-TEST(LibRadosAioEC, OmapPP) {
- Rados cluster;
- std::string pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_ec_pool_pp(pool_name, cluster));
- IoCtx ioctx;
- cluster.ioctx_create(pool_name.c_str(), ioctx);
-
- string header_str = "baz";
- bufferptr bp(header_str.c_str(), header_str.size() + 1);
- bufferlist header_to_set;
- header_to_set.push_back(bp);
- map<string, bufferlist> to_set;
- {
- boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation op;
- to_set["foo"] = header_to_set;
- to_set["foo2"] = header_to_set;
- to_set["qfoo3"] = header_to_set;
- op.omap_set(to_set);
-
- op.omap_set_header(header_to_set);
-
- ioctx.aio_operate("test_obj", my_completion.get(), &op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- EXPECT_EQ(-EOPNOTSUPP, my_completion->get_return_value());
- }
- ioctx.remove("test_obj");
- destroy_one_pool_pp(pool_name, cluster);
-}
-
TEST(LibRadosAioEC, MultiWrite) {
AioTestDataEC test_data;
rados_completion_t my_completion, my_completion2, my_completion3;
@@ -3835,232 +1646,3 @@ TEST(LibRadosAioEC, MultiWrite) {
rados_aio_release(my_completion2);
rados_aio_release(my_completion3);
}
-
-TEST(LibRadosAioEC, MultiWritePP) {
- AioTestDataECPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(buf), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
-
- char buf2[64];
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion2,
- bl2, sizeof(buf2), sizeof(buf)));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(-EOPNOTSUPP, my_completion2->get_return_value());
-
- bufferlist bl3;
- AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion3, my_completion_null);
- ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
- &bl3, (sizeof(buf) + sizeof(buf2) * 3), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ((int)sizeof(buf), my_completion3->get_return_value());
- ASSERT_EQ(sizeof(buf), bl3.length());
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
- delete my_completion;
- delete my_completion2;
- delete my_completion3;
-}
-
-TEST(LibRadosAio, RacingRemovePP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init({{"objecter_retry_writes_after_first_reply", "true"}}));
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion, nullptr);
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_NE(my_completion2, nullptr);
- ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion2));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl, sizeof(buf), 0));
- {
- TestAlarm alarm;
- my_completion2->wait_for_complete();
- my_completion->wait_for_complete();
- }
- ASSERT_EQ(-ENOENT, my_completion2->get_return_value());
- ASSERT_EQ(0, my_completion->get_return_value());
- ASSERT_EQ(0, test_data.m_ioctx.stat("foo", nullptr, nullptr));
- delete my_completion;
- delete my_completion2;
-}
-
-TEST(LibRadosAio, RoundTripCmpExtPP) {
- AioTestDataPP test_data;
- ASSERT_EQ("", test_data.init());
- AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
- char full[128];
- memset(full, 0xcc, sizeof(full));
- bufferlist bl1;
- bl1.append(full, sizeof(full));
- ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
- bl1, sizeof(full), 0));
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion->get_return_value());
-
- /* compare with match */
- bufferlist cbl;
- cbl.append(full, sizeof(full));
- AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_EQ(0, test_data.m_ioctx.aio_cmpext("foo", my_completion2, 0, cbl));
-
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion2->wait_for_complete());
- }
- ASSERT_EQ(0, my_completion2->get_return_value());
-
- /* compare with mismatch */
- memset(full, 0xdd, sizeof(full));
- cbl.clear();
- cbl.append(full, sizeof(full));
- AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
- nullptr, nullptr, nullptr);
- ASSERT_EQ(0, test_data.m_ioctx.aio_cmpext("foo", my_completion3, 0, cbl));
-
- {
- TestAlarm alarm;
- ASSERT_EQ(0, my_completion3->wait_for_complete());
- }
- ASSERT_EQ(-MAX_ERRNO, my_completion3->get_return_value());
-
- delete my_completion;
- delete my_completion2;
- delete my_completion3;
-}
-
-TEST(LibRadosAio, RoundTripCmpExtPP2)
-{
- int ret;
- char buf[128];
- char miscmp_buf[128];
- bufferlist cbl;
- Rados cluster;
- std::string pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
- IoCtx ioctx;
- cluster.ioctx_create(pool_name.c_str(), ioctx);
-
- boost::scoped_ptr<AioCompletion>
- wr_cmpl(cluster.aio_create_completion(0, 0, 0));
- ObjectWriteOperation wr_op;
- memset(buf, 0xcc, sizeof(buf));
- memset(miscmp_buf, 0xdd, sizeof(miscmp_buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- wr_op.write_full(bl);
- wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ioctx.aio_operate("test_obj", wr_cmpl.get(), &wr_op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, wr_cmpl->wait_for_complete());
- }
- EXPECT_EQ(0, wr_cmpl->get_return_value());
-
- /* cmpext as write op. first match then mismatch */
- boost::scoped_ptr<AioCompletion>
- wr_cmpext_cmpl(cluster.aio_create_completion(0, 0, 0));
- cbl.append(buf, sizeof(buf));
- ret = 0;
-
- wr_op.cmpext(0, cbl, &ret);
- wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ioctx.aio_operate("test_obj", wr_cmpext_cmpl.get(), &wr_op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, wr_cmpext_cmpl->wait_for_complete());
- }
- EXPECT_EQ(0, wr_cmpext_cmpl->get_return_value());
- EXPECT_EQ(0, ret);
-
- boost::scoped_ptr<AioCompletion>
- wr_cmpext_cmpl2(cluster.aio_create_completion(0, 0, 0));
- cbl.clear();
- cbl.append(miscmp_buf, sizeof(miscmp_buf));
- ret = 0;
-
- wr_op.cmpext(0, cbl, &ret);
- wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ioctx.aio_operate("test_obj", wr_cmpext_cmpl2.get(), &wr_op);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, wr_cmpext_cmpl2->wait_for_complete());
- }
- EXPECT_EQ(-MAX_ERRNO, wr_cmpext_cmpl2->get_return_value());
- EXPECT_EQ(-MAX_ERRNO, ret);
-
- /* cmpext as read op */
- boost::scoped_ptr<AioCompletion>
- rd_cmpext_cmpl(cluster.aio_create_completion(0, 0, 0));
- ObjectReadOperation rd_op;
- cbl.clear();
- cbl.append(buf, sizeof(buf));
- ret = 0;
- rd_op.cmpext(0, cbl, &ret);
- rd_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ioctx.aio_operate("test_obj", rd_cmpext_cmpl.get(), &rd_op, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, rd_cmpext_cmpl->wait_for_complete());
- }
- EXPECT_EQ(0, rd_cmpext_cmpl->get_return_value());
- EXPECT_EQ(0, ret);
-
- boost::scoped_ptr<AioCompletion>
- rd_cmpext_cmpl2(cluster.aio_create_completion(0, 0, 0));
- cbl.clear();
- cbl.append(miscmp_buf, sizeof(miscmp_buf));
- ret = 0;
-
- rd_op.cmpext(0, cbl, &ret);
- rd_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ioctx.aio_operate("test_obj", rd_cmpext_cmpl2.get(), &rd_op, 0);
- {
- TestAlarm alarm;
- ASSERT_EQ(0, rd_cmpext_cmpl2->wait_for_complete());
- }
- EXPECT_EQ(-MAX_ERRNO, rd_cmpext_cmpl2->get_return_value());
- EXPECT_EQ(-MAX_ERRNO, ret);
-
- ioctx.remove("test_obj");
- destroy_one_pool_pp(pool_name, cluster);
-}
diff --git a/src/test/librados/aio_cxx.cc b/src/test/librados/aio_cxx.cc
new file mode 100644
index 00000000000..b812930766b
--- /dev/null
+++ b/src/test/librados/aio_cxx.cc
@@ -0,0 +1,2443 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <boost/scoped_ptr.hpp>
+
+#include "gtest/gtest.h"
+
+#include "common/errno.h"
+#include "include/err.h"
+#include "include/rados/librados.hpp"
+#include "include/types.h"
+#include "include/stringify.h"
+#include "include/scope_guard.h"
+
+#include "test_cxx.h"
+
+using namespace librados;
+using std::pair;
+using std::ostringstream;
+
+class AioTestDataPP
+{
+public:
+ AioTestDataPP()
+ : m_init(false)
+ {
+ }
+
+ ~AioTestDataPP()
+ {
+ if (m_init) {
+ m_ioctx.close();
+ destroy_one_pool_pp(m_pool_name, m_cluster);
+ }
+ }
+
+ std::string init()
+ {
+ return init({});
+ }
+
+ std::string init(const std::map<std::string, std::string> &config)
+ {
+ int ret;
+
+ m_pool_name = get_temp_pool_name();
+ std::string err = create_one_pool_pp(m_pool_name, m_cluster, config);
+ if (!err.empty()) {
+ ostringstream oss;
+ oss << "create_one_pool(" << m_pool_name << ") failed: error " << err;
+ return oss.str();
+ }
+ ret = m_cluster.ioctx_create(m_pool_name.c_str(), m_ioctx);
+ if (ret) {
+ destroy_one_pool_pp(m_pool_name, m_cluster);
+ ostringstream oss;
+ oss << "rados_ioctx_create failed: error " << ret;
+ return oss.str();
+ }
+ m_init = true;
+ return "";
+ }
+
+ Rados m_cluster;
+ IoCtx m_ioctx;
+ std::string m_pool_name;
+ bool m_init;
+};
+
+TEST(LibRadosAio, TooBigPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+
+ bufferlist bl;
+ AioCompletion *aio_completion = test_data.m_cluster.aio_create_completion(nullptr, NULL, NULL);
+ ASSERT_EQ(-E2BIG, test_data.m_ioctx.aio_write("foo", aio_completion, bl, UINT_MAX, 0));
+ ASSERT_EQ(-E2BIG, test_data.m_ioctx.aio_append("foo", aio_completion, bl, UINT_MAX));
+ // ioctx.aio_write_full no way to overflow bl.length()
+ delete aio_completion;
+}
+
+TEST(LibRadosAio, PoolQuotaPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ string p = get_temp_pool_name();
+ ASSERT_EQ(0, test_data.m_cluster.pool_create(p.c_str()));
+ IoCtx ioctx;
+ ASSERT_EQ(0, test_data.m_cluster.ioctx_create(p.c_str(), ioctx));
+ ioctx.application_enable("rados", true);
+
+ bufferlist inbl;
+ ASSERT_EQ(0, test_data.m_cluster.mon_command(
+ "{\"prefix\": \"osd pool set-quota\", \"pool\": \"" + p +
+ "\", \"field\": \"max_bytes\", \"val\": \"4096\"}",
+ inbl, NULL, NULL));
+
+ bufferlist bl;
+ bufferptr z(4096);
+ bl.append(z);
+ int n;
+ for (n = 0; n < 1024; ++n) {
+ ObjectWriteOperation op;
+ op.write_full(bl);
+ librados::AioCompletion *completion =
+ test_data.m_cluster.aio_create_completion();
+ ASSERT_EQ(0, ioctx.aio_operate(
+ "foo" + stringify(n), completion, &op,
+ librados::OPERATION_FULL_TRY));
+ completion->wait_for_safe();
+ int r = completion->get_return_value();
+ completion->release();
+ if (r == -EDQUOT)
+ break;
+ ASSERT_EQ(0, r);
+ sleep(1);
+ }
+ ASSERT_LT(n, 1024);
+
+ // make sure we have latest map that marked the pool full
+ test_data.m_cluster.wait_for_latest_osdmap();
+
+ // make sure we block without FULL_TRY
+ {
+ ObjectWriteOperation op;
+ op.write_full(bl);
+ librados::AioCompletion *completion =
+ test_data.m_cluster.aio_create_completion();
+ ASSERT_EQ(0, ioctx.aio_operate("bar", completion, &op, 0));
+ sleep(5);
+ ASSERT_FALSE(completion->is_safe());
+ completion->release();
+ }
+
+ ioctx.close();
+ ASSERT_EQ(0, test_data.m_cluster.pool_delete(p.c_str()));
+}
+
+TEST(LibRadosAio, SimpleWritePP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
+ my_completion, bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ delete my_completion;
+ }
+
+ {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ test_data.m_ioctx.set_namespace("nspace");
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
+ my_completion, bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ delete my_completion;
+ }
+}
+
+TEST(LibRadosAio, WaitForSafePP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
+ my_completion, bl1, sizeof(buf), 0));
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_safe());
+ ASSERT_EQ(0, my_completion->get_return_value());
+ delete my_completion;
+}
+
+TEST(LibRadosAio, RoundTripPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
+ my_completion2, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAio, RoundTripPP2) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
+ my_completion2, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_safe());
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+}
+
+//using ObjectWriteOperation/ObjectReadOperation with iohint
+TEST(LibRadosAio, RoundTripPP3)
+{
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ op.write(0, bl);
+ op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ioctx.aio_operate("test_obj", my_completion1.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion1->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion1->get_return_value());
+
+ boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
+ bl.clear();
+ ObjectReadOperation op1;
+ op1.read(0, sizeof(buf), &bl, NULL);
+ op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
+ bufferlist init_value_bl;
+ encode(static_cast<int32_t>(-1), init_value_bl);
+ bufferlist csum_bl;
+ op1.checksum(LIBRADOS_CHECKSUM_TYPE_CRC32C, init_value_bl,
+ 0, 0, 0, &csum_bl, nullptr);
+ ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
+
+ ASSERT_EQ(8U, csum_bl.length());
+ auto csum_bl_it = csum_bl.cbegin();
+ uint32_t csum_count;
+ uint32_t csum;
+ decode(csum_count, csum_bl_it);
+ ASSERT_EQ(1U, csum_count);
+ decode(csum, csum_bl_it);
+ ASSERT_EQ(bl.crc32c(-1), csum);
+ ioctx.remove("test_obj");
+ destroy_one_pool_pp(pool_name, cluster);
+}
+
+TEST(LibRadosAio, RoundTripSparseReadPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ std::map<uint64_t, uint64_t> extents;
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_sparse_read("foo",
+ my_completion2, &extents, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ assert_eq_sparse(bl1, extents, bl2);
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAioPP, XattrsRoundTripPP) {
+ char buf[128];
+ char attr1[] = "attr1";
+ char attr1_buf[] = "foo bar baz";
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
+ bufferlist bl2;
+ // async getxattr
+ boost::scoped_ptr<AioCompletion> my_completion
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr("foo", my_completion.get(), attr1, bl2));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(-ENODATA, my_completion->get_return_value());
+ // append
+ bufferlist bl3;
+ bl3.append(attr1_buf, sizeof(attr1_buf));
+ // async setxattr
+ AioTestDataPP test_data2;
+ ASSERT_EQ("", test_data2.init());
+ boost::scoped_ptr<AioCompletion> my_completion2
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr("foo", my_completion2.get(), attr1, bl3));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ // async getxattr
+ bufferlist bl4;
+ AioTestDataPP test_data3;
+ ASSERT_EQ("", test_data3.init());
+ boost::scoped_ptr<AioCompletion> my_completion3
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr("foo", my_completion3.get(), attr1, bl4));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(attr1_buf), my_completion3->get_return_value());
+ // check content of attribute
+ ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
+}
+
+TEST(LibRadosAioPP, RmXattrPP) {
+ char buf[128];
+ char attr1[] = "attr1";
+ char attr1_buf[] = "foo bar baz";
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
+ // async setxattr
+ bufferlist bl2;
+ bl2.append(attr1_buf, sizeof(attr1_buf));
+ boost::scoped_ptr<AioCompletion> my_completion
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr("foo", my_completion.get(), attr1, bl2));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ // async rmxattr
+ AioTestDataPP test_data2;
+ ASSERT_EQ("", test_data2.init());
+ boost::scoped_ptr<AioCompletion> my_completion2
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_rmxattr("foo", my_completion2.get(), attr1));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ // async getxattr
+ AioTestDataPP test_data3;
+ ASSERT_EQ("", test_data3.init());
+ boost::scoped_ptr<AioCompletion> my_completion3
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ bufferlist bl3;
+ ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr("foo", my_completion3.get(), attr1, bl3));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ(-ENODATA, my_completion3->get_return_value());
+ // Test rmxattr on a removed object
+ char buf2[128];
+ char attr2[] = "attr2";
+ char attr2_buf[] = "foo bar baz";
+ memset(buf2, 0xbb, sizeof(buf2));
+ bufferlist bl21;
+ bl21.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
+ bufferlist bl22;
+ bl22.append(attr2_buf, sizeof(attr2_buf));
+ // async setxattr
+ AioTestDataPP test_data4;
+ ASSERT_EQ("", test_data4.init());
+ boost::scoped_ptr<AioCompletion> my_completion4
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr("foo_rmxattr", my_completion4.get(), attr2, bl22));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion4->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion4->get_return_value());
+ // remove object
+ ASSERT_EQ(0, test_data.m_ioctx.remove("foo_rmxattr"));
+ // async rmxattr on non existing object
+ AioTestDataPP test_data5;
+ ASSERT_EQ("", test_data5.init());
+ boost::scoped_ptr<AioCompletion> my_completion5
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_rmxattr("foo_rmxattr", my_completion5.get(), attr2));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion5->wait_for_complete());
+ }
+ ASSERT_EQ(-ENOENT, my_completion5->get_return_value());
+}
+
+TEST(LibRadosIoPP, XattrListPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ // create an object with 2 attributes
+ char buf[128];
+ char attr1[] = "attr1";
+ char attr1_buf[] = "foo bar baz";
+ char attr2[] = "attr2";
+ char attr2_buf[256];
+ for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
+ attr2_buf[j] = j % 0xff;
+ }
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
+ bufferlist bl2;
+ bl2.append(attr1_buf, sizeof(attr1_buf));
+ ASSERT_EQ(0, test_data.m_ioctx.setxattr("foo", attr1, bl2));
+ bufferlist bl3;
+ bl3.append(attr2_buf, sizeof(attr2_buf));
+ ASSERT_EQ(0, test_data.m_ioctx.setxattr("foo", attr2, bl3));
+ // call async version of getxattrs
+ boost::scoped_ptr<AioCompletion> my_completion
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ std::map<std::string, bufferlist> attrset;
+ ASSERT_EQ(0, test_data.m_ioctx.aio_getxattrs("foo", my_completion.get(), attrset));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
+ i != attrset.end(); ++i) {
+ if (i->first == string(attr1)) {
+ ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
+ }
+ else if (i->first == string(attr2)) {
+ ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
+ }
+ else {
+ ASSERT_EQ(0, 1);
+ }
+ }
+}
+
+TEST(LibRadosAio, IsCompletePP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
+ &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+
+ // Busy-wait until the AIO completes.
+ // Normally we wouldn't do this, but we want to test is_complete.
+ while (true) {
+ int is_complete = my_completion2->is_complete();
+ if (is_complete)
+ break;
+ }
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAio, IsSafePP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+
+ // Busy-wait until the AIO completes.
+ // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
+ while (true) {
+ int is_safe = my_completion->is_safe();
+ if (is_safe)
+ break;
+ }
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ bufferlist bl2;
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
+ &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAio, ReturnValuePP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ bufferlist bl1;
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("nonexistent",
+ my_completion, &bl1, 128, 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(-ENOENT, my_completion->get_return_value());
+ delete my_completion;
+}
+
+TEST(LibRadosAio, FlushPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xee, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_flush());
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
+ &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAio, FlushAsyncPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *flush_completion =
+ test_data.m_cluster.aio_create_completion(NULL, NULL, NULL);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xee, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_flush_async(flush_completion));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, flush_completion->wait_for_complete());
+ ASSERT_EQ(0, flush_completion->wait_for_safe());
+ }
+ ASSERT_EQ(1, my_completion->is_complete());
+ ASSERT_EQ(1, my_completion->is_safe());
+ ASSERT_EQ(1, flush_completion->is_complete());
+ ASSERT_EQ(1, flush_completion->is_safe());
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
+ &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+ delete flush_completion;
+}
+
+TEST(LibRadosAio, RoundTripWriteFullPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ char buf2[64];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write_full("foo", my_completion2, bl2));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ bufferlist bl3;
+ AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion3, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
+ &bl3, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf2), my_completion3->get_return_value());
+ ASSERT_EQ(sizeof(buf2), bl3.length());
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
+ delete my_completion;
+ delete my_completion2;
+ delete my_completion3;
+}
+
+//using ObjectWriteOperation/ObjectReadOperation with iohint
+TEST(LibRadosAio, RoundTripWriteFullPP2)
+{
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf);
+
+ op.write_full(bl);
+ op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ioctx.aio_operate("test_obj", my_completion1.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion1->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion1->get_return_value());
+
+ boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
+ bl.clear();
+ ObjectReadOperation op1;
+ op1.read(0, sizeof(buf), &bl, NULL);
+ op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
+ ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
+
+ ioctx.remove("test_obj");
+ destroy_one_pool_pp(pool_name, cluster);
+}
+
+TEST(LibRadosAio, RoundTripWriteSamePP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char full[128];
+ memset(full, 0xcc, sizeof(full));
+ bufferlist bl1;
+ bl1.append(full, sizeof(full));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(full), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ /* write the same buf four times */
+ char buf[32];
+ size_t ws_write_len = sizeof(full);
+ memset(buf, 0xdd, sizeof(buf));
+ bufferlist bl2;
+ bl2.append(buf, sizeof(buf));
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_writesame("foo", my_completion2, bl2,
+ ws_write_len, 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ bufferlist bl3;
+ AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion3, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
+ &bl3, sizeof(full), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(full), my_completion3->get_return_value());
+ ASSERT_EQ(sizeof(full), bl3.length());
+ for (char *cmp = bl3.c_str(); cmp < bl3.c_str() + bl3.length();
+ cmp += sizeof(buf)) {
+ ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
+ }
+ delete my_completion;
+ delete my_completion2;
+ delete my_completion3;
+}
+
+TEST(LibRadosAio, RoundTripWriteSamePP2)
+{
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ boost::scoped_ptr<AioCompletion>
+ wr_cmpl(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ op.writesame(0, sizeof(buf) * 4, bl);
+ op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ioctx.aio_operate("test_obj", wr_cmpl.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, wr_cmpl->wait_for_complete());
+ }
+ EXPECT_EQ(0, wr_cmpl->get_return_value());
+
+ boost::scoped_ptr<AioCompletion>
+ rd_cmpl(cluster.aio_create_completion(0, 0, 0));
+ char *cmp;
+ char full[sizeof(buf) * 4];
+ memset(full, 0, sizeof(full));
+ bufferlist fl;
+ fl.append(full, sizeof(full));
+ ObjectReadOperation op1;
+ op1.read(0, sizeof(full), &fl, NULL);
+ op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ioctx.aio_operate("test_obj", rd_cmpl.get(), &op1, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, rd_cmpl->wait_for_complete());
+ }
+ EXPECT_EQ(0, rd_cmpl->get_return_value());
+ for (cmp = fl.c_str(); cmp < fl.c_str() + fl.length(); cmp += sizeof(buf)) {
+ ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
+ }
+
+ ioctx.remove("test_obj");
+ destroy_one_pool_pp(pool_name, cluster);
+}
+
+TEST(LibRadosAio, SimpleStatPPNS) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ uint64_t psize;
+ time_t pmtime;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
+ &psize, &pmtime));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), psize);
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAio, SimpleStatPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ uint64_t psize;
+ time_t pmtime;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
+ &psize, &pmtime));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), psize);
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAio, StatRemovePP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ uint64_t psize;
+ time_t pmtime;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
+ &psize, &pmtime));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), psize);
+ uint64_t psize2;
+ time_t pmtime2;
+ AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion3, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion3));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion3->get_return_value());
+
+ AioCompletion *my_completion4 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion4, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion4,
+ &psize2, &pmtime2));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion4->wait_for_complete());
+ }
+ ASSERT_EQ(-ENOENT, my_completion4->get_return_value());
+ delete my_completion;
+ delete my_completion2;
+ delete my_completion3;
+ delete my_completion4;
+}
+
+TEST(LibRadosAio, ExecuteClassPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ bufferlist in, out;
+ ASSERT_EQ(0, test_data.m_ioctx.aio_exec("foo", my_completion2,
+ "hello", "say_hello", in, &out));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
+ delete my_completion;
+ delete my_completion2;
+}
+
+using std::string;
+using std::map;
+using std::set;
+
+TEST(LibRadosAio, OmapPP) {
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ string header_str = "baz";
+ bufferptr bp(header_str.c_str(), header_str.size() + 1);
+ bufferlist header_to_set;
+ header_to_set.push_back(bp);
+ map<string, bufferlist> to_set;
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ to_set["foo"] = header_to_set;
+ to_set["foo2"] = header_to_set;
+ to_set["qfoo3"] = header_to_set;
+ op.omap_set(to_set);
+
+ op.omap_set_header(header_to_set);
+
+ ioctx.aio_operate("test_obj", my_completion.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion->get_return_value());
+ }
+
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectReadOperation op;
+ map<string, pair<bufferlist, int> > assertions;
+ bufferlist val;
+ val.append(string("bar"));
+ assertions["foo"] = pair<bufferlist, int>(val, CEPH_OSD_CMPXATTR_OP_EQ);
+
+ int r;
+ op.omap_cmp(assertions, &r);
+
+ ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(-ECANCELED, my_completion->get_return_value());
+ ASSERT_EQ(-ECANCELED, r);
+ }
+
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectReadOperation op;
+
+ set<string> set_got;
+ map<string, bufferlist> map_got;
+
+ set<string> to_get;
+ map<string, bufferlist> got3;
+
+ map<string, bufferlist> got4;
+
+ bufferlist header;
+
+ op.omap_get_keys2("", 1, &set_got, nullptr, 0);
+ op.omap_get_vals2("foo", 1, &map_got, nullptr, 0);
+
+ to_get.insert("foo");
+ to_get.insert("qfoo3");
+ op.omap_get_vals_by_keys(to_get, &got3, 0);
+
+ op.omap_get_header(&header, 0);
+
+ op.omap_get_vals2("foo2", "q", 1, &got4, nullptr, 0);
+
+ ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion->get_return_value());
+
+ ASSERT_EQ(header.length(), header_to_set.length());
+ ASSERT_EQ(set_got.size(), (unsigned)1);
+ ASSERT_EQ(*set_got.begin(), "foo");
+ ASSERT_EQ(map_got.size(), (unsigned)1);
+ ASSERT_EQ(map_got.begin()->first, "foo2");
+ ASSERT_EQ(got3.size(), (unsigned)2);
+ ASSERT_EQ(got3.begin()->first, "foo");
+ ASSERT_EQ(got3.rbegin()->first, "qfoo3");
+ ASSERT_EQ(got4.size(), (unsigned)1);
+ ASSERT_EQ(got4.begin()->first, "qfoo3");
+ }
+
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ set<string> to_remove;
+ to_remove.insert("foo2");
+ op.omap_rm_keys(to_remove);
+ ioctx.aio_operate("test_obj", my_completion.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion->get_return_value());
+ }
+
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectReadOperation op;
+
+ set<string> set_got;
+ op.omap_get_keys2("", -1, &set_got, nullptr, 0);
+ ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion->get_return_value());
+ ASSERT_EQ(set_got.size(), (unsigned)2);
+ }
+
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ op.omap_clear();
+ ioctx.aio_operate("test_obj", my_completion.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion->get_return_value());
+ }
+
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectReadOperation op;
+
+ set<string> set_got;
+ op.omap_get_keys2("", -1, &set_got, nullptr, 0);
+ ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion->get_return_value());
+ ASSERT_EQ(set_got.size(), (unsigned)0);
+ }
+
+ // omap_clear clears header *and* keys
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ bufferlist bl;
+ bl.append("some data");
+ map<string,bufferlist> to_set;
+ to_set["foo"] = bl;
+ to_set["foo2"] = bl;
+ to_set["qfoo3"] = bl;
+ op.omap_set(to_set);
+ op.omap_set_header(bl);
+ ioctx.aio_operate("foo3", my_completion.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion->get_return_value());
+ }
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ op.omap_clear();
+ ioctx.aio_operate("foo3", my_completion.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion->get_return_value());
+ }
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectReadOperation op;
+ set<string> set_got;
+ bufferlist hdr;
+ op.omap_get_keys2("", -1, &set_got, nullptr, 0);
+ op.omap_get_header(&hdr, NULL);
+ ioctx.aio_operate("foo3", my_completion.get(), &op, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion->get_return_value());
+ ASSERT_EQ(set_got.size(), (unsigned)0);
+ ASSERT_EQ(hdr.length(), 0u);
+ }
+
+ ioctx.remove("test_obj");
+ destroy_one_pool_pp(pool_name, cluster);
+}
+
+TEST(LibRadosAio, MultiWritePP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+
+ char buf2[64];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion2,
+ bl2, sizeof(buf2), sizeof(buf)));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+
+ bufferlist bl3;
+ AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion3, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
+ &bl3, (sizeof(buf) + sizeof(buf2) * 3), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ((int)(sizeof(buf) + sizeof(buf2)), my_completion3->get_return_value());
+ ASSERT_EQ(sizeof(buf) + sizeof(buf2), bl3.length());
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf), buf2, sizeof(buf2)));
+ delete my_completion;
+ delete my_completion2;
+ delete my_completion3;
+}
+
+TEST(LibRadosAio, AioUnlockPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ ASSERT_EQ(0, test_data.m_ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
+ boost::scoped_ptr<AioCompletion> my_completion
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_unlock("foo", "TestLock", "Cookie", my_completion.get()));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ ASSERT_EQ(0, test_data.m_ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
+}
+
+class AioTestDataECPP
+{
+public:
+ AioTestDataECPP()
+ : m_init(false)
+ {}
+
+ ~AioTestDataECPP()
+ {
+ if (m_init) {
+ m_ioctx.close();
+ destroy_one_ec_pool_pp(m_pool_name, m_cluster);
+ }
+ }
+
+ std::string init()
+ {
+ int ret;
+ m_pool_name = get_temp_pool_name();
+ std::string err = create_one_ec_pool_pp(m_pool_name, m_cluster);
+ if (!err.empty()) {
+ ostringstream oss;
+ oss << "create_one_ec_pool(" << m_pool_name << ") failed: error " << err;
+ return oss.str();
+ }
+ ret = m_cluster.ioctx_create(m_pool_name.c_str(), m_ioctx);
+ if (ret) {
+ destroy_one_ec_pool_pp(m_pool_name, m_cluster);
+ ostringstream oss;
+ oss << "rados_ioctx_create failed: error " << ret;
+ return oss.str();
+ }
+ m_init = true;
+ return "";
+ }
+
+ Rados m_cluster;
+ IoCtx m_ioctx;
+ std::string m_pool_name;
+ bool m_init;
+};
+
+// EC test cases
+TEST(LibRadosAioEC, SimpleWritePP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
+ my_completion, bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ delete my_completion;
+ }
+
+ {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ test_data.m_ioctx.set_namespace("nspace");
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
+ my_completion, bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ delete my_completion;
+ }
+}
+
+TEST(LibRadosAioEC, WaitForSafePP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
+ my_completion, bl1, sizeof(buf), 0));
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_safe());
+ ASSERT_EQ(0, my_completion->get_return_value());
+ delete my_completion;
+}
+
+TEST(LibRadosAioEC, RoundTripPP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
+ my_completion2, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAioEC, RoundTripPP2) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
+ my_completion2, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_safe());
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+}
+
+//using ObjectWriteOperation/ObjectReadOperation with iohint
+TEST(LibRadosAioEC, RoundTripPP3)
+{
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf);
+
+ op.write(0, bl);
+ op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ioctx.aio_operate("test_obj", my_completion1.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion1->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion1->get_return_value());
+
+ boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
+ bl.clear();
+ ObjectReadOperation op1;
+ op1.read(0, sizeof(buf), &bl, NULL);
+ op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
+ ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
+
+ ioctx.remove("test_obj");
+ destroy_one_pool_pp(pool_name, cluster);
+}
+
+TEST(LibRadosAio, RoundTripAppendPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion,
+ bl1, sizeof(buf)));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ char buf2[128];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion2,
+ bl2, sizeof(buf2)));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ bufferlist bl3;
+ AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion3, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
+ my_completion3, &bl3, 2 * sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ((int)(sizeof(buf) * 2), my_completion3->get_return_value());
+ ASSERT_EQ(sizeof(buf) * 2, bl3.length());
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf), buf2, sizeof(buf2)));
+ delete my_completion;
+ delete my_completion2;
+ delete my_completion3;
+}
+
+TEST(LibRadosAioPP, RemoveTestPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
+ boost::scoped_ptr<AioCompletion> my_completion
+ (test_data.m_cluster.aio_create_completion
+ (nullptr, nullptr, nullptr));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion.get()));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ ASSERT_EQ(-ENOENT, test_data.m_ioctx.read("foo", bl2, sizeof(buf), 0));
+}
+
+TEST(LibRadosAioEC, RoundTripSparseReadPP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+
+ map<uint64_t, uint64_t> extents;
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_sparse_read("foo",
+ my_completion2, &extents, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ assert_eq_sparse(bl1, extents, bl2);
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAioEC, RoundTripAppendPP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ bool requires;
+ ASSERT_EQ(0, test_data.m_ioctx.pool_requires_alignment2(&requires));
+ ASSERT_TRUE(requires);
+ uint64_t alignment;
+ ASSERT_EQ(0, test_data.m_ioctx.pool_required_alignment2(&alignment));
+ ASSERT_NE((unsigned)0, alignment);
+ int bsize = alignment;
+ char *buf = (char *)new char[bsize];
+ memset(buf, 0xcc, bsize);
+ bufferlist bl1;
+ bl1.append(buf, bsize);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion,
+ bl1, bsize));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+
+ int hbsize = bsize / 2;
+ char *buf2 = (char *)new char[hbsize];
+ memset(buf2, 0xdd, hbsize);
+ bufferlist bl2;
+ bl2.append(buf2, hbsize);
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion2,
+ bl2, hbsize));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+
+ AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion3, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion3,
+ bl2, hbsize));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ EXPECT_EQ(-EOPNOTSUPP, my_completion3->get_return_value());
+
+ bufferlist bl3;
+ AioCompletion *my_completion4 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion4, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
+ my_completion4, &bl3, bsize * 3, 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion4->wait_for_complete());
+ }
+ int tbsize = bsize + hbsize;
+ ASSERT_EQ(tbsize, my_completion4->get_return_value());
+ ASSERT_EQ((unsigned)tbsize, bl3.length());
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
+ ASSERT_EQ(0, memcmp(bl3.c_str() + bsize, buf2, hbsize));
+ delete my_completion;
+ delete my_completion2;
+ delete my_completion3;
+ delete[] buf;
+ delete[] buf2;
+}
+
+TEST(LibRadosAioEC, IsCompletePP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
+ &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+
+ // Busy-wait until the AIO completes.
+ // Normally we wouldn't do this, but we want to test is_complete.
+ while (true) {
+ int is_complete = my_completion2->is_complete();
+ if (is_complete)
+ break;
+ }
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+}
+TEST(LibRadosAioEC, IsSafePP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+
+ // Busy-wait until the AIO completes.
+ // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
+ while (true) {
+ int is_safe = my_completion->is_safe();
+ if (is_safe)
+ break;
+ }
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ bufferlist bl2;
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
+ &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAioEC, ReturnValuePP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ bufferlist bl1;
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("nonexistent",
+ my_completion, &bl1, 128, 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(-ENOENT, my_completion->get_return_value());
+ delete my_completion;
+}
+
+TEST(LibRadosAioEC, FlushPP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xee, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_flush());
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
+ &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAioEC, FlushAsyncPP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *flush_completion =
+ test_data.m_cluster.aio_create_completion(NULL, NULL, NULL);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xee, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_flush_async(flush_completion));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, flush_completion->wait_for_complete());
+ ASSERT_EQ(0, flush_completion->wait_for_safe());
+ }
+ ASSERT_EQ(1, my_completion->is_complete());
+ ASSERT_EQ(1, my_completion->is_safe());
+ ASSERT_EQ(1, flush_completion->is_complete());
+ ASSERT_EQ(1, flush_completion->is_safe());
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
+ &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl2.length());
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+ delete flush_completion;
+}
+
+TEST(LibRadosAioEC, RoundTripWriteFullPP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ char buf2[64];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write_full("foo", my_completion2, bl2));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ bufferlist bl3;
+ AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion3, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
+ &bl3, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf2), my_completion3->get_return_value());
+ ASSERT_EQ(sizeof(buf2), bl3.length());
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
+ delete my_completion;
+ delete my_completion2;
+ delete my_completion3;
+}
+
+//using ObjectWriteOperation/ObjectReadOperation with iohint
+TEST(LibRadosAioEC, RoundTripWriteFullPP2)
+{
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf);
+
+ op.write_full(bl);
+ op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
+ ioctx.aio_operate("test_obj", my_completion1.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion1->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion1->get_return_value());
+
+ boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
+ bl.clear();
+ ObjectReadOperation op1;
+ op1.read(0, sizeof(buf), &bl, NULL);
+ op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
+ ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ EXPECT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
+
+ ioctx.remove("test_obj");
+ destroy_one_pool_pp(pool_name, cluster);
+}
+
+TEST(LibRadosAioEC, SimpleStatPP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ uint64_t psize;
+ time_t pmtime;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
+ &psize, &pmtime));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), psize);
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAioEC, SimpleStatPPNS) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ uint64_t psize;
+ time_t pmtime;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
+ &psize, &pmtime));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), psize);
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAioEC, StatRemovePP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ uint64_t psize;
+ time_t pmtime;
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
+ &psize, &pmtime));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(sizeof(buf), psize);
+ uint64_t psize2;
+ time_t pmtime2;
+ AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion3, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion3));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion3->get_return_value());
+
+ AioCompletion *my_completion4 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion4, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion4,
+ &psize2, &pmtime2));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion4->wait_for_complete());
+ }
+ ASSERT_EQ(-ENOENT, my_completion4->get_return_value());
+ delete my_completion;
+ delete my_completion2;
+ delete my_completion3;
+ delete my_completion4;
+}
+
+TEST(LibRadosAioEC, ExecuteClassPP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ bufferlist in, out;
+ ASSERT_EQ(0, test_data.m_ioctx.aio_exec("foo", my_completion2,
+ "hello", "say_hello", in, &out));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+ ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAioEC, OmapPP) {
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_ec_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ string header_str = "baz";
+ bufferptr bp(header_str.c_str(), header_str.size() + 1);
+ bufferlist header_to_set;
+ header_to_set.push_back(bp);
+ map<string, bufferlist> to_set;
+ {
+ boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation op;
+ to_set["foo"] = header_to_set;
+ to_set["foo2"] = header_to_set;
+ to_set["qfoo3"] = header_to_set;
+ op.omap_set(to_set);
+
+ op.omap_set_header(header_to_set);
+
+ ioctx.aio_operate("test_obj", my_completion.get(), &op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ EXPECT_EQ(-EOPNOTSUPP, my_completion->get_return_value());
+ }
+ ioctx.remove("test_obj");
+ destroy_one_pool_pp(pool_name, cluster);
+}
+
+TEST(LibRadosAioEC, MultiWritePP) {
+ AioTestDataECPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+
+ char buf2[64];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion2,
+ bl2, sizeof(buf2), sizeof(buf)));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(-EOPNOTSUPP, my_completion2->get_return_value());
+
+ bufferlist bl3;
+ AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion3, my_completion_null);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
+ &bl3, (sizeof(buf) + sizeof(buf2) * 3), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ((int)sizeof(buf), my_completion3->get_return_value());
+ ASSERT_EQ(sizeof(buf), bl3.length());
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
+ delete my_completion;
+ delete my_completion2;
+ delete my_completion3;
+}
+
+TEST(LibRadosAio, RacingRemovePP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init({{"objecter_retry_writes_after_first_reply", "true"}}));
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion, nullptr);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_NE(my_completion2, nullptr);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion2));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ my_completion2->wait_for_complete();
+ my_completion->wait_for_complete();
+ }
+ ASSERT_EQ(-ENOENT, my_completion2->get_return_value());
+ ASSERT_EQ(0, my_completion->get_return_value());
+ ASSERT_EQ(0, test_data.m_ioctx.stat("foo", nullptr, nullptr));
+ delete my_completion;
+ delete my_completion2;
+}
+
+TEST(LibRadosAio, RoundTripCmpExtPP) {
+ AioTestDataPP test_data;
+ ASSERT_EQ("", test_data.init());
+ AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+ char full[128];
+ memset(full, 0xcc, sizeof(full));
+ bufferlist bl1;
+ bl1.append(full, sizeof(full));
+ ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
+ bl1, sizeof(full), 0));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+
+ /* compare with match */
+ bufferlist cbl;
+ cbl.append(full, sizeof(full));
+ AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_cmpext("foo", my_completion2, 0, cbl));
+
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion2->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion2->get_return_value());
+
+ /* compare with mismatch */
+ memset(full, 0xdd, sizeof(full));
+ cbl.clear();
+ cbl.append(full, sizeof(full));
+ AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
+ nullptr, nullptr, nullptr);
+ ASSERT_EQ(0, test_data.m_ioctx.aio_cmpext("foo", my_completion3, 0, cbl));
+
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion3->wait_for_complete());
+ }
+ ASSERT_EQ(-MAX_ERRNO, my_completion3->get_return_value());
+
+ delete my_completion;
+ delete my_completion2;
+ delete my_completion3;
+}
+
+TEST(LibRadosAio, RoundTripCmpExtPP2)
+{
+ int ret;
+ char buf[128];
+ char miscmp_buf[128];
+ bufferlist cbl;
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+ boost::scoped_ptr<AioCompletion>
+ wr_cmpl(cluster.aio_create_completion(0, 0, 0));
+ ObjectWriteOperation wr_op;
+ memset(buf, 0xcc, sizeof(buf));
+ memset(miscmp_buf, 0xdd, sizeof(miscmp_buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ wr_op.write_full(bl);
+ wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ioctx.aio_operate("test_obj", wr_cmpl.get(), &wr_op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, wr_cmpl->wait_for_complete());
+ }
+ EXPECT_EQ(0, wr_cmpl->get_return_value());
+
+ /* cmpext as write op. first match then mismatch */
+ boost::scoped_ptr<AioCompletion>
+ wr_cmpext_cmpl(cluster.aio_create_completion(0, 0, 0));
+ cbl.append(buf, sizeof(buf));
+ ret = 0;
+
+ wr_op.cmpext(0, cbl, &ret);
+ wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ioctx.aio_operate("test_obj", wr_cmpext_cmpl.get(), &wr_op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, wr_cmpext_cmpl->wait_for_complete());
+ }
+ EXPECT_EQ(0, wr_cmpext_cmpl->get_return_value());
+ EXPECT_EQ(0, ret);
+
+ boost::scoped_ptr<AioCompletion>
+ wr_cmpext_cmpl2(cluster.aio_create_completion(0, 0, 0));
+ cbl.clear();
+ cbl.append(miscmp_buf, sizeof(miscmp_buf));
+ ret = 0;
+
+ wr_op.cmpext(0, cbl, &ret);
+ wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ioctx.aio_operate("test_obj", wr_cmpext_cmpl2.get(), &wr_op);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, wr_cmpext_cmpl2->wait_for_complete());
+ }
+ EXPECT_EQ(-MAX_ERRNO, wr_cmpext_cmpl2->get_return_value());
+ EXPECT_EQ(-MAX_ERRNO, ret);
+
+ /* cmpext as read op */
+ boost::scoped_ptr<AioCompletion>
+ rd_cmpext_cmpl(cluster.aio_create_completion(0, 0, 0));
+ ObjectReadOperation rd_op;
+ cbl.clear();
+ cbl.append(buf, sizeof(buf));
+ ret = 0;
+ rd_op.cmpext(0, cbl, &ret);
+ rd_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ioctx.aio_operate("test_obj", rd_cmpext_cmpl.get(), &rd_op, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, rd_cmpext_cmpl->wait_for_complete());
+ }
+ EXPECT_EQ(0, rd_cmpext_cmpl->get_return_value());
+ EXPECT_EQ(0, ret);
+
+ boost::scoped_ptr<AioCompletion>
+ rd_cmpext_cmpl2(cluster.aio_create_completion(0, 0, 0));
+ cbl.clear();
+ cbl.append(miscmp_buf, sizeof(miscmp_buf));
+ ret = 0;
+
+ rd_op.cmpext(0, cbl, &ret);
+ rd_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ioctx.aio_operate("test_obj", rd_cmpext_cmpl2.get(), &rd_op, 0);
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, rd_cmpext_cmpl2->wait_for_complete());
+ }
+ EXPECT_EQ(-MAX_ERRNO, rd_cmpext_cmpl2->get_return_value());
+ EXPECT_EQ(-MAX_ERRNO, ret);
+
+ ioctx.remove("test_obj");
+ destroy_one_pool_pp(pool_name, cluster);
+}
diff --git a/src/test/librados/c_write_operations.cc b/src/test/librados/c_write_operations.cc
index 325a2f0a3e0..558d0942f93 100644
--- a/src/test/librados/c_write_operations.cc
+++ b/src/test/librados/c_write_operations.cc
@@ -1,10 +1,10 @@
// Tests for the C API coverage of atomic write operations
#include <errno.h>
+#include "gtest/gtest.h"
#include "include/err.h"
#include "include/rados/librados.h"
#include "test/librados/test.h"
-#include "gtest/gtest.h"
TEST(LibradosCWriteOps, NewDelete) {
rados_write_op_t op = rados_create_write_op();
diff --git a/src/test/librados/cls.cc b/src/test/librados/cls.cc
index 10744b2b9b8..c4f24954dbe 100644
--- a/src/test/librados/cls.cc
+++ b/src/test/librados/cls.cc
@@ -1,13 +1,13 @@
-#include "include/rados/librados.h"
-#include "include/rados/librados.hpp"
-#include "test/librados/test.h"
-
-#include "gtest/gtest.h"
#include <errno.h>
#include <map>
#include <sstream>
#include <string>
+#include "gtest/gtest.h"
+
+#include "include/rados/librados.hpp"
+#include "test/librados/test_cxx.h"
+
using namespace librados;
using std::map;
using std::ostringstream;
diff --git a/src/test/librados/cmd.cc b/src/test/librados/cmd.cc
index 043d98328f5..49465c3bcce 100644
--- a/src/test/librados/cmd.cc
+++ b/src/test/librados/cmd.cc
@@ -13,7 +13,6 @@
#include <sstream>
#include <string>
-using namespace librados;
using std::map;
using std::ostringstream;
using std::string;
@@ -88,18 +87,6 @@ TEST(LibRadosCmd, MonDescribe) {
rados_shutdown(cluster);
}
-TEST(LibRadosCmd, MonDescribePP) {
- Rados cluster;
- ASSERT_EQ("", connect_cluster_pp(cluster));
- bufferlist inbl, outbl;
- string outs;
- ASSERT_EQ(0, cluster.mon_command("{\"prefix\": \"get_command_descriptions\"}",
- inbl, &outbl, &outs));
- ASSERT_LT(0u, outbl.length());
- ASSERT_LE(0u, outs.length());
- cluster.shutdown();
-}
-
TEST(LibRadosCmd, OSDCmd) {
rados_t cluster;
ASSERT_EQ("", connect_cluster(&cluster));
@@ -128,27 +115,6 @@ TEST(LibRadosCmd, OSDCmd) {
rados_shutdown(cluster);
}
-TEST(LibRadosCmd, OSDCmdPP) {
- Rados cluster;
- ASSERT_EQ("", connect_cluster_pp(cluster));
- int r;
- bufferlist inbl, outbl;
- string outs;
- string cmd;
-
- // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
- cmd = "asdfasdf";
- r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
- ASSERT_TRUE(r == -22 || r == -ENXIO);
- cmd = "version";
- r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
- ASSERT_TRUE(r == -22 || r == -ENXIO);
- cmd = "{\"prefix\":\"version\"}";
- r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
- ASSERT_TRUE((r == 0 && outbl.length() > 0) || (r == -ENXIO && outbl.length() == 0));
- cluster.shutdown();
-}
-
TEST(LibRadosCmd, PGCmd) {
rados_t cluster;
std::string pool_name = get_temp_pool_name();
@@ -193,45 +159,6 @@ TEST(LibRadosCmd, PGCmd) {
ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
}
-TEST(LibRadosCmd, PGCmdPP) {
- Rados cluster;
- std::string pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
-
- int r;
- bufferlist inbl, outbl;
- string outs;
- string cmd;
-
- int64_t poolid = cluster.pool_lookup(pool_name.c_str());
- ASSERT_LT(0, poolid);
-
- string pgid = stringify(poolid) + ".0";
-
- cmd = "asdfasdf";
- // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
- r = cluster.pg_command(pgid.c_str(), cmd, inbl, &outbl, &outs);
- ASSERT_TRUE(r == -22 || r == -ENXIO);
-
- // make sure the pg exists on the osd before we query it
- IoCtx io;
- cluster.ioctx_create(pool_name.c_str(), io);
- for (int i=0; i<100; i++) {
- string oid = "obj" + stringify(i);
- ASSERT_EQ(-ENOENT, io.stat(oid, NULL, NULL));
- }
- io.close();
-
- cmd = "{\"prefix\":\"pg\", \"cmd\":\"query\", \"pgid\":\"" + pgid + "\"}";
- // note: tolerate ENOENT/ENXIO here if hte osd is thrashing out underneath us
- r = cluster.pg_command(pgid.c_str(), cmd, inbl, &outbl, &outs);
- ASSERT_TRUE(r == 0 || r == -ENOENT || r == -ENXIO);
-
- ASSERT_LT(0u, outbl.length());
-
- ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
-}
-
struct Log {
list<string> log;
std::condition_variable cond;
diff --git a/src/test/librados/cmd_cxx.cc b/src/test/librados/cmd_cxx.cc
new file mode 100644
index 00000000000..d67e2613b31
--- /dev/null
+++ b/src/test/librados/cmd_cxx.cc
@@ -0,0 +1,92 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <errno.h>
+#include <condition_variable>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include "gtest/gtest.h"
+
+#include "include/rados/librados.hpp"
+#include "include/stringify.h"
+#include "test/librados/test_cxx.h"
+
+using namespace librados;
+using std::map;
+using std::ostringstream;
+using std::string;
+
+TEST(LibRadosCmd, MonDescribePP) {
+ Rados cluster;
+ ASSERT_EQ("", connect_cluster_pp(cluster));
+ bufferlist inbl, outbl;
+ string outs;
+ ASSERT_EQ(0, cluster.mon_command("{\"prefix\": \"get_command_descriptions\"}",
+ inbl, &outbl, &outs));
+ ASSERT_LT(0u, outbl.length());
+ ASSERT_LE(0u, outs.length());
+ cluster.shutdown();
+}
+
+TEST(LibRadosCmd, OSDCmdPP) {
+ Rados cluster;
+ ASSERT_EQ("", connect_cluster_pp(cluster));
+ int r;
+ bufferlist inbl, outbl;
+ string outs;
+ string cmd;
+
+ // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
+ cmd = "asdfasdf";
+ r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
+ ASSERT_TRUE(r == -22 || r == -ENXIO);
+ cmd = "version";
+ r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
+ ASSERT_TRUE(r == -22 || r == -ENXIO);
+ cmd = "{\"prefix\":\"version\"}";
+ r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
+ ASSERT_TRUE((r == 0 && outbl.length() > 0) || (r == -ENXIO && outbl.length() == 0));
+ cluster.shutdown();
+}
+
+TEST(LibRadosCmd, PGCmdPP) {
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+
+ int r;
+ bufferlist inbl, outbl;
+ string outs;
+ string cmd;
+
+ int64_t poolid = cluster.pool_lookup(pool_name.c_str());
+ ASSERT_LT(0, poolid);
+
+ string pgid = stringify(poolid) + ".0";
+
+ cmd = "asdfasdf";
+ // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
+ r = cluster.pg_command(pgid.c_str(), cmd, inbl, &outbl, &outs);
+ ASSERT_TRUE(r == -22 || r == -ENXIO);
+
+ // make sure the pg exists on the osd before we query it
+ IoCtx io;
+ cluster.ioctx_create(pool_name.c_str(), io);
+ for (int i=0; i<100; i++) {
+ string oid = "obj" + stringify(i);
+ ASSERT_EQ(-ENOENT, io.stat(oid, NULL, NULL));
+ }
+ io.close();
+
+ cmd = "{\"prefix\":\"pg\", \"cmd\":\"query\", \"pgid\":\"" + pgid + "\"}";
+ // note: tolerate ENOENT/ENXIO here if hte osd is thrashing out underneath us
+ r = cluster.pg_command(pgid.c_str(), cmd, inbl, &outbl, &outs);
+ ASSERT_TRUE(r == 0 || r == -ENOENT || r == -ENXIO);
+
+ ASSERT_LT(0u, outbl.length());
+
+ ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
+}
+
diff --git a/src/test/librados/io.cc b/src/test/librados/io.cc
index 9e56c79a603..fce3de62122 100644
--- a/src/test/librados/io.cc
+++ b/src/test/librados/io.cc
@@ -4,7 +4,6 @@
#include <climits>
#include "include/rados/librados.h"
-#include "include/rados/librados.hpp"
#include "include/encoding.h"
#include "include/err.h"
#include "include/scope_guard.h"
@@ -14,13 +13,10 @@
#include <errno.h>
#include "gtest/gtest.h"
-using namespace librados;
using std::string;
typedef RadosTest LibRadosIo;
typedef RadosTestEC LibRadosIoEC;
-typedef RadosTestPP LibRadosIoPP;
-typedef RadosTestECPP LibRadosIoECPP;
TEST_F(LibRadosIo, SimpleWrite) {
char buf[128];
@@ -36,12 +32,6 @@ TEST_F(LibRadosIo, TooBig) {
ASSERT_EQ(-E2BIG, rados_append(ioctx, "A", buf, UINT_MAX));
ASSERT_EQ(-E2BIG, rados_write_full(ioctx, "A", buf, UINT_MAX));
ASSERT_EQ(-E2BIG, rados_writesame(ioctx, "A", buf, sizeof(buf), UINT_MAX, 0));
- IoCtx ioctx;
- bufferlist bl;
- ASSERT_EQ(-E2BIG, ioctx.write("foo", bl, UINT_MAX, 0));
- ASSERT_EQ(-E2BIG, ioctx.append("foo", bl, UINT_MAX));
- // ioctx.write_full no way to overflow bl.length()
- ASSERT_EQ(-E2BIG, ioctx.writesame("foo", bl, UINT_MAX, 0));
}
TEST_F(LibRadosIo, ReadTimeout) {
@@ -96,165 +86,6 @@ TEST_F(LibRadosIo, ReadTimeout) {
}
}
-TEST_F(LibRadosIoPP, SimpleWritePP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- ioctx.set_namespace("nspace");
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
-}
-
-TEST_F(LibRadosIoPP, ReadOpPP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
-
- {
- bufferlist op_bl;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), NULL, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist op_bl;
- ObjectReadOperation op;
- op.read(0, 0, NULL, NULL); //len=0 mean read the whole object data.
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist read_bl, op_bl;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), read_bl.length());
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist op_bl;
- int rval = 1000;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), NULL, &rval);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, rval);
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist read_bl, op_bl;
- int rval = 1000;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl, &rval);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), read_bl.length());
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, rval);
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist read_bl1, read_bl2, op_bl;
- int rval1 = 1000, rval2 = 1002;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl1, &rval1);
- op.read(0, sizeof(buf), &read_bl2, &rval2);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), read_bl1.length());
- ASSERT_EQ(sizeof(buf), read_bl2.length());
- ASSERT_EQ(sizeof(buf) * 2, op_bl.length());
- ASSERT_EQ(0, rval1);
- ASSERT_EQ(0, rval2);
- ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(op_bl.c_str() + sizeof(buf), buf, sizeof(buf)));
- }
-
- {
- bufferlist op_bl;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), NULL, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist read_bl;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
- ASSERT_EQ(sizeof(buf), read_bl.length());
- ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- int rval = 1000;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), NULL, &rval);
- ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
- ASSERT_EQ(0, rval);
- }
-
- {
- bufferlist read_bl;
- int rval = 1000;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl, &rval);
- ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
- ASSERT_EQ(sizeof(buf), read_bl.length());
- ASSERT_EQ(0, rval);
- ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist read_bl1, read_bl2;
- int rval1 = 1000, rval2 = 1002;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl1, &rval1);
- op.read(0, sizeof(buf), &read_bl2, &rval2);
- ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
- ASSERT_EQ(sizeof(buf), read_bl1.length());
- ASSERT_EQ(sizeof(buf), read_bl2.length());
- ASSERT_EQ(0, rval1);
- ASSERT_EQ(0, rval2);
- ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
- }
-}
-
-TEST_F(LibRadosIoPP, SparseReadOpPP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
-
- {
- std::map<uint64_t, uint64_t> extents;
- bufferlist read_bl;
- int rval = -1;
- ObjectReadOperation op;
- op.sparse_read(0, sizeof(buf), &extents, &read_bl, &rval);
- ASSERT_EQ(0, ioctx.operate("foo", &op, nullptr));
- ASSERT_EQ(0, rval);
- assert_eq_sparse(bl, extents, read_bl);
- }
-}
TEST_F(LibRadosIo, RoundTrip) {
char buf[128];
@@ -273,34 +104,6 @@ TEST_F(LibRadosIo, RoundTrip) {
ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
}
-TEST_F(LibRadosIoPP, RoundTripPP) {
- char buf[128];
- Rados cluster;
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- bufferlist cl;
- ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", cl, sizeof(buf), 0));
- ASSERT_EQ(0, memcmp(buf, cl.c_str(), sizeof(buf)));
-}
-
-TEST_F(LibRadosIoPP, RoundTripPP2)
-{
- bufferlist bl;
- bl.append("ceph");
- ObjectWriteOperation write;
- write.write(0, bl);
- write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ASSERT_EQ(0, ioctx.operate("foo", &write));
-
- ObjectReadOperation read;
- read.read(0, bl.length(), NULL, NULL);
- read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
- ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
- ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
-}
-
TEST_F(LibRadosIo, Checksum) {
char buf[128];
memset(buf, 0xcc, sizeof(buf));
@@ -318,27 +121,6 @@ TEST_F(LibRadosIo, Checksum) {
ASSERT_EQ(expected_crc, crc[1]);
}
-TEST_F(LibRadosIoPP, Checksum) {
- char buf[128];
- Rados cluster;
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- bufferlist init_value_bl;
- encode(static_cast<uint32_t>(-1), init_value_bl);
- bufferlist csum_bl;
- ASSERT_EQ(0, ioctx.checksum("foo", LIBRADOS_CHECKSUM_TYPE_CRC32C,
- init_value_bl, sizeof(buf), 0, 0, &csum_bl));
- auto csum_bl_it = csum_bl.cbegin();
- uint32_t csum_count;
- decode(csum_count, csum_bl_it);
- ASSERT_EQ(1U, csum_count);
- uint32_t csum;
- decode(csum, csum_bl_it);
- ASSERT_EQ(bl.crc32c(-1), csum);
-}
-
TEST_F(LibRadosIo, OverlappingWriteRoundTrip) {
char buf[128];
char buf2[64];
@@ -353,23 +135,6 @@ TEST_F(LibRadosIo, OverlappingWriteRoundTrip) {
ASSERT_EQ(0, memcmp(buf3 + sizeof(buf2), buf, sizeof(buf) - sizeof(buf2)));
}
-TEST_F(LibRadosIoPP, OverlappingWriteRoundTripPP) {
- char buf[128];
- char buf2[64];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), 0));
- bufferlist bl3;
- ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
- ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf2), buf, sizeof(buf) - sizeof(buf2)));
-}
-
TEST_F(LibRadosIo, WriteFullRoundTrip) {
char buf[128];
char buf2[64];
@@ -383,38 +148,6 @@ TEST_F(LibRadosIo, WriteFullRoundTrip) {
ASSERT_EQ(0, memcmp(buf2, buf3, sizeof(buf2)));
}
-TEST_F(LibRadosIoPP, WriteFullRoundTripPP) {
- char buf[128];
- char buf2[64];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- ASSERT_EQ(0, ioctx.write_full("foo", bl2));
- bufferlist bl3;
- ASSERT_EQ((int)sizeof(buf2), ioctx.read("foo", bl3, sizeof(buf), 0));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
-}
-
-TEST_F(LibRadosIoPP, WriteFullRoundTripPP2)
-{
- bufferlist bl;
- bl.append("ceph");
- ObjectWriteOperation write;
- write.write_full(bl);
- write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
- ASSERT_EQ(0, ioctx.operate("foo", &write));
-
- ObjectReadOperation read;
- read.read(0, bl.length(), NULL, NULL);
- read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
- ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
- ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
-}
-
TEST_F(LibRadosIo, AppendRoundTrip) {
char buf[64];
char buf2[64];
@@ -429,25 +162,6 @@ TEST_F(LibRadosIo, AppendRoundTrip) {
ASSERT_EQ(0, memcmp(buf3 + sizeof(buf), buf2, sizeof(buf2)));
}
-TEST_F(LibRadosIoPP, AppendRoundTripPP) {
- char buf[64];
- char buf2[64];
- memset(buf, 0xde, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
- memset(buf2, 0xad, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- ASSERT_EQ(0, ioctx.append("foo", bl2, sizeof(buf2)));
- bufferlist bl3;
- ASSERT_EQ((int)(sizeof(buf) + sizeof(buf2)),
- ioctx.read("foo", bl3, (sizeof(buf) + sizeof(buf2)), 0));
- const char *bl3_str = bl3.c_str();
- ASSERT_EQ(0, memcmp(bl3_str, buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(bl3_str + sizeof(buf), buf2, sizeof(buf2)));
-}
-
TEST_F(LibRadosIo, TruncTest) {
char buf[128];
char buf2[sizeof(buf)];
@@ -459,18 +173,6 @@ TEST_F(LibRadosIo, TruncTest) {
ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)/2));
}
-TEST_F(LibRadosIoPP, TruncTestPP) {
- char buf[128];
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl, sizeof(buf)));
- ASSERT_EQ(0, ioctx.trunc("foo", sizeof(buf) / 2));
- bufferlist bl2;
- ASSERT_EQ((int)(sizeof(buf)/2), ioctx.read("foo", bl2, sizeof(buf), 0));
- ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)/2));
-}
-
TEST_F(LibRadosIo, RemoveTest) {
char buf[128];
char buf2[sizeof(buf)];
@@ -481,17 +183,6 @@ TEST_F(LibRadosIo, RemoveTest) {
ASSERT_EQ(-ENOENT, rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
}
-TEST_F(LibRadosIoPP, RemoveTestPP) {
- char buf[128];
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
- ASSERT_EQ(0, ioctx.remove("foo"));
- bufferlist bl2;
- ASSERT_EQ(-ENOENT, ioctx.read("foo", bl2, sizeof(buf), 0));
-}
-
TEST_F(LibRadosIo, XattrsRoundTrip) {
char buf[128];
char attr1[] = "attr1";
@@ -505,25 +196,6 @@ TEST_F(LibRadosIo, XattrsRoundTrip) {
ASSERT_EQ(0, memcmp(attr1_buf, buf, sizeof(attr1_buf)));
}
-TEST_F(LibRadosIoPP, XattrsRoundTripPP) {
- char buf[128];
- char attr1[] = "attr1";
- char attr1_buf[] = "foo bar baz";
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
- bufferlist bl2;
- ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl2));
- bufferlist bl3;
- bl3.append(attr1_buf, sizeof(attr1_buf));
- ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl3));
- bufferlist bl4;
- ASSERT_EQ((int)sizeof(attr1_buf),
- ioctx.getxattr("foo", attr1, bl4));
- ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
-}
-
TEST_F(LibRadosIo, RmXattr) {
char buf[128];
char attr1[] = "attr1";
@@ -547,36 +219,6 @@ TEST_F(LibRadosIo, RmXattr) {
ASSERT_EQ(-ENOENT, rados_rmxattr(ioctx, "foo_rmxattr", attr2));
}
-TEST_F(LibRadosIoPP, RmXattrPP) {
- char buf[128];
- char attr1[] = "attr1";
- char attr1_buf[] = "foo bar baz";
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
- bufferlist bl2;
- bl2.append(attr1_buf, sizeof(attr1_buf));
- ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
- ASSERT_EQ(0, ioctx.rmxattr("foo", attr1));
- bufferlist bl3;
- ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl3));
-
- // Test rmxattr on a removed object
- char buf2[128];
- char attr2[] = "attr2";
- char attr2_buf[] = "foo bar baz";
- memset(buf2, 0xbb, sizeof(buf2));
- bufferlist bl21;
- bl21.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
- bufferlist bl22;
- bl22.append(attr2_buf, sizeof(attr2_buf));
- ASSERT_EQ(0, ioctx.setxattr("foo_rmxattr", attr2, bl22));
- ASSERT_EQ(0, ioctx.remove("foo_rmxattr"));
- ASSERT_EQ(-ENOENT, ioctx.rmxattr("foo_rmxattr", attr2));
-}
-
TEST_F(LibRadosIo, XattrIter) {
char buf[128];
char attr1[] = "attr1";
@@ -617,41 +259,6 @@ TEST_F(LibRadosIo, XattrIter) {
rados_getxattrs_end(iter);
}
-TEST_F(LibRadosIoPP, XattrListPP) {
- char buf[128];
- char attr1[] = "attr1";
- char attr1_buf[] = "foo bar baz";
- char attr2[] = "attr2";
- char attr2_buf[256];
- for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
- attr2_buf[j] = j % 0xff;
- }
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
- bufferlist bl2;
- bl2.append(attr1_buf, sizeof(attr1_buf));
- ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
- bufferlist bl3;
- bl3.append(attr2_buf, sizeof(attr2_buf));
- ASSERT_EQ(0, ioctx.setxattr("foo", attr2, bl3));
- std::map<std::string, bufferlist> attrset;
- ASSERT_EQ(0, ioctx.getxattrs("foo", attrset));
- for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
- i != attrset.end(); ++i) {
- if (i->first == string(attr1)) {
- ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
- }
- else if (i->first == string(attr2)) {
- ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
- }
- else {
- ASSERT_EQ(0, 1);
- }
- }
-}
-
TEST_F(LibRadosIoEC, SimpleWrite) {
char buf[128];
memset(buf, 0xcc, sizeof(buf));
@@ -660,166 +267,6 @@ TEST_F(LibRadosIoEC, SimpleWrite) {
ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
}
-TEST_F(LibRadosIoECPP, SimpleWritePP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- ioctx.set_namespace("nspace");
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
-}
-
-TEST_F(LibRadosIoECPP, ReadOpPP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
-
- {
- bufferlist op_bl;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), NULL, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist op_bl;
- ObjectReadOperation op;
- op.read(0, 0, NULL, NULL); //len=0 mean read the whole object data
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist read_bl, op_bl;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), read_bl.length());
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist op_bl;
- int rval = 1000;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), NULL, &rval);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, rval);
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist read_bl, op_bl;
- int rval = 1000;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl, &rval);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), read_bl.length());
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, rval);
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist read_bl1, read_bl2, op_bl;
- int rval1 = 1000, rval2 = 1002;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl1, &rval1);
- op.read(0, sizeof(buf), &read_bl2, &rval2);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), read_bl1.length());
- ASSERT_EQ(sizeof(buf), read_bl2.length());
- ASSERT_EQ(sizeof(buf) * 2, op_bl.length());
- ASSERT_EQ(0, rval1);
- ASSERT_EQ(0, rval2);
- ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(op_bl.c_str() + sizeof(buf), buf, sizeof(buf)));
- }
-
- {
- bufferlist op_bl;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), NULL, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
- ASSERT_EQ(sizeof(buf), op_bl.length());
- ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist read_bl;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
- ASSERT_EQ(sizeof(buf), read_bl.length());
- ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- int rval = 1000;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), NULL, &rval);
- ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
- ASSERT_EQ(0, rval);
- }
-
- {
- bufferlist read_bl;
- int rval = 1000;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl, &rval);
- ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
- ASSERT_EQ(sizeof(buf), read_bl.length());
- ASSERT_EQ(0, rval);
- ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
- }
-
- {
- bufferlist read_bl1, read_bl2;
- int rval1 = 1000, rval2 = 1002;
- ObjectReadOperation op;
- op.read(0, sizeof(buf), &read_bl1, &rval1);
- op.read(0, sizeof(buf), &read_bl2, &rval2);
- ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
- ASSERT_EQ(sizeof(buf), read_bl1.length());
- ASSERT_EQ(sizeof(buf), read_bl2.length());
- ASSERT_EQ(0, rval1);
- ASSERT_EQ(0, rval2);
- ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
- ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
- }
-}
-
-TEST_F(LibRadosIoECPP, SparseReadOpPP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
-
- {
- std::map<uint64_t, uint64_t> extents;
- bufferlist read_bl;
- int rval = -1;
- ObjectReadOperation op;
- op.sparse_read(0, sizeof(buf), &extents, &read_bl, &rval);
- ASSERT_EQ(0, ioctx.operate("foo", &op, nullptr));
- ASSERT_EQ(0, rval);
- assert_eq_sparse(bl, extents, read_bl);
- }
-}
-
TEST_F(LibRadosIoEC, RoundTrip) {
char buf[128];
char buf2[128];
@@ -833,34 +280,6 @@ TEST_F(LibRadosIoEC, RoundTrip) {
ASSERT_EQ(-EOPNOTSUPP, rados_write(ioctx, "bar", buf, sizeof(buf), off));
}
-TEST_F(LibRadosIoECPP, RoundTripPP) {
- char buf[128];
- Rados cluster;
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- bufferlist cl;
- ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", cl, sizeof(buf) * 3, 0));
- ASSERT_EQ(0, memcmp(buf, cl.c_str(), sizeof(buf)));
-}
-
-TEST_F(LibRadosIoECPP, RoundTripPP2)
-{
- bufferlist bl;
- bl.append("ceph");
- ObjectWriteOperation write;
- write.write(0, bl);
- write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ASSERT_EQ(0, ioctx.operate("foo", &write));
-
- ObjectReadOperation read;
- read.read(0, bl.length(), NULL, NULL);
- read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
- ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
- ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
-}
-
TEST_F(LibRadosIoEC, OverlappingWriteRoundTrip) {
int bsize = alignment;
int dbsize = bsize * 2;
@@ -883,30 +302,6 @@ TEST_F(LibRadosIoEC, OverlappingWriteRoundTrip) {
ASSERT_EQ(0, memcmp(buf3, buf, dbsize));
}
-TEST_F(LibRadosIoECPP, OverlappingWriteRoundTripPP) {
- int bsize = alignment;
- int dbsize = bsize * 2;
- char *buf = (char *)new char[dbsize];
- char *buf2 = (char *)new char[bsize];
- auto cleanup = [&] {
- delete[] buf;
- delete[] buf2;
- };
- scope_guard<decltype(cleanup)> sg(std::move(cleanup));
- memset(buf, 0xcc, dbsize);
- bufferlist bl1;
- bl1.append(buf, dbsize);
- ASSERT_EQ(0, ioctx.write("foo", bl1, dbsize, 0));
- memset(buf2, 0xdd, bsize);
- bufferlist bl2;
- bl2.append(buf2, bsize);
- ASSERT_EQ(-EOPNOTSUPP, ioctx.write("foo", bl2, bsize, 0));
- bufferlist bl3;
- ASSERT_EQ(dbsize, ioctx.read("foo", bl3, dbsize, 0));
- // Read the same as first write
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, dbsize));
-}
-
TEST_F(LibRadosIoEC, WriteFullRoundTrip) {
char buf[128];
char buf2[64];
@@ -920,38 +315,6 @@ TEST_F(LibRadosIoEC, WriteFullRoundTrip) {
ASSERT_EQ(0, memcmp(buf3, buf2, sizeof(buf2)));
}
-TEST_F(LibRadosIoECPP, WriteFullRoundTripPP) {
- char buf[128];
- char buf2[64];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- ASSERT_EQ(0, ioctx.write_full("foo", bl2));
- bufferlist bl3;
- ASSERT_EQ((int)sizeof(buf2), ioctx.read("foo", bl3, sizeof(buf), 0));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
-}
-
-TEST_F(LibRadosIoECPP, WriteFullRoundTripPP2)
-{
- bufferlist bl;
- bl.append("ceph");
- ObjectWriteOperation write;
- write.write_full(bl);
- write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ASSERT_EQ(0, ioctx.operate("foo", &write));
-
- ObjectReadOperation read;
- read.read(0, bl.length(), NULL, NULL);
- read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
- ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
- ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
-}
-
TEST_F(LibRadosIoEC, AppendRoundTrip) {
char *buf = (char *)new char[alignment];
char *buf2 = (char *)new char[alignment];
@@ -978,30 +341,6 @@ TEST_F(LibRadosIoEC, AppendRoundTrip) {
ASSERT_EQ(-EOPNOTSUPP, rados_append(ioctx, "foo", unalignedbuf, uasize));
}
-TEST_F(LibRadosIoECPP, AppendRoundTripPP) {
- char *buf = (char *)new char[alignment];
- char *buf2 = (char *)new char[alignment];
- auto cleanup = [&] {
- delete[] buf;
- delete[] buf2;
- };
- scope_guard<decltype(cleanup)> sg(std::move(cleanup));
- memset(buf, 0xde, alignment);
- bufferlist bl1;
- bl1.append(buf, alignment);
- ASSERT_EQ(0, ioctx.append("foo", bl1, alignment));
- memset(buf2, 0xad, alignment);
- bufferlist bl2;
- bl2.append(buf2, alignment);
- ASSERT_EQ(0, ioctx.append("foo", bl2, alignment));
- bufferlist bl3;
- ASSERT_EQ((int)(alignment * 2),
- ioctx.read("foo", bl3, (alignment * 4), 0));
- const char *bl3_str = bl3.c_str();
- ASSERT_EQ(0, memcmp(bl3_str, buf, alignment));
- ASSERT_EQ(0, memcmp(bl3_str + alignment, buf2, alignment));
-}
-
TEST_F(LibRadosIoEC, TruncTest) {
char buf[128];
char buf2[sizeof(buf)];
@@ -1015,20 +354,6 @@ TEST_F(LibRadosIoEC, TruncTest) {
ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
}
-TEST_F(LibRadosIoECPP, TruncTestPP) {
- char buf[128];
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl, sizeof(buf)));
- ASSERT_EQ(-EOPNOTSUPP, ioctx.trunc("foo", sizeof(buf) / 2));
- bufferlist bl2;
- // Same size
- ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl2, sizeof(buf), 0));
- // No change
- ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)));
-}
-
TEST_F(LibRadosIoEC, RemoveTest) {
char buf[128];
char buf2[sizeof(buf)];
@@ -1039,17 +364,6 @@ TEST_F(LibRadosIoEC, RemoveTest) {
ASSERT_EQ(-ENOENT, rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
}
-TEST_F(LibRadosIoECPP, RemoveTestPP) {
- char buf[128];
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
- ASSERT_EQ(0, ioctx.remove("foo"));
- bufferlist bl2;
- ASSERT_EQ(-ENOENT, ioctx.read("foo", bl2, sizeof(buf), 0));
-}
-
TEST_F(LibRadosIoEC, XattrsRoundTrip) {
char buf[128];
char attr1[] = "attr1";
@@ -1063,25 +377,6 @@ TEST_F(LibRadosIoEC, XattrsRoundTrip) {
ASSERT_EQ(0, memcmp(attr1_buf, buf, sizeof(attr1_buf)));
}
-TEST_F(LibRadosIoECPP, XattrsRoundTripPP) {
- char buf[128];
- char attr1[] = "attr1";
- char attr1_buf[] = "foo bar baz";
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
- bufferlist bl2;
- ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl2));
- bufferlist bl3;
- bl3.append(attr1_buf, sizeof(attr1_buf));
- ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl3));
- bufferlist bl4;
- ASSERT_EQ((int)sizeof(attr1_buf),
- ioctx.getxattr("foo", attr1, bl4));
- ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
-}
-
TEST_F(LibRadosIoEC, RmXattr) {
char buf[128];
char attr1[] = "attr1";
@@ -1105,36 +400,6 @@ TEST_F(LibRadosIoEC, RmXattr) {
ASSERT_EQ(-ENOENT, rados_rmxattr(ioctx, "foo_rmxattr", attr2));
}
-TEST_F(LibRadosIoECPP, RmXattrPP) {
- char buf[128];
- char attr1[] = "attr1";
- char attr1_buf[] = "foo bar baz";
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
- bufferlist bl2;
- bl2.append(attr1_buf, sizeof(attr1_buf));
- ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
- ASSERT_EQ(0, ioctx.rmxattr("foo", attr1));
- bufferlist bl3;
- ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl3));
-
- // Test rmxattr on a removed object
- char buf2[128];
- char attr2[] = "attr2";
- char attr2_buf[] = "foo bar baz";
- memset(buf2, 0xbb, sizeof(buf2));
- bufferlist bl21;
- bl21.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
- bufferlist bl22;
- bl22.append(attr2_buf, sizeof(attr2_buf));
- ASSERT_EQ(0, ioctx.setxattr("foo_rmxattr", attr2, bl22));
- ASSERT_EQ(0, ioctx.remove("foo_rmxattr"));
- ASSERT_EQ(-ENOENT, ioctx.rmxattr("foo_rmxattr", attr2));
-}
-
TEST_F(LibRadosIoEC, XattrIter) {
char buf[128];
char attr1[] = "attr1";
@@ -1174,152 +439,3 @@ TEST_F(LibRadosIoEC, XattrIter) {
}
rados_getxattrs_end(iter);
}
-
-TEST_F(LibRadosIoECPP, XattrListPP) {
- char buf[128];
- char attr1[] = "attr1";
- char attr1_buf[] = "foo bar baz";
- char attr2[] = "attr2";
- char attr2_buf[256];
- for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
- attr2_buf[j] = j % 0xff;
- }
- memset(buf, 0xaa, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
- bufferlist bl2;
- bl2.append(attr1_buf, sizeof(attr1_buf));
- ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
- bufferlist bl3;
- bl3.append(attr2_buf, sizeof(attr2_buf));
- ASSERT_EQ(0, ioctx.setxattr("foo", attr2, bl3));
- std::map<std::string, bufferlist> attrset;
- ASSERT_EQ(0, ioctx.getxattrs("foo", attrset));
- for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
- i != attrset.end(); ++i) {
- if (i->first == string(attr1)) {
- ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
- }
- else if (i->first == string(attr2)) {
- ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
- }
- else {
- ASSERT_EQ(0, 1);
- }
- }
-}
-
-TEST_F(LibRadosIoPP, CmpExtPP) {
- bufferlist bl;
- bl.append("ceph");
- ObjectWriteOperation write1;
- write1.write(0, bl);
- ASSERT_EQ(0, ioctx.operate("foo", &write1));
-
- bufferlist new_bl;
- new_bl.append("CEPH");
- ObjectWriteOperation write2;
- write2.cmpext(0, bl, nullptr);
- write2.write(0, new_bl);
- ASSERT_EQ(0, ioctx.operate("foo", &write2));
-
- ObjectReadOperation read;
- read.read(0, bl.length(), NULL, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
- ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
-}
-
-TEST_F(LibRadosIoPP, CmpExtDNEPP) {
- bufferlist bl;
- bl.append(std::string(4, '\0'));
-
- bufferlist new_bl;
- new_bl.append("CEPH");
- ObjectWriteOperation write;
- write.cmpext(0, bl, nullptr);
- write.write(0, new_bl);
- ASSERT_EQ(0, ioctx.operate("foo", &write));
-
- ObjectReadOperation read;
- read.read(0, bl.length(), NULL, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
- ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
-}
-
-TEST_F(LibRadosIoPP, CmpExtMismatchPP) {
- bufferlist bl;
- bl.append("ceph");
- ObjectWriteOperation write1;
- write1.write(0, bl);
- ASSERT_EQ(0, ioctx.operate("foo", &write1));
-
- bufferlist new_bl;
- new_bl.append("CEPH");
- ObjectWriteOperation write2;
- write2.cmpext(0, new_bl, nullptr);
- write2.write(0, new_bl);
- ASSERT_EQ(-MAX_ERRNO, ioctx.operate("foo", &write2));
-
- ObjectReadOperation read;
- read.read(0, bl.length(), NULL, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
- ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
-}
-
-TEST_F(LibRadosIoECPP, CmpExtPP) {
- bufferlist bl;
- bl.append("ceph");
- ObjectWriteOperation write1;
- write1.write(0, bl);
- ASSERT_EQ(0, ioctx.operate("foo", &write1));
-
- bufferlist new_bl;
- new_bl.append("CEPH");
- ObjectWriteOperation write2;
- write2.cmpext(0, bl, nullptr);
- write2.write_full(new_bl);
- ASSERT_EQ(0, ioctx.operate("foo", &write2));
-
- ObjectReadOperation read;
- read.read(0, bl.length(), NULL, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
- ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
-}
-
-TEST_F(LibRadosIoECPP, CmpExtDNEPP) {
- bufferlist bl;
- bl.append(std::string(4, '\0'));
-
- bufferlist new_bl;
- new_bl.append("CEPH");
- ObjectWriteOperation write;
- write.cmpext(0, bl, nullptr);
- write.write_full(new_bl);
- ASSERT_EQ(0, ioctx.operate("foo", &write));
-
- ObjectReadOperation read;
- read.read(0, bl.length(), NULL, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
- ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
-}
-
-TEST_F(LibRadosIoECPP, CmpExtMismatchPP) {
- bufferlist bl;
- bl.append("ceph");
- ObjectWriteOperation write1;
- write1.write(0, bl);
- ASSERT_EQ(0, ioctx.operate("foo", &write1));
-
- bufferlist new_bl;
- new_bl.append("CEPH");
- ObjectWriteOperation write2;
- write2.cmpext(0, new_bl, nullptr);
- write2.write_full(new_bl);
- ASSERT_EQ(-MAX_ERRNO, ioctx.operate("foo", &write2));
-
- ObjectReadOperation read;
- read.read(0, bl.length(), NULL, NULL);
- ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
- ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
-}
diff --git a/src/test/librados/io_cxx.cc b/src/test/librados/io_cxx.cc
new file mode 100644
index 00000000000..5930849100b
--- /dev/null
+++ b/src/test/librados/io_cxx.cc
@@ -0,0 +1,904 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*
+// vim: ts=8 sw=2 smarttab
+
+#include <climits>
+#include <errno.h>
+
+#include "gtest/gtest.h"
+
+#include "include/rados/librados.hpp"
+#include "include/encoding.h"
+#include "include/err.h"
+#include "include/scope_guard.h"
+#include "test/librados/test_cxx.h"
+#include "test/librados/testcase_cxx.h"
+
+using namespace librados;
+using std::string;
+
+typedef RadosTestPP LibRadosIoPP;
+typedef RadosTestECPP LibRadosIoECPP;
+
+TEST_F(LibRadosIoPP, TooBigPP) {
+ IoCtx ioctx;
+ bufferlist bl;
+ ASSERT_EQ(-E2BIG, ioctx.write("foo", bl, UINT_MAX, 0));
+ ASSERT_EQ(-E2BIG, ioctx.append("foo", bl, UINT_MAX));
+ // ioctx.write_full no way to overflow bl.length()
+ ASSERT_EQ(-E2BIG, ioctx.writesame("foo", bl, UINT_MAX, 0));
+}
+
+TEST_F(LibRadosIoPP, SimpleWritePP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ ioctx.set_namespace("nspace");
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+}
+
+TEST_F(LibRadosIoPP, ReadOpPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+
+ {
+ bufferlist op_bl;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), NULL, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist op_bl;
+ ObjectReadOperation op;
+ op.read(0, 0, NULL, NULL); //len=0 mean read the whole object data.
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist read_bl, op_bl;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), read_bl.length());
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist op_bl;
+ int rval = 1000;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), NULL, &rval);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, rval);
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist read_bl, op_bl;
+ int rval = 1000;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl, &rval);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), read_bl.length());
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, rval);
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist read_bl1, read_bl2, op_bl;
+ int rval1 = 1000, rval2 = 1002;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl1, &rval1);
+ op.read(0, sizeof(buf), &read_bl2, &rval2);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), read_bl1.length());
+ ASSERT_EQ(sizeof(buf), read_bl2.length());
+ ASSERT_EQ(sizeof(buf) * 2, op_bl.length());
+ ASSERT_EQ(0, rval1);
+ ASSERT_EQ(0, rval2);
+ ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(op_bl.c_str() + sizeof(buf), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist op_bl;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), NULL, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist read_bl;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+ ASSERT_EQ(sizeof(buf), read_bl.length());
+ ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ int rval = 1000;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), NULL, &rval);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+ ASSERT_EQ(0, rval);
+ }
+
+ {
+ bufferlist read_bl;
+ int rval = 1000;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl, &rval);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+ ASSERT_EQ(sizeof(buf), read_bl.length());
+ ASSERT_EQ(0, rval);
+ ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist read_bl1, read_bl2;
+ int rval1 = 1000, rval2 = 1002;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl1, &rval1);
+ op.read(0, sizeof(buf), &read_bl2, &rval2);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+ ASSERT_EQ(sizeof(buf), read_bl1.length());
+ ASSERT_EQ(sizeof(buf), read_bl2.length());
+ ASSERT_EQ(0, rval1);
+ ASSERT_EQ(0, rval2);
+ ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
+ }
+}
+
+TEST_F(LibRadosIoPP, SparseReadOpPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+
+ {
+ std::map<uint64_t, uint64_t> extents;
+ bufferlist read_bl;
+ int rval = -1;
+ ObjectReadOperation op;
+ op.sparse_read(0, sizeof(buf), &extents, &read_bl, &rval);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, nullptr));
+ ASSERT_EQ(0, rval);
+ assert_eq_sparse(bl, extents, read_bl);
+ }
+}
+
+TEST_F(LibRadosIoPP, RoundTripPP) {
+ char buf[128];
+ Rados cluster;
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ bufferlist cl;
+ ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", cl, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(buf, cl.c_str(), sizeof(buf)));
+}
+
+TEST_F(LibRadosIoPP, RoundTripPP2)
+{
+ bufferlist bl;
+ bl.append("ceph");
+ ObjectWriteOperation write;
+ write.write(0, bl);
+ write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ASSERT_EQ(0, ioctx.operate("foo", &write));
+
+ ObjectReadOperation read;
+ read.read(0, bl.length(), NULL, NULL);
+ read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
+ ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
+ ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
+}
+
+TEST_F(LibRadosIoPP, Checksum) {
+ char buf[128];
+ Rados cluster;
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ bufferlist init_value_bl;
+ encode(static_cast<uint32_t>(-1), init_value_bl);
+ bufferlist csum_bl;
+ ASSERT_EQ(0, ioctx.checksum("foo", LIBRADOS_CHECKSUM_TYPE_CRC32C,
+ init_value_bl, sizeof(buf), 0, 0, &csum_bl));
+ auto csum_bl_it = csum_bl.cbegin();
+ uint32_t csum_count;
+ decode(csum_count, csum_bl_it);
+ ASSERT_EQ(1U, csum_count);
+ uint32_t csum;
+ decode(csum, csum_bl_it);
+ ASSERT_EQ(bl.crc32c(-1), csum);
+}
+
+TEST_F(LibRadosIoPP, OverlappingWriteRoundTripPP) {
+ char buf[128];
+ char buf2[64];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), 0));
+ bufferlist bl3;
+ ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
+ ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf2), buf, sizeof(buf) - sizeof(buf2)));
+}
+
+TEST_F(LibRadosIoPP, WriteFullRoundTripPP) {
+ char buf[128];
+ char buf2[64];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ASSERT_EQ(0, ioctx.write_full("foo", bl2));
+ bufferlist bl3;
+ ASSERT_EQ((int)sizeof(buf2), ioctx.read("foo", bl3, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
+}
+
+TEST_F(LibRadosIoPP, WriteFullRoundTripPP2)
+{
+ bufferlist bl;
+ bl.append("ceph");
+ ObjectWriteOperation write;
+ write.write_full(bl);
+ write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
+ ASSERT_EQ(0, ioctx.operate("foo", &write));
+
+ ObjectReadOperation read;
+ read.read(0, bl.length(), NULL, NULL);
+ read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
+ ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
+ ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
+}
+
+TEST_F(LibRadosIoPP, AppendRoundTripPP) {
+ char buf[64];
+ char buf2[64];
+ memset(buf, 0xde, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
+ memset(buf2, 0xad, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ASSERT_EQ(0, ioctx.append("foo", bl2, sizeof(buf2)));
+ bufferlist bl3;
+ ASSERT_EQ((int)(sizeof(buf) + sizeof(buf2)),
+ ioctx.read("foo", bl3, (sizeof(buf) + sizeof(buf2)), 0));
+ const char *bl3_str = bl3.c_str();
+ ASSERT_EQ(0, memcmp(bl3_str, buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(bl3_str + sizeof(buf), buf2, sizeof(buf2)));
+}
+
+TEST_F(LibRadosIoPP, TruncTestPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl, sizeof(buf)));
+ ASSERT_EQ(0, ioctx.trunc("foo", sizeof(buf) / 2));
+ bufferlist bl2;
+ ASSERT_EQ((int)(sizeof(buf)/2), ioctx.read("foo", bl2, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)/2));
+}
+
+TEST_F(LibRadosIoPP, RemoveTestPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
+ ASSERT_EQ(0, ioctx.remove("foo"));
+ bufferlist bl2;
+ ASSERT_EQ(-ENOENT, ioctx.read("foo", bl2, sizeof(buf), 0));
+}
+
+TEST_F(LibRadosIoPP, XattrsRoundTripPP) {
+ char buf[128];
+ char attr1[] = "attr1";
+ char attr1_buf[] = "foo bar baz";
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
+ bufferlist bl2;
+ ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl2));
+ bufferlist bl3;
+ bl3.append(attr1_buf, sizeof(attr1_buf));
+ ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl3));
+ bufferlist bl4;
+ ASSERT_EQ((int)sizeof(attr1_buf),
+ ioctx.getxattr("foo", attr1, bl4));
+ ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
+}
+
+TEST_F(LibRadosIoPP, RmXattrPP) {
+ char buf[128];
+ char attr1[] = "attr1";
+ char attr1_buf[] = "foo bar baz";
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
+ bufferlist bl2;
+ bl2.append(attr1_buf, sizeof(attr1_buf));
+ ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
+ ASSERT_EQ(0, ioctx.rmxattr("foo", attr1));
+ bufferlist bl3;
+ ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl3));
+
+ // Test rmxattr on a removed object
+ char buf2[128];
+ char attr2[] = "attr2";
+ char attr2_buf[] = "foo bar baz";
+ memset(buf2, 0xbb, sizeof(buf2));
+ bufferlist bl21;
+ bl21.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
+ bufferlist bl22;
+ bl22.append(attr2_buf, sizeof(attr2_buf));
+ ASSERT_EQ(0, ioctx.setxattr("foo_rmxattr", attr2, bl22));
+ ASSERT_EQ(0, ioctx.remove("foo_rmxattr"));
+ ASSERT_EQ(-ENOENT, ioctx.rmxattr("foo_rmxattr", attr2));
+}
+
+TEST_F(LibRadosIoPP, XattrListPP) {
+ char buf[128];
+ char attr1[] = "attr1";
+ char attr1_buf[] = "foo bar baz";
+ char attr2[] = "attr2";
+ char attr2_buf[256];
+ for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
+ attr2_buf[j] = j % 0xff;
+ }
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
+ bufferlist bl2;
+ bl2.append(attr1_buf, sizeof(attr1_buf));
+ ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
+ bufferlist bl3;
+ bl3.append(attr2_buf, sizeof(attr2_buf));
+ ASSERT_EQ(0, ioctx.setxattr("foo", attr2, bl3));
+ std::map<std::string, bufferlist> attrset;
+ ASSERT_EQ(0, ioctx.getxattrs("foo", attrset));
+ for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
+ i != attrset.end(); ++i) {
+ if (i->first == string(attr1)) {
+ ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
+ }
+ else if (i->first == string(attr2)) {
+ ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
+ }
+ else {
+ ASSERT_EQ(0, 1);
+ }
+ }
+}
+
+TEST_F(LibRadosIoECPP, SimpleWritePP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ ioctx.set_namespace("nspace");
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+}
+
+TEST_F(LibRadosIoECPP, ReadOpPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+
+ {
+ bufferlist op_bl;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), NULL, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist op_bl;
+ ObjectReadOperation op;
+ op.read(0, 0, NULL, NULL); //len=0 mean read the whole object data
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist read_bl, op_bl;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), read_bl.length());
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist op_bl;
+ int rval = 1000;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), NULL, &rval);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, rval);
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist read_bl, op_bl;
+ int rval = 1000;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl, &rval);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), read_bl.length());
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, rval);
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist read_bl1, read_bl2, op_bl;
+ int rval1 = 1000, rval2 = 1002;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl1, &rval1);
+ op.read(0, sizeof(buf), &read_bl2, &rval2);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), read_bl1.length());
+ ASSERT_EQ(sizeof(buf), read_bl2.length());
+ ASSERT_EQ(sizeof(buf) * 2, op_bl.length());
+ ASSERT_EQ(0, rval1);
+ ASSERT_EQ(0, rval2);
+ ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(op_bl.c_str() + sizeof(buf), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist op_bl;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), NULL, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+ ASSERT_EQ(sizeof(buf), op_bl.length());
+ ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist read_bl;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+ ASSERT_EQ(sizeof(buf), read_bl.length());
+ ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ int rval = 1000;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), NULL, &rval);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+ ASSERT_EQ(0, rval);
+ }
+
+ {
+ bufferlist read_bl;
+ int rval = 1000;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl, &rval);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+ ASSERT_EQ(sizeof(buf), read_bl.length());
+ ASSERT_EQ(0, rval);
+ ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+ }
+
+ {
+ bufferlist read_bl1, read_bl2;
+ int rval1 = 1000, rval2 = 1002;
+ ObjectReadOperation op;
+ op.read(0, sizeof(buf), &read_bl1, &rval1);
+ op.read(0, sizeof(buf), &read_bl2, &rval2);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+ ASSERT_EQ(sizeof(buf), read_bl1.length());
+ ASSERT_EQ(sizeof(buf), read_bl2.length());
+ ASSERT_EQ(0, rval1);
+ ASSERT_EQ(0, rval2);
+ ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
+ }
+}
+
+TEST_F(LibRadosIoECPP, SparseReadOpPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+
+ {
+ std::map<uint64_t, uint64_t> extents;
+ bufferlist read_bl;
+ int rval = -1;
+ ObjectReadOperation op;
+ op.sparse_read(0, sizeof(buf), &extents, &read_bl, &rval);
+ ASSERT_EQ(0, ioctx.operate("foo", &op, nullptr));
+ ASSERT_EQ(0, rval);
+ assert_eq_sparse(bl, extents, read_bl);
+ }
+}
+
+TEST_F(LibRadosIoECPP, RoundTripPP) {
+ char buf[128];
+ Rados cluster;
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ bufferlist cl;
+ ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", cl, sizeof(buf) * 3, 0));
+ ASSERT_EQ(0, memcmp(buf, cl.c_str(), sizeof(buf)));
+}
+
+TEST_F(LibRadosIoECPP, RoundTripPP2)
+{
+ bufferlist bl;
+ bl.append("ceph");
+ ObjectWriteOperation write;
+ write.write(0, bl);
+ write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ASSERT_EQ(0, ioctx.operate("foo", &write));
+
+ ObjectReadOperation read;
+ read.read(0, bl.length(), NULL, NULL);
+ read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
+ ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
+ ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
+}
+
+TEST_F(LibRadosIoECPP, OverlappingWriteRoundTripPP) {
+ int bsize = alignment;
+ int dbsize = bsize * 2;
+ char *buf = (char *)new char[dbsize];
+ char *buf2 = (char *)new char[bsize];
+ auto cleanup = [&] {
+ delete[] buf;
+ delete[] buf2;
+ };
+ scope_guard<decltype(cleanup)> sg(std::move(cleanup));
+ memset(buf, 0xcc, dbsize);
+ bufferlist bl1;
+ bl1.append(buf, dbsize);
+ ASSERT_EQ(0, ioctx.write("foo", bl1, dbsize, 0));
+ memset(buf2, 0xdd, bsize);
+ bufferlist bl2;
+ bl2.append(buf2, bsize);
+ ASSERT_EQ(-EOPNOTSUPP, ioctx.write("foo", bl2, bsize, 0));
+ bufferlist bl3;
+ ASSERT_EQ(dbsize, ioctx.read("foo", bl3, dbsize, 0));
+ // Read the same as first write
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, dbsize));
+}
+
+TEST_F(LibRadosIoECPP, WriteFullRoundTripPP) {
+ char buf[128];
+ char buf2[64];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ASSERT_EQ(0, ioctx.write_full("foo", bl2));
+ bufferlist bl3;
+ ASSERT_EQ((int)sizeof(buf2), ioctx.read("foo", bl3, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
+}
+
+TEST_F(LibRadosIoECPP, WriteFullRoundTripPP2)
+{
+ bufferlist bl;
+ bl.append("ceph");
+ ObjectWriteOperation write;
+ write.write_full(bl);
+ write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ASSERT_EQ(0, ioctx.operate("foo", &write));
+
+ ObjectReadOperation read;
+ read.read(0, bl.length(), NULL, NULL);
+ read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
+ ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
+ ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
+}
+
+TEST_F(LibRadosIoECPP, AppendRoundTripPP) {
+ char *buf = (char *)new char[alignment];
+ char *buf2 = (char *)new char[alignment];
+ auto cleanup = [&] {
+ delete[] buf;
+ delete[] buf2;
+ };
+ scope_guard<decltype(cleanup)> sg(std::move(cleanup));
+ memset(buf, 0xde, alignment);
+ bufferlist bl1;
+ bl1.append(buf, alignment);
+ ASSERT_EQ(0, ioctx.append("foo", bl1, alignment));
+ memset(buf2, 0xad, alignment);
+ bufferlist bl2;
+ bl2.append(buf2, alignment);
+ ASSERT_EQ(0, ioctx.append("foo", bl2, alignment));
+ bufferlist bl3;
+ ASSERT_EQ((int)(alignment * 2),
+ ioctx.read("foo", bl3, (alignment * 4), 0));
+ const char *bl3_str = bl3.c_str();
+ ASSERT_EQ(0, memcmp(bl3_str, buf, alignment));
+ ASSERT_EQ(0, memcmp(bl3_str + alignment, buf2, alignment));
+}
+
+TEST_F(LibRadosIoECPP, TruncTestPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl, sizeof(buf)));
+ ASSERT_EQ(-EOPNOTSUPP, ioctx.trunc("foo", sizeof(buf) / 2));
+ bufferlist bl2;
+ // Same size
+ ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl2, sizeof(buf), 0));
+ // No change
+ ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)));
+}
+
+TEST_F(LibRadosIoECPP, RemoveTestPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
+ ASSERT_EQ(0, ioctx.remove("foo"));
+ bufferlist bl2;
+ ASSERT_EQ(-ENOENT, ioctx.read("foo", bl2, sizeof(buf), 0));
+}
+
+TEST_F(LibRadosIoECPP, XattrsRoundTripPP) {
+ char buf[128];
+ char attr1[] = "attr1";
+ char attr1_buf[] = "foo bar baz";
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
+ bufferlist bl2;
+ ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl2));
+ bufferlist bl3;
+ bl3.append(attr1_buf, sizeof(attr1_buf));
+ ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl3));
+ bufferlist bl4;
+ ASSERT_EQ((int)sizeof(attr1_buf),
+ ioctx.getxattr("foo", attr1, bl4));
+ ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
+}
+
+TEST_F(LibRadosIoECPP, RmXattrPP) {
+ char buf[128];
+ char attr1[] = "attr1";
+ char attr1_buf[] = "foo bar baz";
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
+ bufferlist bl2;
+ bl2.append(attr1_buf, sizeof(attr1_buf));
+ ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
+ ASSERT_EQ(0, ioctx.rmxattr("foo", attr1));
+ bufferlist bl3;
+ ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl3));
+
+ // Test rmxattr on a removed object
+ char buf2[128];
+ char attr2[] = "attr2";
+ char attr2_buf[] = "foo bar baz";
+ memset(buf2, 0xbb, sizeof(buf2));
+ bufferlist bl21;
+ bl21.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
+ bufferlist bl22;
+ bl22.append(attr2_buf, sizeof(attr2_buf));
+ ASSERT_EQ(0, ioctx.setxattr("foo_rmxattr", attr2, bl22));
+ ASSERT_EQ(0, ioctx.remove("foo_rmxattr"));
+ ASSERT_EQ(-ENOENT, ioctx.rmxattr("foo_rmxattr", attr2));
+}
+
+TEST_F(LibRadosIoECPP, XattrListPP) {
+ char buf[128];
+ char attr1[] = "attr1";
+ char attr1_buf[] = "foo bar baz";
+ char attr2[] = "attr2";
+ char attr2_buf[256];
+ for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
+ attr2_buf[j] = j % 0xff;
+ }
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
+ bufferlist bl2;
+ bl2.append(attr1_buf, sizeof(attr1_buf));
+ ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
+ bufferlist bl3;
+ bl3.append(attr2_buf, sizeof(attr2_buf));
+ ASSERT_EQ(0, ioctx.setxattr("foo", attr2, bl3));
+ std::map<std::string, bufferlist> attrset;
+ ASSERT_EQ(0, ioctx.getxattrs("foo", attrset));
+ for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
+ i != attrset.end(); ++i) {
+ if (i->first == string(attr1)) {
+ ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
+ }
+ else if (i->first == string(attr2)) {
+ ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
+ }
+ else {
+ ASSERT_EQ(0, 1);
+ }
+ }
+}
+
+TEST_F(LibRadosIoPP, CmpExtPP) {
+ bufferlist bl;
+ bl.append("ceph");
+ ObjectWriteOperation write1;
+ write1.write(0, bl);
+ ASSERT_EQ(0, ioctx.operate("foo", &write1));
+
+ bufferlist new_bl;
+ new_bl.append("CEPH");
+ ObjectWriteOperation write2;
+ write2.cmpext(0, bl, nullptr);
+ write2.write(0, new_bl);
+ ASSERT_EQ(0, ioctx.operate("foo", &write2));
+
+ ObjectReadOperation read;
+ read.read(0, bl.length(), NULL, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
+ ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
+}
+
+TEST_F(LibRadosIoPP, CmpExtDNEPP) {
+ bufferlist bl;
+ bl.append(std::string(4, '\0'));
+
+ bufferlist new_bl;
+ new_bl.append("CEPH");
+ ObjectWriteOperation write;
+ write.cmpext(0, bl, nullptr);
+ write.write(0, new_bl);
+ ASSERT_EQ(0, ioctx.operate("foo", &write));
+
+ ObjectReadOperation read;
+ read.read(0, bl.length(), NULL, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
+ ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
+}
+
+TEST_F(LibRadosIoPP, CmpExtMismatchPP) {
+ bufferlist bl;
+ bl.append("ceph");
+ ObjectWriteOperation write1;
+ write1.write(0, bl);
+ ASSERT_EQ(0, ioctx.operate("foo", &write1));
+
+ bufferlist new_bl;
+ new_bl.append("CEPH");
+ ObjectWriteOperation write2;
+ write2.cmpext(0, new_bl, nullptr);
+ write2.write(0, new_bl);
+ ASSERT_EQ(-MAX_ERRNO, ioctx.operate("foo", &write2));
+
+ ObjectReadOperation read;
+ read.read(0, bl.length(), NULL, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
+ ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
+}
+
+TEST_F(LibRadosIoECPP, CmpExtPP) {
+ bufferlist bl;
+ bl.append("ceph");
+ ObjectWriteOperation write1;
+ write1.write(0, bl);
+ ASSERT_EQ(0, ioctx.operate("foo", &write1));
+
+ bufferlist new_bl;
+ new_bl.append("CEPH");
+ ObjectWriteOperation write2;
+ write2.cmpext(0, bl, nullptr);
+ write2.write_full(new_bl);
+ ASSERT_EQ(0, ioctx.operate("foo", &write2));
+
+ ObjectReadOperation read;
+ read.read(0, bl.length(), NULL, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
+ ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
+}
+
+TEST_F(LibRadosIoECPP, CmpExtDNEPP) {
+ bufferlist bl;
+ bl.append(std::string(4, '\0'));
+
+ bufferlist new_bl;
+ new_bl.append("CEPH");
+ ObjectWriteOperation write;
+ write.cmpext(0, bl, nullptr);
+ write.write_full(new_bl);
+ ASSERT_EQ(0, ioctx.operate("foo", &write));
+
+ ObjectReadOperation read;
+ read.read(0, bl.length(), NULL, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
+ ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
+}
+
+TEST_F(LibRadosIoECPP, CmpExtMismatchPP) {
+ bufferlist bl;
+ bl.append("ceph");
+ ObjectWriteOperation write1;
+ write1.write(0, bl);
+ ASSERT_EQ(0, ioctx.operate("foo", &write1));
+
+ bufferlist new_bl;
+ new_bl.append("CEPH");
+ ObjectWriteOperation write2;
+ write2.cmpext(0, new_bl, nullptr);
+ write2.write_full(new_bl);
+ ASSERT_EQ(-MAX_ERRNO, ioctx.operate("foo", &write2));
+
+ ObjectReadOperation read;
+ read.read(0, bl.length(), NULL, NULL);
+ ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
+ ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
+}
diff --git a/src/test/librados/list.cc b/src/test/librados/list.cc
index 045cd37f35b..a1bda0aaff4 100644
--- a/src/test/librados/list.cc
+++ b/src/test/librados/list.cc
@@ -18,9 +18,7 @@
using namespace librados;
typedef RadosTestNSCleanup LibRadosList;
-typedef RadosTestPPNSCleanup LibRadosListPP;
typedef RadosTestECNSCleanup LibRadosListEC;
-typedef RadosTestECPPNSCleanup LibRadosListECPP;
typedef RadosTestNP LibRadosListNP;
@@ -40,104 +38,6 @@ TEST_F(LibRadosList, ListObjects) {
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,
@@ -233,108 +133,6 @@ TEST_F(LibRadosList, ListObjectsNS) {
rados_nobjects_list_close(ctx);
}
-static void check_listpp(std::set<std::string>& myset, IoCtx& ioctx, const 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));
- ASSERT_EQ(std::string("ns2"), ioctx.get_namespace());
-
- 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];
@@ -369,175 +167,17 @@ TEST_F(LibRadosList, ListObjectsStart) {
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(LibRadosListPP, ListObjectsCursorNSPP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- const int max_objs = 16;
-
- map<string, string> oid_to_ns;
-
- for (int i=0; i<max_objs; ++i) {
- stringstream ss;
- ss << "ns" << i / 4;
- ioctx.set_namespace(ss.str());
- string oid = stringify(i);
- ASSERT_EQ(0, ioctx.write(oid, bl, bl.length(), 0));
-
- oid_to_ns[oid] = ss.str();
- }
-
- ioctx.set_namespace(all_nspaces);
-
- librados::NObjectIterator it = ioctx.nobjects_begin();
- std::map<librados::ObjectCursor, string> cursor_to_obj;
-
- int count = 0;
-
- librados::ObjectCursor seek_cursor;
-
- map<string, list<librados::ObjectCursor> > ns_to_cursors;
-
- for (it = ioctx.nobjects_begin(); it != ioctx.nobjects_end(); ++it) {
- librados::ObjectCursor cursor = it.get_cursor();
- string oid = it->get_oid();
- cout << "> oid=" << oid << " cursor=" << it.get_cursor() << std::endl;
- }
-
- vector<string> objs_order;
-
- for (it = ioctx.nobjects_begin(); it != ioctx.nobjects_end(); ++it, ++count) {
- librados::ObjectCursor cursor = it.get_cursor();
- string oid = it->get_oid();
- std::cout << oid << " " << it.get_pg_hash_position() << std::endl;
- cout << ": oid=" << oid << " cursor=" << it.get_cursor() << std::endl;
- cursor_to_obj[cursor] = oid;
-
- ASSERT_EQ(oid_to_ns[oid], it->get_nspace());
-
- it.seek(cursor);
- cout << ": seek to " << cursor << " it.cursor=" << it.get_cursor() << std::endl;
- ASSERT_EQ(oid, it->get_oid());
- ASSERT_LT(count, max_objs); /* avoid infinite loops due to bad seek */
-
- ns_to_cursors[it->get_nspace()].push_back(cursor);
-
- if (count == max_objs/2) {
- seek_cursor = cursor;
- }
- objs_order.push_back(it->get_oid());
- }
-
- ASSERT_EQ(count, max_objs);
-
- /* check that reading past seek also works */
- cout << "seek_cursor=" << seek_cursor << std::endl;
- it.seek(seek_cursor);
- for (count = max_objs/2; count < max_objs; ++count, ++it) {
- ASSERT_EQ(objs_order[count], it->get_oid());
- }
-
- /* seek to all cursors, check that we get expected obj */
- for (auto& niter : ns_to_cursors) {
- const string& ns = niter.first;
- list<librados::ObjectCursor>& cursors = niter.second;
-
- for (auto& cursor : cursors) {
- cout << ": seek to " << cursor << std::endl;
- it.seek(cursor);
- ASSERT_EQ(cursor, it.get_cursor());
- string& expected_oid = cursor_to_obj[cursor];
- cout << ": it->get_cursor()=" << it.get_cursor() << " expected=" << cursor << std::endl;
- cout << ": it->get_oid()=" << it->get_oid() << " expected=" << expected_oid << std::endl;
- cout << ": it->get_nspace()=" << it->get_oid() << " expected=" << ns << std::endl;
- ASSERT_EQ(expected_oid, it->get_oid());
- ASSERT_EQ(it->get_nspace(), ns);
- }
- }
-}
-
-TEST_F(LibRadosListPP, ListObjectsCursorPP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- const int max_objs = 16;
-
- for (int i=0; i<max_objs; ++i) {
- stringstream ss;
- ss << "ns" << i / 4;
- ioctx.set_namespace(ss.str());
- ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0));
- }
-
- ioctx.set_namespace(all_nspaces);
-
- librados::NObjectIterator it = ioctx.nobjects_begin();
- std::map<librados::ObjectCursor, string> cursor_to_obj;
-
- int count = 0;
-
- for (; it != ioctx.nobjects_end(); ++it, ++count) {
- librados::ObjectCursor cursor = it.get_cursor();
- string oid = it->get_oid();
- std::cout << oid << " " << it.get_pg_hash_position() << std::endl;
- cout << ": oid=" << oid << " cursor=" << it.get_cursor() << std::endl;
- cursor_to_obj[cursor] = oid;
-
- it.seek(cursor);
- cout << ": seek to " << cursor << std::endl;
- ASSERT_EQ(oid, it->get_oid());
- ASSERT_LT(count, max_objs); /* avoid infinite loops due to bad seek */
- }
-
- ASSERT_EQ(count, max_objs);
-
- auto p = cursor_to_obj.rbegin();
- it = ioctx.nobjects_begin();
- while (p != cursor_to_obj.rend()) {
- cout << ": seek to " << p->first << std::endl;
- it.seek(p->first);
- ASSERT_EQ(p->first, it.get_cursor());
- cout << ": it->get_cursor()=" << it.get_cursor() << " expected=" << p->first << std::endl;
- cout << ": it->get_oid()=" << it->get_oid() << " expected=" << p->second << std::endl;
- ASSERT_EQ(p->second, it->get_oid());
-
- librados::NObjectIterator it2 = ioctx.nobjects_begin(it.get_cursor());
- ASSERT_EQ(it2->get_oid(), it->get_oid());
-
- ++p;
+// this function replicates
+// librados::operator<<(std::ostream& os, const librados::ObjectCursor& oc)
+// because we don't want to use librados-cxx in librados client.
+std::ostream& operator<<(std::ostream&os, const rados_object_list_cursor& oc)
+{
+ if (oc) {
+ os << *(hobject_t *)oc;
+ } else {
+ os << hobject_t{};
}
+ return os;
}
TEST_F(LibRadosList, ListObjectsCursor) {
@@ -558,15 +198,15 @@ TEST_F(LibRadosList, ListObjectsCursor) {
ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
ASSERT_EQ(rados_nobjects_list_get_cursor(ctx, &cursor), 0);
rados_object_list_cursor first_cursor = cursor;
- cout << "x cursor=" << ObjectCursor(cursor) << std::endl;
+ cout << "x cursor=" << cursor << std::endl;
while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) == 0) {
string oid = entry;
ASSERT_EQ(rados_nobjects_list_get_cursor(ctx, &cursor), 0);
- cout << "> oid=" << oid << " cursor=" << ObjectCursor(cursor) << std::endl;
+ cout << "> oid=" << oid << " cursor=" << cursor << std::endl;
}
rados_nobjects_list_seek_cursor(ctx, first_cursor);
ASSERT_EQ(rados_nobjects_list_next(ctx, &entry, NULL, NULL), 0);
- cout << "FIRST> seek to " << ObjectCursor(first_cursor) << " oid=" << string(entry) << std::endl;
+ cout << "FIRST> seek to " << first_cursor << " oid=" << string(entry) << std::endl;
}
rados_list_ctx_t ctx;
ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
@@ -579,13 +219,13 @@ TEST_F(LibRadosList, ListObjectsCursor) {
rados_object_list_cursor cursor;
ASSERT_EQ(rados_nobjects_list_get_cursor(ctx, &cursor), 0);
string oid = entry;
- cout << ": oid=" << oid << " cursor=" << ObjectCursor(cursor) << std::endl;
+ cout << ": oid=" << oid << " cursor=" << cursor << std::endl;
cursor_to_obj[cursor] = oid;
rados_nobjects_list_seek_cursor(ctx, cursor);
- cout << ": seek to " << ObjectCursor(cursor) << std::endl;
+ cout << ": seek to " << cursor << std::endl;
ASSERT_EQ(rados_nobjects_list_next(ctx, &entry, NULL, NULL), 0);
- cout << "> " << ObjectCursor(cursor) << " -> " << entry << std::endl;
+ cout << "> " << cursor << " -> " << entry << std::endl;
ASSERT_EQ(string(entry), oid);
ASSERT_LT(count, max_objs); /* avoid infinite loops due to bad seek */
@@ -597,15 +237,15 @@ TEST_F(LibRadosList, ListObjectsCursor) {
auto p = cursor_to_obj.rbegin();
ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
while (p != cursor_to_obj.rend()) {
- cout << ": seek to " << ObjectCursor(p->first) << std::endl;
+ cout << ": seek to " << p->first << std::endl;
rados_object_list_cursor cursor;
rados_object_list_cursor oid(p->first);
rados_nobjects_list_seek_cursor(ctx, oid);
ASSERT_EQ(rados_nobjects_list_get_cursor(ctx, &cursor), 0);
- cout << ": cursor()=" << ObjectCursor(cursor) << " expected=" << oid << std::endl;
+ cout << ": cursor()=" << cursor << " expected=" << oid << std::endl;
// ASSERT_EQ(ObjectCursor(oid), ObjectCursor(cursor));
ASSERT_EQ(rados_nobjects_list_next(ctx, &entry, NULL, NULL), 0);
- cout << "> " << ObjectCursor(cursor) << " -> " << entry << std::endl;
+ cout << "> " << cursor << " -> " << entry << std::endl;
cout << ": entry=" << entry << " expected=" << p->second << std::endl;
ASSERT_EQ(p->second, string(entry));
@@ -631,105 +271,6 @@ TEST_F(LibRadosListEC, ListObjects) {
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));
@@ -792,71 +333,6 @@ TEST_F(LibRadosListEC, ListObjectsNS) {
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];
@@ -891,76 +367,6 @@ TEST_F(LibRadosListEC, ListObjectsStart) {
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;
@@ -1117,147 +523,3 @@ TEST_F(LibRadosList, EnumerateObjectsSplit) {
}
ASSERT_EQ(n_objects, saw_obj.size());
}
-
-TEST_F(LibRadosListPP, EnumerateObjectsPP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- const uint32_t n_objects = 16;
- for (unsigned i=0; i<n_objects; ++i) {
- ASSERT_EQ(0, ioctx.write(stringify(i), bl, sizeof(buf), 0));
- }
-
- std::set<std::string> saw_obj;
- ObjectCursor c = ioctx.object_list_begin();
- ObjectCursor end = ioctx.object_list_end();
- while(!ioctx.object_list_is_end(c))
- {
- std::vector<ObjectItem> result;
- int r = ioctx.object_list(c, end, 12, {}, &result, &c);
- ASSERT_GE(r, 0);
- ASSERT_EQ(r, (int)result.size());
- for (int i = 0; i < r; ++i) {
- auto oid = result[i].oid;
- if (saw_obj.count(oid)) {
- std::cerr << "duplicate obj " << oid << std::endl;
- }
- ASSERT_FALSE(saw_obj.count(oid));
- saw_obj.insert(oid);
- }
- }
-
- for (unsigned i=0; i<n_objects; ++i) {
- if (!saw_obj.count(stringify(i))) {
- std::cerr << "missing object " << i << std::endl;
- }
- ASSERT_TRUE(saw_obj.count(stringify(i)));
- }
- ASSERT_EQ(n_objects, saw_obj.size());
-}
-
-TEST_F(LibRadosListPP, EnumerateObjectsSplitPP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- const uint32_t n_objects = 16;
- for (unsigned i=0; i<n_objects; ++i) {
- ASSERT_EQ(0, ioctx.write(stringify(i), bl, sizeof(buf), 0));
- }
-
- ObjectCursor begin = ioctx.object_list_begin();
- ObjectCursor end = ioctx.object_list_end();
-
- // Step through an odd number of shards
- unsigned m = 5;
- std::set<std::string> saw_obj;
- for (unsigned n = 0; n < m; ++n) {
- ObjectCursor shard_start;
- ObjectCursor shard_end;
-
- ioctx.object_list_slice(
- begin,
- end,
- n,
- m,
- &shard_start,
- &shard_end);
-
- ObjectCursor c(shard_start);
- while(c < shard_end)
- {
- std::vector<ObjectItem> result;
- int r = ioctx.object_list(c, shard_end, 12, {}, &result, &c);
- ASSERT_GE(r, 0);
-
- for (const auto & i : result) {
- const auto &oid = i.oid;
- if (saw_obj.count(oid)) {
- std::cerr << "duplicate obj " << oid << std::endl;
- }
- ASSERT_FALSE(saw_obj.count(oid));
- saw_obj.insert(oid);
- }
- }
- }
-
- for (unsigned i=0; i<n_objects; ++i) {
- if (!saw_obj.count(stringify(i))) {
- std::cerr << "missing object " << i << std::endl;
- }
- ASSERT_TRUE(saw_obj.count(stringify(i)));
- }
- ASSERT_EQ(n_objects, saw_obj.size());
-}
-
-
-TEST_F(LibRadosListPP, EnumerateObjectsFilterPP) {
- 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);
-
- ObjectCursor c = ioctx.object_list_begin();
- ObjectCursor end = ioctx.object_list_end();
- bool foundit = false;
- while(!ioctx.object_list_is_end(c))
- {
- std::vector<ObjectItem> result;
- int r = ioctx.object_list(c, end, 12, filter_bl, &result, &c);
- ASSERT_GE(r, 0);
- ASSERT_EQ(r, (int)result.size());
- for (int i = 0; i < r; ++i) {
- auto oid = result[i].oid;
- // We should only see the object that matches the filter
- ASSERT_EQ(oid, "has_xattr");
- // We should only see it once
- ASSERT_FALSE(foundit);
- foundit = true;
- }
- }
- ASSERT_TRUE(foundit);
-}
diff --git a/src/test/librados/list_cxx.cc b/src/test/librados/list_cxx.cc
new file mode 100644
index 00000000000..45368b39cf3
--- /dev/null
+++ b/src/test/librados/list_cxx.cc
@@ -0,0 +1,773 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#include <errno.h>
+#include <string>
+#include <stdexcept>
+
+#include "gtest/gtest.h"
+
+#include "include/rados/librados.hpp"
+#include "include/stringify.h"
+#include "include/types.h"
+#include "common/hobject.h"
+#include "test/librados/test_cxx.h"
+#include "test/librados/test_common.h"
+#include "test/librados/testcase_cxx.h"
+#include "global/global_context.h"
+
+using namespace librados;
+
+typedef RadosTestPPNSCleanup LibRadosListPP;
+typedef RadosTestECPPNSCleanup LibRadosListECPP;
+
+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_listpp(std::set<std::string>& myset, IoCtx& ioctx, const 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));
+ ASSERT_EQ(std::string("ns2"), ioctx.get_namespace());
+
+ 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(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(LibRadosListPP, ListObjectsCursorNSPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ const int max_objs = 16;
+
+ map<string, string> oid_to_ns;
+
+ for (int i=0; i<max_objs; ++i) {
+ stringstream ss;
+ ss << "ns" << i / 4;
+ ioctx.set_namespace(ss.str());
+ string oid = stringify(i);
+ ASSERT_EQ(0, ioctx.write(oid, bl, bl.length(), 0));
+
+ oid_to_ns[oid] = ss.str();
+ }
+
+ ioctx.set_namespace(all_nspaces);
+
+ librados::NObjectIterator it = ioctx.nobjects_begin();
+ std::map<librados::ObjectCursor, string> cursor_to_obj;
+
+ int count = 0;
+
+ librados::ObjectCursor seek_cursor;
+
+ map<string, list<librados::ObjectCursor> > ns_to_cursors;
+
+ for (it = ioctx.nobjects_begin(); it != ioctx.nobjects_end(); ++it) {
+ librados::ObjectCursor cursor = it.get_cursor();
+ string oid = it->get_oid();
+ cout << "> oid=" << oid << " cursor=" << it.get_cursor() << std::endl;
+ }
+
+ vector<string> objs_order;
+
+ for (it = ioctx.nobjects_begin(); it != ioctx.nobjects_end(); ++it, ++count) {
+ librados::ObjectCursor cursor = it.get_cursor();
+ string oid = it->get_oid();
+ std::cout << oid << " " << it.get_pg_hash_position() << std::endl;
+ cout << ": oid=" << oid << " cursor=" << it.get_cursor() << std::endl;
+ cursor_to_obj[cursor] = oid;
+
+ ASSERT_EQ(oid_to_ns[oid], it->get_nspace());
+
+ it.seek(cursor);
+ cout << ": seek to " << cursor << " it.cursor=" << it.get_cursor() << std::endl;
+ ASSERT_EQ(oid, it->get_oid());
+ ASSERT_LT(count, max_objs); /* avoid infinite loops due to bad seek */
+
+ ns_to_cursors[it->get_nspace()].push_back(cursor);
+
+ if (count == max_objs/2) {
+ seek_cursor = cursor;
+ }
+ objs_order.push_back(it->get_oid());
+ }
+
+ ASSERT_EQ(count, max_objs);
+
+ /* check that reading past seek also works */
+ cout << "seek_cursor=" << seek_cursor << std::endl;
+ it.seek(seek_cursor);
+ for (count = max_objs/2; count < max_objs; ++count, ++it) {
+ ASSERT_EQ(objs_order[count], it->get_oid());
+ }
+
+ /* seek to all cursors, check that we get expected obj */
+ for (auto& niter : ns_to_cursors) {
+ const string& ns = niter.first;
+ list<librados::ObjectCursor>& cursors = niter.second;
+
+ for (auto& cursor : cursors) {
+ cout << ": seek to " << cursor << std::endl;
+ it.seek(cursor);
+ ASSERT_EQ(cursor, it.get_cursor());
+ string& expected_oid = cursor_to_obj[cursor];
+ cout << ": it->get_cursor()=" << it.get_cursor() << " expected=" << cursor << std::endl;
+ cout << ": it->get_oid()=" << it->get_oid() << " expected=" << expected_oid << std::endl;
+ cout << ": it->get_nspace()=" << it->get_oid() << " expected=" << ns << std::endl;
+ ASSERT_EQ(expected_oid, it->get_oid());
+ ASSERT_EQ(it->get_nspace(), ns);
+ }
+ }
+}
+
+TEST_F(LibRadosListPP, ListObjectsCursorPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ const int max_objs = 16;
+
+ for (int i=0; i<max_objs; ++i) {
+ stringstream ss;
+ ss << "ns" << i / 4;
+ ioctx.set_namespace(ss.str());
+ ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0));
+ }
+
+ ioctx.set_namespace(all_nspaces);
+
+ librados::NObjectIterator it = ioctx.nobjects_begin();
+ std::map<librados::ObjectCursor, string> cursor_to_obj;
+
+ int count = 0;
+
+ for (; it != ioctx.nobjects_end(); ++it, ++count) {
+ librados::ObjectCursor cursor = it.get_cursor();
+ string oid = it->get_oid();
+ std::cout << oid << " " << it.get_pg_hash_position() << std::endl;
+ cout << ": oid=" << oid << " cursor=" << it.get_cursor() << std::endl;
+ cursor_to_obj[cursor] = oid;
+
+ it.seek(cursor);
+ cout << ": seek to " << cursor << std::endl;
+ ASSERT_EQ(oid, it->get_oid());
+ ASSERT_LT(count, max_objs); /* avoid infinite loops due to bad seek */
+ }
+
+ ASSERT_EQ(count, max_objs);
+
+ auto p = cursor_to_obj.rbegin();
+ it = ioctx.nobjects_begin();
+ while (p != cursor_to_obj.rend()) {
+ cout << ": seek to " << p->first << std::endl;
+ it.seek(p->first);
+ ASSERT_EQ(p->first, it.get_cursor());
+ cout << ": it->get_cursor()=" << it.get_cursor() << " expected=" << p->first << std::endl;
+ cout << ": it->get_oid()=" << it->get_oid() << " expected=" << p->second << std::endl;
+ ASSERT_EQ(p->second, it->get_oid());
+
+ librados::NObjectIterator it2 = ioctx.nobjects_begin(it.get_cursor());
+ ASSERT_EQ(it2->get_oid(), it->get_oid());
+
+ ++p;
+ }
+}
+
+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(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(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(LibRadosListPP, EnumerateObjectsPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ const uint32_t n_objects = 16;
+ for (unsigned i=0; i<n_objects; ++i) {
+ ASSERT_EQ(0, ioctx.write(stringify(i), bl, sizeof(buf), 0));
+ }
+
+ std::set<std::string> saw_obj;
+ ObjectCursor c = ioctx.object_list_begin();
+ ObjectCursor end = ioctx.object_list_end();
+ while(!ioctx.object_list_is_end(c))
+ {
+ std::vector<ObjectItem> result;
+ int r = ioctx.object_list(c, end, 12, {}, &result, &c);
+ ASSERT_GE(r, 0);
+ ASSERT_EQ(r, (int)result.size());
+ for (int i = 0; i < r; ++i) {
+ auto oid = result[i].oid;
+ if (saw_obj.count(oid)) {
+ std::cerr << "duplicate obj " << oid << std::endl;
+ }
+ ASSERT_FALSE(saw_obj.count(oid));
+ saw_obj.insert(oid);
+ }
+ }
+
+ for (unsigned i=0; i<n_objects; ++i) {
+ if (!saw_obj.count(stringify(i))) {
+ std::cerr << "missing object " << i << std::endl;
+ }
+ ASSERT_TRUE(saw_obj.count(stringify(i)));
+ }
+ ASSERT_EQ(n_objects, saw_obj.size());
+}
+
+TEST_F(LibRadosListPP, EnumerateObjectsSplitPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ const uint32_t n_objects = 16;
+ for (unsigned i=0; i<n_objects; ++i) {
+ ASSERT_EQ(0, ioctx.write(stringify(i), bl, sizeof(buf), 0));
+ }
+
+ ObjectCursor begin = ioctx.object_list_begin();
+ ObjectCursor end = ioctx.object_list_end();
+
+ // Step through an odd number of shards
+ unsigned m = 5;
+ std::set<std::string> saw_obj;
+ for (unsigned n = 0; n < m; ++n) {
+ ObjectCursor shard_start;
+ ObjectCursor shard_end;
+
+ ioctx.object_list_slice(
+ begin,
+ end,
+ n,
+ m,
+ &shard_start,
+ &shard_end);
+
+ ObjectCursor c(shard_start);
+ while(c < shard_end)
+ {
+ std::vector<ObjectItem> result;
+ int r = ioctx.object_list(c, shard_end, 12, {}, &result, &c);
+ ASSERT_GE(r, 0);
+
+ for (const auto & i : result) {
+ const auto &oid = i.oid;
+ if (saw_obj.count(oid)) {
+ std::cerr << "duplicate obj " << oid << std::endl;
+ }
+ ASSERT_FALSE(saw_obj.count(oid));
+ saw_obj.insert(oid);
+ }
+ }
+ }
+
+ for (unsigned i=0; i<n_objects; ++i) {
+ if (!saw_obj.count(stringify(i))) {
+ std::cerr << "missing object " << i << std::endl;
+ }
+ ASSERT_TRUE(saw_obj.count(stringify(i)));
+ }
+ ASSERT_EQ(n_objects, saw_obj.size());
+}
+
+
+TEST_F(LibRadosListPP, EnumerateObjectsFilterPP) {
+ 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);
+
+ ObjectCursor c = ioctx.object_list_begin();
+ ObjectCursor end = ioctx.object_list_end();
+ bool foundit = false;
+ while(!ioctx.object_list_is_end(c))
+ {
+ std::vector<ObjectItem> result;
+ int r = ioctx.object_list(c, end, 12, filter_bl, &result, &c);
+ ASSERT_GE(r, 0);
+ ASSERT_EQ(r, (int)result.size());
+ for (int i = 0; i < r; ++i) {
+ auto oid = result[i].oid;
+ // We should only see the object that matches the filter
+ ASSERT_EQ(oid, "has_xattr");
+ // We should only see it once
+ ASSERT_FALSE(foundit);
+ foundit = true;
+ }
+ }
+ ASSERT_TRUE(foundit);
+}
diff --git a/src/test/librados/lock.cc b/src/test/librados/lock.cc
index 65d3fcdf09f..53ed300e7ba 100644
--- a/src/test/librados/lock.cc
+++ b/src/test/librados/lock.cc
@@ -1,5 +1,4 @@
#include "include/rados/librados.h"
-#include "include/rados/librados.hpp"
#include "test/librados/test.h"
#include "test/librados/TestCase.h"
#include "cls/lock/cls_lock_client.h"
@@ -12,55 +11,21 @@
#include <sys/time.h>
using namespace std::chrono_literals;
-using namespace librados;
typedef RadosTest LibRadosLock;
-typedef RadosTestPP LibRadosLockPP;
typedef RadosTestEC LibRadosLockEC;
-typedef RadosTestECPP LibRadosLockECPP;
-template<class Rep, class Period, typename Func, typename... Args,
- typename Return = std::result_of_t<Func&&(Args&&...)>>
-Return wait_until(const std::chrono::duration<Rep, Period>& rel_time,
- const std::chrono::duration<Rep, Period>& step,
- const Return& expected,
- Func&& func, Args&&... args)
-{
- std::this_thread::sleep_for(rel_time - step);
- for (auto& s : {step, step}) {
- if (!s.count()) {
- break;
- }
- auto ret = func(std::forward<Args>(args)...);
- if (ret == expected) {
- return ret;
- }
- std::this_thread::sleep_for(s);
- }
- return func(std::forward<Args>(args)...);
-}
-
TEST_F(LibRadosLock, LockExclusive) {
ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock1", "Cookie", "", NULL, 0));
ASSERT_EQ(-EEXIST, rados_lock_exclusive(ioctx, "foo", "TestLock1", "Cookie", "", NULL, 0));
}
-TEST_F(LibRadosLockPP, LockExclusivePP) {
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP1", "Cookie", "", NULL, 0));
- ASSERT_EQ(-EEXIST, ioctx.lock_exclusive("foo", "TestLockPP1", "Cookie", "", NULL, 0));
-}
-
TEST_F(LibRadosLock, LockShared) {
ASSERT_EQ(0, rados_lock_shared(ioctx, "foo", "TestLock2", "Cookie", "Tag", "", NULL, 0));
ASSERT_EQ(-EEXIST, rados_lock_shared(ioctx, "foo", "TestLock2", "Cookie", "Tag", "", NULL, 0));
}
-TEST_F(LibRadosLockPP, LockSharedPP) {
- ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockPP2", "Cookie", "Tag", "", NULL, 0));
- ASSERT_EQ(-EEXIST, ioctx.lock_shared("foo", "TestLockPP2", "Cookie", "Tag", "", NULL, 0));
-}
-
TEST_F(LibRadosLock, LockExclusiveDur) {
struct timeval tv;
tv.tv_sec = 1;
@@ -73,18 +38,6 @@ TEST_F(LibRadosLock, LockExclusiveDur) {
ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_exclusive, nullptr));
}
-TEST_F(LibRadosLockPP, LockExclusiveDurPP) {
- struct timeval tv;
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- auto lock_exclusive = [this](timeval* tv) {
- return ioctx.lock_exclusive("foo", "TestLockPP3", "Cookie", "", tv, 0);
- };
- constexpr int expected = 0;
- ASSERT_EQ(expected, lock_exclusive(&tv));
- ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_exclusive, nullptr));
-}
-
TEST_F(LibRadosLock, LockSharedDur) {
struct timeval tv;
tv.tv_sec = 1;
@@ -97,28 +50,11 @@ TEST_F(LibRadosLock, LockSharedDur) {
ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_shared, nullptr));
}
-TEST_F(LibRadosLockPP, LockSharedDurPP) {
- struct timeval tv;
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- auto lock_shared = [this](timeval* tv) {
- return ioctx.lock_shared("foo", "TestLockPP4", "Cookie", "Tag", "", tv, 0);
- };
- constexpr int expected = 0;
- ASSERT_EQ(expected, lock_shared(&tv));
- ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_shared, nullptr));
-}
-TEST_F(LibRadosLock, LockRenew) {
+TEST_F(LibRadosLock, LockMayRenew) {
ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock5", "Cookie", "", NULL, 0));
ASSERT_EQ(-EEXIST, rados_lock_exclusive(ioctx, "foo", "TestLock5", "Cookie", "", NULL, 0));
- ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock5", "Cookie", "", NULL, LOCK_FLAG_RENEW));
-}
-
-TEST_F(LibRadosLockPP, LockRenewPP) {
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP5", "Cookie", "", NULL, 0));
- ASSERT_EQ(-EEXIST, ioctx.lock_exclusive("foo", "TestLockPP5", "Cookie", "", NULL, 0));
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP5", "Cookie", "", NULL, LOCK_FLAG_RENEW));
+ ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock5", "Cookie", "", NULL, LOCK_FLAG_MAY_RENEW));
}
TEST_F(LibRadosLock, Unlock) {
@@ -127,12 +63,6 @@ TEST_F(LibRadosLock, Unlock) {
ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock6", "Cookie", "", NULL, 0));
}
-TEST_F(LibRadosLockPP, UnlockPP) {
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP6", "Cookie", "", NULL, 0));
- ASSERT_EQ(0, ioctx.unlock("foo", "TestLockPP6", "Cookie"));
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP6", "Cookie", "", NULL, 0));
-}
-
TEST_F(LibRadosLock, ListLockers) {
int exclusive;
char tag[1024];
@@ -165,31 +95,6 @@ TEST_F(LibRadosLock, ListLockers) {
ASSERT_EQ(strlen("Cookie") + 1, cookies_len);
}
-TEST_F(LibRadosLockPP, ListLockersPP) {
- std::stringstream sstm;
- sstm << "client." << cluster.get_instance_id();
- std::string me = sstm.str();
- ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockPP7", "Cookie", "Tag", "", NULL, 0));
- ASSERT_EQ(0, ioctx.unlock("foo", "TestLockPP7", "Cookie"));
- {
- int exclusive;
- std::string tag;
- std::list<librados::locker_t> lockers;
- ASSERT_EQ(0, ioctx.list_lockers("foo", "TestLockPP7", &exclusive, &tag, &lockers));
- }
- ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockPP7", "Cookie", "Tag", "", NULL, 0));
- {
- int exclusive;
- std::string tag;
- std::list<librados::locker_t> lockers;
- ASSERT_EQ(1, ioctx.list_lockers("foo", "TestLockPP7", &exclusive, &tag, &lockers));
- std::list<librados::locker_t>::iterator it = lockers.begin();
- ASSERT_FALSE(lockers.end() == it);
- ASSERT_EQ(me, it->client);
- ASSERT_EQ("Cookie", it->cookie);
- }
-}
-
TEST_F(LibRadosLock, BreakLock) {
int exclusive;
char tag[1024];
@@ -215,43 +120,17 @@ TEST_F(LibRadosLock, BreakLock) {
ASSERT_EQ(0, rados_break_lock(ioctx, "foo", "TestLock8", clients, "Cookie"));
}
-TEST_F(LibRadosLockPP, BreakLockPP) {
- int exclusive;
- std::string tag;
- std::list<librados::locker_t> lockers;
- std::stringstream sstm;
- sstm << "client." << cluster.get_instance_id();
- std::string me = sstm.str();
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP8", "Cookie", "", NULL, 0));
- ASSERT_EQ(1, ioctx.list_lockers("foo", "TestLockPP8", &exclusive, &tag, &lockers));
- std::list<librados::locker_t>::iterator it = lockers.begin();
- ASSERT_FALSE(lockers.end() == it);
- ASSERT_EQ(me, it->client);
- ASSERT_EQ("Cookie", it->cookie);
- ASSERT_EQ(0, ioctx.break_lock("foo", "TestLockPP8", it->client, "Cookie"));
-}
-
// EC testing
TEST_F(LibRadosLockEC, LockExclusive) {
ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLockEC1", "Cookie", "", NULL, 0));
ASSERT_EQ(-EEXIST, rados_lock_exclusive(ioctx, "foo", "TestLockEC1", "Cookie", "", NULL, 0));
}
-TEST_F(LibRadosLockECPP, LockExclusivePP) {
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP1", "Cookie", "", NULL, 0));
- ASSERT_EQ(-EEXIST, ioctx.lock_exclusive("foo", "TestLockECPP1", "Cookie", "", NULL, 0));
-}
-
TEST_F(LibRadosLockEC, LockShared) {
ASSERT_EQ(0, rados_lock_shared(ioctx, "foo", "TestLockEC2", "Cookie", "Tag", "", NULL, 0));
ASSERT_EQ(-EEXIST, rados_lock_shared(ioctx, "foo", "TestLockEC2", "Cookie", "Tag", "", NULL, 0));
}
-TEST_F(LibRadosLockECPP, LockSharedPP) {
- ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockECPP2", "Cookie", "Tag", "", NULL, 0));
- ASSERT_EQ(-EEXIST, ioctx.lock_shared("foo", "TestLockECPP2", "Cookie", "Tag", "", NULL, 0));
-}
-
TEST_F(LibRadosLockEC, LockExclusiveDur) {
struct timeval tv;
tv.tv_sec = 1;
@@ -264,18 +143,6 @@ TEST_F(LibRadosLockEC, LockExclusiveDur) {
ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_exclusive, nullptr));
}
-TEST_F(LibRadosLockECPP, LockExclusiveDurPP) {
- struct timeval tv;
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- auto lock_exclusive = [this](timeval* tv) {
- return ioctx.lock_exclusive("foo", "TestLockECPP3", "Cookie", "", tv, 0);
- };
- constexpr int expected = 0;
- ASSERT_EQ(expected, lock_exclusive(&tv));
- ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_exclusive, nullptr));
-}
-
TEST_F(LibRadosLockEC, LockSharedDur) {
struct timeval tv;
tv.tv_sec = 1;
@@ -288,28 +155,11 @@ TEST_F(LibRadosLockEC, LockSharedDur) {
ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_shared, nullptr));
}
-TEST_F(LibRadosLockECPP, LockSharedDurPP) {
- struct timeval tv;
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- auto lock_shared = [this](timeval* tv) {
- return ioctx.lock_shared("foo", "TestLockECPP4", "Cookie", "Tag", "", tv, 0);
- };
- const int expected = 0;
- ASSERT_EQ(expected, lock_shared(&tv));
- ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_shared, nullptr));
-}
-TEST_F(LibRadosLockEC, LockRenew) {
+TEST_F(LibRadosLockEC, LockMayRenew) {
ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLockEC5", "Cookie", "", NULL, 0));
ASSERT_EQ(-EEXIST, rados_lock_exclusive(ioctx, "foo", "TestLockEC5", "Cookie", "", NULL, 0));
- ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLockEC5", "Cookie", "", NULL, LOCK_FLAG_RENEW));
-}
-
-TEST_F(LibRadosLockECPP, LockRenewPP) {
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP5", "Cookie", "", NULL, 0));
- ASSERT_EQ(-EEXIST, ioctx.lock_exclusive("foo", "TestLockECPP5", "Cookie", "", NULL, 0));
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP5", "Cookie", "", NULL, LOCK_FLAG_RENEW));
+ ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLockEC5", "Cookie", "", NULL, LOCK_FLAG_MAY_RENEW));
}
TEST_F(LibRadosLockEC, Unlock) {
@@ -318,12 +168,6 @@ TEST_F(LibRadosLockEC, Unlock) {
ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLockEC6", "Cookie", "", NULL, 0));
}
-TEST_F(LibRadosLockECPP, UnlockPP) {
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP6", "Cookie", "", NULL, 0));
- ASSERT_EQ(0, ioctx.unlock("foo", "TestLockECPP6", "Cookie"));
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP6", "Cookie", "", NULL, 0));
-}
-
TEST_F(LibRadosLockEC, ListLockers) {
int exclusive;
char tag[1024];
@@ -356,31 +200,6 @@ TEST_F(LibRadosLockEC, ListLockers) {
ASSERT_EQ(strlen("Cookie") + 1, cookies_len);
}
-TEST_F(LibRadosLockECPP, ListLockersPP) {
- std::stringstream sstm;
- sstm << "client." << cluster.get_instance_id();
- std::string me = sstm.str();
- ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockECPP7", "Cookie", "Tag", "", NULL, 0));
- ASSERT_EQ(0, ioctx.unlock("foo", "TestLockECPP7", "Cookie"));
- {
- int exclusive;
- std::string tag;
- std::list<librados::locker_t> lockers;
- ASSERT_EQ(0, ioctx.list_lockers("foo", "TestLockECPP7", &exclusive, &tag, &lockers));
- }
- ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockECPP7", "Cookie", "Tag", "", NULL, 0));
- {
- int exclusive;
- std::string tag;
- std::list<librados::locker_t> lockers;
- ASSERT_EQ(1, ioctx.list_lockers("foo", "TestLockECPP7", &exclusive, &tag, &lockers));
- std::list<librados::locker_t>::iterator it = lockers.begin();
- ASSERT_FALSE(lockers.end() == it);
- ASSERT_EQ(me, it->client);
- ASSERT_EQ("Cookie", it->cookie);
- }
-}
-
TEST_F(LibRadosLockEC, BreakLock) {
int exclusive;
char tag[1024];
@@ -406,18 +225,3 @@ TEST_F(LibRadosLockEC, BreakLock) {
ASSERT_EQ(0, rados_break_lock(ioctx, "foo", "TestLockEC8", clients, "Cookie"));
}
-TEST_F(LibRadosLockECPP, BreakLockPP) {
- int exclusive;
- std::string tag;
- std::list<librados::locker_t> lockers;
- std::stringstream sstm;
- sstm << "client." << cluster.get_instance_id();
- std::string me = sstm.str();
- ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP8", "Cookie", "", NULL, 0));
- ASSERT_EQ(1, ioctx.list_lockers("foo", "TestLockECPP8", &exclusive, &tag, &lockers));
- std::list<librados::locker_t>::iterator it = lockers.begin();
- ASSERT_FALSE(lockers.end() == it);
- ASSERT_EQ(me, it->client);
- ASSERT_EQ("Cookie", it->cookie);
- ASSERT_EQ(0, ioctx.break_lock("foo", "TestLockECPP8", it->client, "Cookie"));
-}
diff --git a/src/test/librados/lock_cxx.cc b/src/test/librados/lock_cxx.cc
new file mode 100644
index 00000000000..3007b22686a
--- /dev/null
+++ b/src/test/librados/lock_cxx.cc
@@ -0,0 +1,193 @@
+#include <algorithm>
+#include <chrono>
+#include <thread>
+#include <errno.h>
+#include <sys/time.h>
+#include "gtest/gtest.h"
+
+#include "include/rados/librados.hpp"
+#include "cls/lock/cls_lock_client.h"
+
+#include "test/librados/test_cxx.h"
+#include "test/librados/testcase_cxx.h"
+
+using namespace std::chrono_literals;
+using namespace librados;
+
+typedef RadosTestPP LibRadosLockPP;
+typedef RadosTestECPP LibRadosLockECPP;
+
+TEST_F(LibRadosLockPP, LockExclusivePP) {
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP1", "Cookie", "", NULL, 0));
+ ASSERT_EQ(-EEXIST, ioctx.lock_exclusive("foo", "TestLockPP1", "Cookie", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockPP, LockSharedPP) {
+ ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockPP2", "Cookie", "Tag", "", NULL, 0));
+ ASSERT_EQ(-EEXIST, ioctx.lock_shared("foo", "TestLockPP2", "Cookie", "Tag", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockPP, LockExclusiveDurPP) {
+ struct timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ auto lock_exclusive = [this](timeval* tv) {
+ return ioctx.lock_exclusive("foo", "TestLockPP3", "Cookie", "", tv, 0);
+ };
+ constexpr int expected = 0;
+ ASSERT_EQ(expected, lock_exclusive(&tv));
+ ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_exclusive, nullptr));
+}
+
+TEST_F(LibRadosLockPP, LockSharedDurPP) {
+ struct timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ auto lock_shared = [this](timeval* tv) {
+ return ioctx.lock_shared("foo", "TestLockPP4", "Cookie", "Tag", "", tv, 0);
+ };
+ constexpr int expected = 0;
+ ASSERT_EQ(expected, lock_shared(&tv));
+ ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_shared, nullptr));
+}
+
+TEST_F(LibRadosLockPP, LockMayRenewPP) {
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP5", "Cookie", "", NULL, 0));
+ ASSERT_EQ(-EEXIST, ioctx.lock_exclusive("foo", "TestLockPP5", "Cookie", "", NULL, 0));
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP5", "Cookie", "", NULL, LOCK_FLAG_MAY_RENEW));
+}
+
+TEST_F(LibRadosLockPP, UnlockPP) {
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP6", "Cookie", "", NULL, 0));
+ ASSERT_EQ(0, ioctx.unlock("foo", "TestLockPP6", "Cookie"));
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP6", "Cookie", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockPP, ListLockersPP) {
+ std::stringstream sstm;
+ sstm << "client." << cluster.get_instance_id();
+ std::string me = sstm.str();
+ ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockPP7", "Cookie", "Tag", "", NULL, 0));
+ ASSERT_EQ(0, ioctx.unlock("foo", "TestLockPP7", "Cookie"));
+ {
+ int exclusive;
+ std::string tag;
+ std::list<librados::locker_t> lockers;
+ ASSERT_EQ(0, ioctx.list_lockers("foo", "TestLockPP7", &exclusive, &tag, &lockers));
+ }
+ ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockPP7", "Cookie", "Tag", "", NULL, 0));
+ {
+ int exclusive;
+ std::string tag;
+ std::list<librados::locker_t> lockers;
+ ASSERT_EQ(1, ioctx.list_lockers("foo", "TestLockPP7", &exclusive, &tag, &lockers));
+ std::list<librados::locker_t>::iterator it = lockers.begin();
+ ASSERT_FALSE(lockers.end() == it);
+ ASSERT_EQ(me, it->client);
+ ASSERT_EQ("Cookie", it->cookie);
+ }
+}
+
+TEST_F(LibRadosLockPP, BreakLockPP) {
+ int exclusive;
+ std::string tag;
+ std::list<librados::locker_t> lockers;
+ std::stringstream sstm;
+ sstm << "client." << cluster.get_instance_id();
+ std::string me = sstm.str();
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockPP8", "Cookie", "", NULL, 0));
+ ASSERT_EQ(1, ioctx.list_lockers("foo", "TestLockPP8", &exclusive, &tag, &lockers));
+ std::list<librados::locker_t>::iterator it = lockers.begin();
+ ASSERT_FALSE(lockers.end() == it);
+ ASSERT_EQ(me, it->client);
+ ASSERT_EQ("Cookie", it->cookie);
+ ASSERT_EQ(0, ioctx.break_lock("foo", "TestLockPP8", it->client, "Cookie"));
+}
+
+// EC testing
+TEST_F(LibRadosLockECPP, LockExclusivePP) {
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP1", "Cookie", "", NULL, 0));
+ ASSERT_EQ(-EEXIST, ioctx.lock_exclusive("foo", "TestLockECPP1", "Cookie", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockECPP, LockSharedPP) {
+ ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockECPP2", "Cookie", "Tag", "", NULL, 0));
+ ASSERT_EQ(-EEXIST, ioctx.lock_shared("foo", "TestLockECPP2", "Cookie", "Tag", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockECPP, LockExclusiveDurPP) {
+ struct timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ auto lock_exclusive = [this](timeval* tv) {
+ return ioctx.lock_exclusive("foo", "TestLockECPP3", "Cookie", "", tv, 0);
+ };
+ constexpr int expected = 0;
+ ASSERT_EQ(expected, lock_exclusive(&tv));
+ ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_exclusive, nullptr));
+}
+
+TEST_F(LibRadosLockECPP, LockSharedDurPP) {
+ struct timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ auto lock_shared = [this](timeval* tv) {
+ return ioctx.lock_shared("foo", "TestLockECPP4", "Cookie", "Tag", "", tv, 0);
+ };
+ const int expected = 0;
+ ASSERT_EQ(expected, lock_shared(&tv));
+ ASSERT_EQ(expected, wait_until(1.0s, 0.1s, expected, lock_shared, nullptr));
+}
+
+TEST_F(LibRadosLockECPP, LockMayRenewPP) {
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP5", "Cookie", "", NULL, 0));
+ ASSERT_EQ(-EEXIST, ioctx.lock_exclusive("foo", "TestLockECPP5", "Cookie", "", NULL, 0));
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP5", "Cookie", "", NULL, LOCK_FLAG_MAY_RENEW));
+}
+
+TEST_F(LibRadosLockECPP, UnlockPP) {
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP6", "Cookie", "", NULL, 0));
+ ASSERT_EQ(0, ioctx.unlock("foo", "TestLockECPP6", "Cookie"));
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP6", "Cookie", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockECPP, ListLockersPP) {
+ std::stringstream sstm;
+ sstm << "client." << cluster.get_instance_id();
+ std::string me = sstm.str();
+ ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockECPP7", "Cookie", "Tag", "", NULL, 0));
+ ASSERT_EQ(0, ioctx.unlock("foo", "TestLockECPP7", "Cookie"));
+ {
+ int exclusive;
+ std::string tag;
+ std::list<librados::locker_t> lockers;
+ ASSERT_EQ(0, ioctx.list_lockers("foo", "TestLockECPP7", &exclusive, &tag, &lockers));
+ }
+ ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLockECPP7", "Cookie", "Tag", "", NULL, 0));
+ {
+ int exclusive;
+ std::string tag;
+ std::list<librados::locker_t> lockers;
+ ASSERT_EQ(1, ioctx.list_lockers("foo", "TestLockECPP7", &exclusive, &tag, &lockers));
+ std::list<librados::locker_t>::iterator it = lockers.begin();
+ ASSERT_FALSE(lockers.end() == it);
+ ASSERT_EQ(me, it->client);
+ ASSERT_EQ("Cookie", it->cookie);
+ }
+}
+
+TEST_F(LibRadosLockECPP, BreakLockPP) {
+ int exclusive;
+ std::string tag;
+ std::list<librados::locker_t> lockers;
+ std::stringstream sstm;
+ sstm << "client." << cluster.get_instance_id();
+ std::string me = sstm.str();
+ ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLockECPP8", "Cookie", "", NULL, 0));
+ ASSERT_EQ(1, ioctx.list_lockers("foo", "TestLockECPP8", &exclusive, &tag, &lockers));
+ std::list<librados::locker_t>::iterator it = lockers.begin();
+ ASSERT_FALSE(lockers.end() == it);
+ ASSERT_EQ(me, it->client);
+ ASSERT_EQ("Cookie", it->cookie);
+ ASSERT_EQ(0, ioctx.break_lock("foo", "TestLockECPP8", it->client, "Cookie"));
+}
diff --git a/src/test/librados/misc.cc b/src/test/librados/misc.cc
index 50f87186566..5f7fdd889f5 100644
--- a/src/test/librados/misc.cc
+++ b/src/test/librados/misc.cc
@@ -29,19 +29,12 @@ using std::ostringstream;
using std::string;
typedef RadosTest LibRadosMisc;
-typedef RadosTestPP LibRadosMiscPP;
-typedef RadosTestECPP LibRadosMiscECPP;
TEST(LibRadosMiscVersion, Version) {
int major, minor, extra;
rados_version(&major, &minor, &extra);
}
-TEST(LibRadosMiscVersion, VersionPP) {
- int major, minor, extra;
- Rados::version(&major, &minor, &extra);
-}
-
static void test_rados_log_cb(void *arg,
const char *line,
const char *who,
@@ -161,350 +154,6 @@ TEST_F(LibRadosMisc, ClusterFSID) {
(size_t)rados_cluster_fsid(cluster, fsid, sizeof(fsid)));
}
-TEST_F(LibRadosMiscPP, WaitOSDMapPP) {
- ASSERT_EQ(0, cluster.wait_for_latest_osdmap());
-}
-
-TEST_F(LibRadosMiscPP, LongNamePP) {
- bufferlist bl;
- bl.append("content");
- int maxlen = g_conf()->osd_max_object_name_len;
- ASSERT_EQ(0, ioctx.write(string(maxlen/2, 'a').c_str(), bl, bl.length(), 0));
- ASSERT_EQ(0, ioctx.write(string(maxlen-1, 'a').c_str(), bl, bl.length(), 0));
- ASSERT_EQ(0, ioctx.write(string(maxlen, 'a').c_str(), bl, bl.length(), 0));
- ASSERT_EQ(-ENAMETOOLONG, ioctx.write(string(maxlen+1, 'a').c_str(), bl, bl.length(), 0));
- ASSERT_EQ(-ENAMETOOLONG, ioctx.write(string(maxlen*2, 'a').c_str(), bl, bl.length(), 0));
-}
-
-TEST_F(LibRadosMiscPP, LongLocatorPP) {
- bufferlist bl;
- bl.append("content");
- int maxlen = g_conf()->osd_max_object_name_len;
- ioctx.locator_set_key(
- string((maxlen/2), 'a'));
- ASSERT_EQ(
- 0,
- ioctx.write(
- string("a").c_str(),
- bl, bl.length(), 0));
- ioctx.locator_set_key(
- string(maxlen - 1, 'a'));
- ASSERT_EQ(
- 0,
- ioctx.write(
- string("a").c_str(),
- bl, bl.length(), 0));
- ioctx.locator_set_key(
- string(maxlen, 'a'));
- ASSERT_EQ(
- 0,
- ioctx.write(
- string("a").c_str(),
- bl, bl.length(), 0));
- ioctx.locator_set_key(
- string(maxlen+1, 'a'));
- ASSERT_EQ(
- -ENAMETOOLONG,
- ioctx.write(
- string("a").c_str(),
- bl, bl.length(), 0));
- ioctx.locator_set_key(
- string((maxlen*2), 'a'));
- ASSERT_EQ(
- -ENAMETOOLONG,
- ioctx.write(
- string("a").c_str(),
- bl, bl.length(), 0));
-}
-
-TEST_F(LibRadosMiscPP, LongNSpacePP) {
- bufferlist bl;
- bl.append("content");
- int maxlen = g_conf()->osd_max_object_namespace_len;
- ioctx.set_namespace(
- string((maxlen/2), 'a'));
- ASSERT_EQ(
- 0,
- ioctx.write(
- string("a").c_str(),
- bl, bl.length(), 0));
- ioctx.set_namespace(
- string(maxlen - 1, 'a'));
- ASSERT_EQ(
- 0,
- ioctx.write(
- string("a").c_str(),
- bl, bl.length(), 0));
- ioctx.set_namespace(
- string(maxlen, 'a'));
- ASSERT_EQ(
- 0,
- ioctx.write(
- string("a").c_str(),
- bl, bl.length(), 0));
- ioctx.set_namespace(
- string(maxlen+1, 'a'));
- ASSERT_EQ(
- -ENAMETOOLONG,
- ioctx.write(
- string("a").c_str(),
- bl, bl.length(), 0));
- ioctx.set_namespace(
- string((maxlen*2), 'a'));
- ASSERT_EQ(
- -ENAMETOOLONG,
- ioctx.write(
- string("a").c_str(),
- bl, bl.length(), 0));
-}
-
-TEST_F(LibRadosMiscPP, LongAttrNamePP) {
- bufferlist bl;
- bl.append("content");
- int maxlen = g_conf()->osd_max_attr_name_len;
- ASSERT_EQ(0, ioctx.setxattr("bigattrobj", string(maxlen/2, 'a').c_str(), bl));
- ASSERT_EQ(0, ioctx.setxattr("bigattrobj", string(maxlen-1, 'a').c_str(), bl));
- ASSERT_EQ(0, ioctx.setxattr("bigattrobj", string(maxlen, 'a').c_str(), bl));
- ASSERT_EQ(-ENAMETOOLONG, ioctx.setxattr("bigattrobj", string(maxlen+1, 'a').c_str(), bl));
- ASSERT_EQ(-ENAMETOOLONG, ioctx.setxattr("bigattrobj", string(maxlen*2, 'a').c_str(), bl));
-}
-
-static std::string read_key_from_tmap(IoCtx& ioctx, const std::string &obj,
- const std::string &key)
-{
- bufferlist bl;
- int r = ioctx.read(obj, bl, 0, 0);
- if (r <= 0) {
- ostringstream oss;
- oss << "ioctx.read(" << obj << ", bl, 0, 0) returned " << r;
- return oss.str();
- }
- auto p = bl.cbegin();
- bufferlist header;
- map<string, bufferlist> m;
- decode(header, p);
- decode(m, p);
- map<string, bufferlist>::iterator i = m.find(key);
- if (i == m.end())
- return "";
- std::string retstring;
- decode(retstring, i->second);
- return retstring;
-}
-
-static std::string add_key_to_tmap(IoCtx &ioctx, const std::string &obj,
- const std::string &key, const std::string &val)
-{
- __u8 c = CEPH_OSD_TMAP_SET;
-
- bufferlist tmbl;
- encode(c, tmbl);
- encode(key, tmbl);
- bufferlist blbl;
- encode(val, blbl);
- encode(blbl, tmbl);
- int ret = ioctx.tmap_update(obj, tmbl);
- if (ret) {
- ostringstream oss;
- oss << "ioctx.tmap_update(obj=" << obj << ", key="
- << key << ", val=" << val << ") failed with error " << ret;
- return oss.str();
- }
- return "";
-}
-
-static int remove_key_from_tmap(IoCtx &ioctx, const std::string &obj,
- const std::string &key)
-{
- __u8 c = CEPH_OSD_TMAP_RM;
-
- bufferlist tmbl;
- encode(c, tmbl);
- encode(key, tmbl);
- int ret = ioctx.tmap_update(obj, tmbl);
- if (ret) {
- ostringstream oss;
- oss << "ioctx.tmap_update(obj=" << obj << ", key="
- << key << ") failed with error " << ret;
- }
- return ret;
-}
-
-TEST_F(LibRadosMiscPP, TmapUpdatePP) {
- // create tmap
- {
- __u8 c = CEPH_OSD_TMAP_CREATE;
- std::string my_tmap("my_tmap");
- bufferlist emptybl;
-
- bufferlist tmbl;
- encode(c, tmbl);
- encode(my_tmap, tmbl);
- encode(emptybl, tmbl);
- ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl));
- }
-
- ASSERT_EQ(string(""), add_key_to_tmap(ioctx, "foo", "key1", "val1"));
-
- ASSERT_EQ(string(""), add_key_to_tmap(ioctx, "foo", "key2", "val2"));
-
- // read key1 from the tmap
- ASSERT_EQ(string("val1"), read_key_from_tmap(ioctx, "foo", "key1"));
-
- // remove key1 from tmap
- ASSERT_EQ(0, remove_key_from_tmap(ioctx, "foo", "key1"));
- ASSERT_EQ(-ENOENT, remove_key_from_tmap(ioctx, "foo", "key1"));
-
- // key should be removed
- ASSERT_EQ(string(""), read_key_from_tmap(ioctx, "foo", "key1"));
-}
-
-TEST_F(LibRadosMiscPP, TmapUpdateMisorderedPP) {
- // create tmap
- {
- __u8 c = CEPH_OSD_TMAP_CREATE;
- std::string my_tmap("my_tmap");
- bufferlist emptybl;
-
- bufferlist tmbl;
- encode(c, tmbl);
- encode(my_tmap, tmbl);
- encode(emptybl, tmbl);
- ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl));
- }
-
- // good update
- {
- __u8 c = CEPH_OSD_TMAP_SET;
- bufferlist tmbl;
- encode(c, tmbl);
- encode("a", tmbl);
- bufferlist blbl;
- encode("old", blbl);
- encode(blbl, tmbl);
-
- encode(c, tmbl);
- encode("b", tmbl);
- encode(blbl, tmbl);
-
- encode(c, tmbl);
- encode("c", tmbl);
- encode(blbl, tmbl);
-
- ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl));
- }
-
- // bad update
- {
- __u8 c = CEPH_OSD_TMAP_SET;
- bufferlist tmbl;
- encode(c, tmbl);
- encode("b", tmbl);
- bufferlist blbl;
- encode("new", blbl);
- encode(blbl, tmbl);
-
- encode(c, tmbl);
- encode("a", tmbl);
- encode(blbl, tmbl);
-
- encode(c, tmbl);
- encode("c", tmbl);
- encode(blbl, tmbl);
-
- ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl));
- }
-
- // check
- ASSERT_EQ(string("new"), read_key_from_tmap(ioctx, "foo", "a"));
- ASSERT_EQ(string("new"), read_key_from_tmap(ioctx, "foo", "b"));
- ASSERT_EQ(string("new"), read_key_from_tmap(ioctx, "foo", "c"));
-
- ASSERT_EQ(0, remove_key_from_tmap(ioctx, "foo", "a"));
- ASSERT_EQ(string(""), read_key_from_tmap(ioctx, "foo", "a"));
-
- ASSERT_EQ(0, remove_key_from_tmap(ioctx, "foo", "b"));
- ASSERT_EQ(string(""), read_key_from_tmap(ioctx, "foo", "a"));
-}
-
-TEST_F(LibRadosMiscPP, TmapUpdateMisorderedPutPP) {
- // create unsorted tmap
- string h("header");
- bufferlist bl;
- encode(h, bl);
- uint32_t n = 3;
- encode(n, bl);
- encode(string("b"), bl);
- encode(string("bval"), bl);
- encode(string("a"), bl);
- encode(string("aval"), bl);
- encode(string("c"), bl);
- encode(string("cval"), bl);
- bufferlist orig = bl; // tmap_put steals bl content
- ASSERT_EQ(0, ioctx.tmap_put("foo", bl));
-
- // check
- bufferlist newbl;
- ioctx.read("foo", newbl, orig.length(), 0);
- ASSERT_EQ(orig.contents_equal(newbl), false);
-}
-
-TEST_F(LibRadosMiscPP, Tmap2OmapPP) {
- // create tmap
- bufferlist hdr;
- hdr.append("header");
- map<string, bufferlist> omap;
- omap["1"].append("a");
- omap["2"].append("b");
- omap["3"].append("c");
- {
- bufferlist bl;
- encode(hdr, bl);
- encode(omap, bl);
- ASSERT_EQ(0, ioctx.tmap_put("foo", bl));
- }
-
- // convert tmap to omap
- ASSERT_EQ(0, ioctx.tmap_to_omap("foo", false));
-
- // if tmap was truncated ?
- {
- uint64_t size;
- time_t mtime;
- ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
- ASSERT_EQ(0U, size);
- }
-
- // if 'nullok' works
- ASSERT_EQ(0, ioctx.tmap_to_omap("foo", true));
- ASSERT_LE(ioctx.tmap_to_omap("foo", false), 0);
-
- {
- // read omap
- bufferlist got;
- map<string, bufferlist> m;
- ObjectReadOperation o;
- o.omap_get_header(&got, NULL);
- o.omap_get_vals2("", 1024, &m, nullptr, nullptr);
- ASSERT_EQ(0, ioctx.operate("foo", &o, NULL));
-
- // compare header
- ASSERT_TRUE(hdr.contents_equal(got));
-
- // compare values
- ASSERT_EQ(omap.size(), m.size());
- bool same = true;
- for (map<string, bufferlist>::iterator p = omap.begin(); p != omap.end(); ++p) {
- map<string, bufferlist>::iterator q = m.find(p->first);
- if (q == m.end() || !p->second.contents_equal(q->second)) {
- same = false;
- break;
- }
- }
- ASSERT_TRUE(same);
- }
-}
-
TEST_F(LibRadosMisc, Exec) {
char buf[128];
memset(buf, 0xcc, sizeof(buf));
@@ -522,535 +171,6 @@ TEST_F(LibRadosMisc, Exec) {
ASSERT_NE(all_features, (unsigned)0);
}
-TEST_F(LibRadosMiscPP, ExecPP) {
- bufferlist bl;
- ASSERT_EQ(0, ioctx.write("foo", bl, 0, 0));
- bufferlist bl2, out;
- int r = ioctx.exec("foo", "rbd", "get_all_features", bl2, out);
- ASSERT_EQ(0, r);
- auto iter = out.cbegin();
- uint64_t all_features;
- decode(all_features, iter);
- // make sure *some* features are specified; don't care which ones
- ASSERT_NE(all_features, (unsigned)0);
-}
-
-void set_completion_complete(rados_completion_t cb, void *arg)
-{
- bool *my_aio_complete = (bool*)arg;
- *my_aio_complete = true;
-}
-
-TEST_F(LibRadosMiscPP, BadFlagsPP) {
- unsigned badflags = CEPH_OSD_FLAG_PARALLELEXEC;
- {
- bufferlist bl;
- bl.append("data");
- ASSERT_EQ(0, ioctx.write("badfoo", bl, bl.length(), 0));
- }
- {
- ASSERT_EQ(-EINVAL, ioctx.remove("badfoo", badflags));
- }
-}
-
-TEST_F(LibRadosMiscPP, Operate1PP) {
- ObjectWriteOperation o;
- {
- bufferlist bl;
- o.write(0, bl);
- }
- std::string val1("val1");
- {
- bufferlist bl;
- bl.append(val1.c_str(), val1.size() + 1);
- o.setxattr("key1", bl);
- o.omap_clear(); // shouldn't affect attrs!
- }
- ASSERT_EQ(0, ioctx.operate("foo", &o));
-
- ObjectWriteOperation empty;
- ASSERT_EQ(0, ioctx.operate("foo", &empty));
-
- {
- bufferlist bl;
- ASSERT_GT(ioctx.getxattr("foo", "key1", bl), 0);
- ASSERT_EQ(0, strcmp(bl.c_str(), val1.c_str()));
- }
- ObjectWriteOperation o2;
- {
- bufferlist bl;
- bl.append(val1);
- o2.cmpxattr("key1", CEPH_OSD_CMPXATTR_OP_EQ, bl);
- o2.rmxattr("key1");
- }
- ASSERT_EQ(-ECANCELED, ioctx.operate("foo", &o2));
- ObjectWriteOperation o3;
- {
- bufferlist bl;
- bl.append(val1);
- o3.cmpxattr("key1", CEPH_OSD_CMPXATTR_OP_EQ, bl);
- }
- ASSERT_EQ(-ECANCELED, ioctx.operate("foo", &o3));
-}
-
-TEST_F(LibRadosMiscPP, Operate2PP) {
- ObjectWriteOperation o;
- {
- bufferlist bl;
- bl.append("abcdefg");
- o.write(0, bl);
- }
- std::string val1("val1");
- {
- bufferlist bl;
- bl.append(val1.c_str(), val1.size() + 1);
- o.setxattr("key1", bl);
- o.truncate(0);
- }
- ASSERT_EQ(0, ioctx.operate("foo", &o));
- uint64_t size;
- time_t mtime;
- ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
- ASSERT_EQ(0U, size);
-}
-
-TEST_F(LibRadosMiscPP, BigObjectPP) {
- bufferlist bl;
- bl.append("abcdefg");
- ASSERT_EQ(0, ioctx.write("foo", bl, bl.length(), 0));
-
- {
- ObjectWriteOperation o;
- o.truncate(500000000000ull);
- ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o));
- }
- {
- ObjectWriteOperation o;
- o.zero(500000000000ull, 1);
- ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o));
- }
- {
- ObjectWriteOperation o;
- o.zero(1, 500000000000ull);
- ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o));
- }
- {
- ObjectWriteOperation o;
- o.zero(500000000000ull, 500000000000ull);
- ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o));
- }
-
-#ifdef __LP64__
- // this test only works on 64-bit platforms
- ASSERT_EQ(-EFBIG, ioctx.write("foo", bl, bl.length(), 500000000000ull));
-#endif
-}
-
-TEST_F(LibRadosMiscPP, AioOperatePP) {
- bool my_aio_complete = false;
- AioCompletion *my_completion = cluster.aio_create_completion(
- (void*)&my_aio_complete, set_completion_complete, NULL);
- AioCompletion *my_completion_null = NULL;
- ASSERT_NE(my_completion, my_completion_null);
-
- ObjectWriteOperation o;
- {
- bufferlist bl;
- o.write(0, bl);
- }
- std::string val1("val1");
- {
- bufferlist bl;
- bl.append(val1.c_str(), val1.size() + 1);
- o.setxattr("key1", bl);
- bufferlist bl2;
- char buf2[1024];
- memset(buf2, 0xdd, sizeof(buf2));
- bl2.append(buf2, sizeof(buf2));
- o.append(bl2);
- }
- ASSERT_EQ(0, ioctx.aio_operate("foo", my_completion, &o));
- ASSERT_EQ(0, my_completion->wait_for_complete_and_cb());
- ASSERT_EQ(my_aio_complete, true);
- my_completion->release();
-
- uint64_t size;
- time_t mtime;
- ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
- ASSERT_EQ(1024U, size);
-}
-
-TEST_F(LibRadosMiscPP, AssertExistsPP) {
- char buf[64];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- ObjectWriteOperation op;
- op.assert_exists();
- op.write(0, bl);
- ASSERT_EQ(-ENOENT, ioctx.operate("asdffoo", &op));
- ASSERT_EQ(0, ioctx.create("asdffoo", true));
- ASSERT_EQ(0, ioctx.operate("asdffoo", &op));
- ASSERT_EQ(-EEXIST, ioctx.create("asdffoo", true));
-}
-
-TEST_F(LibRadosMiscPP, AssertVersionPP) {
- char buf[64];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- // Create test object...
- ASSERT_EQ(0, ioctx.create("asdfbar", true));
- // ...then write it again to guarantee that the
- // (unsigned) version must be at least 1 (not 0)
- // since we want to decrement it by 1 later.
- ASSERT_EQ(0, ioctx.write_full("asdfbar", bl));
-
- uint64_t v = ioctx.get_last_version();
- ObjectWriteOperation op1;
- op1.assert_version(v+1);
- op1.write(0, bl);
- ASSERT_EQ(-EOVERFLOW, ioctx.operate("asdfbar", &op1));
- ObjectWriteOperation op2;
- op2.assert_version(v-1);
- op2.write(0, bl);
- ASSERT_EQ(-ERANGE, ioctx.operate("asdfbar", &op2));
- ObjectWriteOperation op3;
- op3.assert_version(v);
- op3.write(0, bl);
- ASSERT_EQ(0, ioctx.operate("asdfbar", &op3));
-}
-
-TEST_F(LibRadosMiscPP, BigAttrPP) {
- char buf[64];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- ASSERT_EQ(0, ioctx.create("foo", true));
-
- bufferlist got;
-
- cout << "osd_max_attr_size = " << g_conf()->osd_max_attr_size << std::endl;
- if (g_conf()->osd_max_attr_size) {
- bl.clear();
- got.clear();
- bl.append(buffer::create(g_conf()->osd_max_attr_size));
- ASSERT_EQ(0, ioctx.setxattr("foo", "one", bl));
- ASSERT_EQ((int)bl.length(), ioctx.getxattr("foo", "one", got));
- ASSERT_TRUE(bl.contents_equal(got));
-
- bl.clear();
- bl.append(buffer::create(g_conf()->osd_max_attr_size+1));
- ASSERT_EQ(-EFBIG, ioctx.setxattr("foo", "one", bl));
- } else {
- cout << "osd_max_attr_size == 0; skipping test" << std::endl;
- }
-
- for (int i=0; i<1000; i++) {
- bl.clear();
- got.clear();
- bl.append(buffer::create(std::min<uint64_t>(g_conf()->osd_max_attr_size,
- 1024)));
- char n[10];
- snprintf(n, sizeof(n), "a%d", i);
- ASSERT_EQ(0, ioctx.setxattr("foo", n, bl));
- ASSERT_EQ((int)bl.length(), ioctx.getxattr("foo", n, got));
- ASSERT_TRUE(bl.contents_equal(got));
- }
-}
-
-TEST_F(LibRadosMiscPP, CopyPP) {
- bufferlist bl, x;
- bl.append("hi there");
- x.append("bar");
-
- // small object
- bufferlist blc = bl;
- bufferlist xc = x;
- ASSERT_EQ(0, ioctx.write_full("foo", blc));
- ASSERT_EQ(0, ioctx.setxattr("foo", "myattr", xc));
-
- version_t uv = ioctx.get_last_version();
- {
- // pass future version
- ObjectWriteOperation op;
- op.copy_from2("foo", ioctx, uv + 1, LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ASSERT_EQ(-EOVERFLOW, ioctx.operate("foo.copy", &op));
- }
- {
- // pass old version
- ObjectWriteOperation op;
- op.copy_from2("foo", ioctx, uv - 1, LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ASSERT_EQ(-ERANGE, ioctx.operate("foo.copy", &op));
- }
- {
- ObjectWriteOperation op;
- op.copy_from2("foo", ioctx, uv, LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ASSERT_EQ(0, ioctx.operate("foo.copy", &op));
-
- bufferlist bl2, x2;
- ASSERT_EQ((int)bl.length(), ioctx.read("foo.copy", bl2, 10000, 0));
- ASSERT_TRUE(bl.contents_equal(bl2));
- ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy", "myattr", x2));
- ASSERT_TRUE(x.contents_equal(x2));
- }
-
- // small object without a version
- {
- ObjectWriteOperation op;
- op.copy_from2("foo", ioctx, 0, LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ASSERT_EQ(0, ioctx.operate("foo.copy2", &op));
-
- bufferlist bl2, x2;
- ASSERT_EQ((int)bl.length(), ioctx.read("foo.copy2", bl2, 10000, 0));
- ASSERT_TRUE(bl.contents_equal(bl2));
- ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy2", "myattr", x2));
- ASSERT_TRUE(x.contents_equal(x2));
- }
-
- // do a big object
- bl.append(buffer::create(g_conf()->osd_copyfrom_max_chunk * 3));
- bl.zero();
- bl.append("tail");
- blc = bl;
- xc = x;
- ASSERT_EQ(0, ioctx.write_full("big", blc));
- ASSERT_EQ(0, ioctx.setxattr("big", "myattr", xc));
-
- {
- ObjectWriteOperation op;
- op.copy_from2("big", ioctx, ioctx.get_last_version(), LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
- ASSERT_EQ(0, ioctx.operate("big.copy", &op));
-
- bufferlist bl2, x2;
- ASSERT_EQ((int)bl.length(), ioctx.read("big.copy", bl2, bl.length(), 0));
- ASSERT_TRUE(bl.contents_equal(bl2));
- ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy", "myattr", x2));
- ASSERT_TRUE(x.contents_equal(x2));
- }
-
- {
- ObjectWriteOperation op;
- op.copy_from2("big", ioctx, 0, LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL);
- ASSERT_EQ(0, ioctx.operate("big.copy2", &op));
-
- bufferlist bl2, x2;
- ASSERT_EQ((int)bl.length(), ioctx.read("big.copy2", bl2, bl.length(), 0));
- ASSERT_TRUE(bl.contents_equal(bl2));
- ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy2", "myattr", x2));
- ASSERT_TRUE(x.contents_equal(x2));
- }
-}
-
-class LibRadosTwoPoolsECPP : public RadosTestECPP
-{
-public:
- LibRadosTwoPoolsECPP() {};
- ~LibRadosTwoPoolsECPP() override {};
-protected:
- static void SetUpTestCase() {
- pool_name = get_temp_pool_name();
- ASSERT_EQ("", create_one_ec_pool_pp(pool_name, s_cluster));
- src_pool_name = get_temp_pool_name();
- ASSERT_EQ(0, s_cluster.pool_create(src_pool_name.c_str()));
-
- librados::IoCtx ioctx;
- ASSERT_EQ(0, s_cluster.ioctx_create(pool_name.c_str(), ioctx));
- ioctx.application_enable("rados", true);
-
- librados::IoCtx src_ioctx;
- ASSERT_EQ(0, s_cluster.ioctx_create(src_pool_name.c_str(), src_ioctx));
- src_ioctx.application_enable("rados", true);
- }
- static void TearDownTestCase() {
- ASSERT_EQ(0, s_cluster.pool_delete(src_pool_name.c_str()));
- ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, s_cluster));
- }
- static std::string src_pool_name;
-
- void SetUp() override {
- RadosTestECPP::SetUp();
- ASSERT_EQ(0, cluster.ioctx_create(src_pool_name.c_str(), src_ioctx));
- src_ioctx.set_namespace(nspace);
- }
- void TearDown() override {
- // wait for maps to settle before next test
- cluster.wait_for_latest_osdmap();
-
- RadosTestECPP::TearDown();
-
- cleanup_default_namespace(src_ioctx);
- cleanup_namespace(src_ioctx, nspace);
-
- src_ioctx.close();
- }
-
- librados::IoCtx src_ioctx;
-};
-std::string LibRadosTwoPoolsECPP::src_pool_name;
-
-//copy_from between ecpool and no-ecpool.
-TEST_F(LibRadosTwoPoolsECPP, CopyFrom) {
- bufferlist z;
- z.append_zero(4194304*2);
- bufferlist b;
- b.append("copyfrom");
-
- // create big object w/ omapheader
- {
- ASSERT_EQ(0, src_ioctx.write_full("foo", z));
- ASSERT_EQ(0, src_ioctx.omap_set_header("foo", b));
- version_t uv = src_ioctx.get_last_version();
- ObjectWriteOperation op;
- op.copy_from("foo", src_ioctx, uv);
- ASSERT_EQ(-EOPNOTSUPP, ioctx.operate("foo.copy", &op));
- }
-
- // same with small object
- {
- ASSERT_EQ(0, src_ioctx.omap_set_header("bar", b));
- version_t uv = src_ioctx.get_last_version();
- ObjectWriteOperation op;
- op.copy_from("bar", src_ioctx, uv);
- ASSERT_EQ(-EOPNOTSUPP, ioctx.operate("bar.copy", &op));
- }
-}
-
-TEST_F(LibRadosMiscPP, CopyScrubPP) {
- bufferlist inbl, bl, x;
- for (int i=0; i<100; ++i)
- x.append("barrrrrrrrrrrrrrrrrrrrrrrrrr");
- bl.append(buffer::create(g_conf()->osd_copyfrom_max_chunk * 3));
- bl.zero();
- bl.append("tail");
- bufferlist cbl;
-
- map<string, bufferlist> to_set;
- for (int i=0; i<1000; ++i)
- to_set[string("foo") + stringify(i)] = x;
-
- // small
- cbl = x;
- ASSERT_EQ(0, ioctx.write_full("small", cbl));
- ASSERT_EQ(0, ioctx.setxattr("small", "myattr", x));
-
- // big
- cbl = bl;
- ASSERT_EQ(0, ioctx.write_full("big", cbl));
-
- // without header
- cbl = bl;
- ASSERT_EQ(0, ioctx.write_full("big2", cbl));
- ASSERT_EQ(0, ioctx.setxattr("big2", "myattr", x));
- ASSERT_EQ(0, ioctx.setxattr("big2", "myattr2", x));
- ASSERT_EQ(0, ioctx.omap_set("big2", to_set));
-
- // with header
- cbl = bl;
- ASSERT_EQ(0, ioctx.write_full("big3", cbl));
- ASSERT_EQ(0, ioctx.omap_set_header("big3", x));
- ASSERT_EQ(0, ioctx.omap_set("big3", to_set));
-
- // deep scrub to ensure digests are in place
- {
- for (int i=0; i<10; ++i) {
- ostringstream ss;
- ss << "{\"prefix\": \"pg deep-scrub\", \"pgid\": \""
- << ioctx.get_id() << "." << i
- << "\"}";
- cluster.mon_command(ss.str(), inbl, NULL, NULL);
- }
-
- // give it a few seconds to go. this is sloppy but is usually enough time
- cout << "waiting for initial deep scrubs..." << std::endl;
- sleep(30);
- cout << "done waiting, doing copies" << std::endl;
- }
-
- {
- ObjectWriteOperation op;
- op.copy_from("small", ioctx, 0);
- ASSERT_EQ(0, ioctx.operate("small.copy", &op));
- }
-
- {
- ObjectWriteOperation op;
- op.copy_from("big", ioctx, 0);
- ASSERT_EQ(0, ioctx.operate("big.copy", &op));
- }
-
- {
- ObjectWriteOperation op;
- op.copy_from("big2", ioctx, 0);
- ASSERT_EQ(0, ioctx.operate("big2.copy", &op));
- }
-
- {
- ObjectWriteOperation op;
- op.copy_from("big3", ioctx, 0);
- ASSERT_EQ(0, ioctx.operate("big3.copy", &op));
- }
-
- // deep scrub to ensure digests are correct
- {
- for (int i=0; i<10; ++i) {
- ostringstream ss;
- ss << "{\"prefix\": \"pg deep-scrub\", \"pgid\": \""
- << ioctx.get_id() << "." << i
- << "\"}";
- cluster.mon_command(ss.str(), inbl, NULL, NULL);
- }
-
- // give it a few seconds to go. this is sloppy but is usually enough time
- cout << "waiting for final deep scrubs..." << std::endl;
- sleep(30);
- cout << "done waiting" << std::endl;
- }
-}
-
-TEST_F(LibRadosMiscPP, WriteSamePP) {
- bufferlist bl;
- char buf[128];
- bufferlist fl;
- char full[128 * 4];
- char *cmp;
-
- /* zero the full range before using writesame */
- memset(full, 0, sizeof(full));
- fl.append(full, sizeof(full));
- ASSERT_EQ(0, ioctx.write("ws", fl, fl.length(), 0));
-
- memset(buf, 0xcc, sizeof(buf));
- bl.clear();
- bl.append(buf, sizeof(buf));
- /* write the same buf four times */
- ASSERT_EQ(0, ioctx.writesame("ws", bl, sizeof(full), 0));
-
- /* read back the full buffer and confirm that it matches */
- fl.clear();
- fl.append(full, sizeof(full));
- ASSERT_EQ((int)fl.length(), ioctx.read("ws", fl, fl.length(), 0));
-
- for (cmp = fl.c_str(); cmp < fl.c_str() + fl.length(); cmp += sizeof(buf)) {
- ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
- }
-
- /* write_len not a multiple of data_len should throw error */
- bl.clear();
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(-EINVAL, ioctx.writesame("ws", bl, (sizeof(buf) * 4) - 1, 0));
- ASSERT_EQ(-EINVAL,
- ioctx.writesame("ws", bl, bl.length() / 2, 0));
- /* write_len = data_len, i.e. same as write() */
- ASSERT_EQ(0, ioctx.writesame("ws", bl, sizeof(buf), 0));
- bl.clear();
- ASSERT_EQ(-EINVAL,
- ioctx.writesame("ws", bl, sizeof(buf), 0));
-}
-
TEST_F(LibRadosMisc, WriteSame) {
char buf[128];
char full[128 * 4];
@@ -1082,147 +202,6 @@ TEST_F(LibRadosMisc, WriteSame) {
ASSERT_EQ(0, rados_writesame(ioctx, "ws", buf, sizeof(buf), sizeof(buf), 0));
}
-template <typename T>
-class LibRadosChecksum : public LibRadosMiscPP {
-public:
- typedef typename T::alg_t alg_t;
- typedef typename T::value_t value_t;
- typedef typename alg_t::init_value_t init_value_t;
-
- static const rados_checksum_type_t type = T::type;
-
- bufferlist content_bl;
-
- using LibRadosMiscPP::SetUpTestCase;
- using LibRadosMiscPP::TearDownTestCase;
-
- void SetUp() override {
- LibRadosMiscPP::SetUp();
-
- std::string content(4096, '\0');
- for (size_t i = 0; i < content.length(); ++i) {
- content[i] = static_cast<char>(rand() % (126 - 33) + 33);
- }
- content_bl.append(content);
- ASSERT_EQ(0, ioctx.write("foo", content_bl, content_bl.length(), 0));
- }
-};
-
-template <rados_checksum_type_t _type, typename AlgT, typename ValueT>
-class LibRadosChecksumParams {
-public:
- typedef AlgT alg_t;
- typedef ValueT value_t;
- static const rados_checksum_type_t type = _type;
-};
-
-typedef ::testing::Types<
- LibRadosChecksumParams<LIBRADOS_CHECKSUM_TYPE_XXHASH32,
- Checksummer::xxhash32, uint32_t>,
- LibRadosChecksumParams<LIBRADOS_CHECKSUM_TYPE_XXHASH64,
- Checksummer::xxhash64, uint64_t>,
- LibRadosChecksumParams<LIBRADOS_CHECKSUM_TYPE_CRC32C,
- Checksummer::crc32c, uint32_t>
- > LibRadosChecksumTypes;
-
-TYPED_TEST_CASE(LibRadosChecksum, LibRadosChecksumTypes);
-
-TYPED_TEST(LibRadosChecksum, Subset) {
- uint32_t chunk_size = 1024;
- uint32_t csum_count = this->content_bl.length() / chunk_size;
-
- typename TestFixture::init_value_t init_value = -1;
- bufferlist init_value_bl;
- encode(init_value, init_value_bl);
-
- std::vector<bufferlist> checksum_bls(csum_count);
- std::vector<int> checksum_rvals(csum_count);
-
- // individual checksum ops for each chunk
- ObjectReadOperation op;
- for (uint32_t i = 0; i < csum_count; ++i) {
- op.checksum(TestFixture::type, init_value_bl, i * chunk_size, chunk_size,
- 0, &checksum_bls[i], &checksum_rvals[i]);
- }
- ASSERT_EQ(0, this->ioctx.operate("foo", &op, NULL));
-
- for (uint32_t i = 0; i < csum_count; ++i) {
- ASSERT_EQ(0, checksum_rvals[i]);
-
- auto bl_it = checksum_bls[i].cbegin();
- uint32_t count;
- decode(count, bl_it);
- ASSERT_EQ(1U, count);
-
- typename TestFixture::value_t value;
- decode(value, bl_it);
-
- bufferlist content_sub_bl;
- content_sub_bl.substr_of(this->content_bl, i * chunk_size, chunk_size);
-
- typename TestFixture::value_t expected_value;
- bufferptr expected_value_bp = buffer::create_static(
- sizeof(expected_value), reinterpret_cast<char*>(&expected_value));
- Checksummer::template calculate<typename TestFixture::alg_t>(
- init_value, chunk_size, 0, chunk_size, content_sub_bl,
- &expected_value_bp);
- ASSERT_EQ(expected_value, value);
- }
-}
-
-TYPED_TEST(LibRadosChecksum, Chunked) {
- uint32_t chunk_size = 1024;
- uint32_t csum_count = this->content_bl.length() / chunk_size;
-
- typename TestFixture::init_value_t init_value = -1;
- bufferlist init_value_bl;
- encode(init_value, init_value_bl);
-
- bufferlist checksum_bl;
- int checksum_rval;
-
- // single op with chunked checksum results
- ObjectReadOperation op;
- op.checksum(TestFixture::type, init_value_bl, 0, this->content_bl.length(),
- chunk_size, &checksum_bl, &checksum_rval);
- ASSERT_EQ(0, this->ioctx.operate("foo", &op, NULL));
- ASSERT_EQ(0, checksum_rval);
-
- auto bl_it = checksum_bl.cbegin();
- uint32_t count;
- decode(count, bl_it);
- ASSERT_EQ(csum_count, count);
-
- std::vector<typename TestFixture::value_t> expected_values(csum_count);
- bufferptr expected_values_bp = buffer::create_static(
- csum_count * sizeof(typename TestFixture::value_t),
- reinterpret_cast<char*>(&expected_values[0]));
-
- Checksummer::template calculate<typename TestFixture::alg_t>(
- init_value, chunk_size, 0, this->content_bl.length(), this->content_bl,
- &expected_values_bp);
-
- for (uint32_t i = 0; i < csum_count; ++i) {
- typename TestFixture::value_t value;
- decode(value, bl_it);
- ASSERT_EQ(expected_values[i], value);
- }
-}
-
-TEST_F(LibRadosMiscPP, CmpExtPP) {
- bufferlist cmp_bl, bad_cmp_bl, write_bl;
- char stored_str[] = "1234567891";
- char mismatch_str[] = "1234577777";
-
- write_bl.append(stored_str);
- ioctx.write("cmpextpp", write_bl, write_bl.length(), 0);
- cmp_bl.append(stored_str);
- ASSERT_EQ(0, ioctx.cmpext("cmpextpp", 0, cmp_bl));
-
- bad_cmp_bl.append(mismatch_str);
- ASSERT_EQ(-MAX_ERRNO - 5, ioctx.cmpext("cmpextpp", 0, bad_cmp_bl));
-}
-
TEST_F(LibRadosMisc, CmpExt) {
bufferlist cmp_bl, bad_cmp_bl, write_bl;
char stored_str[] = "1234567891";
@@ -1310,74 +289,6 @@ TEST_F(LibRadosMisc, Applications) {
ASSERT_EQ(0, memcmp("value2\0", vals, val_len));
}
-TEST_F(LibRadosMiscPP, Applications) {
- bufferlist inbl, outbl;
- string outs;
- ASSERT_EQ(0, cluster.mon_command("{\"prefix\": \"osd dump\"}",
- inbl, &outbl, &outs));
- ASSERT_LT(0u, outbl.length());
- ASSERT_LE(0u, outs.length());
- if (!std::regex_search(outbl.to_str(),
- std::regex("require_osd_release [l-z]"))) {
- std::cout << "SKIPPING";
- return;
- }
-
- std::set<std::string> expected_apps = {"rados"};
- std::set<std::string> apps;
- ASSERT_EQ(0, ioctx.application_list(&apps));
- ASSERT_EQ(expected_apps, apps);
-
- ASSERT_EQ(0, ioctx.application_enable("app1", true));
- ASSERT_EQ(-EPERM, ioctx.application_enable("app2", false));
- ASSERT_EQ(0, ioctx.application_enable("app2", true));
-
- expected_apps = {"app1", "app2", "rados"};
- ASSERT_EQ(0, ioctx.application_list(&apps));
- ASSERT_EQ(expected_apps, apps);
-
- std::map<std::string, std::string> expected_meta;
- std::map<std::string, std::string> meta;
- ASSERT_EQ(-ENOENT, ioctx.application_metadata_list("dne", &meta));
- ASSERT_EQ(0, ioctx.application_metadata_list("app1", &meta));
- ASSERT_EQ(expected_meta, meta);
-
- ASSERT_EQ(-ENOENT, ioctx.application_metadata_set("dne", "key1", "value1"));
- ASSERT_EQ(0, ioctx.application_metadata_set("app1", "key1", "value1"));
- ASSERT_EQ(0, ioctx.application_metadata_set("app1", "key2", "value2"));
-
- expected_meta = {{"key1", "value1"}, {"key2", "value2"}};
- ASSERT_EQ(0, ioctx.application_metadata_list("app1", &meta));
- ASSERT_EQ(expected_meta, meta);
-
- ASSERT_EQ(0, ioctx.application_metadata_remove("app1", "key1"));
-
- expected_meta = {{"key2", "value2"}};
- ASSERT_EQ(0, ioctx.application_metadata_list("app1", &meta));
- ASSERT_EQ(expected_meta, meta);
-}
-
-TEST_F(LibRadosMiscECPP, CompareExtentRange) {
- bufferlist bl1;
- bl1.append("ceph");
- ObjectWriteOperation write;
- write.write(0, bl1);
- ASSERT_EQ(0, ioctx.operate("foo", &write));
-
- bufferlist bl2;
- bl2.append("ph");
- bl2.append(std::string(2, '\0'));
- ObjectReadOperation read1;
- read1.cmpext(2, bl2, nullptr);
- ASSERT_EQ(0, ioctx.operate("foo", &read1, nullptr));
-
- bufferlist bl3;
- bl3.append(std::string(4, '\0'));
- ObjectReadOperation read2;
- read2.cmpext(2097152, bl3, nullptr);
- ASSERT_EQ(0, ioctx.operate("foo", &read2, nullptr));
-}
-
TEST_F(LibRadosMisc, MinCompatOSD) {
int8_t require_osd_release;
ASSERT_EQ(0, rados_get_min_compatible_osd(cluster, &require_osd_release));
@@ -1385,13 +296,6 @@ TEST_F(LibRadosMisc, MinCompatOSD) {
ASSERT_GT(CEPH_RELEASE_MAX, require_osd_release);
}
-TEST_F(LibRadosMiscPP, MinCompatOSD) {
- int8_t require_osd_release;
- ASSERT_EQ(0, cluster.get_min_compatible_osd(&require_osd_release));
- ASSERT_LE(-1, require_osd_release);
- ASSERT_GT(CEPH_RELEASE_MAX, require_osd_release);
-}
-
TEST_F(LibRadosMisc, MinCompatClient) {
int8_t min_compat_client;
int8_t require_min_compat_client;
@@ -1404,30 +308,3 @@ TEST_F(LibRadosMisc, MinCompatClient) {
ASSERT_LE(-1, require_min_compat_client);
ASSERT_GT(CEPH_RELEASE_MAX, require_min_compat_client);
}
-
-TEST_F(LibRadosMiscPP, MinCompatClient) {
- int8_t min_compat_client;
- int8_t require_min_compat_client;
- ASSERT_EQ(0, cluster.get_min_compatible_client(&min_compat_client,
- &require_min_compat_client));
- ASSERT_LE(-1, min_compat_client);
- ASSERT_GT(CEPH_RELEASE_MAX, min_compat_client);
-
- ASSERT_LE(-1, require_min_compat_client);
- ASSERT_GT(CEPH_RELEASE_MAX, require_min_compat_client);
-}
-
-TEST_F(LibRadosMiscPP, Conf) {
- const char* const option = "bluestore_throttle_bytes";
- size_t new_size = 1 << 20;
- std::string original;
- ASSERT_EQ(0, cluster.conf_get(option, original));
- auto restore_setting = make_scope_guard([&] {
- cluster.conf_set(option, original.c_str());
- });
- std::string expected = std::to_string(new_size);
- ASSERT_EQ(0, cluster.conf_set(option, expected.c_str()));
- std::string actual;
- ASSERT_EQ(0, cluster.conf_get(option, actual));
- ASSERT_EQ(expected, actual);
-}
diff --git a/src/test/librados/misc_cxx.cc b/src/test/librados/misc_cxx.cc
new file mode 100644
index 00000000000..cf11c19d04c
--- /dev/null
+++ b/src/test/librados/misc_cxx.cc
@@ -0,0 +1,1151 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#include <errno.h>
+#include <map>
+#include <sstream>
+#include <string>
+#include <regex>
+
+#include "gtest/gtest.h"
+
+#include "include/err.h"
+#include "include/buffer.h"
+#include "include/rbd_types.h"
+#include "include/rados.h"
+#include "include/rados/librados.hpp"
+#include "include/scope_guard.h"
+#include "include/stringify.h"
+#include "common/Checksummer.h"
+#include "mds/mdstypes.h"
+#include "global/global_context.h"
+#include "test/librados/testcase_cxx.h"
+#include "test/librados/test_cxx.h"
+
+using namespace librados;
+using std::map;
+using std::ostringstream;
+using std::string;
+
+typedef RadosTestPP LibRadosMiscPP;
+typedef RadosTestECPP LibRadosMiscECPP;
+
+TEST(LibRadosMiscVersion, VersionPP) {
+ int major, minor, extra;
+ Rados::version(&major, &minor, &extra);
+}
+
+TEST_F(LibRadosMiscPP, WaitOSDMapPP) {
+ ASSERT_EQ(0, cluster.wait_for_latest_osdmap());
+}
+
+TEST_F(LibRadosMiscPP, LongNamePP) {
+ bufferlist bl;
+ bl.append("content");
+ int maxlen = g_conf()->osd_max_object_name_len;
+ ASSERT_EQ(0, ioctx.write(string(maxlen/2, 'a').c_str(), bl, bl.length(), 0));
+ ASSERT_EQ(0, ioctx.write(string(maxlen-1, 'a').c_str(), bl, bl.length(), 0));
+ ASSERT_EQ(0, ioctx.write(string(maxlen, 'a').c_str(), bl, bl.length(), 0));
+ ASSERT_EQ(-ENAMETOOLONG, ioctx.write(string(maxlen+1, 'a').c_str(), bl, bl.length(), 0));
+ ASSERT_EQ(-ENAMETOOLONG, ioctx.write(string(maxlen*2, 'a').c_str(), bl, bl.length(), 0));
+}
+
+TEST_F(LibRadosMiscPP, LongLocatorPP) {
+ bufferlist bl;
+ bl.append("content");
+ int maxlen = g_conf()->osd_max_object_name_len;
+ ioctx.locator_set_key(
+ string((maxlen/2), 'a'));
+ ASSERT_EQ(
+ 0,
+ ioctx.write(
+ string("a").c_str(),
+ bl, bl.length(), 0));
+ ioctx.locator_set_key(
+ string(maxlen - 1, 'a'));
+ ASSERT_EQ(
+ 0,
+ ioctx.write(
+ string("a").c_str(),
+ bl, bl.length(), 0));
+ ioctx.locator_set_key(
+ string(maxlen, 'a'));
+ ASSERT_EQ(
+ 0,
+ ioctx.write(
+ string("a").c_str(),
+ bl, bl.length(), 0));
+ ioctx.locator_set_key(
+ string(maxlen+1, 'a'));
+ ASSERT_EQ(
+ -ENAMETOOLONG,
+ ioctx.write(
+ string("a").c_str(),
+ bl, bl.length(), 0));
+ ioctx.locator_set_key(
+ string((maxlen*2), 'a'));
+ ASSERT_EQ(
+ -ENAMETOOLONG,
+ ioctx.write(
+ string("a").c_str(),
+ bl, bl.length(), 0));
+}
+
+TEST_F(LibRadosMiscPP, LongNSpacePP) {
+ bufferlist bl;
+ bl.append("content");
+ int maxlen = g_conf()->osd_max_object_namespace_len;
+ ioctx.set_namespace(
+ string((maxlen/2), 'a'));
+ ASSERT_EQ(
+ 0,
+ ioctx.write(
+ string("a").c_str(),
+ bl, bl.length(), 0));
+ ioctx.set_namespace(
+ string(maxlen - 1, 'a'));
+ ASSERT_EQ(
+ 0,
+ ioctx.write(
+ string("a").c_str(),
+ bl, bl.length(), 0));
+ ioctx.set_namespace(
+ string(maxlen, 'a'));
+ ASSERT_EQ(
+ 0,
+ ioctx.write(
+ string("a").c_str(),
+ bl, bl.length(), 0));
+ ioctx.set_namespace(
+ string(maxlen+1, 'a'));
+ ASSERT_EQ(
+ -ENAMETOOLONG,
+ ioctx.write(
+ string("a").c_str(),
+ bl, bl.length(), 0));
+ ioctx.set_namespace(
+ string((maxlen*2), 'a'));
+ ASSERT_EQ(
+ -ENAMETOOLONG,
+ ioctx.write(
+ string("a").c_str(),
+ bl, bl.length(), 0));
+}
+
+TEST_F(LibRadosMiscPP, LongAttrNamePP) {
+ bufferlist bl;
+ bl.append("content");
+ int maxlen = g_conf()->osd_max_attr_name_len;
+ ASSERT_EQ(0, ioctx.setxattr("bigattrobj", string(maxlen/2, 'a').c_str(), bl));
+ ASSERT_EQ(0, ioctx.setxattr("bigattrobj", string(maxlen-1, 'a').c_str(), bl));
+ ASSERT_EQ(0, ioctx.setxattr("bigattrobj", string(maxlen, 'a').c_str(), bl));
+ ASSERT_EQ(-ENAMETOOLONG, ioctx.setxattr("bigattrobj", string(maxlen+1, 'a').c_str(), bl));
+ ASSERT_EQ(-ENAMETOOLONG, ioctx.setxattr("bigattrobj", string(maxlen*2, 'a').c_str(), bl));
+}
+
+static std::string read_key_from_tmap(IoCtx& ioctx, const std::string &obj,
+ const std::string &key)
+{
+ bufferlist bl;
+ int r = ioctx.read(obj, bl, 0, 0);
+ if (r <= 0) {
+ ostringstream oss;
+ oss << "ioctx.read(" << obj << ", bl, 0, 0) returned " << r;
+ return oss.str();
+ }
+ auto p = bl.cbegin();
+ bufferlist header;
+ map<string, bufferlist> m;
+ decode(header, p);
+ decode(m, p);
+ map<string, bufferlist>::iterator i = m.find(key);
+ if (i == m.end())
+ return "";
+ std::string retstring;
+ decode(retstring, i->second);
+ return retstring;
+}
+
+static std::string add_key_to_tmap(IoCtx &ioctx, const std::string &obj,
+ const std::string &key, const std::string &val)
+{
+ __u8 c = CEPH_OSD_TMAP_SET;
+
+ bufferlist tmbl;
+ encode(c, tmbl);
+ encode(key, tmbl);
+ bufferlist blbl;
+ encode(val, blbl);
+ encode(blbl, tmbl);
+ int ret = ioctx.tmap_update(obj, tmbl);
+ if (ret) {
+ ostringstream oss;
+ oss << "ioctx.tmap_update(obj=" << obj << ", key="
+ << key << ", val=" << val << ") failed with error " << ret;
+ return oss.str();
+ }
+ return "";
+}
+
+static int remove_key_from_tmap(IoCtx &ioctx, const std::string &obj,
+ const std::string &key)
+{
+ __u8 c = CEPH_OSD_TMAP_RM;
+
+ bufferlist tmbl;
+ encode(c, tmbl);
+ encode(key, tmbl);
+ int ret = ioctx.tmap_update(obj, tmbl);
+ if (ret) {
+ ostringstream oss;
+ oss << "ioctx.tmap_update(obj=" << obj << ", key="
+ << key << ") failed with error " << ret;
+ }
+ return ret;
+}
+
+TEST_F(LibRadosMiscPP, TmapUpdatePP) {
+ // create tmap
+ {
+ __u8 c = CEPH_OSD_TMAP_CREATE;
+ std::string my_tmap("my_tmap");
+ bufferlist emptybl;
+
+ bufferlist tmbl;
+ encode(c, tmbl);
+ encode(my_tmap, tmbl);
+ encode(emptybl, tmbl);
+ ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl));
+ }
+
+ ASSERT_EQ(string(""), add_key_to_tmap(ioctx, "foo", "key1", "val1"));
+
+ ASSERT_EQ(string(""), add_key_to_tmap(ioctx, "foo", "key2", "val2"));
+
+ // read key1 from the tmap
+ ASSERT_EQ(string("val1"), read_key_from_tmap(ioctx, "foo", "key1"));
+
+ // remove key1 from tmap
+ ASSERT_EQ(0, remove_key_from_tmap(ioctx, "foo", "key1"));
+ ASSERT_EQ(-ENOENT, remove_key_from_tmap(ioctx, "foo", "key1"));
+
+ // key should be removed
+ ASSERT_EQ(string(""), read_key_from_tmap(ioctx, "foo", "key1"));
+}
+
+TEST_F(LibRadosMiscPP, TmapUpdateMisorderedPP) {
+ // create tmap
+ {
+ __u8 c = CEPH_OSD_TMAP_CREATE;
+ std::string my_tmap("my_tmap");
+ bufferlist emptybl;
+
+ bufferlist tmbl;
+ encode(c, tmbl);
+ encode(my_tmap, tmbl);
+ encode(emptybl, tmbl);
+ ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl));
+ }
+
+ // good update
+ {
+ __u8 c = CEPH_OSD_TMAP_SET;
+ bufferlist tmbl;
+ encode(c, tmbl);
+ encode("a", tmbl);
+ bufferlist blbl;
+ encode("old", blbl);
+ encode(blbl, tmbl);
+
+ encode(c, tmbl);
+ encode("b", tmbl);
+ encode(blbl, tmbl);
+
+ encode(c, tmbl);
+ encode("c", tmbl);
+ encode(blbl, tmbl);
+
+ ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl));
+ }
+
+ // bad update
+ {
+ __u8 c = CEPH_OSD_TMAP_SET;
+ bufferlist tmbl;
+ encode(c, tmbl);
+ encode("b", tmbl);
+ bufferlist blbl;
+ encode("new", blbl);
+ encode(blbl, tmbl);
+
+ encode(c, tmbl);
+ encode("a", tmbl);
+ encode(blbl, tmbl);
+
+ encode(c, tmbl);
+ encode("c", tmbl);
+ encode(blbl, tmbl);
+
+ ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl));
+ }
+
+ // check
+ ASSERT_EQ(string("new"), read_key_from_tmap(ioctx, "foo", "a"));
+ ASSERT_EQ(string("new"), read_key_from_tmap(ioctx, "foo", "b"));
+ ASSERT_EQ(string("new"), read_key_from_tmap(ioctx, "foo", "c"));
+
+ ASSERT_EQ(0, remove_key_from_tmap(ioctx, "foo", "a"));
+ ASSERT_EQ(string(""), read_key_from_tmap(ioctx, "foo", "a"));
+
+ ASSERT_EQ(0, remove_key_from_tmap(ioctx, "foo", "b"));
+ ASSERT_EQ(string(""), read_key_from_tmap(ioctx, "foo", "a"));
+}
+
+TEST_F(LibRadosMiscPP, TmapUpdateMisorderedPutPP) {
+ // create unsorted tmap
+ string h("header");
+ bufferlist bl;
+ encode(h, bl);
+ uint32_t n = 3;
+ encode(n, bl);
+ encode(string("b"), bl);
+ encode(string("bval"), bl);
+ encode(string("a"), bl);
+ encode(string("aval"), bl);
+ encode(string("c"), bl);
+ encode(string("cval"), bl);
+ bufferlist orig = bl; // tmap_put steals bl content
+ ASSERT_EQ(0, ioctx.tmap_put("foo", bl));
+
+ // check
+ bufferlist newbl;
+ ioctx.read("foo", newbl, orig.length(), 0);
+ ASSERT_EQ(orig.contents_equal(newbl), false);
+}
+
+TEST_F(LibRadosMiscPP, Tmap2OmapPP) {
+ // create tmap
+ bufferlist hdr;
+ hdr.append("header");
+ map<string, bufferlist> omap;
+ omap["1"].append("a");
+ omap["2"].append("b");
+ omap["3"].append("c");
+ {
+ bufferlist bl;
+ encode(hdr, bl);
+ encode(omap, bl);
+ ASSERT_EQ(0, ioctx.tmap_put("foo", bl));
+ }
+
+ // convert tmap to omap
+ ASSERT_EQ(0, ioctx.tmap_to_omap("foo", false));
+
+ // if tmap was truncated ?
+ {
+ uint64_t size;
+ time_t mtime;
+ ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+ ASSERT_EQ(0U, size);
+ }
+
+ // if 'nullok' works
+ ASSERT_EQ(0, ioctx.tmap_to_omap("foo", true));
+ ASSERT_LE(ioctx.tmap_to_omap("foo", false), 0);
+
+ {
+ // read omap
+ bufferlist got;
+ map<string, bufferlist> m;
+ ObjectReadOperation o;
+ o.omap_get_header(&got, NULL);
+ o.omap_get_vals2("", 1024, &m, nullptr, nullptr);
+ ASSERT_EQ(0, ioctx.operate("foo", &o, NULL));
+
+ // compare header
+ ASSERT_TRUE(hdr.contents_equal(got));
+
+ // compare values
+ ASSERT_EQ(omap.size(), m.size());
+ bool same = true;
+ for (map<string, bufferlist>::iterator p = omap.begin(); p != omap.end(); ++p) {
+ map<string, bufferlist>::iterator q = m.find(p->first);
+ if (q == m.end() || !p->second.contents_equal(q->second)) {
+ same = false;
+ break;
+ }
+ }
+ ASSERT_TRUE(same);
+ }
+}
+
+TEST_F(LibRadosMiscPP, ExecPP) {
+ bufferlist bl;
+ ASSERT_EQ(0, ioctx.write("foo", bl, 0, 0));
+ bufferlist bl2, out;
+ int r = ioctx.exec("foo", "rbd", "get_all_features", bl2, out);
+ ASSERT_EQ(0, r);
+ auto iter = out.cbegin();
+ uint64_t all_features;
+ decode(all_features, iter);
+ // make sure *some* features are specified; don't care which ones
+ ASSERT_NE(all_features, (unsigned)0);
+}
+
+void set_completion_complete(rados_completion_t cb, void *arg)
+{
+ bool *my_aio_complete = (bool*)arg;
+ *my_aio_complete = true;
+}
+
+TEST_F(LibRadosMiscPP, BadFlagsPP) {
+ unsigned badflags = CEPH_OSD_FLAG_PARALLELEXEC;
+ {
+ bufferlist bl;
+ bl.append("data");
+ ASSERT_EQ(0, ioctx.write("badfoo", bl, bl.length(), 0));
+ }
+ {
+ ASSERT_EQ(-EINVAL, ioctx.remove("badfoo", badflags));
+ }
+}
+
+TEST_F(LibRadosMiscPP, Operate1PP) {
+ ObjectWriteOperation o;
+ {
+ bufferlist bl;
+ o.write(0, bl);
+ }
+ std::string val1("val1");
+ {
+ bufferlist bl;
+ bl.append(val1.c_str(), val1.size() + 1);
+ o.setxattr("key1", bl);
+ o.omap_clear(); // shouldn't affect attrs!
+ }
+ ASSERT_EQ(0, ioctx.operate("foo", &o));
+
+ ObjectWriteOperation empty;
+ ASSERT_EQ(0, ioctx.operate("foo", &empty));
+
+ {
+ bufferlist bl;
+ ASSERT_GT(ioctx.getxattr("foo", "key1", bl), 0);
+ ASSERT_EQ(0, strcmp(bl.c_str(), val1.c_str()));
+ }
+ ObjectWriteOperation o2;
+ {
+ bufferlist bl;
+ bl.append(val1);
+ o2.cmpxattr("key1", CEPH_OSD_CMPXATTR_OP_EQ, bl);
+ o2.rmxattr("key1");
+ }
+ ASSERT_EQ(-ECANCELED, ioctx.operate("foo", &o2));
+ ObjectWriteOperation o3;
+ {
+ bufferlist bl;
+ bl.append(val1);
+ o3.cmpxattr("key1", CEPH_OSD_CMPXATTR_OP_EQ, bl);
+ }
+ ASSERT_EQ(-ECANCELED, ioctx.operate("foo", &o3));
+}
+
+TEST_F(LibRadosMiscPP, Operate2PP) {
+ ObjectWriteOperation o;
+ {
+ bufferlist bl;
+ bl.append("abcdefg");
+ o.write(0, bl);
+ }
+ std::string val1("val1");
+ {
+ bufferlist bl;
+ bl.append(val1.c_str(), val1.size() + 1);
+ o.setxattr("key1", bl);
+ o.truncate(0);
+ }
+ ASSERT_EQ(0, ioctx.operate("foo", &o));
+ uint64_t size;
+ time_t mtime;
+ ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+ ASSERT_EQ(0U, size);
+}
+
+TEST_F(LibRadosMiscPP, BigObjectPP) {
+ bufferlist bl;
+ bl.append("abcdefg");
+ ASSERT_EQ(0, ioctx.write("foo", bl, bl.length(), 0));
+
+ {
+ ObjectWriteOperation o;
+ o.truncate(500000000000ull);
+ ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o));
+ }
+ {
+ ObjectWriteOperation o;
+ o.zero(500000000000ull, 1);
+ ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o));
+ }
+ {
+ ObjectWriteOperation o;
+ o.zero(1, 500000000000ull);
+ ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o));
+ }
+ {
+ ObjectWriteOperation o;
+ o.zero(500000000000ull, 500000000000ull);
+ ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o));
+ }
+
+#ifdef __LP64__
+ // this test only works on 64-bit platforms
+ ASSERT_EQ(-EFBIG, ioctx.write("foo", bl, bl.length(), 500000000000ull));
+#endif
+}
+
+TEST_F(LibRadosMiscPP, AioOperatePP) {
+ bool my_aio_complete = false;
+ AioCompletion *my_completion = cluster.aio_create_completion(
+ (void*)&my_aio_complete, set_completion_complete, NULL);
+ AioCompletion *my_completion_null = NULL;
+ ASSERT_NE(my_completion, my_completion_null);
+
+ ObjectWriteOperation o;
+ {
+ bufferlist bl;
+ o.write(0, bl);
+ }
+ std::string val1("val1");
+ {
+ bufferlist bl;
+ bl.append(val1.c_str(), val1.size() + 1);
+ o.setxattr("key1", bl);
+ bufferlist bl2;
+ char buf2[1024];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bl2.append(buf2, sizeof(buf2));
+ o.append(bl2);
+ }
+ ASSERT_EQ(0, ioctx.aio_operate("foo", my_completion, &o));
+ ASSERT_EQ(0, my_completion->wait_for_complete_and_cb());
+ ASSERT_EQ(my_aio_complete, true);
+ my_completion->release();
+
+ uint64_t size;
+ time_t mtime;
+ ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+ ASSERT_EQ(1024U, size);
+}
+
+TEST_F(LibRadosMiscPP, AssertExistsPP) {
+ char buf[64];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ ObjectWriteOperation op;
+ op.assert_exists();
+ op.write(0, bl);
+ ASSERT_EQ(-ENOENT, ioctx.operate("asdffoo", &op));
+ ASSERT_EQ(0, ioctx.create("asdffoo", true));
+ ASSERT_EQ(0, ioctx.operate("asdffoo", &op));
+ ASSERT_EQ(-EEXIST, ioctx.create("asdffoo", true));
+}
+
+TEST_F(LibRadosMiscPP, AssertVersionPP) {
+ char buf[64];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ // Create test object...
+ ASSERT_EQ(0, ioctx.create("asdfbar", true));
+ // ...then write it again to guarantee that the
+ // (unsigned) version must be at least 1 (not 0)
+ // since we want to decrement it by 1 later.
+ ASSERT_EQ(0, ioctx.write_full("asdfbar", bl));
+
+ uint64_t v = ioctx.get_last_version();
+ ObjectWriteOperation op1;
+ op1.assert_version(v+1);
+ op1.write(0, bl);
+ ASSERT_EQ(-EOVERFLOW, ioctx.operate("asdfbar", &op1));
+ ObjectWriteOperation op2;
+ op2.assert_version(v-1);
+ op2.write(0, bl);
+ ASSERT_EQ(-ERANGE, ioctx.operate("asdfbar", &op2));
+ ObjectWriteOperation op3;
+ op3.assert_version(v);
+ op3.write(0, bl);
+ ASSERT_EQ(0, ioctx.operate("asdfbar", &op3));
+}
+
+TEST_F(LibRadosMiscPP, BigAttrPP) {
+ char buf[64];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ ASSERT_EQ(0, ioctx.create("foo", true));
+
+ bufferlist got;
+
+ cout << "osd_max_attr_size = " << g_conf()->osd_max_attr_size << std::endl;
+ if (g_conf()->osd_max_attr_size) {
+ bl.clear();
+ got.clear();
+ bl.append(buffer::create(g_conf()->osd_max_attr_size));
+ ASSERT_EQ(0, ioctx.setxattr("foo", "one", bl));
+ ASSERT_EQ((int)bl.length(), ioctx.getxattr("foo", "one", got));
+ ASSERT_TRUE(bl.contents_equal(got));
+
+ bl.clear();
+ bl.append(buffer::create(g_conf()->osd_max_attr_size+1));
+ ASSERT_EQ(-EFBIG, ioctx.setxattr("foo", "one", bl));
+ } else {
+ cout << "osd_max_attr_size == 0; skipping test" << std::endl;
+ }
+
+ for (int i=0; i<1000; i++) {
+ bl.clear();
+ got.clear();
+ bl.append(buffer::create(std::min<uint64_t>(g_conf()->osd_max_attr_size,
+ 1024)));
+ char n[10];
+ snprintf(n, sizeof(n), "a%d", i);
+ ASSERT_EQ(0, ioctx.setxattr("foo", n, bl));
+ ASSERT_EQ((int)bl.length(), ioctx.getxattr("foo", n, got));
+ ASSERT_TRUE(bl.contents_equal(got));
+ }
+}
+
+TEST_F(LibRadosMiscPP, CopyPP) {
+ bufferlist bl, x;
+ bl.append("hi there");
+ x.append("bar");
+
+ // small object
+ bufferlist blc = bl;
+ bufferlist xc = x;
+ ASSERT_EQ(0, ioctx.write_full("foo", blc));
+ ASSERT_EQ(0, ioctx.setxattr("foo", "myattr", xc));
+
+ version_t uv = ioctx.get_last_version();
+ {
+ // pass future version
+ ObjectWriteOperation op;
+ op.copy_from2("foo", ioctx, uv + 1, LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ASSERT_EQ(-EOVERFLOW, ioctx.operate("foo.copy", &op));
+ }
+ {
+ // pass old version
+ ObjectWriteOperation op;
+ op.copy_from2("foo", ioctx, uv - 1, LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ASSERT_EQ(-ERANGE, ioctx.operate("foo.copy", &op));
+ }
+ {
+ ObjectWriteOperation op;
+ op.copy_from2("foo", ioctx, uv, LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ASSERT_EQ(0, ioctx.operate("foo.copy", &op));
+
+ bufferlist bl2, x2;
+ ASSERT_EQ((int)bl.length(), ioctx.read("foo.copy", bl2, 10000, 0));
+ ASSERT_TRUE(bl.contents_equal(bl2));
+ ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy", "myattr", x2));
+ ASSERT_TRUE(x.contents_equal(x2));
+ }
+
+ // small object without a version
+ {
+ ObjectWriteOperation op;
+ op.copy_from2("foo", ioctx, 0, LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ASSERT_EQ(0, ioctx.operate("foo.copy2", &op));
+
+ bufferlist bl2, x2;
+ ASSERT_EQ((int)bl.length(), ioctx.read("foo.copy2", bl2, 10000, 0));
+ ASSERT_TRUE(bl.contents_equal(bl2));
+ ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy2", "myattr", x2));
+ ASSERT_TRUE(x.contents_equal(x2));
+ }
+
+ // do a big object
+ bl.append(buffer::create(g_conf()->osd_copyfrom_max_chunk * 3));
+ bl.zero();
+ bl.append("tail");
+ blc = bl;
+ xc = x;
+ ASSERT_EQ(0, ioctx.write_full("big", blc));
+ ASSERT_EQ(0, ioctx.setxattr("big", "myattr", xc));
+
+ {
+ ObjectWriteOperation op;
+ op.copy_from2("big", ioctx, ioctx.get_last_version(), LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ ASSERT_EQ(0, ioctx.operate("big.copy", &op));
+
+ bufferlist bl2, x2;
+ ASSERT_EQ((int)bl.length(), ioctx.read("big.copy", bl2, bl.length(), 0));
+ ASSERT_TRUE(bl.contents_equal(bl2));
+ ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy", "myattr", x2));
+ ASSERT_TRUE(x.contents_equal(x2));
+ }
+
+ {
+ ObjectWriteOperation op;
+ op.copy_from2("big", ioctx, 0, LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL);
+ ASSERT_EQ(0, ioctx.operate("big.copy2", &op));
+
+ bufferlist bl2, x2;
+ ASSERT_EQ((int)bl.length(), ioctx.read("big.copy2", bl2, bl.length(), 0));
+ ASSERT_TRUE(bl.contents_equal(bl2));
+ ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy2", "myattr", x2));
+ ASSERT_TRUE(x.contents_equal(x2));
+ }
+}
+
+class LibRadosTwoPoolsECPP : public RadosTestECPP
+{
+public:
+ LibRadosTwoPoolsECPP() {};
+ ~LibRadosTwoPoolsECPP() override {};
+protected:
+ static void SetUpTestCase() {
+ pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_ec_pool_pp(pool_name, s_cluster));
+ src_pool_name = get_temp_pool_name();
+ ASSERT_EQ(0, s_cluster.pool_create(src_pool_name.c_str()));
+
+ librados::IoCtx ioctx;
+ ASSERT_EQ(0, s_cluster.ioctx_create(pool_name.c_str(), ioctx));
+ ioctx.application_enable("rados", true);
+
+ librados::IoCtx src_ioctx;
+ ASSERT_EQ(0, s_cluster.ioctx_create(src_pool_name.c_str(), src_ioctx));
+ src_ioctx.application_enable("rados", true);
+ }
+ static void TearDownTestCase() {
+ ASSERT_EQ(0, s_cluster.pool_delete(src_pool_name.c_str()));
+ ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, s_cluster));
+ }
+ static std::string src_pool_name;
+
+ void SetUp() override {
+ RadosTestECPP::SetUp();
+ ASSERT_EQ(0, cluster.ioctx_create(src_pool_name.c_str(), src_ioctx));
+ src_ioctx.set_namespace(nspace);
+ }
+ void TearDown() override {
+ // wait for maps to settle before next test
+ cluster.wait_for_latest_osdmap();
+
+ RadosTestECPP::TearDown();
+
+ cleanup_default_namespace(src_ioctx);
+ cleanup_namespace(src_ioctx, nspace);
+
+ src_ioctx.close();
+ }
+
+ librados::IoCtx src_ioctx;
+};
+std::string LibRadosTwoPoolsECPP::src_pool_name;
+
+//copy_from between ecpool and no-ecpool.
+TEST_F(LibRadosTwoPoolsECPP, CopyFrom) {
+ bufferlist z;
+ z.append_zero(4194304*2);
+ bufferlist b;
+ b.append("copyfrom");
+
+ // create big object w/ omapheader
+ {
+ ASSERT_EQ(0, src_ioctx.write_full("foo", z));
+ ASSERT_EQ(0, src_ioctx.omap_set_header("foo", b));
+ version_t uv = src_ioctx.get_last_version();
+ ObjectWriteOperation op;
+ op.copy_from("foo", src_ioctx, uv);
+ ASSERT_EQ(-EOPNOTSUPP, ioctx.operate("foo.copy", &op));
+ }
+
+ // same with small object
+ {
+ ASSERT_EQ(0, src_ioctx.omap_set_header("bar", b));
+ version_t uv = src_ioctx.get_last_version();
+ ObjectWriteOperation op;
+ op.copy_from("bar", src_ioctx, uv);
+ ASSERT_EQ(-EOPNOTSUPP, ioctx.operate("bar.copy", &op));
+ }
+}
+
+TEST_F(LibRadosMiscPP, CopyScrubPP) {
+ bufferlist inbl, bl, x;
+ for (int i=0; i<100; ++i)
+ x.append("barrrrrrrrrrrrrrrrrrrrrrrrrr");
+ bl.append(buffer::create(g_conf()->osd_copyfrom_max_chunk * 3));
+ bl.zero();
+ bl.append("tail");
+ bufferlist cbl;
+
+ map<string, bufferlist> to_set;
+ for (int i=0; i<1000; ++i)
+ to_set[string("foo") + stringify(i)] = x;
+
+ // small
+ cbl = x;
+ ASSERT_EQ(0, ioctx.write_full("small", cbl));
+ ASSERT_EQ(0, ioctx.setxattr("small", "myattr", x));
+
+ // big
+ cbl = bl;
+ ASSERT_EQ(0, ioctx.write_full("big", cbl));
+
+ // without header
+ cbl = bl;
+ ASSERT_EQ(0, ioctx.write_full("big2", cbl));
+ ASSERT_EQ(0, ioctx.setxattr("big2", "myattr", x));
+ ASSERT_EQ(0, ioctx.setxattr("big2", "myattr2", x));
+ ASSERT_EQ(0, ioctx.omap_set("big2", to_set));
+
+ // with header
+ cbl = bl;
+ ASSERT_EQ(0, ioctx.write_full("big3", cbl));
+ ASSERT_EQ(0, ioctx.omap_set_header("big3", x));
+ ASSERT_EQ(0, ioctx.omap_set("big3", to_set));
+
+ // deep scrub to ensure digests are in place
+ {
+ for (int i=0; i<10; ++i) {
+ ostringstream ss;
+ ss << "{\"prefix\": \"pg deep-scrub\", \"pgid\": \""
+ << ioctx.get_id() << "." << i
+ << "\"}";
+ cluster.mon_command(ss.str(), inbl, NULL, NULL);
+ }
+
+ // give it a few seconds to go. this is sloppy but is usually enough time
+ cout << "waiting for initial deep scrubs..." << std::endl;
+ sleep(30);
+ cout << "done waiting, doing copies" << std::endl;
+ }
+
+ {
+ ObjectWriteOperation op;
+ op.copy_from("small", ioctx, 0);
+ ASSERT_EQ(0, ioctx.operate("small.copy", &op));
+ }
+
+ {
+ ObjectWriteOperation op;
+ op.copy_from("big", ioctx, 0);
+ ASSERT_EQ(0, ioctx.operate("big.copy", &op));
+ }
+
+ {
+ ObjectWriteOperation op;
+ op.copy_from("big2", ioctx, 0);
+ ASSERT_EQ(0, ioctx.operate("big2.copy", &op));
+ }
+
+ {
+ ObjectWriteOperation op;
+ op.copy_from("big3", ioctx, 0);
+ ASSERT_EQ(0, ioctx.operate("big3.copy", &op));
+ }
+
+ // deep scrub to ensure digests are correct
+ {
+ for (int i=0; i<10; ++i) {
+ ostringstream ss;
+ ss << "{\"prefix\": \"pg deep-scrub\", \"pgid\": \""
+ << ioctx.get_id() << "." << i
+ << "\"}";
+ cluster.mon_command(ss.str(), inbl, NULL, NULL);
+ }
+
+ // give it a few seconds to go. this is sloppy but is usually enough time
+ cout << "waiting for final deep scrubs..." << std::endl;
+ sleep(30);
+ cout << "done waiting" << std::endl;
+ }
+}
+
+TEST_F(LibRadosMiscPP, WriteSamePP) {
+ bufferlist bl;
+ char buf[128];
+ bufferlist fl;
+ char full[128 * 4];
+ char *cmp;
+
+ /* zero the full range before using writesame */
+ memset(full, 0, sizeof(full));
+ fl.append(full, sizeof(full));
+ ASSERT_EQ(0, ioctx.write("ws", fl, fl.length(), 0));
+
+ memset(buf, 0xcc, sizeof(buf));
+ bl.clear();
+ bl.append(buf, sizeof(buf));
+ /* write the same buf four times */
+ ASSERT_EQ(0, ioctx.writesame("ws", bl, sizeof(full), 0));
+
+ /* read back the full buffer and confirm that it matches */
+ fl.clear();
+ fl.append(full, sizeof(full));
+ ASSERT_EQ((int)fl.length(), ioctx.read("ws", fl, fl.length(), 0));
+
+ for (cmp = fl.c_str(); cmp < fl.c_str() + fl.length(); cmp += sizeof(buf)) {
+ ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
+ }
+
+ /* write_len not a multiple of data_len should throw error */
+ bl.clear();
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(-EINVAL, ioctx.writesame("ws", bl, (sizeof(buf) * 4) - 1, 0));
+ ASSERT_EQ(-EINVAL,
+ ioctx.writesame("ws", bl, bl.length() / 2, 0));
+ /* write_len = data_len, i.e. same as write() */
+ ASSERT_EQ(0, ioctx.writesame("ws", bl, sizeof(buf), 0));
+ bl.clear();
+ ASSERT_EQ(-EINVAL,
+ ioctx.writesame("ws", bl, sizeof(buf), 0));
+}
+
+template <typename T>
+class LibRadosChecksum : public LibRadosMiscPP {
+public:
+ typedef typename T::alg_t alg_t;
+ typedef typename T::value_t value_t;
+ typedef typename alg_t::init_value_t init_value_t;
+
+ static const rados_checksum_type_t type = T::type;
+
+ bufferlist content_bl;
+
+ using LibRadosMiscPP::SetUpTestCase;
+ using LibRadosMiscPP::TearDownTestCase;
+
+ void SetUp() override {
+ LibRadosMiscPP::SetUp();
+
+ std::string content(4096, '\0');
+ for (size_t i = 0; i < content.length(); ++i) {
+ content[i] = static_cast<char>(rand() % (126 - 33) + 33);
+ }
+ content_bl.append(content);
+ ASSERT_EQ(0, ioctx.write("foo", content_bl, content_bl.length(), 0));
+ }
+};
+
+template <rados_checksum_type_t _type, typename AlgT, typename ValueT>
+class LibRadosChecksumParams {
+public:
+ typedef AlgT alg_t;
+ typedef ValueT value_t;
+ static const rados_checksum_type_t type = _type;
+};
+
+typedef ::testing::Types<
+ LibRadosChecksumParams<LIBRADOS_CHECKSUM_TYPE_XXHASH32,
+ Checksummer::xxhash32, uint32_t>,
+ LibRadosChecksumParams<LIBRADOS_CHECKSUM_TYPE_XXHASH64,
+ Checksummer::xxhash64, uint64_t>,
+ LibRadosChecksumParams<LIBRADOS_CHECKSUM_TYPE_CRC32C,
+ Checksummer::crc32c, uint32_t>
+ > LibRadosChecksumTypes;
+
+TYPED_TEST_CASE(LibRadosChecksum, LibRadosChecksumTypes);
+
+TYPED_TEST(LibRadosChecksum, Subset) {
+ uint32_t chunk_size = 1024;
+ uint32_t csum_count = this->content_bl.length() / chunk_size;
+
+ typename TestFixture::init_value_t init_value = -1;
+ bufferlist init_value_bl;
+ encode(init_value, init_value_bl);
+
+ std::vector<bufferlist> checksum_bls(csum_count);
+ std::vector<int> checksum_rvals(csum_count);
+
+ // individual checksum ops for each chunk
+ ObjectReadOperation op;
+ for (uint32_t i = 0; i < csum_count; ++i) {
+ op.checksum(TestFixture::type, init_value_bl, i * chunk_size, chunk_size,
+ 0, &checksum_bls[i], &checksum_rvals[i]);
+ }
+ ASSERT_EQ(0, this->ioctx.operate("foo", &op, NULL));
+
+ for (uint32_t i = 0; i < csum_count; ++i) {
+ ASSERT_EQ(0, checksum_rvals[i]);
+
+ auto bl_it = checksum_bls[i].cbegin();
+ uint32_t count;
+ decode(count, bl_it);
+ ASSERT_EQ(1U, count);
+
+ typename TestFixture::value_t value;
+ decode(value, bl_it);
+
+ bufferlist content_sub_bl;
+ content_sub_bl.substr_of(this->content_bl, i * chunk_size, chunk_size);
+
+ typename TestFixture::value_t expected_value;
+ bufferptr expected_value_bp = buffer::create_static(
+ sizeof(expected_value), reinterpret_cast<char*>(&expected_value));
+ Checksummer::template calculate<typename TestFixture::alg_t>(
+ init_value, chunk_size, 0, chunk_size, content_sub_bl,
+ &expected_value_bp);
+ ASSERT_EQ(expected_value, value);
+ }
+}
+
+TYPED_TEST(LibRadosChecksum, Chunked) {
+ uint32_t chunk_size = 1024;
+ uint32_t csum_count = this->content_bl.length() / chunk_size;
+
+ typename TestFixture::init_value_t init_value = -1;
+ bufferlist init_value_bl;
+ encode(init_value, init_value_bl);
+
+ bufferlist checksum_bl;
+ int checksum_rval;
+
+ // single op with chunked checksum results
+ ObjectReadOperation op;
+ op.checksum(TestFixture::type, init_value_bl, 0, this->content_bl.length(),
+ chunk_size, &checksum_bl, &checksum_rval);
+ ASSERT_EQ(0, this->ioctx.operate("foo", &op, NULL));
+ ASSERT_EQ(0, checksum_rval);
+
+ auto bl_it = checksum_bl.cbegin();
+ uint32_t count;
+ decode(count, bl_it);
+ ASSERT_EQ(csum_count, count);
+
+ std::vector<typename TestFixture::value_t> expected_values(csum_count);
+ bufferptr expected_values_bp = buffer::create_static(
+ csum_count * sizeof(typename TestFixture::value_t),
+ reinterpret_cast<char*>(&expected_values[0]));
+
+ Checksummer::template calculate<typename TestFixture::alg_t>(
+ init_value, chunk_size, 0, this->content_bl.length(), this->content_bl,
+ &expected_values_bp);
+
+ for (uint32_t i = 0; i < csum_count; ++i) {
+ typename TestFixture::value_t value;
+ decode(value, bl_it);
+ ASSERT_EQ(expected_values[i], value);
+ }
+}
+
+TEST_F(LibRadosMiscPP, CmpExtPP) {
+ bufferlist cmp_bl, bad_cmp_bl, write_bl;
+ char stored_str[] = "1234567891";
+ char mismatch_str[] = "1234577777";
+
+ write_bl.append(stored_str);
+ ioctx.write("cmpextpp", write_bl, write_bl.length(), 0);
+ cmp_bl.append(stored_str);
+ ASSERT_EQ(0, ioctx.cmpext("cmpextpp", 0, cmp_bl));
+
+ bad_cmp_bl.append(mismatch_str);
+ ASSERT_EQ(-MAX_ERRNO - 5, ioctx.cmpext("cmpextpp", 0, bad_cmp_bl));
+}
+
+TEST_F(LibRadosMiscPP, Applications) {
+ bufferlist inbl, outbl;
+ string outs;
+ ASSERT_EQ(0, cluster.mon_command("{\"prefix\": \"osd dump\"}",
+ inbl, &outbl, &outs));
+ ASSERT_LT(0u, outbl.length());
+ ASSERT_LE(0u, outs.length());
+ if (!std::regex_search(outbl.to_str(),
+ std::regex("require_osd_release [l-z]"))) {
+ std::cout << "SKIPPING";
+ return;
+ }
+
+ std::set<std::string> expected_apps = {"rados"};
+ std::set<std::string> apps;
+ ASSERT_EQ(0, ioctx.application_list(&apps));
+ ASSERT_EQ(expected_apps, apps);
+
+ ASSERT_EQ(0, ioctx.application_enable("app1", true));
+ ASSERT_EQ(-EPERM, ioctx.application_enable("app2", false));
+ ASSERT_EQ(0, ioctx.application_enable("app2", true));
+
+ expected_apps = {"app1", "app2", "rados"};
+ ASSERT_EQ(0, ioctx.application_list(&apps));
+ ASSERT_EQ(expected_apps, apps);
+
+ std::map<std::string, std::string> expected_meta;
+ std::map<std::string, std::string> meta;
+ ASSERT_EQ(-ENOENT, ioctx.application_metadata_list("dne", &meta));
+ ASSERT_EQ(0, ioctx.application_metadata_list("app1", &meta));
+ ASSERT_EQ(expected_meta, meta);
+
+ ASSERT_EQ(-ENOENT, ioctx.application_metadata_set("dne", "key1", "value1"));
+ ASSERT_EQ(0, ioctx.application_metadata_set("app1", "key1", "value1"));
+ ASSERT_EQ(0, ioctx.application_metadata_set("app1", "key2", "value2"));
+
+ expected_meta = {{"key1", "value1"}, {"key2", "value2"}};
+ ASSERT_EQ(0, ioctx.application_metadata_list("app1", &meta));
+ ASSERT_EQ(expected_meta, meta);
+
+ ASSERT_EQ(0, ioctx.application_metadata_remove("app1", "key1"));
+
+ expected_meta = {{"key2", "value2"}};
+ ASSERT_EQ(0, ioctx.application_metadata_list("app1", &meta));
+ ASSERT_EQ(expected_meta, meta);
+}
+
+TEST_F(LibRadosMiscECPP, CompareExtentRange) {
+ bufferlist bl1;
+ bl1.append("ceph");
+ ObjectWriteOperation write;
+ write.write(0, bl1);
+ ASSERT_EQ(0, ioctx.operate("foo", &write));
+
+ bufferlist bl2;
+ bl2.append("ph");
+ bl2.append(std::string(2, '\0'));
+ ObjectReadOperation read1;
+ read1.cmpext(2, bl2, nullptr);
+ ASSERT_EQ(0, ioctx.operate("foo", &read1, nullptr));
+
+ bufferlist bl3;
+ bl3.append(std::string(4, '\0'));
+ ObjectReadOperation read2;
+ read2.cmpext(2097152, bl3, nullptr);
+ ASSERT_EQ(0, ioctx.operate("foo", &read2, nullptr));
+}
+
+TEST_F(LibRadosMiscPP, MinCompatOSD) {
+ int8_t require_osd_release;
+ ASSERT_EQ(0, cluster.get_min_compatible_osd(&require_osd_release));
+ ASSERT_LE(-1, require_osd_release);
+ ASSERT_GT(CEPH_RELEASE_MAX, require_osd_release);
+}
+
+TEST_F(LibRadosMiscPP, MinCompatClient) {
+ int8_t min_compat_client;
+ int8_t require_min_compat_client;
+ ASSERT_EQ(0, cluster.get_min_compatible_client(&min_compat_client,
+ &require_min_compat_client));
+ ASSERT_LE(-1, min_compat_client);
+ ASSERT_GT(CEPH_RELEASE_MAX, min_compat_client);
+
+ ASSERT_LE(-1, require_min_compat_client);
+ ASSERT_GT(CEPH_RELEASE_MAX, require_min_compat_client);
+}
+
+TEST_F(LibRadosMiscPP, Conf) {
+ const char* const option = "bluestore_throttle_bytes";
+ size_t new_size = 1 << 20;
+ std::string original;
+ ASSERT_EQ(0, cluster.conf_get(option, original));
+ auto restore_setting = make_scope_guard([&] {
+ cluster.conf_set(option, original.c_str());
+ });
+ std::string expected = std::to_string(new_size);
+ ASSERT_EQ(0, cluster.conf_set(option, expected.c_str()));
+ std::string actual;
+ ASSERT_EQ(0, cluster.conf_get(option, actual));
+ ASSERT_EQ(expected, actual);
+}
diff --git a/src/test/librados/pool.cc b/src/test/librados/pool.cc
index 74c89595bf1..14906651922 100644
--- a/src/test/librados/pool.cc
+++ b/src/test/librados/pool.cc
@@ -1,9 +1,8 @@
-#include "include/rados/librados.h"
-#include "test/librados/test.h"
-
-#include "gtest/gtest.h"
#include <errno.h>
#include <vector>
+#include "gtest/gtest.h"
+#include "include/rados/librados.h"
+#include "test/librados/test.h"
#define POOL_LIST_BUF_SZ 32768
diff --git a/src/test/librados/service.cc b/src/test/librados/service.cc
index da37fb3d62f..9bc9cd50691 100644
--- a/src/test/librados/service.cc
+++ b/src/test/librados/service.cc
@@ -69,94 +69,3 @@ TEST(LibRadosService, Status) {
}
rados_shutdown(cluster);
}
-
-TEST(LibRadosServicePP, RegisterEarly) {
- Rados cluster;
- cluster.init("admin");
- ASSERT_EQ(0, cluster.conf_read_file(NULL));
- cluster.conf_parse_env(NULL);
- string name = string("pid") + stringify(getpid());
- ASSERT_EQ(0, cluster.service_daemon_register(
- "laundry", name, {{"foo", "bar"}, {"this", "that"}}));
- ASSERT_EQ(-EEXIST, cluster.service_daemon_register(
- "laundry", name, {{"foo", "bar"}, {"this", "that"}}));
- ASSERT_EQ(0, cluster.connect());
- sleep(5);
- cluster.shutdown();
-}
-
-TEST(LibRadosServicePP, RegisterLate) {
- Rados cluster;
- cluster.init("admin");
- ASSERT_EQ(0, cluster.conf_read_file(NULL));
- cluster.conf_parse_env(NULL);
- ASSERT_EQ("", connect_cluster_pp(cluster));
- string name = string("pid") + stringify(getpid());
- ASSERT_EQ(0, cluster.service_daemon_register(
- "laundry", name, {{"foo", "bar"}, {"this", "that"}}));
-}
-
-TEST(LibRadosServicePP, Status) {
- Rados cluster;
- cluster.init("admin");
- ASSERT_EQ(0, cluster.conf_read_file(NULL));
- cluster.conf_parse_env(NULL);
- string name = string("pid") + stringify(getpid());
- ASSERT_EQ(-ENOTCONN, cluster.service_daemon_update_status(
- {{"testing", "starting"}}));
- ASSERT_EQ(0, cluster.connect());
- ASSERT_EQ(0, cluster.service_daemon_register(
- "laundry", name, {{"foo", "bar"}, {"this", "that"}}));
- for (int i=0; i<20; ++i) {
- ASSERT_EQ(0, cluster.service_daemon_update_status({
- {"testing", "running"},
- {"count", stringify(i)}
- }));
- sleep(1);
- }
- cluster.shutdown();
-}
-
-TEST(LibRadosServicePP, Close) {
- int tries = 20;
- string name = string("close-test-pid") + stringify(getpid());
- int i;
- for (i = 0; i < tries; ++i) {
- cout << "attempt " << i << " of " << tries << std::endl;
- {
- Rados cluster;
- cluster.init("admin");
- ASSERT_EQ(0, cluster.conf_read_file(NULL));
- cluster.conf_parse_env(NULL);
- ASSERT_EQ(0, cluster.connect());
- ASSERT_EQ(0, cluster.service_daemon_register(
- "laundry", name, {{"foo", "bar"}, {"this", "that"}}));
- sleep(3); // let it register
- cluster.shutdown();
- }
- // mgr updates servicemap every tick
- //sleep(g_conf().get_val<int64_t>("mgr_tick_period"));
- std::this_thread::sleep_for(g_conf().get_val<std::chrono::seconds>(
- "mgr_tick_period"));
- // make sure we are deregistered
- {
- Rados cluster;
- cluster.init("admin");
- ASSERT_EQ(0, cluster.conf_read_file(NULL));
- cluster.conf_parse_env(NULL);
- ASSERT_EQ(0, cluster.connect());
- bufferlist inbl, outbl;
- ASSERT_EQ(0, cluster.mon_command("{\"prefix\": \"service dump\"}",
- inbl, &outbl, NULL));
- string s = outbl.to_str();
- cluster.shutdown();
-
- if (s.find(name) != string::npos) {
- cout << " failed to deregister:\n" << s << std::endl;
- } else {
- break;
- }
- }
- }
- ASSERT_LT(i, tries);
-}
diff --git a/src/test/librados/service_cxx.cc b/src/test/librados/service_cxx.cc
new file mode 100644
index 00000000000..40869f0f8d9
--- /dev/null
+++ b/src/test/librados/service_cxx.cc
@@ -0,0 +1,104 @@
+#include <algorithm>
+#include <thread>
+#include <errno.h>
+#include "gtest/gtest.h"
+
+#include "include/rados/librados.hpp"
+#include "include/stringify.h"
+#include "common/config_proxy.h"
+#include "test/librados/test_cxx.h"
+#include "test/librados/testcase_cxx.h"
+#include "test/unit.cc"
+
+using namespace librados;
+
+TEST(LibRadosServicePP, RegisterEarly) {
+ Rados cluster;
+ cluster.init("admin");
+ ASSERT_EQ(0, cluster.conf_read_file(NULL));
+ cluster.conf_parse_env(NULL);
+ string name = string("pid") + stringify(getpid());
+ ASSERT_EQ(0, cluster.service_daemon_register(
+ "laundry", name, {{"foo", "bar"}, {"this", "that"}}));
+ ASSERT_EQ(-EEXIST, cluster.service_daemon_register(
+ "laundry", name, {{"foo", "bar"}, {"this", "that"}}));
+ ASSERT_EQ(0, cluster.connect());
+ sleep(5);
+ cluster.shutdown();
+}
+
+TEST(LibRadosServicePP, RegisterLate) {
+ Rados cluster;
+ cluster.init("admin");
+ ASSERT_EQ(0, cluster.conf_read_file(NULL));
+ cluster.conf_parse_env(NULL);
+ ASSERT_EQ("", connect_cluster_pp(cluster));
+ string name = string("pid") + stringify(getpid());
+ ASSERT_EQ(0, cluster.service_daemon_register(
+ "laundry", name, {{"foo", "bar"}, {"this", "that"}}));
+}
+
+TEST(LibRadosServicePP, Status) {
+ Rados cluster;
+ cluster.init("admin");
+ ASSERT_EQ(0, cluster.conf_read_file(NULL));
+ cluster.conf_parse_env(NULL);
+ string name = string("pid") + stringify(getpid());
+ ASSERT_EQ(-ENOTCONN, cluster.service_daemon_update_status(
+ {{"testing", "starting"}}));
+ ASSERT_EQ(0, cluster.connect());
+ ASSERT_EQ(0, cluster.service_daemon_register(
+ "laundry", name, {{"foo", "bar"}, {"this", "that"}}));
+ for (int i=0; i<20; ++i) {
+ ASSERT_EQ(0, cluster.service_daemon_update_status({
+ {"testing", "running"},
+ {"count", stringify(i)}
+ }));
+ sleep(1);
+ }
+ cluster.shutdown();
+}
+
+TEST(LibRadosServicePP, Close) {
+ int tries = 20;
+ string name = string("close-test-pid") + stringify(getpid());
+ int i;
+ for (i = 0; i < tries; ++i) {
+ cout << "attempt " << i << " of " << tries << std::endl;
+ {
+ Rados cluster;
+ cluster.init("admin");
+ ASSERT_EQ(0, cluster.conf_read_file(NULL));
+ cluster.conf_parse_env(NULL);
+ ASSERT_EQ(0, cluster.connect());
+ ASSERT_EQ(0, cluster.service_daemon_register(
+ "laundry", name, {{"foo", "bar"}, {"this", "that"}}));
+ sleep(3); // let it register
+ cluster.shutdown();
+ }
+ // mgr updates servicemap every tick
+ //sleep(g_conf().get_val<int64_t>("mgr_tick_period"));
+ std::this_thread::sleep_for(g_conf().get_val<std::chrono::seconds>(
+ "mgr_tick_period"));
+ // make sure we are deregistered
+ {
+ Rados cluster;
+ cluster.init("admin");
+ ASSERT_EQ(0, cluster.conf_read_file(NULL));
+ cluster.conf_parse_env(NULL);
+ ASSERT_EQ(0, cluster.connect());
+ bufferlist inbl, outbl;
+ ASSERT_EQ(0, cluster.mon_command("{\"prefix\": \"service dump\"}",
+ inbl, &outbl, NULL));
+ string s = outbl.to_str();
+ cluster.shutdown();
+
+ if (s.find(name) != string::npos) {
+ cout << " failed to deregister:\n" << s << std::endl;
+ } else {
+ break;
+ }
+ }
+ }
+ ASSERT_LT(i, tries);
+}
diff --git a/src/test/librados/snapshots.cc b/src/test/librados/snapshots.cc
index 49bd9961efc..966ec19add6 100644
--- a/src/test/librados/snapshots.cc
+++ b/src/test/librados/snapshots.cc
@@ -1,5 +1,4 @@
#include "include/rados.h"
-#include "include/rados/librados.hpp"
#include "test/librados/test.h"
#include "test/librados/TestCase.h"
@@ -8,17 +7,12 @@
#include "gtest/gtest.h"
#include <string>
-using namespace librados;
using std::string;
typedef RadosTest LibRadosSnapshots;
typedef RadosTest LibRadosSnapshotsSelfManaged;
-typedef RadosTestPP LibRadosSnapshotsPP;
-typedef RadosTestPP LibRadosSnapshotsSelfManagedPP;
typedef RadosTestEC LibRadosSnapshotsEC;
typedef RadosTestEC LibRadosSnapshotsSelfManagedEC;
-typedef RadosTestECPP LibRadosSnapshotsECPP;
-typedef RadosTestECPP LibRadosSnapshotsSelfManagedECPP;
const int bufsize = 128;
@@ -36,25 +30,6 @@ TEST_F(LibRadosSnapshots, SnapList) {
EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
}
-TEST_F(LibRadosSnapshotsPP, SnapListPP) {
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
- ASSERT_EQ(0, ioctx.snap_create("snap1"));
- ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
- std::vector<snap_t> snaps;
- EXPECT_EQ(0, ioctx.snap_list(&snaps));
- EXPECT_EQ(1U, snaps.size());
- snap_t rid;
- EXPECT_EQ(0, ioctx.snap_lookup("snap1", &rid));
- EXPECT_EQ(rid, snaps[0]);
- EXPECT_EQ(0, ioctx.snap_remove("snap1"));
- ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
-}
-
TEST_F(LibRadosSnapshots, SnapRemove) {
char buf[bufsize];
memset(buf, 0xcc, sizeof(buf));
@@ -67,19 +42,6 @@ TEST_F(LibRadosSnapshots, SnapRemove) {
ASSERT_EQ(-ENOENT, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
}
-TEST_F(LibRadosSnapshotsPP, SnapRemovePP) {
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.snap_create("snap1"));
- rados_snap_t rid;
- ASSERT_EQ(0, ioctx.snap_lookup("snap1", &rid));
- ASSERT_EQ(0, ioctx.snap_remove("snap1"));
- ASSERT_EQ(-ENOENT, ioctx.snap_lookup("snap1", &rid));
-}
-
TEST_F(LibRadosSnapshots, Rollback) {
char buf[bufsize];
memset(buf, 0xcc, sizeof(buf));
@@ -95,25 +57,6 @@ TEST_F(LibRadosSnapshots, Rollback) {
EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
}
-TEST_F(LibRadosSnapshotsPP, RollbackPP) {
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.snap_create("snap1"));
- char buf2[sizeof(buf)];
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- EXPECT_EQ(0, ioctx.write_full("foo", bl2));
- EXPECT_EQ(0, ioctx.snap_rollback("foo", "snap1"));
- bufferlist bl3;
- EXPECT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
- EXPECT_EQ(0, memcmp(buf, bl3.c_str(), sizeof(buf)));
- EXPECT_EQ(0, ioctx.snap_remove("snap1"));
-}
-
TEST_F(LibRadosSnapshots, SnapGetName) {
char buf[bufsize];
memset(buf, 0xcc, sizeof(buf));
@@ -131,42 +74,6 @@ TEST_F(LibRadosSnapshots, SnapGetName) {
EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snapfoo"));
}
-TEST_F(LibRadosSnapshotsPP, SnapGetNamePP) {
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
- rados_snap_t rid;
- EXPECT_EQ(0, ioctx.snap_lookup("snapfoo", &rid));
- EXPECT_EQ(-ENOENT, ioctx.snap_lookup("snapbar", &rid));
- std::string name;
- EXPECT_EQ(0, ioctx.snap_get_name(rid, &name));
- time_t snaptime;
- EXPECT_EQ(0, ioctx.snap_get_stamp(rid, &snaptime));
- EXPECT_EQ(0, strcmp(name.c_str(), "snapfoo"));
- EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
-}
-
-TEST_F(LibRadosSnapshotsPP, SnapCreateRemovePP) {
- // reproduces http://tracker.ceph.com/issues/10262
- bufferlist bl;
- bl.append("foo");
- ASSERT_EQ(0, ioctx.write("foo", bl, bl.length(), 0));
- ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
- ASSERT_EQ(0, ioctx.remove("foo"));
- ASSERT_EQ(0, ioctx.snap_create("snapbar"));
-
- std::unique_ptr<librados::ObjectWriteOperation> op(new librados::ObjectWriteOperation());
- op->create(false);
- op->remove();
- ASSERT_EQ(0, ioctx.operate("foo", op.get()));
-
- EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
- EXPECT_EQ(0, ioctx.snap_remove("snapbar"));
-}
-
TEST_F(LibRadosSnapshotsSelfManaged, Snap) {
std::vector<uint64_t> my_snaps;
my_snaps.push_back(-2);
@@ -246,355 +153,6 @@ TEST_F(LibRadosSnapshotsSelfManaged, Rollback) {
ASSERT_EQ(0, rados_remove(ioctx, "foo"));
}
-TEST_F(LibRadosSnapshotsSelfManagedPP, SnapPP) {
- std::vector<uint64_t> my_snaps;
- my_snaps.push_back(-2);
- ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ASSERT_TRUE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
-
- my_snaps.push_back(-2);
- librados::AioCompletion *completion = cluster.aio_create_completion();
- ioctx.aio_selfmanaged_snap_create(&my_snaps.back(), completion);
- ASSERT_EQ(0, completion->wait_for_complete());
- completion->release();
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- char buf2[sizeof(buf)];
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), 0));
-
- ioctx.snap_set_read(my_snaps[1]);
- bufferlist bl3;
- ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
-
- completion = cluster.aio_create_completion();
- ioctx.aio_selfmanaged_snap_remove(my_snaps.back(), completion);
- ASSERT_EQ(0, completion->wait_for_complete());
- completion->release();
- my_snaps.pop_back();
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
- ASSERT_TRUE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
- ASSERT_EQ(0, ioctx.remove("foo"));
-}
-
-TEST_F(LibRadosSnapshotsSelfManagedPP, RollbackPP) {
- std::vector<uint64_t> my_snaps;
- IoCtx readioctx;
- ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), readioctx));
- readioctx.set_namespace(nspace);
- readioctx.snap_set_read(LIBRADOS_SNAP_DIR);
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- //Write 3 consecutive buffers
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*2));
-
- snap_set_t ss;
-
- snap_t head = SNAP_HEAD;
- ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
- ASSERT_EQ(1u, ss.clones.size());
- ASSERT_EQ(head, ss.clones[0].cloneid);
- ASSERT_EQ(0u, ss.clones[0].snaps.size());
- ASSERT_EQ(0u, ss.clones[0].overlap.size());
- ASSERT_EQ(384u, ss.clones[0].size);
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- char buf2[sizeof(buf)];
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- //Change the middle buffer
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize));
- //Add another after
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*3));
-
- ASSERT_EQ(-EINVAL, ioctx.list_snaps("foo", &ss));
- ObjectReadOperation o;
- o.list_snaps(&ss, NULL);
- ASSERT_EQ(-EINVAL, ioctx.operate("foo", &o, NULL));
-
- ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
- ASSERT_EQ(2u, ss.clones.size());
- ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
- ASSERT_EQ(1u, ss.clones[0].snaps.size());
- ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
- ASSERT_EQ(2u, ss.clones[0].overlap.size());
- ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[0].second);
- ASSERT_EQ(256u, ss.clones[0].overlap[1].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[1].second);
- ASSERT_EQ(384u, ss.clones[0].size);
- ASSERT_EQ(head, ss.clones[1].cloneid);
- ASSERT_EQ(0u, ss.clones[1].snaps.size());
- ASSERT_EQ(0u, ss.clones[1].overlap.size());
- ASSERT_EQ(512u, ss.clones[1].size);
-
- ioctx.selfmanaged_snap_rollback("foo", my_snaps[1]);
-
- bufferlist bl3;
- ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
- ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), bufsize));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
- ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), bufsize*2));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
- ASSERT_EQ((int)0, ioctx.read("foo", bl3, sizeof(buf), bufsize*3));
-
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- readioctx.close();
-}
-
-TEST_F(LibRadosSnapshotsSelfManagedPP, SnapOverlapPP) {
- std::vector<uint64_t> my_snaps;
- IoCtx readioctx;
- ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), readioctx));
- readioctx.set_namespace(nspace);
- readioctx.snap_set_read(LIBRADOS_SNAP_DIR);
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*2));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*4));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*6));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*8));
-
- snap_set_t ss;
- snap_t head = SNAP_HEAD;
- ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
- ASSERT_EQ(1u, ss.clones.size());
- ASSERT_EQ(head, ss.clones[0].cloneid);
- ASSERT_EQ(0u, ss.clones[0].snaps.size());
- ASSERT_EQ(0u, ss.clones[0].overlap.size());
- ASSERT_EQ(1152u, ss.clones[0].size);
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- char buf2[sizeof(buf)];
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*1));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*3));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*5));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*7));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*9));
-
- ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
- ASSERT_EQ(2u, ss.clones.size());
- ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
- ASSERT_EQ(1u, ss.clones[0].snaps.size());
- ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
- ASSERT_EQ(5u, ss.clones[0].overlap.size());
- ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[0].second);
- ASSERT_EQ(256u, ss.clones[0].overlap[1].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[1].second);
- ASSERT_EQ(512u, ss.clones[0].overlap[2].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[2].second);
- ASSERT_EQ(768u, ss.clones[0].overlap[3].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[3].second);
- ASSERT_EQ(1024u, ss.clones[0].overlap[4].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[4].second);
- ASSERT_EQ(1152u, ss.clones[0].size);
- ASSERT_EQ(head, ss.clones[1].cloneid);
- ASSERT_EQ(0u, ss.clones[1].snaps.size());
- ASSERT_EQ(0u, ss.clones[1].overlap.size());
- ASSERT_EQ(1280u, ss.clones[1].size);
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
-
- char buf3[sizeof(buf)];
- memset(buf3, 0xee, sizeof(buf3));
- bufferlist bl4;
- bl4.append(buf3, sizeof(buf3));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*1));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*4));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*5));
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*8));
-
- ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
- ASSERT_EQ(3u, ss.clones.size());
- ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
- ASSERT_EQ(1u, ss.clones[0].snaps.size());
- ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
- ASSERT_EQ(5u, ss.clones[0].overlap.size());
- ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[0].second);
- ASSERT_EQ(256u, ss.clones[0].overlap[1].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[1].second);
- ASSERT_EQ(512u, ss.clones[0].overlap[2].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[2].second);
- ASSERT_EQ(768u, ss.clones[0].overlap[3].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[3].second);
- ASSERT_EQ(1024u, ss.clones[0].overlap[4].first);
- ASSERT_EQ(128u, ss.clones[0].overlap[4].second);
- ASSERT_EQ(1152u, ss.clones[0].size);
-
- ASSERT_EQ(my_snaps[2], ss.clones[1].cloneid);
- ASSERT_EQ(1u, ss.clones[1].snaps.size());
- ASSERT_EQ(my_snaps[2], ss.clones[1].snaps[0]);
- ASSERT_EQ(4u, ss.clones[1].overlap.size());
- ASSERT_EQ(0u, ss.clones[1].overlap[0].first);
- ASSERT_EQ(128u, ss.clones[1].overlap[0].second);
- ASSERT_EQ(256u, ss.clones[1].overlap[1].first);
- ASSERT_EQ(256u, ss.clones[1].overlap[1].second);
- ASSERT_EQ(768u, ss.clones[1].overlap[2].first);
- ASSERT_EQ(256u, ss.clones[1].overlap[2].second);
- ASSERT_EQ(1152u, ss.clones[1].overlap[3].first);
- ASSERT_EQ(128u, ss.clones[1].overlap[3].second);
- ASSERT_EQ(1280u, ss.clones[1].size);
-
- ASSERT_EQ(head, ss.clones[2].cloneid);
- ASSERT_EQ(0u, ss.clones[2].snaps.size());
- ASSERT_EQ(0u, ss.clones[2].overlap.size());
- ASSERT_EQ(1280u, ss.clones[2].size);
-
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- readioctx.close();
-}
-
-TEST_F(LibRadosSnapshotsSelfManagedPP, Bug11677) {
- std::vector<uint64_t> my_snaps;
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
-
- int bsize = 1<<20;
- char *buf = (char *)new char[bsize];
- memset(buf, 0xcc, bsize);
- bufferlist bl1;
- bl1.append(buf, bsize);
- ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
-
- std::unique_ptr<librados::ObjectWriteOperation> op(new librados::ObjectWriteOperation());
- op->assert_exists();
- op->remove();
- ASSERT_EQ(0, ioctx.operate("foo", op.get()));
-
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
- delete[] buf;
-}
-
-TEST_F(LibRadosSnapshotsSelfManagedPP, OrderSnap) {
- std::vector<uint64_t> my_snaps;
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
-
- int flags = librados::OPERATION_ORDERSNAP;
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ObjectWriteOperation op1;
- op1.write(0, bl);
- librados::AioCompletion *comp1 = cluster.aio_create_completion();
- ASSERT_EQ(0, ioctx.aio_operate("foo", comp1, &op1, flags));
- ASSERT_EQ(0, comp1->wait_for_complete());
- ASSERT_EQ(0, comp1->get_return_value());
- comp1->release();
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ObjectWriteOperation op2;
- op2.write(0, bl);
- librados::AioCompletion *comp2 = cluster.aio_create_completion();
- ASSERT_EQ(0, ioctx.aio_operate("foo", comp2, &op2, flags));
- ASSERT_EQ(0, comp2->wait_for_complete());
- ASSERT_EQ(0, comp2->get_return_value());
- comp2->release();
-
- my_snaps.pop_back();
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ObjectWriteOperation op3;
- op3.write(0, bl);
- librados::AioCompletion *comp3 = cluster.aio_create_completion();
- ASSERT_EQ(0, ioctx.aio_operate("foo", comp3, &op3, flags));
- ASSERT_EQ(0, comp3->wait_for_complete());
- ASSERT_EQ(-EOLDSNAPC, comp3->get_return_value());
- comp3->release();
-
- ObjectWriteOperation op4;
- op4.write(0, bl);
- librados::AioCompletion *comp4 = cluster.aio_create_completion();
- ASSERT_EQ(0, ioctx.aio_operate("foo", comp4, &op4, 0));
- ASSERT_EQ(0, comp4->wait_for_complete());
- ASSERT_EQ(0, comp4->get_return_value());
- comp4->release();
-}
-
// EC testing
TEST_F(LibRadosSnapshotsEC, SnapList) {
char buf[bufsize];
@@ -610,22 +168,6 @@ TEST_F(LibRadosSnapshotsEC, SnapList) {
EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
}
-TEST_F(LibRadosSnapshotsECPP, SnapListPP) {
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.snap_create("snap1"));
- std::vector<snap_t> snaps;
- EXPECT_EQ(0, ioctx.snap_list(&snaps));
- EXPECT_EQ(1U, snaps.size());
- snap_t rid;
- EXPECT_EQ(0, ioctx.snap_lookup("snap1", &rid));
- EXPECT_EQ(rid, snaps[0]);
- EXPECT_EQ(0, ioctx.snap_remove("snap1"));
-}
-
TEST_F(LibRadosSnapshotsEC, SnapRemove) {
char buf[bufsize];
memset(buf, 0xcc, sizeof(buf));
@@ -638,19 +180,6 @@ TEST_F(LibRadosSnapshotsEC, SnapRemove) {
ASSERT_EQ(-ENOENT, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
}
-TEST_F(LibRadosSnapshotsECPP, SnapRemovePP) {
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.snap_create("snap1"));
- rados_snap_t rid;
- ASSERT_EQ(0, ioctx.snap_lookup("snap1", &rid));
- ASSERT_EQ(0, ioctx.snap_remove("snap1"));
- ASSERT_EQ(-ENOENT, ioctx.snap_lookup("snap1", &rid));
-}
-
TEST_F(LibRadosSnapshotsEC, Rollback) {
char buf[bufsize];
memset(buf, 0xcc, sizeof(buf));
@@ -666,25 +195,6 @@ TEST_F(LibRadosSnapshotsEC, Rollback) {
EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
}
-TEST_F(LibRadosSnapshotsECPP, RollbackPP) {
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.snap_create("snap1"));
- char buf2[sizeof(buf)];
- memset(buf2, 0xdd, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- EXPECT_EQ(0, ioctx.write_full("foo", bl2));
- EXPECT_EQ(0, ioctx.snap_rollback("foo", "snap1"));
- bufferlist bl3;
- EXPECT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
- EXPECT_EQ(0, memcmp(buf, bl3.c_str(), sizeof(buf)));
- EXPECT_EQ(0, ioctx.snap_remove("snap1"));
-}
-
TEST_F(LibRadosSnapshotsEC, SnapGetName) {
char buf[bufsize];
memset(buf, 0xcc, sizeof(buf));
@@ -702,24 +212,6 @@ TEST_F(LibRadosSnapshotsEC, SnapGetName) {
EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snapfoo"));
}
-TEST_F(LibRadosSnapshotsECPP, SnapGetNamePP) {
- char buf[bufsize];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
- rados_snap_t rid;
- EXPECT_EQ(0, ioctx.snap_lookup("snapfoo", &rid));
- EXPECT_EQ(-ENOENT, ioctx.snap_lookup("snapbar", &rid));
- std::string name;
- EXPECT_EQ(0, ioctx.snap_get_name(rid, &name));
- time_t snaptime;
- EXPECT_EQ(0, ioctx.snap_get_stamp(rid, &snaptime));
- EXPECT_EQ(0, strcmp(name.c_str(), "snapfoo"));
- EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
-}
-
TEST_F(LibRadosSnapshotsSelfManagedEC, Snap) {
std::vector<uint64_t> my_snaps;
my_snaps.push_back(-2);
@@ -807,171 +299,3 @@ TEST_F(LibRadosSnapshotsSelfManagedEC, Rollback) {
delete[] buf2;
delete[] buf3;
}
-
-TEST_F(LibRadosSnapshotsSelfManagedECPP, SnapPP) {
- std::vector<uint64_t> my_snaps;
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- int bsize = alignment;
- char *buf = (char *)new char[bsize];
- memset(buf, 0xcc, bsize);
- bufferlist bl1;
- bl1.append(buf, bsize);
- ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
-
- my_snaps.push_back(-2);
- librados::AioCompletion *completion = cluster.aio_create_completion();
- ioctx.aio_selfmanaged_snap_create(&my_snaps.back(), completion);
- ASSERT_EQ(0, completion->wait_for_complete());
- completion->release();
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- char *buf2 = (char *)new char[bsize];
- memset(buf2, 0xdd, bsize);
- bufferlist bl2;
- bl2.append(buf2, bsize);
- // Add another aligned buffer
- ASSERT_EQ(0, ioctx.write("foo", bl2, bsize, bsize));
-
- ioctx.snap_set_read(my_snaps[1]);
- bufferlist bl3;
- ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize*3, 0));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
-
- completion = cluster.aio_create_completion();
- ioctx.aio_selfmanaged_snap_remove(my_snaps.back(), completion);
- ASSERT_EQ(0, completion->wait_for_complete());
- completion->release();
- my_snaps.pop_back();
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
- ASSERT_EQ(0, ioctx.remove("foo"));
- delete[] buf;
- delete[] buf2;
-}
-
-TEST_F(LibRadosSnapshotsSelfManagedECPP, RollbackPP) {
- std::vector<uint64_t> my_snaps;
- IoCtx readioctx;
- ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), readioctx));
- readioctx.set_namespace(nspace);
- readioctx.snap_set_read(LIBRADOS_SNAP_DIR);
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- int bsize = alignment;
- char *buf = (char *)new char[bsize];
- memset(buf, 0xcc, bsize);
- bufferlist bl1;
- bl1.append(buf, bsize);
- //Write 3 consecutive buffers
- ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
- ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, bsize));
- ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, bsize*2));
-
- snap_set_t ss;
-
- snap_t head = SNAP_HEAD;
- ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
- ASSERT_EQ(1u, ss.clones.size());
- ASSERT_EQ(head, ss.clones[0].cloneid);
- ASSERT_EQ(0u, ss.clones[0].snaps.size());
- ASSERT_EQ(0u, ss.clones[0].overlap.size());
- ASSERT_EQ((unsigned)(bsize*3), ss.clones[0].size);
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- char *buf2 = (char *)new char[bsize];
- memset(buf2, 0xdd, bsize);
- bufferlist bl2;
- bl2.append(buf2, bsize);
- //Change the middle buffer
- //ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize));
- //Add another after
- ASSERT_EQ(0, ioctx.write("foo", bl2, bsize, bsize*3));
-
- ASSERT_EQ(-EINVAL, ioctx.list_snaps("foo", &ss));
- ObjectReadOperation o;
- o.list_snaps(&ss, NULL);
- ASSERT_EQ(-EINVAL, ioctx.operate("foo", &o, NULL));
-
- ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
- ASSERT_EQ(2u, ss.clones.size());
- ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
- ASSERT_EQ(1u, ss.clones[0].snaps.size());
- ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
- ASSERT_EQ(1u, ss.clones[0].overlap.size());
- ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
- ASSERT_EQ((unsigned)bsize*3, ss.clones[0].overlap[0].second);
- ASSERT_EQ((unsigned)bsize*3, ss.clones[0].size);
- ASSERT_EQ(head, ss.clones[1].cloneid);
- ASSERT_EQ(0u, ss.clones[1].snaps.size());
- ASSERT_EQ(0u, ss.clones[1].overlap.size());
- ASSERT_EQ((unsigned)bsize*4, ss.clones[1].size);
-
- ioctx.selfmanaged_snap_rollback("foo", my_snaps[1]);
-
- bufferlist bl3;
- ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, 0));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
- ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, bsize));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
- ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, bsize*2));
- ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
- ASSERT_EQ(0, ioctx.read("foo", bl3, bsize, bsize*3));
-
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- readioctx.close();
-
- delete[] buf;
- delete[] buf2;
-}
-
-TEST_F(LibRadosSnapshotsSelfManagedECPP, Bug11677) {
- std::vector<uint64_t> my_snaps;
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
-
- int bsize = alignment;
- char *buf = (char *)new char[bsize];
- memset(buf, 0xcc, bsize);
- bufferlist bl1;
- bl1.append(buf, bsize);
- ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
-
- my_snaps.push_back(-2);
- ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
- ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
- ::std::reverse(my_snaps.begin(), my_snaps.end());
-
- std::unique_ptr<librados::ObjectWriteOperation> op(new librados::ObjectWriteOperation());
- op->assert_exists();
- op->remove();
- ASSERT_EQ(0, ioctx.operate("foo", op.get()));
-
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
- my_snaps.pop_back();
- ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
- delete[] buf;
-}
-
diff --git a/src/test/librados/snapshots_cxx.cc b/src/test/librados/snapshots_cxx.cc
new file mode 100644
index 00000000000..be3087f9140
--- /dev/null
+++ b/src/test/librados/snapshots_cxx.cc
@@ -0,0 +1,689 @@
+#include <algorithm>
+#include <errno.h>
+#include <string>
+
+#include "gtest/gtest.h"
+
+#include "include/rados.h"
+#include "include/rados/librados.hpp"
+#include "test/librados/test_cxx.h"
+#include "test/librados/testcase_cxx.h"
+
+using namespace librados;
+
+typedef RadosTestPP LibRadosSnapshotsPP;
+typedef RadosTestPP LibRadosSnapshotsSelfManagedPP;
+typedef RadosTestECPP LibRadosSnapshotsECPP;
+typedef RadosTestECPP LibRadosSnapshotsSelfManagedECPP;
+
+const int bufsize = 128;
+
+TEST_F(LibRadosSnapshotsPP, SnapListPP) {
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
+ ASSERT_EQ(0, ioctx.snap_create("snap1"));
+ ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
+ std::vector<snap_t> snaps;
+ EXPECT_EQ(0, ioctx.snap_list(&snaps));
+ EXPECT_EQ(1U, snaps.size());
+ snap_t rid;
+ EXPECT_EQ(0, ioctx.snap_lookup("snap1", &rid));
+ EXPECT_EQ(rid, snaps[0]);
+ EXPECT_EQ(0, ioctx.snap_remove("snap1"));
+ ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
+}
+
+TEST_F(LibRadosSnapshotsPP, SnapRemovePP) {
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.snap_create("snap1"));
+ rados_snap_t rid;
+ ASSERT_EQ(0, ioctx.snap_lookup("snap1", &rid));
+ ASSERT_EQ(0, ioctx.snap_remove("snap1"));
+ ASSERT_EQ(-ENOENT, ioctx.snap_lookup("snap1", &rid));
+}
+
+TEST_F(LibRadosSnapshotsPP, RollbackPP) {
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.snap_create("snap1"));
+ char buf2[sizeof(buf)];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ EXPECT_EQ(0, ioctx.write_full("foo", bl2));
+ EXPECT_EQ(0, ioctx.snap_rollback("foo", "snap1"));
+ bufferlist bl3;
+ EXPECT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
+ EXPECT_EQ(0, memcmp(buf, bl3.c_str(), sizeof(buf)));
+ EXPECT_EQ(0, ioctx.snap_remove("snap1"));
+}
+
+TEST_F(LibRadosSnapshotsPP, SnapGetNamePP) {
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
+ rados_snap_t rid;
+ EXPECT_EQ(0, ioctx.snap_lookup("snapfoo", &rid));
+ EXPECT_EQ(-ENOENT, ioctx.snap_lookup("snapbar", &rid));
+ std::string name;
+ EXPECT_EQ(0, ioctx.snap_get_name(rid, &name));
+ time_t snaptime;
+ EXPECT_EQ(0, ioctx.snap_get_stamp(rid, &snaptime));
+ EXPECT_EQ(0, strcmp(name.c_str(), "snapfoo"));
+ EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
+}
+
+TEST_F(LibRadosSnapshotsPP, SnapCreateRemovePP) {
+ // reproduces http://tracker.ceph.com/issues/10262
+ bufferlist bl;
+ bl.append("foo");
+ ASSERT_EQ(0, ioctx.write("foo", bl, bl.length(), 0));
+ ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
+ ASSERT_EQ(0, ioctx.remove("foo"));
+ ASSERT_EQ(0, ioctx.snap_create("snapbar"));
+
+ std::unique_ptr<librados::ObjectWriteOperation> op(new librados::ObjectWriteOperation());
+ op->create(false);
+ op->remove();
+ ASSERT_EQ(0, ioctx.operate("foo", op.get()));
+
+ EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
+ EXPECT_EQ(0, ioctx.snap_remove("snapbar"));
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedPP, SnapPP) {
+ std::vector<uint64_t> my_snaps;
+ my_snaps.push_back(-2);
+ ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ASSERT_TRUE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+
+ my_snaps.push_back(-2);
+ librados::AioCompletion *completion = cluster.aio_create_completion();
+ ioctx.aio_selfmanaged_snap_create(&my_snaps.back(), completion);
+ ASSERT_EQ(0, completion->wait_for_complete());
+ completion->release();
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ char buf2[sizeof(buf)];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), 0));
+
+ ioctx.snap_set_read(my_snaps[1]);
+ bufferlist bl3;
+ ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
+
+ completion = cluster.aio_create_completion();
+ ioctx.aio_selfmanaged_snap_remove(my_snaps.back(), completion);
+ ASSERT_EQ(0, completion->wait_for_complete());
+ completion->release();
+ my_snaps.pop_back();
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
+ ASSERT_TRUE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
+ ASSERT_EQ(0, ioctx.remove("foo"));
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedPP, RollbackPP) {
+ std::vector<uint64_t> my_snaps;
+ IoCtx readioctx;
+ ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), readioctx));
+ readioctx.set_namespace(nspace);
+ readioctx.snap_set_read(LIBRADOS_SNAP_DIR);
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ //Write 3 consecutive buffers
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*2));
+
+ snap_set_t ss;
+
+ snap_t head = SNAP_HEAD;
+ ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
+ ASSERT_EQ(1u, ss.clones.size());
+ ASSERT_EQ(head, ss.clones[0].cloneid);
+ ASSERT_EQ(0u, ss.clones[0].snaps.size());
+ ASSERT_EQ(0u, ss.clones[0].overlap.size());
+ ASSERT_EQ(384u, ss.clones[0].size);
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ char buf2[sizeof(buf)];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ //Change the middle buffer
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize));
+ //Add another after
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*3));
+
+ ASSERT_EQ(-EINVAL, ioctx.list_snaps("foo", &ss));
+ ObjectReadOperation o;
+ o.list_snaps(&ss, NULL);
+ ASSERT_EQ(-EINVAL, ioctx.operate("foo", &o, NULL));
+
+ ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
+ ASSERT_EQ(2u, ss.clones.size());
+ ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
+ ASSERT_EQ(1u, ss.clones[0].snaps.size());
+ ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
+ ASSERT_EQ(2u, ss.clones[0].overlap.size());
+ ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[0].second);
+ ASSERT_EQ(256u, ss.clones[0].overlap[1].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[1].second);
+ ASSERT_EQ(384u, ss.clones[0].size);
+ ASSERT_EQ(head, ss.clones[1].cloneid);
+ ASSERT_EQ(0u, ss.clones[1].snaps.size());
+ ASSERT_EQ(0u, ss.clones[1].overlap.size());
+ ASSERT_EQ(512u, ss.clones[1].size);
+
+ ioctx.selfmanaged_snap_rollback("foo", my_snaps[1]);
+
+ bufferlist bl3;
+ ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), bufsize));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), bufsize*2));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ((int)0, ioctx.read("foo", bl3, sizeof(buf), bufsize*3));
+
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ readioctx.close();
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedPP, SnapOverlapPP) {
+ std::vector<uint64_t> my_snaps;
+ IoCtx readioctx;
+ ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), readioctx));
+ readioctx.set_namespace(nspace);
+ readioctx.snap_set_read(LIBRADOS_SNAP_DIR);
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*2));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*4));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*6));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*8));
+
+ snap_set_t ss;
+ snap_t head = SNAP_HEAD;
+ ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
+ ASSERT_EQ(1u, ss.clones.size());
+ ASSERT_EQ(head, ss.clones[0].cloneid);
+ ASSERT_EQ(0u, ss.clones[0].snaps.size());
+ ASSERT_EQ(0u, ss.clones[0].overlap.size());
+ ASSERT_EQ(1152u, ss.clones[0].size);
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ char buf2[sizeof(buf)];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*1));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*3));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*5));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*7));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*9));
+
+ ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
+ ASSERT_EQ(2u, ss.clones.size());
+ ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
+ ASSERT_EQ(1u, ss.clones[0].snaps.size());
+ ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
+ ASSERT_EQ(5u, ss.clones[0].overlap.size());
+ ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[0].second);
+ ASSERT_EQ(256u, ss.clones[0].overlap[1].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[1].second);
+ ASSERT_EQ(512u, ss.clones[0].overlap[2].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[2].second);
+ ASSERT_EQ(768u, ss.clones[0].overlap[3].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[3].second);
+ ASSERT_EQ(1024u, ss.clones[0].overlap[4].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[4].second);
+ ASSERT_EQ(1152u, ss.clones[0].size);
+ ASSERT_EQ(head, ss.clones[1].cloneid);
+ ASSERT_EQ(0u, ss.clones[1].snaps.size());
+ ASSERT_EQ(0u, ss.clones[1].overlap.size());
+ ASSERT_EQ(1280u, ss.clones[1].size);
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+
+ char buf3[sizeof(buf)];
+ memset(buf3, 0xee, sizeof(buf3));
+ bufferlist bl4;
+ bl4.append(buf3, sizeof(buf3));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*1));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*4));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*5));
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*8));
+
+ ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
+ ASSERT_EQ(3u, ss.clones.size());
+ ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
+ ASSERT_EQ(1u, ss.clones[0].snaps.size());
+ ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
+ ASSERT_EQ(5u, ss.clones[0].overlap.size());
+ ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[0].second);
+ ASSERT_EQ(256u, ss.clones[0].overlap[1].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[1].second);
+ ASSERT_EQ(512u, ss.clones[0].overlap[2].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[2].second);
+ ASSERT_EQ(768u, ss.clones[0].overlap[3].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[3].second);
+ ASSERT_EQ(1024u, ss.clones[0].overlap[4].first);
+ ASSERT_EQ(128u, ss.clones[0].overlap[4].second);
+ ASSERT_EQ(1152u, ss.clones[0].size);
+
+ ASSERT_EQ(my_snaps[2], ss.clones[1].cloneid);
+ ASSERT_EQ(1u, ss.clones[1].snaps.size());
+ ASSERT_EQ(my_snaps[2], ss.clones[1].snaps[0]);
+ ASSERT_EQ(4u, ss.clones[1].overlap.size());
+ ASSERT_EQ(0u, ss.clones[1].overlap[0].first);
+ ASSERT_EQ(128u, ss.clones[1].overlap[0].second);
+ ASSERT_EQ(256u, ss.clones[1].overlap[1].first);
+ ASSERT_EQ(256u, ss.clones[1].overlap[1].second);
+ ASSERT_EQ(768u, ss.clones[1].overlap[2].first);
+ ASSERT_EQ(256u, ss.clones[1].overlap[2].second);
+ ASSERT_EQ(1152u, ss.clones[1].overlap[3].first);
+ ASSERT_EQ(128u, ss.clones[1].overlap[3].second);
+ ASSERT_EQ(1280u, ss.clones[1].size);
+
+ ASSERT_EQ(head, ss.clones[2].cloneid);
+ ASSERT_EQ(0u, ss.clones[2].snaps.size());
+ ASSERT_EQ(0u, ss.clones[2].overlap.size());
+ ASSERT_EQ(1280u, ss.clones[2].size);
+
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ readioctx.close();
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedPP, Bug11677) {
+ std::vector<uint64_t> my_snaps;
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+
+ int bsize = 1<<20;
+ char *buf = (char *)new char[bsize];
+ memset(buf, 0xcc, bsize);
+ bufferlist bl1;
+ bl1.append(buf, bsize);
+ ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+
+ std::unique_ptr<librados::ObjectWriteOperation> op(new librados::ObjectWriteOperation());
+ op->assert_exists();
+ op->remove();
+ ASSERT_EQ(0, ioctx.operate("foo", op.get()));
+
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
+ delete[] buf;
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedPP, OrderSnap) {
+ std::vector<uint64_t> my_snaps;
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ int flags = librados::OPERATION_ORDERSNAP;
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ObjectWriteOperation op1;
+ op1.write(0, bl);
+ librados::AioCompletion *comp1 = cluster.aio_create_completion();
+ ASSERT_EQ(0, ioctx.aio_operate("foo", comp1, &op1, flags));
+ ASSERT_EQ(0, comp1->wait_for_complete());
+ ASSERT_EQ(0, comp1->get_return_value());
+ comp1->release();
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ObjectWriteOperation op2;
+ op2.write(0, bl);
+ librados::AioCompletion *comp2 = cluster.aio_create_completion();
+ ASSERT_EQ(0, ioctx.aio_operate("foo", comp2, &op2, flags));
+ ASSERT_EQ(0, comp2->wait_for_complete());
+ ASSERT_EQ(0, comp2->get_return_value());
+ comp2->release();
+
+ my_snaps.pop_back();
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ObjectWriteOperation op3;
+ op3.write(0, bl);
+ librados::AioCompletion *comp3 = cluster.aio_create_completion();
+ ASSERT_EQ(0, ioctx.aio_operate("foo", comp3, &op3, flags));
+ ASSERT_EQ(0, comp3->wait_for_complete());
+ ASSERT_EQ(-EOLDSNAPC, comp3->get_return_value());
+ comp3->release();
+
+ ObjectWriteOperation op4;
+ op4.write(0, bl);
+ librados::AioCompletion *comp4 = cluster.aio_create_completion();
+ ASSERT_EQ(0, ioctx.aio_operate("foo", comp4, &op4, 0));
+ ASSERT_EQ(0, comp4->wait_for_complete());
+ ASSERT_EQ(0, comp4->get_return_value());
+ comp4->release();
+}
+
+// EC testing
+TEST_F(LibRadosSnapshotsECPP, SnapListPP) {
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.snap_create("snap1"));
+ std::vector<snap_t> snaps;
+ EXPECT_EQ(0, ioctx.snap_list(&snaps));
+ EXPECT_EQ(1U, snaps.size());
+ snap_t rid;
+ EXPECT_EQ(0, ioctx.snap_lookup("snap1", &rid));
+ EXPECT_EQ(rid, snaps[0]);
+ EXPECT_EQ(0, ioctx.snap_remove("snap1"));
+}
+
+TEST_F(LibRadosSnapshotsECPP, SnapRemovePP) {
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.snap_create("snap1"));
+ rados_snap_t rid;
+ ASSERT_EQ(0, ioctx.snap_lookup("snap1", &rid));
+ ASSERT_EQ(0, ioctx.snap_remove("snap1"));
+ ASSERT_EQ(-ENOENT, ioctx.snap_lookup("snap1", &rid));
+}
+
+TEST_F(LibRadosSnapshotsECPP, RollbackPP) {
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.snap_create("snap1"));
+ char buf2[sizeof(buf)];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ EXPECT_EQ(0, ioctx.write_full("foo", bl2));
+ EXPECT_EQ(0, ioctx.snap_rollback("foo", "snap1"));
+ bufferlist bl3;
+ EXPECT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
+ EXPECT_EQ(0, memcmp(buf, bl3.c_str(), sizeof(buf)));
+ EXPECT_EQ(0, ioctx.snap_remove("snap1"));
+}
+
+TEST_F(LibRadosSnapshotsECPP, SnapGetNamePP) {
+ char buf[bufsize];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
+ rados_snap_t rid;
+ EXPECT_EQ(0, ioctx.snap_lookup("snapfoo", &rid));
+ EXPECT_EQ(-ENOENT, ioctx.snap_lookup("snapbar", &rid));
+ std::string name;
+ EXPECT_EQ(0, ioctx.snap_get_name(rid, &name));
+ time_t snaptime;
+ EXPECT_EQ(0, ioctx.snap_get_stamp(rid, &snaptime));
+ EXPECT_EQ(0, strcmp(name.c_str(), "snapfoo"));
+ EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedECPP, SnapPP) {
+ std::vector<uint64_t> my_snaps;
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ int bsize = alignment;
+ char *buf = (char *)new char[bsize];
+ memset(buf, 0xcc, bsize);
+ bufferlist bl1;
+ bl1.append(buf, bsize);
+ ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
+
+ my_snaps.push_back(-2);
+ librados::AioCompletion *completion = cluster.aio_create_completion();
+ ioctx.aio_selfmanaged_snap_create(&my_snaps.back(), completion);
+ ASSERT_EQ(0, completion->wait_for_complete());
+ completion->release();
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ char *buf2 = (char *)new char[bsize];
+ memset(buf2, 0xdd, bsize);
+ bufferlist bl2;
+ bl2.append(buf2, bsize);
+ // Add another aligned buffer
+ ASSERT_EQ(0, ioctx.write("foo", bl2, bsize, bsize));
+
+ ioctx.snap_set_read(my_snaps[1]);
+ bufferlist bl3;
+ ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize*3, 0));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
+
+ completion = cluster.aio_create_completion();
+ ioctx.aio_selfmanaged_snap_remove(my_snaps.back(), completion);
+ ASSERT_EQ(0, completion->wait_for_complete());
+ completion->release();
+ my_snaps.pop_back();
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
+ ASSERT_EQ(0, ioctx.remove("foo"));
+ delete[] buf;
+ delete[] buf2;
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedECPP, RollbackPP) {
+ std::vector<uint64_t> my_snaps;
+ IoCtx readioctx;
+ ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), readioctx));
+ readioctx.set_namespace(nspace);
+ readioctx.snap_set_read(LIBRADOS_SNAP_DIR);
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ int bsize = alignment;
+ char *buf = (char *)new char[bsize];
+ memset(buf, 0xcc, bsize);
+ bufferlist bl1;
+ bl1.append(buf, bsize);
+ //Write 3 consecutive buffers
+ ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, bsize));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, bsize*2));
+
+ snap_set_t ss;
+
+ snap_t head = SNAP_HEAD;
+ ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
+ ASSERT_EQ(1u, ss.clones.size());
+ ASSERT_EQ(head, ss.clones[0].cloneid);
+ ASSERT_EQ(0u, ss.clones[0].snaps.size());
+ ASSERT_EQ(0u, ss.clones[0].overlap.size());
+ ASSERT_EQ((unsigned)(bsize*3), ss.clones[0].size);
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ char *buf2 = (char *)new char[bsize];
+ memset(buf2, 0xdd, bsize);
+ bufferlist bl2;
+ bl2.append(buf2, bsize);
+ //Change the middle buffer
+ //ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize));
+ //Add another after
+ ASSERT_EQ(0, ioctx.write("foo", bl2, bsize, bsize*3));
+
+ ASSERT_EQ(-EINVAL, ioctx.list_snaps("foo", &ss));
+ ObjectReadOperation o;
+ o.list_snaps(&ss, NULL);
+ ASSERT_EQ(-EINVAL, ioctx.operate("foo", &o, NULL));
+
+ ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
+ ASSERT_EQ(2u, ss.clones.size());
+ ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
+ ASSERT_EQ(1u, ss.clones[0].snaps.size());
+ ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
+ ASSERT_EQ(1u, ss.clones[0].overlap.size());
+ ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
+ ASSERT_EQ((unsigned)bsize*3, ss.clones[0].overlap[0].second);
+ ASSERT_EQ((unsigned)bsize*3, ss.clones[0].size);
+ ASSERT_EQ(head, ss.clones[1].cloneid);
+ ASSERT_EQ(0u, ss.clones[1].snaps.size());
+ ASSERT_EQ(0u, ss.clones[1].overlap.size());
+ ASSERT_EQ((unsigned)bsize*4, ss.clones[1].size);
+
+ ioctx.selfmanaged_snap_rollback("foo", my_snaps[1]);
+
+ bufferlist bl3;
+ ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, 0));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
+ ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, bsize));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
+ ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, bsize*2));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
+ ASSERT_EQ(0, ioctx.read("foo", bl3, bsize, bsize*3));
+
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ readioctx.close();
+
+ delete[] buf;
+ delete[] buf2;
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedECPP, Bug11677) {
+ std::vector<uint64_t> my_snaps;
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+
+ int bsize = alignment;
+ char *buf = (char *)new char[bsize];
+ memset(buf, 0xcc, bsize);
+ bufferlist bl1;
+ bl1.append(buf, bsize);
+ ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
+
+ my_snaps.push_back(-2);
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+ ::std::reverse(my_snaps.begin(), my_snaps.end());
+
+ std::unique_ptr<librados::ObjectWriteOperation> op(new librados::ObjectWriteOperation());
+ op->assert_exists();
+ op->remove();
+ ASSERT_EQ(0, ioctx.operate("foo", op.get()));
+
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+ my_snaps.pop_back();
+ ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
+ delete[] buf;
+}
diff --git a/src/test/librados/stat.cc b/src/test/librados/stat.cc
index 9641bb8138d..fd667742738 100644
--- a/src/test/librados/stat.cc
+++ b/src/test/librados/stat.cc
@@ -1,5 +1,4 @@
#include "include/rados/librados.h"
-#include "include/rados/librados.hpp"
#include "test/librados/test.h"
#include "test/librados/TestCase.h"
@@ -9,12 +8,8 @@
#include <errno.h>
#include "gtest/gtest.h"
-using namespace librados;
-
typedef RadosTest LibRadosStat;
-typedef RadosTestPP LibRadosStatPP;
typedef RadosTestEC LibRadosStatEC;
-typedef RadosTestECPP LibRadosStatECPP;
TEST_F(LibRadosStat, Stat) {
char buf[128];
@@ -27,49 +22,6 @@ TEST_F(LibRadosStat, Stat) {
ASSERT_EQ(-ENOENT, rados_stat(ioctx, "nonexistent", &size, &mtime));
}
-TEST_F(LibRadosStatPP, StatPP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- uint64_t size;
- time_t mtime;
- ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
- ASSERT_EQ(sizeof(buf), size);
- ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
-}
-
-TEST_F(LibRadosStatPP, Stat2Mtime2PP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- librados::ObjectWriteOperation op;
- struct timespec ts;
- ts.tv_sec = 1457129052;
- ts.tv_nsec = 123456789;
- op.mtime2(&ts);
- op.write(0, bl);
- ASSERT_EQ(0, ioctx.operate("foo", &op));
-
- /* XXX time comparison asserts could spuriously fail */
-
- uint64_t size;
- time_t mtime;
- ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
- ASSERT_EQ(sizeof(buf), size);
- ASSERT_EQ(mtime, ts.tv_sec);
-
- struct timespec ts2;
- ASSERT_EQ(0, ioctx.stat2("foo", &size, &ts2));
- ASSERT_EQ(sizeof(buf), size);
- ASSERT_EQ(ts2.tv_sec, ts.tv_sec);
- ASSERT_EQ(ts2.tv_nsec, ts.tv_nsec);
-
- ASSERT_EQ(-ENOENT, ioctx.stat2("nonexistent", &size, &ts2));
-}
-
TEST_F(LibRadosStat, StatNS) {
char buf[128];
memset(buf, 0xcc, sizeof(buf));
@@ -96,46 +48,11 @@ TEST_F(LibRadosStat, StatNS) {
ASSERT_EQ(-ENOENT, rados_stat(ioctx, "foo2", &size, &mtime));
}
-TEST_F(LibRadosStatPP, StatPPNS) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ioctx.set_namespace("");
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.write("foo2", bl, sizeof(buf), 0));
-
- char buf2[64];
- memset(buf2, 0xbb, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- ioctx.set_namespace("nspace");
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), 0));
-
- uint64_t size;
- time_t mtime;
- ioctx.set_namespace("");
- ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
- ASSERT_EQ(sizeof(buf), size);
- ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
-
- ioctx.set_namespace("nspace");
- ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
- ASSERT_EQ(sizeof(buf2), size);
- ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
- ASSERT_EQ(-ENOENT, ioctx.stat("foo2", &size, &mtime));
-}
-
TEST_F(LibRadosStat, ClusterStat) {
struct rados_cluster_stat_t result;
ASSERT_EQ(0, rados_cluster_stat(cluster, &result));
}
-TEST_F(LibRadosStatPP, ClusterStatPP) {
- cluster_stat_t cstat;
- ASSERT_EQ(0, cluster.cluster_stat(cstat));
-}
-
TEST_F(LibRadosStat, PoolStat) {
char buf[128];
char actual_pool_name[80];
@@ -149,19 +66,6 @@ TEST_F(LibRadosStat, PoolStat) {
ASSERT_EQ(0, rados_ioctx_pool_stat(ioctx, &stats));
}
-TEST_F(LibRadosStatPP, PoolStatPP) {
- std::string n = ioctx.get_pool_name();
- ASSERT_EQ(n, pool_name);
- char buf[128];
- memset(buf, 0xff, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- std::list<std::string> v;
- std::map<std::string,stats_map> stats;
- ASSERT_EQ(0, cluster.get_pool_stats(v, stats));
-}
-
TEST_F(LibRadosStatEC, Stat) {
char buf[128];
memset(buf, 0xcc, sizeof(buf));
@@ -173,19 +77,6 @@ TEST_F(LibRadosStatEC, Stat) {
ASSERT_EQ(-ENOENT, rados_stat(ioctx, "nonexistent", &size, &mtime));
}
-TEST_F(LibRadosStatECPP, StatPP) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- uint64_t size;
- time_t mtime;
- ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
- ASSERT_EQ(sizeof(buf), size);
- ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
-}
-
TEST_F(LibRadosStatEC, StatNS) {
char buf[128];
memset(buf, 0xcc, sizeof(buf));
@@ -212,46 +103,11 @@ TEST_F(LibRadosStatEC, StatNS) {
ASSERT_EQ(-ENOENT, rados_stat(ioctx, "foo2", &size, &mtime));
}
-TEST_F(LibRadosStatECPP, StatPPNS) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ioctx.set_namespace("");
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- ASSERT_EQ(0, ioctx.write("foo2", bl, sizeof(buf), 0));
-
- char buf2[64];
- memset(buf2, 0xbb, sizeof(buf2));
- bufferlist bl2;
- bl2.append(buf2, sizeof(buf2));
- ioctx.set_namespace("nspace");
- ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), 0));
-
- uint64_t size;
- time_t mtime;
- ioctx.set_namespace("");
- ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
- ASSERT_EQ(sizeof(buf), size);
- ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
-
- ioctx.set_namespace("nspace");
- ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
- ASSERT_EQ(sizeof(buf2), size);
- ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
- ASSERT_EQ(-ENOENT, ioctx.stat("foo2", &size, &mtime));
-}
-
TEST_F(LibRadosStatEC, ClusterStat) {
struct rados_cluster_stat_t result;
ASSERT_EQ(0, rados_cluster_stat(cluster, &result));
}
-TEST_F(LibRadosStatECPP, ClusterStatPP) {
- cluster_stat_t cstat;
- ASSERT_EQ(0, cluster.cluster_stat(cstat));
-}
-
TEST_F(LibRadosStatEC, PoolStat) {
char buf[128];
char actual_pool_name[80];
@@ -264,16 +120,3 @@ TEST_F(LibRadosStatEC, PoolStat) {
memset(&stats, 0, sizeof(stats));
ASSERT_EQ(0, rados_ioctx_pool_stat(ioctx, &stats));
}
-
-TEST_F(LibRadosStatECPP, PoolStatPP) {
- std::string n = ioctx.get_pool_name();
- ASSERT_EQ(n, pool_name);
- char buf[128];
- memset(buf, 0xff, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
- std::list<std::string> v;
- std::map<std::string,stats_map> stats;
- ASSERT_EQ(0, cluster.get_pool_stats(v, stats));
-}
diff --git a/src/test/librados/stat_cxx.cc b/src/test/librados/stat_cxx.cc
new file mode 100644
index 00000000000..d0d0116dfec
--- /dev/null
+++ b/src/test/librados/stat_cxx.cc
@@ -0,0 +1,163 @@
+#include "gtest/gtest.h"
+
+#include "include/rados/librados.hpp"
+
+#include "test/librados/test_cxx.h"
+#include "test/librados/testcase_cxx.h"
+
+using namespace librados;
+
+typedef RadosTestPP LibRadosStatPP;
+typedef RadosTestECPP LibRadosStatECPP;
+
+TEST_F(LibRadosStatPP, StatPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ uint64_t size;
+ time_t mtime;
+ ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+ ASSERT_EQ(sizeof(buf), size);
+ ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
+}
+
+TEST_F(LibRadosStatPP, Stat2Mtime2PP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ librados::ObjectWriteOperation op;
+ struct timespec ts;
+ ts.tv_sec = 1457129052;
+ ts.tv_nsec = 123456789;
+ op.mtime2(&ts);
+ op.write(0, bl);
+ ASSERT_EQ(0, ioctx.operate("foo", &op));
+
+ /* XXX time comparison asserts could spuriously fail */
+
+ uint64_t size;
+ time_t mtime;
+ ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+ ASSERT_EQ(sizeof(buf), size);
+ ASSERT_EQ(mtime, ts.tv_sec);
+
+ struct timespec ts2;
+ ASSERT_EQ(0, ioctx.stat2("foo", &size, &ts2));
+ ASSERT_EQ(sizeof(buf), size);
+ ASSERT_EQ(ts2.tv_sec, ts.tv_sec);
+ ASSERT_EQ(ts2.tv_nsec, ts.tv_nsec);
+
+ ASSERT_EQ(-ENOENT, ioctx.stat2("nonexistent", &size, &ts2));
+}
+
+TEST_F(LibRadosStatPP, ClusterStatPP) {
+ cluster_stat_t cstat;
+ ASSERT_EQ(0, cluster.cluster_stat(cstat));
+}
+
+TEST_F(LibRadosStatPP, PoolStatPP) {
+ std::string n = ioctx.get_pool_name();
+ ASSERT_EQ(n, pool_name);
+ char buf[128];
+ memset(buf, 0xff, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ std::list<std::string> v;
+ std::map<std::string,stats_map> stats;
+ ASSERT_EQ(0, cluster.get_pool_stats(v, stats));
+}
+
+TEST_F(LibRadosStatECPP, StatPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ uint64_t size;
+ time_t mtime;
+ ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+ ASSERT_EQ(sizeof(buf), size);
+ ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
+}
+
+TEST_F(LibRadosStatECPP, ClusterStatPP) {
+ cluster_stat_t cstat;
+ ASSERT_EQ(0, cluster.cluster_stat(cstat));
+}
+
+TEST_F(LibRadosStatECPP, PoolStatPP) {
+ std::string n = ioctx.get_pool_name();
+ ASSERT_EQ(n, pool_name);
+ char buf[128];
+ memset(buf, 0xff, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
+ std::list<std::string> v;
+ std::map<std::string,stats_map> stats;
+ ASSERT_EQ(0, cluster.get_pool_stats(v, stats));
+}
+
+TEST_F(LibRadosStatPP, StatPPNS) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ioctx.set_namespace("");
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.write("foo2", bl, sizeof(buf), 0));
+
+ char buf2[64];
+ memset(buf2, 0xbb, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ioctx.set_namespace("nspace");
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), 0));
+
+ uint64_t size;
+ time_t mtime;
+ ioctx.set_namespace("");
+ ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+ ASSERT_EQ(sizeof(buf), size);
+ ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
+
+ ioctx.set_namespace("nspace");
+ ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+ ASSERT_EQ(sizeof(buf2), size);
+ ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
+ ASSERT_EQ(-ENOENT, ioctx.stat("foo2", &size, &mtime));
+}
+
+TEST_F(LibRadosStatECPP, StatPPNS) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ioctx.set_namespace("");
+ ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
+ ASSERT_EQ(0, ioctx.write("foo2", bl, sizeof(buf), 0));
+
+ char buf2[64];
+ memset(buf2, 0xbb, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ioctx.set_namespace("nspace");
+ ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), 0));
+
+ uint64_t size;
+ time_t mtime;
+ ioctx.set_namespace("");
+ ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+ ASSERT_EQ(sizeof(buf), size);
+ ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
+
+ ioctx.set_namespace("nspace");
+ ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+ ASSERT_EQ(sizeof(buf2), size);
+ ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
+ ASSERT_EQ(-ENOENT, ioctx.stat("foo2", &size, &mtime));
+}
diff --git a/src/test/librados/test.cc b/src/test/librados/test.cc
index 04fd0452e66..fdfbc54199c 100644
--- a/src/test/librados/test.cc
+++ b/src/test/librados/test.cc
@@ -18,22 +18,6 @@
#include <iostream>
#include "gtest/gtest.h"
-using namespace librados;
-
-std::string get_temp_pool_name(const std::string &prefix)
-{
- char hostname[80];
- char out[160];
- memset(hostname, 0, sizeof(hostname));
- memset(out, 0, sizeof(out));
- gethostname(hostname, sizeof(hostname)-1);
- static int num = 1;
- snprintf(out, sizeof(out), "%s-%d-%d", hostname, getpid(), num);
- num++;
- return prefix + out;
-}
-
-
std::string create_one_pool(
const std::string &pool_name, rados_t *cluster, uint32_t pg_num)
{
@@ -149,109 +133,6 @@ std::string create_one_ec_pool(const std::string &pool_name, rados_t *cluster)
return "";
}
-std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster)
-{
- return create_one_pool_pp(pool_name, cluster, {});
-}
-std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster,
- const std::map<std::string, std::string> &config)
-{
- std::string err = connect_cluster_pp(cluster, config);
- if (err.length())
- return err;
- int ret = cluster.pool_create(pool_name.c_str());
- if (ret) {
- cluster.shutdown();
- std::ostringstream oss;
- oss << "cluster.pool_create(" << pool_name << ") failed with error " << ret;
- return oss.str();
- }
-
- IoCtx ioctx;
- ret = cluster.ioctx_create(pool_name.c_str(), ioctx);
- if (ret < 0) {
- cluster.shutdown();
- std::ostringstream oss;
- oss << "cluster.ioctx_create(" << pool_name << ") failed with error "
- << ret;
- return oss.str();
- }
- ioctx.application_enable("rados", true);
- return "";
-}
-
-int destroy_ruleset_pp(Rados &cluster,
- const std::string &ruleset,
- std::ostream &oss)
-{
- bufferlist inbl;
- int ret = cluster.mon_command("{\"prefix\": \"osd crush rule rm\", \"name\":\"" +
- ruleset + "\"}", inbl, NULL, NULL);
- if (ret)
- oss << "mon_command: osd crush rule rm " + ruleset + " failed with error " << ret << std::endl;
- return ret;
-}
-
-int destroy_ec_profile_pp(Rados &cluster, const std::string& pool_name,
- std::ostream &oss)
-{
- bufferlist inbl;
- int ret = cluster.mon_command("{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile-" + pool_name + "\"}",
- inbl, NULL, NULL);
- if (ret)
- oss << "mon_command: osd erasure-code-profile rm testprofile-" << pool_name << " failed with error " << ret << std::endl;
- return ret;
-}
-
-int destroy_ec_profile_and_ruleset_pp(Rados &cluster,
- const std::string &ruleset,
- std::ostream &oss)
-{
- int ret;
- ret = destroy_ec_profile_pp(cluster, ruleset, oss);
- if (ret)
- return ret;
- return destroy_ruleset_pp(cluster, ruleset, oss);
-}
-
-std::string create_one_ec_pool_pp(const std::string &pool_name, Rados &cluster)
-{
- std::string err = connect_cluster_pp(cluster);
- if (err.length())
- return err;
-
- std::ostringstream oss;
- int ret = destroy_ec_profile_and_ruleset_pp(cluster, pool_name, oss);
- if (ret) {
- cluster.shutdown();
- return oss.str();
- }
-
- bufferlist inbl;
- ret = cluster.mon_command(
- "{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile-" + pool_name + "\", \"profile\": [ \"k=2\", \"m=1\", \"crush-failure-domain=osd\"]}",
- inbl, NULL, NULL);
- if (ret) {
- cluster.shutdown();
- oss << "mon_command erasure-code-profile set name:testprofile-" << pool_name << " failed with error " << ret;
- return oss.str();
- }
-
- ret = cluster.mon_command(
- "{\"prefix\": \"osd pool create\", \"pool\": \"" + pool_name + "\", \"pool_type\":\"erasure\", \"pg_num\":8, \"pgp_num\":8, \"erasure_code_profile\":\"testprofile-" + pool_name + "\"}",
- inbl, NULL, NULL);
- if (ret) {
- bufferlist inbl;
- destroy_ec_profile_pp(cluster, pool_name, oss);
- cluster.shutdown();
- oss << "mon_command osd pool create pool:" << pool_name << " pool_type:erasure failed with error " << ret;
- return oss.str();
- }
-
- cluster.wait_for_latest_osdmap();
- return "";
-}
-
std::string connect_cluster(rados_t *cluster)
{
char *id = getenv("CEPH_CLIENT_ID");
@@ -282,53 +163,6 @@ std::string connect_cluster(rados_t *cluster)
return "";
}
-std::string connect_cluster_pp(librados::Rados &cluster)
-{
- return connect_cluster_pp(cluster, {});
-}
-
-std::string connect_cluster_pp(librados::Rados &cluster,
- const std::map<std::string, std::string> &config)
-{
- char *id = getenv("CEPH_CLIENT_ID");
- if (id) std::cerr << "Client id is: " << id << std::endl;
-
- int ret;
- ret = cluster.init(id);
- if (ret) {
- std::ostringstream oss;
- oss << "cluster.init failed with error " << ret;
- return oss.str();
- }
- ret = cluster.conf_read_file(NULL);
- if (ret) {
- cluster.shutdown();
- std::ostringstream oss;
- oss << "cluster.conf_read_file failed with error " << ret;
- return oss.str();
- }
- cluster.conf_parse_env(NULL);
-
- for (auto &setting : config) {
- ret = cluster.conf_set(setting.first.c_str(), setting.second.c_str());
- if (ret) {
- std::ostringstream oss;
- oss << "failed to set config value " << setting.first << " to '"
- << setting.second << "': " << strerror(-ret);
- return oss.str();
- }
- }
-
- ret = cluster.connect();
- if (ret) {
- cluster.shutdown();
- std::ostringstream oss;
- oss << "cluster.connect failed with error " << ret;
- return oss.str();
- }
- return "";
-}
-
int destroy_one_pool(const std::string &pool_name, rados_t *cluster)
{
int ret = rados_pool_delete(*cluster, pool_name.c_str());
@@ -362,61 +196,3 @@ int destroy_one_ec_pool(const std::string &pool_name, rados_t *cluster)
rados_shutdown(*cluster);
return ret;
}
-
-int destroy_one_pool_pp(const std::string &pool_name, Rados &cluster)
-{
- int ret = cluster.pool_delete(pool_name.c_str());
- if (ret) {
- cluster.shutdown();
- return ret;
- }
- cluster.shutdown();
- return 0;
-}
-
-int destroy_one_ec_pool_pp(const std::string &pool_name, Rados &cluster)
-{
- int ret = cluster.pool_delete(pool_name.c_str());
- if (ret) {
- cluster.shutdown();
- return ret;
- }
-
- CephContext *cct = static_cast<CephContext*>(cluster.cct());
- if (!cct->_conf->mon_fake_pool_delete) { // hope this is in [global]
- std::ostringstream oss;
- ret = destroy_ec_profile_and_ruleset_pp(cluster, pool_name, oss);
- if (ret) {
- cluster.shutdown();
- return ret;
- }
- }
-
- cluster.wait_for_latest_osdmap();
- cluster.shutdown();
- return ret;
-}
-
-void assert_eq_sparse(bufferlist& expected,
- const std::map<uint64_t, uint64_t>& extents,
- bufferlist& actual) {
- auto i = expected.begin();
- auto p = actual.begin();
- uint64_t pos = 0;
- for (auto extent : extents) {
- const uint64_t start = extent.first;
- const uint64_t end = start + extent.second;
- for (; pos < end; ++i, ++pos) {
- ASSERT_FALSE(i.end());
- if (pos < start) {
- // check the hole
- ASSERT_EQ('\0', *i);
- } else {
- // then the extent
- ASSERT_EQ(*i, *p);
- ++p;
- }
- }
- }
- ASSERT_EQ(expected.length(), pos);
-}
diff --git a/src/test/librados/test.h b/src/test/librados/test.h
index 8b505957fd0..b3e0115fb46 100644
--- a/src/test/librados/test.h
+++ b/src/test/librados/test.h
@@ -16,45 +16,17 @@
#define CEPH_TEST_RADOS_API_TEST_H
#include "include/rados/librados.h"
-#include "include/rados/librados.hpp"
+#include "test/librados/test_shared.h"
#include <map>
#include <string>
#include <unistd.h>
-std::string get_temp_pool_name(const std::string &prefix = "test-rados-api-");
-
std::string create_one_pool(const std::string &pool_name, rados_t *cluster,
uint32_t pg_num=0);
std::string create_one_ec_pool(const std::string &pool_name, rados_t *cluster);
-std::string create_one_pool_pp(const std::string &pool_name,
- librados::Rados &cluster);
-std::string create_one_pool_pp(const std::string &pool_name,
- librados::Rados &cluster,
- const std::map<std::string, std::string> &config);
-std::string create_one_ec_pool_pp(const std::string &pool_name,
- librados::Rados &cluster);
std::string connect_cluster(rados_t *cluster);
-std::string connect_cluster_pp(librados::Rados &cluster);
-std::string connect_cluster_pp(librados::Rados &cluster,
- const std::map<std::string, std::string> &config);
int destroy_one_pool(const std::string &pool_name, rados_t *cluster);
int destroy_one_ec_pool(const std::string &pool_name, rados_t *cluster);
-int destroy_one_pool_pp(const std::string &pool_name, librados::Rados &cluster);
-int destroy_one_ec_pool_pp(const std::string &pool_name, librados::Rados &cluster);
-void assert_eq_sparse(bufferlist& expected,
- const std::map<uint64_t, uint64_t>& extents,
- bufferlist& actual);
-
-class TestAlarm
-{
-public:
- TestAlarm() {
- alarm(1200);
- }
- ~TestAlarm() {
- alarm(0);
- }
-};
#endif
diff --git a/src/test/librados/test_cxx.cc b/src/test/librados/test_cxx.cc
new file mode 100644
index 00000000000..9349aece8dc
--- /dev/null
+++ b/src/test/librados/test_cxx.cc
@@ -0,0 +1,203 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*
+// vim: ts=8 sw=2 smarttab
+
+#include "test_cxx.h"
+
+#include "include/stringify.h"
+#include "common/ceph_context.h"
+#include "common/config.h"
+
+#include <errno.h>
+#include <sstream>
+#include <stdlib.h>
+#include <string>
+#include <time.h>
+#include <unistd.h>
+#include <iostream>
+#include "gtest/gtest.h"
+
+using namespace librados;
+
+std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster)
+{
+ return create_one_pool_pp(pool_name, cluster, {});
+}
+std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster,
+ const std::map<std::string, std::string> &config)
+{
+ std::string err = connect_cluster_pp(cluster, config);
+ if (err.length())
+ return err;
+ int ret = cluster.pool_create(pool_name.c_str());
+ if (ret) {
+ cluster.shutdown();
+ std::ostringstream oss;
+ oss << "cluster.pool_create(" << pool_name << ") failed with error " << ret;
+ return oss.str();
+ }
+
+ IoCtx ioctx;
+ ret = cluster.ioctx_create(pool_name.c_str(), ioctx);
+ if (ret < 0) {
+ cluster.shutdown();
+ std::ostringstream oss;
+ oss << "cluster.ioctx_create(" << pool_name << ") failed with error "
+ << ret;
+ return oss.str();
+ }
+ ioctx.application_enable("rados", true);
+ return "";
+}
+
+int destroy_ruleset_pp(Rados &cluster,
+ const std::string &ruleset,
+ std::ostream &oss)
+{
+ bufferlist inbl;
+ int ret = cluster.mon_command("{\"prefix\": \"osd crush rule rm\", \"name\":\"" +
+ ruleset + "\"}", inbl, NULL, NULL);
+ if (ret)
+ oss << "mon_command: osd crush rule rm " + ruleset + " failed with error " << ret << std::endl;
+ return ret;
+}
+
+int destroy_ec_profile_pp(Rados &cluster, const std::string& pool_name,
+ std::ostream &oss)
+{
+ bufferlist inbl;
+ int ret = cluster.mon_command("{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile-" + pool_name + "\"}",
+ inbl, NULL, NULL);
+ if (ret)
+ oss << "mon_command: osd erasure-code-profile rm testprofile-" << pool_name << " failed with error " << ret << std::endl;
+ return ret;
+}
+
+int destroy_ec_profile_and_ruleset_pp(Rados &cluster,
+ const std::string &ruleset,
+ std::ostream &oss)
+{
+ int ret;
+ ret = destroy_ec_profile_pp(cluster, ruleset, oss);
+ if (ret)
+ return ret;
+ return destroy_ruleset_pp(cluster, ruleset, oss);
+}
+
+std::string create_one_ec_pool_pp(const std::string &pool_name, Rados &cluster)
+{
+ std::string err = connect_cluster_pp(cluster);
+ if (err.length())
+ return err;
+
+ std::ostringstream oss;
+ int ret = destroy_ec_profile_and_ruleset_pp(cluster, pool_name, oss);
+ if (ret) {
+ cluster.shutdown();
+ return oss.str();
+ }
+
+ bufferlist inbl;
+ ret = cluster.mon_command(
+ "{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile-" + pool_name + "\", \"profile\": [ \"k=2\", \"m=1\", \"crush-failure-domain=osd\"]}",
+ inbl, NULL, NULL);
+ if (ret) {
+ cluster.shutdown();
+ oss << "mon_command erasure-code-profile set name:testprofile-" << pool_name << " failed with error " << ret;
+ return oss.str();
+ }
+
+ ret = cluster.mon_command(
+ "{\"prefix\": \"osd pool create\", \"pool\": \"" + pool_name + "\", \"pool_type\":\"erasure\", \"pg_num\":8, \"pgp_num\":8, \"erasure_code_profile\":\"testprofile-" + pool_name + "\"}",
+ inbl, NULL, NULL);
+ if (ret) {
+ bufferlist inbl;
+ destroy_ec_profile_pp(cluster, pool_name, oss);
+ cluster.shutdown();
+ oss << "mon_command osd pool create pool:" << pool_name << " pool_type:erasure failed with error " << ret;
+ return oss.str();
+ }
+
+ cluster.wait_for_latest_osdmap();
+ return "";
+}
+
+std::string connect_cluster_pp(librados::Rados &cluster)
+{
+ return connect_cluster_pp(cluster, {});
+}
+
+std::string connect_cluster_pp(librados::Rados &cluster,
+ const std::map<std::string, std::string> &config)
+{
+ char *id = getenv("CEPH_CLIENT_ID");
+ if (id) std::cerr << "Client id is: " << id << std::endl;
+
+ int ret;
+ ret = cluster.init(id);
+ if (ret) {
+ std::ostringstream oss;
+ oss << "cluster.init failed with error " << ret;
+ return oss.str();
+ }
+ ret = cluster.conf_read_file(NULL);
+ if (ret) {
+ cluster.shutdown();
+ std::ostringstream oss;
+ oss << "cluster.conf_read_file failed with error " << ret;
+ return oss.str();
+ }
+ cluster.conf_parse_env(NULL);
+
+ for (auto &setting : config) {
+ ret = cluster.conf_set(setting.first.c_str(), setting.second.c_str());
+ if (ret) {
+ std::ostringstream oss;
+ oss << "failed to set config value " << setting.first << " to '"
+ << setting.second << "': " << strerror(-ret);
+ return oss.str();
+ }
+ }
+
+ ret = cluster.connect();
+ if (ret) {
+ cluster.shutdown();
+ std::ostringstream oss;
+ oss << "cluster.connect failed with error " << ret;
+ return oss.str();
+ }
+ return "";
+}
+
+int destroy_one_pool_pp(const std::string &pool_name, Rados &cluster)
+{
+ int ret = cluster.pool_delete(pool_name.c_str());
+ if (ret) {
+ cluster.shutdown();
+ return ret;
+ }
+ cluster.shutdown();
+ return 0;
+}
+
+int destroy_one_ec_pool_pp(const std::string &pool_name, Rados &cluster)
+{
+ int ret = cluster.pool_delete(pool_name.c_str());
+ if (ret) {
+ cluster.shutdown();
+ return ret;
+ }
+
+ CephContext *cct = static_cast<CephContext*>(cluster.cct());
+ if (!cct->_conf->mon_fake_pool_delete) { // hope this is in [global]
+ std::ostringstream oss;
+ ret = destroy_ec_profile_and_ruleset_pp(cluster, pool_name, oss);
+ if (ret) {
+ cluster.shutdown();
+ return ret;
+ }
+ }
+
+ cluster.wait_for_latest_osdmap();
+ cluster.shutdown();
+ return ret;
+}
diff --git a/src/test/librados/test_cxx.h b/src/test/librados/test_cxx.h
new file mode 100644
index 00000000000..1d11d69236d
--- /dev/null
+++ b/src/test/librados/test_cxx.h
@@ -0,0 +1,19 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#pragma once
+
+#include "include/rados/librados.hpp"
+#include "test/librados/test_shared.h"
+
+std::string create_one_pool_pp(const std::string &pool_name,
+ librados::Rados &cluster);
+std::string create_one_pool_pp(const std::string &pool_name,
+ librados::Rados &cluster,
+ const std::map<std::string, std::string> &config);
+std::string create_one_ec_pool_pp(const std::string &pool_name,
+ librados::Rados &cluster);
+std::string connect_cluster_pp(librados::Rados &cluster);
+std::string connect_cluster_pp(librados::Rados &cluster,
+ const std::map<std::string, std::string> &config);
+int destroy_one_pool_pp(const std::string &pool_name, librados::Rados &cluster);
+int destroy_one_ec_pool_pp(const std::string &pool_name, librados::Rados &cluster);
diff --git a/src/test/librados/test_shared.cc b/src/test/librados/test_shared.cc
new file mode 100644
index 00000000000..8b50d112e45
--- /dev/null
+++ b/src/test/librados/test_shared.cc
@@ -0,0 +1,44 @@
+#include "test_shared.h"
+
+#include <cstring>
+#include "gtest/gtest.h"
+#include "include/buffer.h"
+
+using namespace ceph;
+
+std::string get_temp_pool_name(const std::string &prefix)
+{
+ char hostname[80];
+ char out[160];
+ memset(hostname, 0, sizeof(hostname));
+ memset(out, 0, sizeof(out));
+ gethostname(hostname, sizeof(hostname)-1);
+ static int num = 1;
+ snprintf(out, sizeof(out), "%s-%d-%d", hostname, getpid(), num);
+ num++;
+ return prefix + out;
+}
+
+void assert_eq_sparse(bufferlist& expected,
+ const std::map<uint64_t, uint64_t>& extents,
+ bufferlist& actual) {
+ auto i = expected.begin();
+ auto p = actual.begin();
+ uint64_t pos = 0;
+ for (auto extent : extents) {
+ const uint64_t start = extent.first;
+ const uint64_t end = start + extent.second;
+ for (; pos < end; ++i, ++pos) {
+ ASSERT_FALSE(i.end());
+ if (pos < start) {
+ // check the hole
+ ASSERT_EQ('\0', *i);
+ } else {
+ // then the extent
+ ASSERT_EQ(*i, *p);
+ ++p;
+ }
+ }
+ }
+ ASSERT_EQ(expected.length(), pos);
+}
diff --git a/src/test/librados/test_shared.h b/src/test/librados/test_shared.h
new file mode 100644
index 00000000000..29e23b471ca
--- /dev/null
+++ b/src/test/librados/test_shared.h
@@ -0,0 +1,49 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include <unistd.h>
+#include <chrono>
+#include <map>
+#include <string>
+#include <thread>
+
+#include "include/buffer_fwd.h"
+
+// helpers shared by librados and librados-cxx tests
+std::string get_temp_pool_name(const std::string &prefix = "test-rados-api-");
+void assert_eq_sparse(ceph::bufferlist& expected,
+ const std::map<uint64_t, uint64_t>& extents,
+ ceph::bufferlist& actual);
+class TestAlarm
+{
+public:
+ TestAlarm() {
+ alarm(1200);
+ }
+ ~TestAlarm() {
+ alarm(0);
+ }
+};
+
+template<class Rep, class Period, typename Func, typename... Args,
+ typename Return = std::result_of_t<Func&&(Args&&...)>>
+Return wait_until(const std::chrono::duration<Rep, Period>& rel_time,
+ const std::chrono::duration<Rep, Period>& step,
+ const Return& expected,
+ Func&& func, Args&&... args)
+{
+ std::this_thread::sleep_for(rel_time - step);
+ for (auto& s : {step, step}) {
+ if (!s.count()) {
+ break;
+ }
+ auto ret = func(std::forward<Args>(args)...);
+ if (ret == expected) {
+ return ret;
+ }
+ std::this_thread::sleep_for(s);
+ }
+ return func(std::forward<Args>(args)...);
+}
diff --git a/src/test/librados/testcase_cxx.cc b/src/test/librados/testcase_cxx.cc
new file mode 100644
index 00000000000..0a71fa39ca2
--- /dev/null
+++ b/src/test/librados/testcase_cxx.cc
@@ -0,0 +1,390 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "testcase_cxx.h"
+
+#include <errno.h>
+#include "test_cxx.h"
+#include "test_shared.h"
+#include "include/scope_guard.h"
+
+using namespace librados;
+
+namespace {
+
+void init_rand() {
+ static bool seeded = false;
+ if (!seeded) {
+ seeded = true;
+ int seed = getpid();
+ std::cout << "seed " << seed << std::endl;
+ srand(seed);
+ }
+}
+
+} // anonymous namespace
+
+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));
+ bool requires;
+ ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
+ ASSERT_FALSE(requires);
+}
+
+void RadosTestPPNS::TearDown()
+{
+ if (cleanup)
+ cleanup_all_objects(ioctx);
+ ioctx.close();
+}
+
+void RadosTestPPNS::cleanup_all_objects(librados::IoCtx ioctx)
+{
+ // remove all objects to avoid polluting other tests
+ ioctx.snap_set_read(librados::SNAP_HEAD);
+ 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));
+ bool requires;
+ ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
+ ASSERT_FALSE(requires);
+}
+
+void RadosTestParamPPNS::TearDown()
+{
+ if (cleanup)
+ cleanup_all_objects(ioctx);
+ ioctx.close();
+}
+
+void RadosTestParamPPNS::cleanup_all_objects(librados::IoCtx ioctx)
+{
+ // remove all objects to avoid polluting other tests
+ ioctx.snap_set_read(librados::SNAP_HEAD);
+ 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 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));
+ bool requires;
+ ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
+ ASSERT_TRUE(requires);
+ ASSERT_EQ(0, ioctx.pool_required_alignment2(&alignment));
+ ASSERT_NE(0U, alignment);
+}
+
+void RadosTestECPPNS::TearDown()
+{
+ if (cleanup)
+ cleanup_all_objects(ioctx);
+ ioctx.close();
+}
+
+std::string RadosTestPP::pool_name;
+Rados RadosTestPP::s_cluster;
+
+void RadosTestPP::SetUpTestCase()
+{
+ init_rand();
+
+ pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestPP::TearDownTestCase()
+{
+ ASSERT_EQ(0, destroy_one_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestPP::SetUp()
+{
+ ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
+ nspace = get_temp_pool_name();
+ ioctx.set_namespace(nspace);
+ bool requires;
+ ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
+ ASSERT_FALSE(requires);
+}
+
+void RadosTestPP::TearDown()
+{
+ if (cleanup) {
+ cleanup_default_namespace(ioctx);
+ cleanup_namespace(ioctx, nspace);
+ }
+ ioctx.close();
+}
+
+void RadosTestPP::cleanup_default_namespace(librados::IoCtx ioctx)
+{
+ // remove all objects from the default namespace to avoid polluting
+ // other tests
+ cleanup_namespace(ioctx, "");
+}
+
+void RadosTestPP::cleanup_namespace(librados::IoCtx ioctx, std::string ns)
+{
+ ioctx.snap_set_read(librados::SNAP_HEAD);
+ ioctx.set_namespace(ns);
+ int tries = 600;
+ while (--tries) {
+ int got_enoent = 0;
+ for (NObjectIterator it = ioctx.nobjects_begin();
+ it != ioctx.nobjects_end(); ++it) {
+ ioctx.locator_set_key(it->get_locator());
+ ObjectWriteOperation op;
+ op.remove();
+ librados::AioCompletion *completion = s_cluster.aio_create_completion();
+ auto sg = make_scope_guard([&] { completion->release(); });
+ ASSERT_EQ(0, ioctx.aio_operate(it->get_oid(), completion, &op,
+ librados::OPERATION_IGNORE_CACHE));
+ completion->wait_for_safe();
+ if (completion->get_return_value() == -ENOENT) {
+ ++got_enoent;
+ std::cout << " got ENOENT removing " << it->get_oid() << std::endl;
+ } else {
+ ASSERT_EQ(0, completion->get_return_value());
+ }
+ }
+ if (!got_enoent) {
+ break;
+ }
+ std::cout << " got ENOENT on " << got_enoent
+ << " objects, waiting a bit for snap"
+ << " trimming before retrying " << tries << " more times..."
+ << std::endl;
+ sleep(1);
+ }
+ if (tries == 0) {
+ std::cout << "failed to clean up" << std::endl;
+ ASSERT_TRUE(false);
+ }
+}
+
+std::string RadosTestParamPP::pool_name;
+std::string RadosTestParamPP::cache_pool_name;
+Rados RadosTestParamPP::s_cluster;
+
+void RadosTestParamPP::SetUpTestCase()
+{
+ pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestParamPP::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 RadosTestParamPP::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));
+ nspace = get_temp_pool_name();
+ ioctx.set_namespace(nspace);
+ bool requires;
+ ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
+ ASSERT_FALSE(requires);
+}
+
+void RadosTestParamPP::TearDown()
+{
+ if (cleanup) {
+ cleanup_default_namespace(ioctx);
+ cleanup_namespace(ioctx, nspace);
+ }
+ ioctx.close();
+}
+
+void RadosTestParamPP::cleanup_default_namespace(librados::IoCtx ioctx)
+{
+ // remove all objects from the default namespace to avoid polluting
+ // other tests
+ cleanup_namespace(ioctx, "");
+}
+
+void RadosTestParamPP::cleanup_namespace(librados::IoCtx ioctx, std::string ns)
+{
+ ioctx.snap_set_read(librados::SNAP_HEAD);
+ ioctx.set_namespace(ns);
+ 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()));
+ }
+}
+
+std::string RadosTestECPP::pool_name;
+Rados RadosTestECPP::s_cluster;
+
+void RadosTestECPP::SetUpTestCase()
+{
+ pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_ec_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestECPP::TearDownTestCase()
+{
+ ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestECPP::SetUp()
+{
+ ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
+ nspace = get_temp_pool_name();
+ ioctx.set_namespace(nspace);
+ bool requires;
+ ASSERT_EQ(0, ioctx.pool_requires_alignment2(&requires));
+ ASSERT_TRUE(requires);
+ ASSERT_EQ(0, ioctx.pool_required_alignment2(&alignment));
+ ASSERT_NE(0U, alignment);
+}
+
+void RadosTestECPP::TearDown()
+{
+ if (cleanup) {
+ cleanup_default_namespace(ioctx);
+ cleanup_namespace(ioctx, nspace);
+ }
+ ioctx.close();
+}
+
diff --git a/src/test/librados/testcase_cxx.h b/src/test/librados/testcase_cxx.h
new file mode 100644
index 00000000000..637ec11eefc
--- /dev/null
+++ b/src/test/librados/testcase_cxx.h
@@ -0,0 +1,130 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include "gtest/gtest.h"
+#include "include/rados/librados.hpp"
+
+class RadosTestPPNS : public ::testing::Test {
+public:
+ RadosTestPPNS(bool c=false) : cluster(s_cluster), cleanup(c) {}
+ ~RadosTestPPNS() override {}
+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;
+
+ void SetUp() override;
+ void TearDown() override;
+ librados::Rados &cluster;
+ librados::IoCtx ioctx;
+ bool cleanup;
+};
+
+struct RadosTestPPNSCleanup : public RadosTestPPNS {
+ RadosTestPPNSCleanup() : RadosTestPPNS(true) {}
+};
+
+class RadosTestParamPPNS : public ::testing::TestWithParam<const char*> {
+public:
+ RadosTestParamPPNS(bool c=false) : cluster(s_cluster), cleanup(c) {}
+ ~RadosTestParamPPNS() override {}
+ 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;
+
+ void SetUp() override;
+ void TearDown() override;
+ librados::Rados &cluster;
+ librados::IoCtx ioctx;
+ bool cleanup;
+};
+
+class RadosTestECPPNS : public RadosTestPPNS {
+public:
+ RadosTestECPPNS(bool c=false) : cluster(s_cluster), cleanup(c) {}
+ ~RadosTestECPPNS() override {}
+protected:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+ static librados::Rados s_cluster;
+ static std::string pool_name;
+
+ void SetUp() override;
+ void TearDown() override;
+ librados::Rados &cluster;
+ librados::IoCtx ioctx;
+ uint64_t alignment = 0;
+ bool cleanup;
+};
+
+struct RadosTestECPPNSCleanup : public RadosTestECPPNS {
+ RadosTestECPPNSCleanup() : RadosTestECPPNS(true) {}
+};
+
+class RadosTestPP : public ::testing::Test {
+public:
+ RadosTestPP(bool c=false) : cluster(s_cluster), cleanup(c) {}
+ ~RadosTestPP() override {}
+protected:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+ static void cleanup_default_namespace(librados::IoCtx ioctx);
+ static void cleanup_namespace(librados::IoCtx ioctx, std::string ns);
+ static librados::Rados s_cluster;
+ static std::string pool_name;
+
+ void SetUp() override;
+ void TearDown() override;
+ librados::Rados &cluster;
+ librados::IoCtx ioctx;
+ bool cleanup;
+ std::string nspace;
+};
+
+class RadosTestParamPP : public ::testing::TestWithParam<const char*> {
+public:
+ RadosTestParamPP(bool c=false) : cluster(s_cluster), cleanup(c) {}
+ ~RadosTestParamPP() override {}
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+protected:
+ static void cleanup_default_namespace(librados::IoCtx ioctx);
+ static void cleanup_namespace(librados::IoCtx ioctx, std::string ns);
+ static librados::Rados s_cluster;
+ static std::string pool_name;
+ static std::string cache_pool_name;
+
+ void SetUp() override;
+ void TearDown() override;
+ librados::Rados &cluster;
+ librados::IoCtx ioctx;
+ bool cleanup;
+ std::string nspace;
+};
+
+class RadosTestECPP : public RadosTestPP {
+public:
+ RadosTestECPP(bool c=false) : cluster(s_cluster), cleanup(c) {}
+ ~RadosTestECPP() override {}
+protected:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+ static librados::Rados s_cluster;
+ static std::string pool_name;
+
+ void SetUp() override;
+ void TearDown() override;
+ librados::Rados &cluster;
+ librados::IoCtx ioctx;
+ bool cleanup;
+ std::string nspace;
+ uint64_t alignment = 0;
+};
diff --git a/src/test/librados/tier.cc b/src/test/librados/tier_cxx.cc
index d7f30e6e51d..e6acd304771 100644
--- a/src/test/librados/tier.cc
+++ b/src/test/librados/tier_cxx.cc
@@ -5,14 +5,13 @@
#include "mds/mdstypes.h"
#include "include/buffer.h"
#include "include/rbd_types.h"
-#include "include/rados/librados.h"
#include "include/rados/librados.hpp"
#include "include/stringify.h"
#include "include/types.h"
#include "global/global_context.h"
#include "common/Cond.h"
-#include "test/librados/test.h"
-#include "test/librados/TestCase.h"
+#include "test/librados/test_cxx.h"
+#include "test/librados/testcase_cxx.h"
#include "json_spirit/json_spirit.h"
#include "cls/cas/cls_cas_ops.h"
diff --git a/src/test/librados/watch_notify.cc b/src/test/librados/watch_notify.cc
index bae3c0852fe..54e54b0803a 100644
--- a/src/test/librados/watch_notify.cc
+++ b/src/test/librados/watch_notify.cc
@@ -1,5 +1,4 @@
#include "include/rados/librados.h"
-#include "include/rados/librados.hpp"
#include "include/rados/rados_types.h"
#include "test/librados/test.h"
#include "test/librados/TestCase.h"
@@ -12,10 +11,7 @@
#include <set>
#include <map>
-using namespace librados;
-
typedef RadosTestEC LibRadosWatchNotifyEC;
-typedef RadosTestECPP LibRadosWatchNotifyECPP;
int notify_sleep = 0;
@@ -28,16 +24,6 @@ static void watch_notify_test_cb(uint8_t opcode, uint64_t ver, void *arg)
sem_post(sem);
}
-class WatchNotifyTestCtx : public WatchCtx
-{
-public:
- void notify(uint8_t opcode, uint64_t ver, bufferlist& bl) override
- {
- std::cout << __func__ << std::endl;
- sem_post(sem);
- }
-};
-
class LibRadosWatchNotify : public RadosTest
{
protected:
@@ -91,49 +77,6 @@ void LibRadosWatchNotify::watch_notify2_test_errcb(void *arg,
}
class WatchNotifyTestCtx2;
-class LibRadosWatchNotifyPP : public RadosTestParamPP
-{
-protected:
- bufferlist notify_bl;
- std::set<uint64_t> notify_cookies;
- rados_ioctx_t notify_io;
- const char *notify_oid = nullptr;
- int notify_err = 0;
-
- friend class WatchNotifyTestCtx2;
-};
-
-IoCtx *notify_ioctx;
-
-class WatchNotifyTestCtx2 : public WatchCtx2
-{
- LibRadosWatchNotifyPP *notify;
-
-public:
- WatchNotifyTestCtx2(LibRadosWatchNotifyPP *notify)
- : notify(notify)
- {}
-
- void handle_notify(uint64_t notify_id, uint64_t cookie, uint64_t notifier_gid,
- bufferlist& bl) override {
- std::cout << __func__ << " cookie " << cookie << " notify_id " << notify_id
- << " notifier_gid " << notifier_gid << std::endl;
- notify->notify_bl = bl;
- notify->notify_cookies.insert(cookie);
- bufferlist reply;
- reply.append("reply", 5);
- if (notify_sleep)
- sleep(notify_sleep);
- notify_ioctx->notify_ack(notify->notify_oid, notify_id, cookie, reply);
- }
-
- void handle_error(uint64_t cookie, int err) override {
- std::cout << __func__ << " cookie " << cookie
- << " err " << err << std::endl;
- ceph_assert(cookie > 1000);
- notify->notify_err = err;
- }
-};
// --
@@ -161,27 +104,6 @@ TEST_F(LibRadosWatchNotify, WatchNotify) {
sem_close(sem);
}
-TEST_P(LibRadosWatchNotifyPP, WatchNotify) {
- ASSERT_NE(SEM_FAILED, (sem = sem_open("/test_watch_notify_sem", O_CREAT, 0644, 0)));
- 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));
- uint64_t handle;
- WatchNotifyTestCtx ctx;
- ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
- std::list<obj_watch_t> watches;
- ASSERT_EQ(0, ioctx.list_watchers("foo", &watches));
- ASSERT_EQ(1u, watches.size());
- bufferlist bl2;
- ASSERT_EQ(0, ioctx.notify("foo", 0, bl2));
- TestAlarm alarm;
- sem_wait(sem);
- ioctx.unwatch("foo", handle);
- sem_close(sem);
-}
-
TEST_F(LibRadosWatchNotifyEC, WatchNotify) {
ASSERT_NE(SEM_FAILED, (sem = sem_open("/test_watch_notify_sem", O_CREAT, 0644, 0)));
char buf[128];
@@ -197,63 +119,6 @@ TEST_F(LibRadosWatchNotifyEC, WatchNotify) {
sem_close(sem);
}
-TEST_F(LibRadosWatchNotifyECPP, WatchNotify) {
- ASSERT_NE(SEM_FAILED, (sem = sem_open("/test_watch_notify_sem", O_CREAT, 0644, 0)));
- 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));
- uint64_t handle;
- WatchNotifyTestCtx ctx;
- ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
- std::list<obj_watch_t> watches;
- ASSERT_EQ(0, ioctx.list_watchers("foo", &watches));
- ASSERT_EQ(1u, watches.size());
- bufferlist bl2;
- ASSERT_EQ(0, ioctx.notify("foo", 0, bl2));
- TestAlarm alarm;
- sem_wait(sem);
- ioctx.unwatch("foo", handle);
- sem_close(sem);
-}
-
-// --
-
-TEST_P(LibRadosWatchNotifyPP, WatchNotifyTimeout) {
- ASSERT_NE(SEM_FAILED, (sem = sem_open("/test_watch_notify_sem", O_CREAT, 0644, 0)));
- ioctx.set_notify_timeout(1);
- uint64_t handle;
- WatchNotifyTestCtx ctx;
-
- 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));
-
- ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
- sem_close(sem);
- ASSERT_EQ(0, ioctx.unwatch("foo", handle));
-}
-
-TEST_F(LibRadosWatchNotifyECPP, WatchNotifyTimeout) {
- ASSERT_NE(SEM_FAILED, (sem = sem_open("/test_watch_notify_sem", O_CREAT, 0644, 0)));
- ioctx.set_notify_timeout(1);
- uint64_t handle;
- WatchNotifyTestCtx ctx;
-
- 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));
-
- ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
- sem_close(sem);
- ASSERT_EQ(0, ioctx.unwatch("foo", handle));
-}
-
#pragma GCC diagnostic pop
#pragma GCC diagnostic warning "-Wpragmas"
@@ -476,121 +341,6 @@ TEST_F(LibRadosWatchNotify, AioNotify) {
rados_watch_flush(cluster);
}
-TEST_P(LibRadosWatchNotifyPP, WatchNotify2) {
- notify_oid = "foo";
- notify_ioctx = &ioctx;
- notify_cookies.clear();
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write(notify_oid, bl1, sizeof(buf), 0));
- uint64_t handle;
- WatchNotifyTestCtx2 ctx(this);
- ASSERT_EQ(0, ioctx.watch2(notify_oid, &handle, &ctx));
- ASSERT_GT(ioctx.watch_check(handle), 0);
- std::list<obj_watch_t> watches;
- ASSERT_EQ(0, ioctx.list_watchers(notify_oid, &watches));
- ASSERT_EQ(watches.size(), 1u);
- bufferlist bl2, bl_reply;
- ASSERT_EQ(0, ioctx.notify2(notify_oid, bl2, 300000, &bl_reply));
- auto p = bl_reply.cbegin();
- std::map<std::pair<uint64_t,uint64_t>,bufferlist> reply_map;
- std::set<std::pair<uint64_t,uint64_t> > missed_map;
- decode(reply_map, p);
- decode(missed_map, p);
- ASSERT_EQ(1u, notify_cookies.size());
- ASSERT_EQ(1u, notify_cookies.count(handle));
- ASSERT_EQ(1u, reply_map.size());
- ASSERT_EQ(5u, reply_map.begin()->second.length());
- ASSERT_EQ(0, strncmp("reply", reply_map.begin()->second.c_str(), 5));
- ASSERT_EQ(0u, missed_map.size());
- ASSERT_GT(ioctx.watch_check(handle), 0);
- ioctx.unwatch2(handle);
-}
-
-TEST_P(LibRadosWatchNotifyPP, AioWatchNotify2) {
- notify_oid = "foo";
- notify_ioctx = &ioctx;
- notify_cookies.clear();
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write(notify_oid, bl1, sizeof(buf), 0));
-
- uint64_t handle;
- WatchNotifyTestCtx2 ctx(this);
- librados::AioCompletion *comp = cluster.aio_create_completion();
- ASSERT_EQ(0, ioctx.aio_watch(notify_oid, comp, &handle, &ctx));
- ASSERT_EQ(0, comp->wait_for_complete());
- ASSERT_EQ(0, comp->get_return_value());
- comp->release();
-
- ASSERT_GT(ioctx.watch_check(handle), 0);
- std::list<obj_watch_t> watches;
- ASSERT_EQ(0, ioctx.list_watchers(notify_oid, &watches));
- ASSERT_EQ(watches.size(), 1u);
- bufferlist bl2, bl_reply;
- ASSERT_EQ(0, ioctx.notify2(notify_oid, bl2, 300000, &bl_reply));
- auto p = bl_reply.cbegin();
- std::map<std::pair<uint64_t,uint64_t>,bufferlist> reply_map;
- std::set<std::pair<uint64_t,uint64_t> > missed_map;
- decode(reply_map, p);
- decode(missed_map, p);
- ASSERT_EQ(1u, notify_cookies.size());
- ASSERT_EQ(1u, notify_cookies.count(handle));
- ASSERT_EQ(1u, reply_map.size());
- ASSERT_EQ(5u, reply_map.begin()->second.length());
- ASSERT_EQ(0, strncmp("reply", reply_map.begin()->second.c_str(), 5));
- ASSERT_EQ(0u, missed_map.size());
- ASSERT_GT(ioctx.watch_check(handle), 0);
-
- comp = cluster.aio_create_completion();
- ioctx.aio_unwatch(handle, comp);
- ASSERT_EQ(0, comp->wait_for_complete());
- comp->release();
-}
-
-
-TEST_P(LibRadosWatchNotifyPP, AioNotify) {
- notify_oid = "foo";
- notify_ioctx = &ioctx;
- notify_cookies.clear();
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write(notify_oid, bl1, sizeof(buf), 0));
- uint64_t handle;
- WatchNotifyTestCtx2 ctx(this);
- ASSERT_EQ(0, ioctx.watch2(notify_oid, &handle, &ctx));
- ASSERT_GT(ioctx.watch_check(handle), 0);
- std::list<obj_watch_t> watches;
- ASSERT_EQ(0, ioctx.list_watchers(notify_oid, &watches));
- ASSERT_EQ(watches.size(), 1u);
- bufferlist bl2, bl_reply;
- librados::AioCompletion *comp = cluster.aio_create_completion();
- ASSERT_EQ(0, ioctx.aio_notify(notify_oid, comp, bl2, 300000, &bl_reply));
- ASSERT_EQ(0, comp->wait_for_complete());
- ASSERT_EQ(0, comp->get_return_value());
- comp->release();
- auto p = bl_reply.cbegin();
- std::map<std::pair<uint64_t,uint64_t>,bufferlist> reply_map;
- std::set<std::pair<uint64_t,uint64_t> > missed_map;
- decode(reply_map, p);
- decode(missed_map, p);
- ASSERT_EQ(1u, notify_cookies.size());
- ASSERT_EQ(1u, notify_cookies.count(handle));
- ASSERT_EQ(1u, reply_map.size());
- ASSERT_EQ(5u, reply_map.begin()->second.length());
- ASSERT_EQ(0, strncmp("reply", reply_map.begin()->second.c_str(), 5));
- ASSERT_EQ(0u, missed_map.size());
- ASSERT_GT(ioctx.watch_check(handle), 0);
- ioctx.unwatch2(handle);
- cluster.watch_flush();
-}
-
// --
TEST_F(LibRadosWatchNotify, WatchNotify2Multi) {
@@ -695,88 +445,6 @@ TEST_F(LibRadosWatchNotify, WatchNotify2Timeout) {
}
-TEST_P(LibRadosWatchNotifyPP, WatchNotify2Timeout) {
- notify_oid = "foo";
- notify_ioctx = &ioctx;
- notify_sleep = 3; // 3s
- notify_cookies.clear();
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write(notify_oid, bl1, sizeof(buf), 0));
- uint64_t handle;
- WatchNotifyTestCtx2 ctx(this);
- ASSERT_EQ(0, ioctx.watch2(notify_oid, &handle, &ctx));
- ASSERT_GT(ioctx.watch_check(handle), 0);
- std::list<obj_watch_t> watches;
- ASSERT_EQ(0, ioctx.list_watchers(notify_oid, &watches));
- ASSERT_EQ(watches.size(), 1u);
- ASSERT_EQ(0u, notify_cookies.size());
- bufferlist bl2, bl_reply;
- std::cout << " trying..." << std::endl;
- ASSERT_EQ(-ETIMEDOUT, ioctx.notify2(notify_oid, bl2, 1000 /* 1s */,
- &bl_reply));
- std::cout << " timed out" << std::endl;
- ASSERT_GT(ioctx.watch_check(handle), 0);
- ioctx.unwatch2(handle);
-
- std::cout << " flushing" << std::endl;
- librados::AioCompletion *comp = cluster.aio_create_completion();
- cluster.aio_watch_flush(comp);
- ASSERT_EQ(0, comp->wait_for_complete());
- ASSERT_EQ(0, comp->get_return_value());
- std::cout << " flushed" << std::endl;
- comp->release();
-}
-
-TEST_P(LibRadosWatchNotifyPP, WatchNotify3) {
- notify_oid = "foo";
- notify_ioctx = &ioctx;
- notify_cookies.clear();
- uint32_t timeout = 12; // configured timeout
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl1;
- bl1.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write(notify_oid, bl1, sizeof(buf), 0));
- uint64_t handle;
- WatchNotifyTestCtx2 ctx(this);
- ASSERT_EQ(0, ioctx.watch3(notify_oid, &handle, &ctx, timeout));
- ASSERT_GT(ioctx.watch_check(handle), 0);
- std::list<obj_watch_t> watches;
- ASSERT_EQ(0, ioctx.list_watchers(notify_oid, &watches));
- ASSERT_EQ(watches.size(), 1u);
- std::cout << "List watches" << std::endl;
- for (std::list<obj_watch_t>::iterator it = watches.begin();
- it != watches.end(); ++it) {
- ASSERT_EQ(it->timeout_seconds, timeout);
- }
- bufferlist bl2, bl_reply;
- std::cout << "notify2" << std::endl;
- ASSERT_EQ(0, ioctx.notify2(notify_oid, bl2, 300000, &bl_reply));
- std::cout << "notify2 done" << std::endl;
- auto p = bl_reply.cbegin();
- std::map<std::pair<uint64_t,uint64_t>,bufferlist> reply_map;
- std::set<std::pair<uint64_t,uint64_t> > missed_map;
- decode(reply_map, p);
- decode(missed_map, p);
- ASSERT_EQ(1u, notify_cookies.size());
- ASSERT_EQ(1u, notify_cookies.count(handle));
- ASSERT_EQ(1u, reply_map.size());
- ASSERT_EQ(5u, reply_map.begin()->second.length());
- ASSERT_EQ(0, strncmp("reply", reply_map.begin()->second.c_str(), 5));
- ASSERT_EQ(0u, missed_map.size());
- std::cout << "watch_check" << std::endl;
- ASSERT_GT(ioctx.watch_check(handle), 0);
- std::cout << "unwatch2" << std::endl;
- ioctx.unwatch2(handle);
-
- std::cout << " flushing" << std::endl;
- cluster.watch_flush();
- std::cout << "done" << std::endl;
-}
-
TEST_F(LibRadosWatchNotify, Watch3Timeout) {
notify_io = ioctx;
notify_oid = "foo";
@@ -913,7 +581,3 @@ TEST_F(LibRadosWatchNotify, AioWatchDelete2) {
ASSERT_EQ(-ENOENT, rados_aio_get_return_value(comp));
rados_aio_release(comp);
}
-// --
-
-INSTANTIATE_TEST_CASE_P(LibRadosWatchNotifyPPTests, LibRadosWatchNotifyPP,
- ::testing::Values("", "cache"));
diff --git a/src/test/librados/watch_notify_cxx.cc b/src/test/librados/watch_notify_cxx.cc
new file mode 100644
index 00000000000..0289cba8b70
--- /dev/null
+++ b/src/test/librados/watch_notify_cxx.cc
@@ -0,0 +1,364 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <set>
+#include <map>
+
+#include "gtest/gtest.h"
+
+#include "include/encoding.h"
+#include "include/rados/librados.hpp"
+#include "include/rados/rados_types.h"
+#include "test/librados/test_cxx.h"
+#include "test/librados/testcase_cxx.h"
+
+
+using namespace librados;
+
+typedef RadosTestECPP LibRadosWatchNotifyECPP;
+
+int notify_sleep = 0;
+
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+class LibRadosWatchNotifyPP : public RadosTestParamPP
+{
+protected:
+ bufferlist notify_bl;
+ std::set<uint64_t> notify_cookies;
+ rados_ioctx_t notify_io;
+ const char *notify_oid = nullptr;
+ int notify_err = 0;
+
+ friend class WatchNotifyTestCtx2;
+};
+
+IoCtx *notify_ioctx;
+
+class WatchNotifyTestCtx2 : public WatchCtx2
+{
+ LibRadosWatchNotifyPP *notify;
+
+public:
+ WatchNotifyTestCtx2(LibRadosWatchNotifyPP *notify)
+ : notify(notify)
+ {}
+
+ void handle_notify(uint64_t notify_id, uint64_t cookie, uint64_t notifier_gid,
+ bufferlist& bl) override {
+ std::cout << __func__ << " cookie " << cookie << " notify_id " << notify_id
+ << " notifier_gid " << notifier_gid << std::endl;
+ notify->notify_bl = bl;
+ notify->notify_cookies.insert(cookie);
+ bufferlist reply;
+ reply.append("reply", 5);
+ if (notify_sleep)
+ sleep(notify_sleep);
+ notify_ioctx->notify_ack(notify->notify_oid, notify_id, cookie, reply);
+ }
+
+ void handle_error(uint64_t cookie, int err) override {
+ std::cout << __func__ << " cookie " << cookie
+ << " err " << err << std::endl;
+ ceph_assert(cookie > 1000);
+ notify->notify_err = err;
+ }
+};
+
+// notify
+static sem_t *sem;
+
+class WatchNotifyTestCtx : public WatchCtx
+{
+public:
+ void notify(uint8_t opcode, uint64_t ver, bufferlist& bl) override
+ {
+ std::cout << __func__ << std::endl;
+ sem_post(sem);
+ }
+};
+
+TEST_P(LibRadosWatchNotifyPP, WatchNotify) {
+ ASSERT_NE(SEM_FAILED, (sem = sem_open("/test_watch_notify_sem", O_CREAT, 0644, 0)));
+ 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));
+ uint64_t handle;
+ WatchNotifyTestCtx ctx;
+ ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
+ std::list<obj_watch_t> watches;
+ ASSERT_EQ(0, ioctx.list_watchers("foo", &watches));
+ ASSERT_EQ(1u, watches.size());
+ bufferlist bl2;
+ ASSERT_EQ(0, ioctx.notify("foo", 0, bl2));
+ TestAlarm alarm;
+ sem_wait(sem);
+ ioctx.unwatch("foo", handle);
+ sem_close(sem);
+}
+
+TEST_F(LibRadosWatchNotifyECPP, WatchNotify) {
+ ASSERT_NE(SEM_FAILED, (sem = sem_open("/test_watch_notify_sem", O_CREAT, 0644, 0)));
+ 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));
+ uint64_t handle;
+ WatchNotifyTestCtx ctx;
+ ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
+ std::list<obj_watch_t> watches;
+ ASSERT_EQ(0, ioctx.list_watchers("foo", &watches));
+ ASSERT_EQ(1u, watches.size());
+ bufferlist bl2;
+ ASSERT_EQ(0, ioctx.notify("foo", 0, bl2));
+ TestAlarm alarm;
+ sem_wait(sem);
+ ioctx.unwatch("foo", handle);
+ sem_close(sem);
+}
+
+// --
+
+TEST_P(LibRadosWatchNotifyPP, WatchNotifyTimeout) {
+ ASSERT_NE(SEM_FAILED, (sem = sem_open("/test_watch_notify_sem", O_CREAT, 0644, 0)));
+ ioctx.set_notify_timeout(1);
+ uint64_t handle;
+ WatchNotifyTestCtx ctx;
+
+ 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));
+
+ ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
+ sem_close(sem);
+ ASSERT_EQ(0, ioctx.unwatch("foo", handle));
+}
+
+TEST_F(LibRadosWatchNotifyECPP, WatchNotifyTimeout) {
+ ASSERT_NE(SEM_FAILED, (sem = sem_open("/test_watch_notify_sem", O_CREAT, 0644, 0)));
+ ioctx.set_notify_timeout(1);
+ uint64_t handle;
+ WatchNotifyTestCtx ctx;
+
+ 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));
+
+ ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
+ sem_close(sem);
+ ASSERT_EQ(0, ioctx.unwatch("foo", handle));
+}
+
+#pragma GCC diagnostic pop
+#pragma GCC diagnostic warning "-Wpragmas"
+
+TEST_P(LibRadosWatchNotifyPP, WatchNotify2) {
+ notify_oid = "foo";
+ notify_ioctx = &ioctx;
+ notify_cookies.clear();
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write(notify_oid, bl1, sizeof(buf), 0));
+ uint64_t handle;
+ WatchNotifyTestCtx2 ctx(this);
+ ASSERT_EQ(0, ioctx.watch2(notify_oid, &handle, &ctx));
+ ASSERT_GT(ioctx.watch_check(handle), 0);
+ std::list<obj_watch_t> watches;
+ ASSERT_EQ(0, ioctx.list_watchers(notify_oid, &watches));
+ ASSERT_EQ(watches.size(), 1u);
+ bufferlist bl2, bl_reply;
+ ASSERT_EQ(0, ioctx.notify2(notify_oid, bl2, 300000, &bl_reply));
+ auto p = bl_reply.cbegin();
+ std::map<std::pair<uint64_t,uint64_t>,bufferlist> reply_map;
+ std::set<std::pair<uint64_t,uint64_t> > missed_map;
+ decode(reply_map, p);
+ decode(missed_map, p);
+ ASSERT_EQ(1u, notify_cookies.size());
+ ASSERT_EQ(1u, notify_cookies.count(handle));
+ ASSERT_EQ(1u, reply_map.size());
+ ASSERT_EQ(5u, reply_map.begin()->second.length());
+ ASSERT_EQ(0, strncmp("reply", reply_map.begin()->second.c_str(), 5));
+ ASSERT_EQ(0u, missed_map.size());
+ ASSERT_GT(ioctx.watch_check(handle), 0);
+ ioctx.unwatch2(handle);
+}
+
+TEST_P(LibRadosWatchNotifyPP, AioWatchNotify2) {
+ notify_oid = "foo";
+ notify_ioctx = &ioctx;
+ notify_cookies.clear();
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write(notify_oid, bl1, sizeof(buf), 0));
+
+ uint64_t handle;
+ WatchNotifyTestCtx2 ctx(this);
+ librados::AioCompletion *comp = cluster.aio_create_completion();
+ ASSERT_EQ(0, ioctx.aio_watch(notify_oid, comp, &handle, &ctx));
+ ASSERT_EQ(0, comp->wait_for_complete());
+ ASSERT_EQ(0, comp->get_return_value());
+ comp->release();
+
+ ASSERT_GT(ioctx.watch_check(handle), 0);
+ std::list<obj_watch_t> watches;
+ ASSERT_EQ(0, ioctx.list_watchers(notify_oid, &watches));
+ ASSERT_EQ(watches.size(), 1u);
+ bufferlist bl2, bl_reply;
+ ASSERT_EQ(0, ioctx.notify2(notify_oid, bl2, 300000, &bl_reply));
+ auto p = bl_reply.cbegin();
+ std::map<std::pair<uint64_t,uint64_t>,bufferlist> reply_map;
+ std::set<std::pair<uint64_t,uint64_t> > missed_map;
+ decode(reply_map, p);
+ decode(missed_map, p);
+ ASSERT_EQ(1u, notify_cookies.size());
+ ASSERT_EQ(1u, notify_cookies.count(handle));
+ ASSERT_EQ(1u, reply_map.size());
+ ASSERT_EQ(5u, reply_map.begin()->second.length());
+ ASSERT_EQ(0, strncmp("reply", reply_map.begin()->second.c_str(), 5));
+ ASSERT_EQ(0u, missed_map.size());
+ ASSERT_GT(ioctx.watch_check(handle), 0);
+
+ comp = cluster.aio_create_completion();
+ ioctx.aio_unwatch(handle, comp);
+ ASSERT_EQ(0, comp->wait_for_complete());
+ comp->release();
+}
+
+
+TEST_P(LibRadosWatchNotifyPP, AioNotify) {
+ notify_oid = "foo";
+ notify_ioctx = &ioctx;
+ notify_cookies.clear();
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write(notify_oid, bl1, sizeof(buf), 0));
+ uint64_t handle;
+ WatchNotifyTestCtx2 ctx(this);
+ ASSERT_EQ(0, ioctx.watch2(notify_oid, &handle, &ctx));
+ ASSERT_GT(ioctx.watch_check(handle), 0);
+ std::list<obj_watch_t> watches;
+ ASSERT_EQ(0, ioctx.list_watchers(notify_oid, &watches));
+ ASSERT_EQ(watches.size(), 1u);
+ bufferlist bl2, bl_reply;
+ librados::AioCompletion *comp = cluster.aio_create_completion();
+ ASSERT_EQ(0, ioctx.aio_notify(notify_oid, comp, bl2, 300000, &bl_reply));
+ ASSERT_EQ(0, comp->wait_for_complete());
+ ASSERT_EQ(0, comp->get_return_value());
+ comp->release();
+ auto p = bl_reply.cbegin();
+ std::map<std::pair<uint64_t,uint64_t>,bufferlist> reply_map;
+ std::set<std::pair<uint64_t,uint64_t> > missed_map;
+ decode(reply_map, p);
+ decode(missed_map, p);
+ ASSERT_EQ(1u, notify_cookies.size());
+ ASSERT_EQ(1u, notify_cookies.count(handle));
+ ASSERT_EQ(1u, reply_map.size());
+ ASSERT_EQ(5u, reply_map.begin()->second.length());
+ ASSERT_EQ(0, strncmp("reply", reply_map.begin()->second.c_str(), 5));
+ ASSERT_EQ(0u, missed_map.size());
+ ASSERT_GT(ioctx.watch_check(handle), 0);
+ ioctx.unwatch2(handle);
+ cluster.watch_flush();
+}
+
+// --
+TEST_P(LibRadosWatchNotifyPP, WatchNotify2Timeout) {
+ notify_oid = "foo";
+ notify_ioctx = &ioctx;
+ notify_sleep = 3; // 3s
+ notify_cookies.clear();
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write(notify_oid, bl1, sizeof(buf), 0));
+ uint64_t handle;
+ WatchNotifyTestCtx2 ctx(this);
+ ASSERT_EQ(0, ioctx.watch2(notify_oid, &handle, &ctx));
+ ASSERT_GT(ioctx.watch_check(handle), 0);
+ std::list<obj_watch_t> watches;
+ ASSERT_EQ(0, ioctx.list_watchers(notify_oid, &watches));
+ ASSERT_EQ(watches.size(), 1u);
+ ASSERT_EQ(0u, notify_cookies.size());
+ bufferlist bl2, bl_reply;
+ std::cout << " trying..." << std::endl;
+ ASSERT_EQ(-ETIMEDOUT, ioctx.notify2(notify_oid, bl2, 1000 /* 1s */,
+ &bl_reply));
+ std::cout << " timed out" << std::endl;
+ ASSERT_GT(ioctx.watch_check(handle), 0);
+ ioctx.unwatch2(handle);
+
+ std::cout << " flushing" << std::endl;
+ librados::AioCompletion *comp = cluster.aio_create_completion();
+ cluster.aio_watch_flush(comp);
+ ASSERT_EQ(0, comp->wait_for_complete());
+ ASSERT_EQ(0, comp->get_return_value());
+ std::cout << " flushed" << std::endl;
+ comp->release();
+}
+
+TEST_P(LibRadosWatchNotifyPP, WatchNotify3) {
+ notify_oid = "foo";
+ notify_ioctx = &ioctx;
+ notify_cookies.clear();
+ uint32_t timeout = 12; // configured timeout
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, ioctx.write(notify_oid, bl1, sizeof(buf), 0));
+ uint64_t handle;
+ WatchNotifyTestCtx2 ctx(this);
+ ASSERT_EQ(0, ioctx.watch3(notify_oid, &handle, &ctx, timeout));
+ ASSERT_GT(ioctx.watch_check(handle), 0);
+ std::list<obj_watch_t> watches;
+ ASSERT_EQ(0, ioctx.list_watchers(notify_oid, &watches));
+ ASSERT_EQ(watches.size(), 1u);
+ std::cout << "List watches" << std::endl;
+ for (std::list<obj_watch_t>::iterator it = watches.begin();
+ it != watches.end(); ++it) {
+ ASSERT_EQ(it->timeout_seconds, timeout);
+ }
+ bufferlist bl2, bl_reply;
+ std::cout << "notify2" << std::endl;
+ ASSERT_EQ(0, ioctx.notify2(notify_oid, bl2, 300000, &bl_reply));
+ std::cout << "notify2 done" << std::endl;
+ auto p = bl_reply.cbegin();
+ std::map<std::pair<uint64_t,uint64_t>,bufferlist> reply_map;
+ std::set<std::pair<uint64_t,uint64_t> > missed_map;
+ decode(reply_map, p);
+ decode(missed_map, p);
+ ASSERT_EQ(1u, notify_cookies.size());
+ ASSERT_EQ(1u, notify_cookies.count(handle));
+ ASSERT_EQ(1u, reply_map.size());
+ ASSERT_EQ(5u, reply_map.begin()->second.length());
+ ASSERT_EQ(0, strncmp("reply", reply_map.begin()->second.c_str(), 5));
+ ASSERT_EQ(0u, missed_map.size());
+ std::cout << "watch_check" << std::endl;
+ ASSERT_GT(ioctx.watch_check(handle), 0);
+ std::cout << "unwatch2" << std::endl;
+ ioctx.unwatch2(handle);
+
+ std::cout << " flushing" << std::endl;
+ cluster.watch_flush();
+ std::cout << "done" << std::endl;
+}
+// --
+
+INSTANTIATE_TEST_CASE_P(LibRadosWatchNotifyPPTests, LibRadosWatchNotifyPP,
+ ::testing::Values("", "cache"));
diff --git a/src/test/librados_test_stub/LibradosTestStub.cc b/src/test/librados_test_stub/LibradosTestStub.cc
index dd9ebba273f..17221b24c30 100644
--- a/src/test/librados_test_stub/LibradosTestStub.cc
+++ b/src/test/librados_test_stub/LibradosTestStub.cc
@@ -1176,6 +1176,12 @@ int cls_cxx_create(cls_method_context_t hctx, bool exclusive) {
return ctx->io_ctx_impl->create(ctx->oid, exclusive);
}
+int cls_cxx_remove(cls_method_context_t hctx) {
+ librados::TestClassHandler::MethodContext *ctx =
+ reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
+ return ctx->io_ctx_impl->remove(ctx->oid, ctx->io_ctx_impl->get_snap_context());
+}
+
int cls_get_request_origin(cls_method_context_t hctx, entity_inst_t *origin) {
librados::TestClassHandler::MethodContext *ctx =
reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
diff --git a/src/test/libradosstriper/CMakeLists.txt b/src/test/libradosstriper/CMakeLists.txt
index 9403810329a..14de7ca83b1 100644
--- a/src/test/libradosstriper/CMakeLists.txt
+++ b/src/test/libradosstriper/CMakeLists.txt
@@ -4,26 +4,33 @@
add_library(rados_striper_test STATIC TestCase.cc)
target_link_libraries(rados_striper_test
radostest
+ radostest-cxx
GTest::GTest)
add_executable(ceph_test_rados_striper_api_striping
striping.cc
)
-target_link_libraries(ceph_test_rados_striper_api_striping librados radosstriper
- ${UNITTEST_LIBS} rados_striper_test)
+target_link_libraries(ceph_test_rados_striper_api_striping
+ ${UNITTEST_LIBS} rados_striper_test
+ radosstriper
+ librados
+ librados-cxx)
install(TARGETS ceph_test_rados_striper_api_striping
DESTINATION ${CMAKE_INSTALL_BINDIR})
add_executable(ceph_test_rados_striper_api_io
io.cc)
-target_link_libraries(ceph_test_rados_striper_api_io librados radosstriper
- ${UNITTEST_LIBS} rados_striper_test)
+target_link_libraries(ceph_test_rados_striper_api_io
+ ${UNITTEST_LIBS} rados_striper_test
+ radosstriper
+ librados
+ librados-cxx)
install(TARGETS ceph_test_rados_striper_api_io
DESTINATION ${CMAKE_INSTALL_BINDIR})
add_executable(ceph_test_rados_striper_api_aio
aio.cc)
-target_link_libraries(ceph_test_rados_striper_api_aio librados radosstriper
+target_link_libraries(ceph_test_rados_striper_api_aio librados-cxx radosstriper
${UNITTEST_LIBS} rados_striper_test)
install(TARGETS ceph_test_rados_striper_api_aio
DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/test/libradosstriper/TestCase.cc b/src/test/libradosstriper/TestCase.cc
index 5e1d34a9f0a..98e81f49c51 100644
--- a/src/test/libradosstriper/TestCase.cc
+++ b/src/test/libradosstriper/TestCase.cc
@@ -3,6 +3,7 @@
#include <errno.h>
#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "test/libradosstriper/TestCase.h"
using namespace libradosstriper;
diff --git a/src/test/librbd/CMakeLists.txt b/src/test/librbd/CMakeLists.txt
index d0f1a02f5b6..002b0d2c0a9 100644
--- a/src/test/librbd/CMakeLists.txt
+++ b/src/test/librbd/CMakeLists.txt
@@ -23,6 +23,9 @@ set(librbd_test
add_library(rbd_test STATIC ${librbd_test})
target_link_libraries(rbd_test PRIVATE
rbd_test_support
+ radostest
+ radostest-cxx
+ librados
Boost::thread
GMock::GMock
GTest::GTest)
@@ -120,8 +123,7 @@ target_link_libraries(unittest_librbd
osdc
ceph-common
global
- ${UNITTEST_LIBS}
- radostest)
+ ${UNITTEST_LIBS})
add_executable(ceph_test_librbd
test_main.cc
@@ -135,6 +137,7 @@ target_link_libraries(ceph_test_librbd
cls_journal_client
cls_rbd_client
librados
+ librados-cxx
${UNITTEST_LIBS}
radostest)
target_compile_definitions(ceph_test_librbd PRIVATE "TEST_LIBRBD_INTERNALS")
@@ -143,12 +146,14 @@ add_executable(ceph_test_librbd_api
test_support.cc
test_librbd.cc
test_main.cc
- $<TARGET_OBJECTS:libradostest_obj>
$<TARGET_OBJECTS:common_texttable_obj>)
target_link_libraries(ceph_test_librbd_api
ceph-common
+ radostest
+ radostest-cxx
librbd
librados
+ librados-cxx
${UNITTEST_LIBS})
add_executable(ceph_test_librbd_fsx
@@ -158,6 +163,7 @@ add_executable(ceph_test_librbd_fsx
target_link_libraries(ceph_test_librbd_fsx
librbd
librados
+ librados-cxx
journal
global
m
diff --git a/src/test/librbd/test_Migration.cc b/src/test/librbd/test_Migration.cc
index a42e201634f..b9e0791b234 100644
--- a/src/test/librbd/test_Migration.cc
+++ b/src/test/librbd/test_Migration.cc
@@ -213,9 +213,11 @@ struct TestMigration : public TestFixture {
EXPECT_EQ(0, librbd::api::Migration<>::status(m_ioctx, m_image_name,
&status));
EXPECT_EQ(status.source_pool_id, m_ioctx.get_id());
+ EXPECT_EQ(status.source_pool_namespace, m_ioctx.get_namespace());
EXPECT_EQ(status.source_image_name, m_image_name);
EXPECT_EQ(status.source_image_id, m_image_id);
EXPECT_EQ(status.dest_pool_id, m_ictx->md_ctx.get_id());
+ EXPECT_EQ(status.dest_pool_namespace, m_ictx->md_ctx.get_namespace());
EXPECT_EQ(status.dest_image_name, m_ictx->name);
EXPECT_EQ(status.dest_image_id, m_ictx->id);
EXPECT_EQ(status.state, state);
diff --git a/src/test/librbd/test_fixture.cc b/src/test/librbd/test_fixture.cc
index 27b47eb66c9..de5741a3bb1 100644
--- a/src/test/librbd/test_fixture.cc
+++ b/src/test/librbd/test_fixture.cc
@@ -13,6 +13,7 @@
#include "cls/rbd/cls_rbd_types.h"
#include "librbd/internal.h"
#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include <iostream>
#include <sstream>
#include <stdlib.h>
diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc
index 432d626ef2a..f77c5fdf682 100644
--- a/src/test/librbd/test_librbd.cc
+++ b/src/test/librbd/test_librbd.cc
@@ -41,6 +41,7 @@
#include <vector>
#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "test/librbd/test_support.h"
#include "common/event_socket.h"
#include "include/interval_set.h"
diff --git a/src/test/librbd/test_main.cc b/src/test/librbd/test_main.cc
index 939f68b254a..17b974b8e66 100644
--- a/src/test/librbd/test_main.cc
+++ b/src/test/librbd/test_main.cc
@@ -4,6 +4,7 @@
#include "include/rados/librados.hpp"
#include "global/global_context.h"
#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
#include <iostream>
#include <string>
diff --git a/src/test/multi_stress_watch.cc b/src/test/multi_stress_watch.cc
index a8c690f391e..0871f3380d2 100644
--- a/src/test/multi_stress_watch.cc
+++ b/src/test/multi_stress_watch.cc
@@ -1,7 +1,7 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
#include "include/rados/librados.h"
#include "include/rados/librados.hpp"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include <semaphore.h>
#include <errno.h>
diff --git a/src/test/osd/CMakeLists.txt b/src/test/osd/CMakeLists.txt
index 64639d5ec8e..565a82064dc 100644
--- a/src/test/osd/CMakeLists.txt
+++ b/src/test/osd/CMakeLists.txt
@@ -6,7 +6,7 @@ add_executable(ceph_test_rados
RadosModel.cc
)
target_link_libraries(ceph_test_rados
- librados
+ librados-cxx
global
${BLKID_LIBRARIES}
${CMAKE_DL_LIBS}
diff --git a/src/test/rbd_mirror/CMakeLists.txt b/src/test/rbd_mirror/CMakeLists.txt
index 0b8497180ba..f6aa221bf80 100644
--- a/src/test/rbd_mirror/CMakeLists.txt
+++ b/src/test/rbd_mirror/CMakeLists.txt
@@ -64,7 +64,7 @@ target_link_libraries(unittest_rbd_mirror
librados
osdc
global
- radostest
+ radostest-cxx
)
add_executable(ceph_test_rbd_mirror
@@ -81,15 +81,15 @@ target_link_libraries(ceph_test_rbd_mirror
cls_rbd_client
cls_journal_client
rbd_types
- librados
- radostest
+ librados-cxx
+ radostest-cxx
${UNITTEST_LIBS}
)
add_executable(ceph_test_rbd_mirror_random_write
random_write.cc)
target_link_libraries(ceph_test_rbd_mirror_random_write
- librbd librados global)
+ librbd librados-cxx global)
install(TARGETS
ceph_test_rbd_mirror
diff --git a/src/test/rbd_mirror/test_ClusterWatcher.cc b/src/test/rbd_mirror/test_ClusterWatcher.cc
index a69085cc12e..05ca2c1080f 100644
--- a/src/test/rbd_mirror/test_ClusterWatcher.cc
+++ b/src/test/rbd_mirror/test_ClusterWatcher.cc
@@ -10,7 +10,7 @@
#include "tools/rbd_mirror/ServiceDaemon.h"
#include "tools/rbd_mirror/Types.h"
#include "test/rbd_mirror/test_fixture.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "test/librbd/test_support.h"
#include "gtest/gtest.h"
#include <boost/scope_exit.hpp>
diff --git a/src/test/rbd_mirror/test_ImageReplayer.cc b/src/test/rbd_mirror/test_ImageReplayer.cc
index 51eb8b560c6..a4e2f869287 100644
--- a/src/test/rbd_mirror/test_ImageReplayer.cc
+++ b/src/test/rbd_mirror/test_ImageReplayer.cc
@@ -40,7 +40,7 @@
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/Types.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
using rbd::mirror::RadosRef;
diff --git a/src/test/rbd_mirror/test_InstanceWatcher.cc b/src/test/rbd_mirror/test_InstanceWatcher.cc
index 1924928f0c2..d495a9ea5c4 100644
--- a/src/test/rbd_mirror/test_InstanceWatcher.cc
+++ b/src/test/rbd_mirror/test_InstanceWatcher.cc
@@ -11,7 +11,7 @@
#include "tools/rbd_mirror/InstanceWatcher.h"
#include "tools/rbd_mirror/Threads.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
using rbd::mirror::InstanceWatcher;
diff --git a/src/test/rbd_mirror/test_LeaderWatcher.cc b/src/test/rbd_mirror/test_LeaderWatcher.cc
index 63118ebfe4f..86dc6d904b7 100644
--- a/src/test/rbd_mirror/test_LeaderWatcher.cc
+++ b/src/test/rbd_mirror/test_LeaderWatcher.cc
@@ -10,7 +10,7 @@
#include "tools/rbd_mirror/LeaderWatcher.h"
#include "tools/rbd_mirror/Threads.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
using librbd::util::unique_lock_name;
diff --git a/src/test/rbd_mirror/test_PoolWatcher.cc b/src/test/rbd_mirror/test_PoolWatcher.cc
index 1f31f177337..46098807c4b 100644
--- a/src/test/rbd_mirror/test_PoolWatcher.cc
+++ b/src/test/rbd_mirror/test_PoolWatcher.cc
@@ -21,7 +21,7 @@
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/Types.h"
#include "tools/rbd_mirror/pool_watcher/Types.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
#include <boost/scope_exit.hpp>
#include <iostream>
diff --git a/src/test/rbd_mirror/test_fixture.cc b/src/test/rbd_mirror/test_fixture.cc
index 1c312a9a871..0e30a17a125 100644
--- a/src/test/rbd_mirror/test_fixture.cc
+++ b/src/test/rbd_mirror/test_fixture.cc
@@ -8,7 +8,7 @@
#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
#include "librbd/Operations.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "tools/rbd_mirror/Threads.h"
namespace rbd {
diff --git a/src/test/rbd_mirror/test_main.cc b/src/test/rbd_mirror/test_main.cc
index eb31af1e506..d5859cac919 100644
--- a/src/test/rbd_mirror/test_main.cc
+++ b/src/test/rbd_mirror/test_main.cc
@@ -3,7 +3,7 @@
#include "include/rados/librados.hpp"
#include "global/global_context.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
#include <iostream>
#include <string>
diff --git a/src/test/rbd_mirror/test_mock_ImageMap.cc b/src/test/rbd_mirror/test_mock_ImageMap.cc
index a82d117c930..e223b8b9dc6 100644
--- a/src/test/rbd_mirror/test_mock_ImageMap.cc
+++ b/src/test/rbd_mirror/test_mock_ImageMap.cc
@@ -293,8 +293,9 @@ public:
for (auto& global_image_id : global_image_ids) {
auto it = peer_ack_ctxs->find(global_image_id);
ASSERT_TRUE(it != peer_ack_ctxs->end());
- it->second->complete(ret);
+ auto ack_ctx = it->second;
peer_ack_ctxs->erase(it);
+ ack_ctx->complete(ret);
wait_for_scheduled_task();
}
}
@@ -306,8 +307,9 @@ public:
for (auto& global_image_id : global_image_ids) {
auto it = peer_ack_ctxs->find(global_image_id);
ASSERT_TRUE(it != peer_ack_ctxs->end());
- it->second->complete(ret);
+ auto ack_ctx = it->second;
peer_ack_ctxs->erase(it);
+ ack_ctx->complete(ret);
wait_for_scheduled_task();
ASSERT_TRUE(wait_for_map_update(1));
}
@@ -320,8 +322,9 @@ public:
for (auto& global_image_id : global_image_ids) {
auto it = peer_ack_ctxs->find(global_image_id);
ASSERT_TRUE(it != peer_ack_ctxs->end());
- it->second->complete(ret);
+ auto ack_ctx = it->second;
peer_ack_ctxs->erase(it);
+ ack_ctx->complete(ret);
ASSERT_TRUE(wait_for_map_update(1));
ASSERT_TRUE(wait_for_listener_notify(1));
}
diff --git a/src/test/rbd_mirror/test_mock_InstanceWatcher.cc b/src/test/rbd_mirror/test_mock_InstanceWatcher.cc
index ec2b7057df7..c6942b7738b 100644
--- a/src/test/rbd_mirror/test_mock_InstanceWatcher.cc
+++ b/src/test/rbd_mirror/test_mock_InstanceWatcher.cc
@@ -3,7 +3,7 @@
#include "librados/AioCompletionImpl.h"
#include "librbd/ManagedLock.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "test/librados_test_stub/MockTestMemRadosClient.h"
#include "test/librbd/mock/MockImageCtx.h"
diff --git a/src/test/test_stress_watch.cc b/src/test/test_stress_watch.cc
index 8604328b59c..003fc2b0ac5 100644
--- a/src/test/test_stress_watch.cc
+++ b/src/test/test_stress_watch.cc
@@ -3,7 +3,7 @@
#include "include/utime.h"
#include "common/Thread.h"
#include "common/Clock.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "gtest/gtest.h"
#include <semaphore.h>
@@ -14,7 +14,7 @@
#include <string>
#include <atomic>
-#include "test/librados/TestCase.h"
+#include "test/librados/testcase_cxx.h"
using namespace librados;
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
index 6ac9035553c..6579d5f6d91 100644
--- a/src/tools/CMakeLists.txt
+++ b/src/tools/CMakeLists.txt
@@ -8,7 +8,7 @@ set(rados_srcs
${PROJECT_SOURCE_DIR}/src/osd/ECUtil.cc)
add_executable(rados ${rados_srcs})
-target_link_libraries(rados librados global ${BLKID_LIBRARIES} ${CMAKE_DL_LIBS})
+target_link_libraries(rados librados-cxx global ${BLKID_LIBRARIES} ${CMAKE_DL_LIBS})
if(WITH_LIBRADOSSTRIPER)
target_link_libraries(rados radosstriper)
else()
@@ -22,11 +22,11 @@ target_link_libraries(ceph_scratchtool librados global)
install(TARGETS ceph_scratchtool DESTINATION bin)
add_executable(ceph_scratchtoolpp scratchtoolpp.cc)
-target_link_libraries(ceph_scratchtoolpp librados global)
+target_link_libraries(ceph_scratchtoolpp librados-cxx global)
install(TARGETS ceph_scratchtoolpp DESTINATION bin)
add_executable(ceph_radosacl radosacl.cc)
-target_link_libraries(ceph_radosacl librados global)
+target_link_libraries(ceph_radosacl librados-cxx global)
install(TARGETS ceph_radosacl DESTINATION bin)
install(PROGRAMS
diff --git a/src/tools/cephfs/CMakeLists.txt b/src/tools/cephfs/CMakeLists.txt
index 2cca8dc034c..dbfc74e6a33 100644
--- a/src/tools/cephfs/CMakeLists.txt
+++ b/src/tools/cephfs/CMakeLists.txt
@@ -9,7 +9,7 @@ set(cephfs_journal_tool_srcs
RoleSelector.cc
MDSUtility.cc)
add_executable(cephfs-journal-tool ${cephfs_journal_tool_srcs})
-target_link_libraries(cephfs-journal-tool librados mds osdc global
+target_link_libraries(cephfs-journal-tool librados-cxx mds osdc global
${BLKID_LIBRARIES} ${CMAKE_DL_LIBS})
set(cephfs_table_tool_srcs
@@ -18,7 +18,7 @@ set(cephfs_table_tool_srcs
RoleSelector.cc
MDSUtility.cc)
add_executable(cephfs-table-tool ${cephfs_table_tool_srcs})
-target_link_libraries(cephfs-table-tool librados mds osdc global
+target_link_libraries(cephfs-table-tool librados-cxx mds osdc global
${BLKID_LIBRARIES} ${CMAKE_DL_LIBS})
set(cephfs_data_scan_srcs
@@ -28,7 +28,7 @@ set(cephfs_data_scan_srcs
PgFiles.cc
MDSUtility.cc)
add_executable(cephfs-data-scan ${cephfs_data_scan_srcs})
-target_link_libraries(cephfs-data-scan librados cephfs mds osdc global
+target_link_libraries(cephfs-data-scan librados-cxx cephfs mds osdc global
cls_cephfs_client
${BLKID_LIBRARIES} ${CMAKE_DL_LIBS})
diff --git a/src/tools/rbd/CMakeLists.txt b/src/tools/rbd/CMakeLists.txt
index 76cc57904fd..e28a21a42da 100644
--- a/src/tools/rbd/CMakeLists.txt
+++ b/src/tools/rbd/CMakeLists.txt
@@ -45,7 +45,7 @@ set(rbd_srcs
add_executable(rbd ${rbd_srcs}
$<TARGET_OBJECTS:common_texttable_obj>)
set_target_properties(rbd PROPERTIES OUTPUT_NAME rbd)
-target_link_libraries(rbd librbd librados
+target_link_libraries(rbd librbd librados-cxx
cls_journal_client cls_rbd_client
rbd_types
journal
diff --git a/src/tools/rbd/action/DiskUsage.cc b/src/tools/rbd/action/DiskUsage.cc
index 57447cd9f61..abc9cf41862 100644
--- a/src/tools/rbd/action/DiskUsage.cc
+++ b/src/tools/rbd/action/DiskUsage.cc
@@ -132,7 +132,7 @@ static int do_disk_usage(librbd::RBD &rbd, librados::IoCtx &io_ctx,
}
uint64_t features;
- int r = image.features(&features);
+ r = image.features(&features);
if (r < 0) {
std::cerr << "rbd: failed to retrieve image features: " << cpp_strerror(r)
<< std::endl;
diff --git a/src/tools/rbd/action/Snap.cc b/src/tools/rbd/action/Snap.cc
index 9f49f1d4e35..70cf62dab0c 100644
--- a/src/tools/rbd/action/Snap.cc
+++ b/src/tools/rbd/action/Snap.cc
@@ -828,6 +828,7 @@ int execute_rename(const po::variables_map &vm,
} else if (namespace_name != dest_namespace_name) {
std::cerr << "rbd: source and destination namespace must be the same"
<< std::endl;
+ return -EINVAL;
} else if (image_name != dest_image_name) {
std::cerr << "rbd: source and destination image name must be the same"
<< std::endl;
diff --git a/src/tools/rbd/action/Status.cc b/src/tools/rbd/action/Status.cc
index 253f9508f30..75afdd77431 100644
--- a/src/tools/rbd/action/Status.cc
+++ b/src/tools/rbd/action/Status.cc
@@ -101,9 +101,13 @@ static int do_show_status(librados::IoCtx& io_ctx, const std::string &image_name
if (!migration_state.empty()) {
f->open_object_section("migration");
f->dump_string("source_pool_name", source_pool_name);
+ f->dump_string("source_pool_namespace",
+ migration_status.source_pool_namespace);
f->dump_string("source_image_name", migration_status.source_image_name);
f->dump_string("source_image_id", migration_status.source_image_id);
f->dump_string("dest_pool_name", dest_pool_name);
+ f->dump_string("dest_pool_namespace",
+ migration_status.dest_pool_namespace);
f->dump_string("dest_image_name", migration_status.dest_image_name);
f->dump_string("dest_image_id", migration_status.dest_image_id);
f->dump_string("state", migration_state);
@@ -121,6 +125,13 @@ static int do_show_status(librados::IoCtx& io_ctx, const std::string &image_name
std::cout << "Watchers: none" << std::endl;
}
if (!migration_state.empty()) {
+ if (!migration_status.source_pool_namespace.empty()) {
+ source_pool_name += ("/" + migration_status.source_pool_namespace);
+ }
+ if (!migration_status.dest_pool_namespace.empty()) {
+ dest_pool_name += ("/" + migration_status.dest_pool_namespace);
+ }
+
std::cout << "Migration:" << std::endl;
std::cout << "\tsource: " << source_pool_name << "/"
<< migration_status.source_image_name;
diff --git a/src/tools/rbd_mirror/CMakeLists.txt b/src/tools/rbd_mirror/CMakeLists.txt
index fb39f9c5221..1ad8ad34af3 100644
--- a/src/tools/rbd_mirror/CMakeLists.txt
+++ b/src/tools/rbd_mirror/CMakeLists.txt
@@ -59,7 +59,7 @@ target_link_libraries(rbd-mirror
rbd_internal
rbd_types
journal
- librados
+ librados-cxx
osdc
cls_rbd_client
cls_lock_client
diff --git a/src/tools/rbd_mirror/ImageReplayer.cc b/src/tools/rbd_mirror/ImageReplayer.cc
index 57adaca3bf4..5cb5b6b9b78 100644
--- a/src/tools/rbd_mirror/ImageReplayer.cc
+++ b/src/tools/rbd_mirror/ImageReplayer.cc
@@ -791,7 +791,7 @@ void ImageReplayer<I>::on_stop_journal_replay(int r, const std::string &desc)
}
set_state_description(r, desc);
- update_mirror_image_status(false, boost::none);
+ update_mirror_image_status(true, boost::none);
reschedule_update_status_task(-1);
shut_down(0);
}
@@ -1398,7 +1398,7 @@ void ImageReplayer<I>::send_mirror_status_update(const OptionalState &opt_state)
case STATE_STOPPING:
if (stopping_replay) {
status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY;
- status.description = "stopping replay";
+ status.description = state_desc.empty() ? "stopping replay" : state_desc;
break;
}
// FALLTHROUGH
diff --git a/src/tools/rbd_nbd/CMakeLists.txt b/src/tools/rbd_nbd/CMakeLists.txt
index d7ce811e963..73ea9913786 100644
--- a/src/tools/rbd_nbd/CMakeLists.txt
+++ b/src/tools/rbd_nbd/CMakeLists.txt
@@ -1,3 +1,3 @@
add_executable(rbd-nbd rbd-nbd.cc)
-target_link_libraries(rbd-nbd librbd librados global)
+target_link_libraries(rbd-nbd librbd librados-cxx global)
install(TARGETS rbd-nbd DESTINATION bin)
diff --git a/src/tracing/CMakeLists.txt b/src/tracing/CMakeLists.txt
index d63399d589f..68a054961a7 100644
--- a/src/tracing/CMakeLists.txt
+++ b/src/tracing/CMakeLists.txt
@@ -43,7 +43,7 @@ endfunction()
set(osd_traces oprequest.tp osd.tp pg.tp)
add_tracing_library(osd_tp "${osd_traces}" 1.0.0)
-add_tracing_library(rados_tp librados.tp 2.0.0)
+add_tracing_library(rados_tp librados.tp 3.0.0)
add_tracing_library(os_tp objectstore.tp 1.0.0)
add_tracing_library(rgw_op_tp rgw_op.tp 1.0.0)
add_tracing_library(rgw_rados_tp rgw_rados.tp 1.0.0)