diff options
Diffstat (limited to 'src/test/librados/service.cc')
-rw-r--r-- | src/test/librados/service.cc | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/test/librados/service.cc b/src/test/librados/service.cc new file mode 100644 index 000000000..6d88f0da9 --- /dev/null +++ b/src/test/librados/service.cc @@ -0,0 +1,209 @@ +#include "include/rados/librados.h" +#include "include/rados/librados.hpp" +#include "include/stringify.h" +#include "common/config_proxy.h" +#include "test/librados/test.h" +#include "test/librados/TestCase.h" +#ifndef _WIN32 +#include <sys/resource.h> +#endif + +#include <mutex> +#include <condition_variable> +#include <algorithm> +#include <thread> +#include <errno.h> +#include "gtest/gtest.h" +#include "test/unit.cc" + +using namespace std; +using namespace librados; + +TEST(LibRadosService, RegisterEarly) { + rados_t cluster; + ASSERT_EQ(0, rados_create(&cluster, "admin")); + ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); + ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); + + string name = string("pid") + stringify(getpid()); + ASSERT_EQ(0, rados_service_register(cluster, "laundry", name.c_str(), + "foo\0bar\0this\0that\0")); + ASSERT_EQ(-EEXIST, rados_service_register(cluster, "laundry", name.c_str(), + "foo\0bar\0this\0that\0")); + + ASSERT_EQ(0, rados_connect(cluster)); + sleep(5); + rados_shutdown(cluster); +} + +TEST(LibRadosService, RegisterLate) { + rados_t cluster; + ASSERT_EQ(0, rados_create(&cluster, "admin")); + ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); + ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); + ASSERT_EQ(0, rados_connect(cluster)); + + string name = string("pid") + stringify(getpid()); + ASSERT_EQ(0, rados_service_register(cluster, "laundry", name.c_str(), + "foo\0bar\0this\0that\0")); + ASSERT_EQ(-EEXIST, rados_service_register(cluster, "laundry", name.c_str(), + "foo\0bar\0this\0that\0")); + rados_shutdown(cluster); +} + +static void status_format_func(const int i, std::mutex &lock, + std::condition_variable &cond, + int &threads_started, bool &stopped) +{ + rados_t cluster; + char metadata_buf[4096]; + + ASSERT_EQ(0, rados_create(&cluster, "admin")); + ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); + ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); + + ASSERT_EQ(0, rados_connect(cluster)); + if (i == 0) { + ASSERT_LT(0, sprintf(metadata_buf, "%s%c%s%c", + "foo", '\0', "bar", '\0')); + } else if (i == 1) { + ASSERT_LT(0, sprintf(metadata_buf, "%s%c%s%c", + "daemon_type", '\0', "portal", '\0')); + } else if (i == 2) { + ASSERT_LT(0, sprintf(metadata_buf, "%s%c%s%c", + "daemon_prefix", '\0', "gateway", '\0')); + } else { + string prefix = string("gw") + stringify(i % 4); + string zone = string("z") + stringify(i % 3); + ASSERT_LT(0, sprintf(metadata_buf, "%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s%c", + "daemon_type", '\0', "portal", '\0', + "daemon_prefix", '\0', prefix.c_str(), '\0', + "hostname", '\0', prefix.c_str(), '\0', + "zone_id", '\0', zone.c_str(), '\0')); + } + string name = string("rbd/image") + stringify(i); + ASSERT_EQ(0, rados_service_register(cluster, "foo", name.c_str(), + metadata_buf)); + + std::unique_lock<std::mutex> l(lock); + threads_started++; + cond.notify_all(); + cond.wait(l, [&stopped] { + return stopped; + }); + + rados_shutdown(cluster); +} + +TEST(LibRadosService, StatusFormat) { + const int nthreads = 16; + std::thread threads[nthreads]; + std::mutex lock; + std::condition_variable cond; + bool stopped = false; + int threads_started = 0; + + // no rlimits on Windows + #ifndef _WIN32 + // Need a bunch of fd's for this test + struct rlimit rold, rnew; + ASSERT_EQ(getrlimit(RLIMIT_NOFILE, &rold), 0); + rnew = rold; + rnew.rlim_cur = rnew.rlim_max; + ASSERT_EQ(setrlimit(RLIMIT_NOFILE, &rnew), 0); + #endif + + for (int i = 0; i < nthreads; ++i) + threads[i] = std::thread(status_format_func, i, std::ref(lock), + std::ref(cond), std::ref(threads_started), + std::ref(stopped)); + + { + std::unique_lock<std::mutex> l(lock); + cond.wait(l, [&threads_started] { + return nthreads == threads_started; + }); + } + + int retry = 60; // mon thrashing may make this take a long time + while (retry) { + rados_t cluster; + + ASSERT_EQ(0, rados_create(&cluster, "admin")); + ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); + ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); + + ASSERT_EQ(0, rados_connect(cluster)); + JSONFormatter cmd_f; + cmd_f.open_object_section("command"); + cmd_f.dump_string("prefix", "status"); + cmd_f.close_section(); + std::ostringstream cmd_stream; + cmd_f.flush(cmd_stream); + const std::string serialized_cmd = cmd_stream.str(); + const char *cmd[2]; + cmd[1] = NULL; + cmd[0] = serialized_cmd.c_str(); + char *outbuf = NULL; + size_t outlen = 0; + ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, + &outbuf, &outlen, NULL, NULL)); + std::string out(outbuf, outlen); + cout << out << std::endl; + bool success = false; + auto r1 = out.find("16 portals active (1 hosts, 3 zones)"); + if (std::string::npos != r1) { + success = true; + } + rados_buffer_free(outbuf); + rados_shutdown(cluster); + + if (success || !retry) { + break; + } + + // wait for 2 seconds to make sure all the + // services have been successfully updated + // to ceph mon, then retry it. + sleep(2); + retry--; + } + + { + std::scoped_lock<std::mutex> l(lock); + stopped = true; + cond.notify_all(); + } + for (int i = 0; i < nthreads; ++i) + threads[i].join(); + + ASSERT_NE(0, retry); + #ifndef _WIN32 + ASSERT_EQ(setrlimit(RLIMIT_NOFILE, &rold), 0); + #endif +} + +TEST(LibRadosService, Status) { + rados_t cluster; + ASSERT_EQ(0, rados_create(&cluster, "admin")); + ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); + ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); + + ASSERT_EQ(-ENOTCONN, rados_service_update_status(cluster, + "testing\0testing\0")); + + ASSERT_EQ(0, rados_connect(cluster)); + string name = string("pid") + stringify(getpid()); + ASSERT_EQ(0, rados_service_register(cluster, "laundry", name.c_str(), + "foo\0bar\0this\0that\0")); + + for (int i=0; i<20; ++i) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%s%c%s%c%s%c%d%c", + "testing", '\0', "testing", '\0', + "count", '\0', i, '\0'); + ASSERT_EQ(0, rados_service_update_status(cluster, buffer)); + sleep(1); + } + rados_shutdown(cluster); +} |