]>
Commit | Line | Data |
---|---|---|
1 | #include "include/rados/librados.h" | |
2 | #include "include/rados/librados.hpp" | |
3 | #include "include/stringify.h" | |
4 | #include "common/config_proxy.h" | |
5 | #include "test/librados/test.h" | |
6 | #include "test/librados/TestCase.h" | |
7 | #ifndef _WIN32 | |
8 | #include <sys/resource.h> | |
9 | #endif | |
10 | ||
11 | #include <mutex> | |
12 | #include <condition_variable> | |
13 | #include <algorithm> | |
14 | #include <thread> | |
15 | #include <errno.h> | |
16 | #include "gtest/gtest.h" | |
17 | #include "test/unit.cc" | |
18 | ||
19 | using namespace std; | |
20 | using namespace librados; | |
21 | ||
22 | TEST(LibRadosService, RegisterEarly) { | |
23 | rados_t cluster; | |
24 | ASSERT_EQ(0, rados_create(&cluster, "admin")); | |
25 | ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); | |
26 | ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); | |
27 | ||
28 | string name = string("pid") + stringify(getpid()); | |
29 | ASSERT_EQ(0, rados_service_register(cluster, "laundry", name.c_str(), | |
30 | "foo\0bar\0this\0that\0")); | |
31 | ASSERT_EQ(-EEXIST, rados_service_register(cluster, "laundry", name.c_str(), | |
32 | "foo\0bar\0this\0that\0")); | |
33 | ||
34 | ASSERT_EQ(0, rados_connect(cluster)); | |
35 | sleep(5); | |
36 | rados_shutdown(cluster); | |
37 | } | |
38 | ||
39 | TEST(LibRadosService, RegisterLate) { | |
40 | rados_t cluster; | |
41 | ASSERT_EQ(0, rados_create(&cluster, "admin")); | |
42 | ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); | |
43 | ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); | |
44 | ASSERT_EQ(0, rados_connect(cluster)); | |
45 | ||
46 | string name = string("pid") + stringify(getpid()); | |
47 | ASSERT_EQ(0, rados_service_register(cluster, "laundry", name.c_str(), | |
48 | "foo\0bar\0this\0that\0")); | |
49 | ASSERT_EQ(-EEXIST, rados_service_register(cluster, "laundry", name.c_str(), | |
50 | "foo\0bar\0this\0that\0")); | |
51 | rados_shutdown(cluster); | |
52 | } | |
53 | ||
54 | static void status_format_func(const int i, std::mutex &lock, | |
55 | std::condition_variable &cond, | |
56 | int &threads_started, bool &stopped) | |
57 | { | |
58 | rados_t cluster; | |
59 | char metadata_buf[4096]; | |
60 | ||
61 | ASSERT_EQ(0, rados_create(&cluster, "admin")); | |
62 | ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); | |
63 | ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); | |
64 | ||
65 | ASSERT_EQ(0, rados_connect(cluster)); | |
66 | if (i == 0) { | |
67 | ASSERT_LT(0, sprintf(metadata_buf, "%s%c%s%c", | |
68 | "foo", '\0', "bar", '\0')); | |
69 | } else if (i == 1) { | |
70 | ASSERT_LT(0, sprintf(metadata_buf, "%s%c%s%c", | |
71 | "daemon_type", '\0', "portal", '\0')); | |
72 | } else if (i == 2) { | |
73 | ASSERT_LT(0, sprintf(metadata_buf, "%s%c%s%c", | |
74 | "daemon_prefix", '\0', "gateway", '\0')); | |
75 | } else { | |
76 | string prefix = string("gw") + stringify(i % 4); | |
77 | string zone = string("z") + stringify(i % 3); | |
78 | ASSERT_LT(0, sprintf(metadata_buf, "%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s%c", | |
79 | "daemon_type", '\0', "portal", '\0', | |
80 | "daemon_prefix", '\0', prefix.c_str(), '\0', | |
81 | "hostname", '\0', prefix.c_str(), '\0', | |
82 | "zone_id", '\0', zone.c_str(), '\0')); | |
83 | } | |
84 | string name = string("rbd/image") + stringify(i); | |
85 | ASSERT_EQ(0, rados_service_register(cluster, "foo", name.c_str(), | |
86 | metadata_buf)); | |
87 | ||
88 | std::unique_lock<std::mutex> l(lock); | |
89 | threads_started++; | |
90 | cond.notify_all(); | |
91 | cond.wait(l, [&stopped] { | |
92 | return stopped; | |
93 | }); | |
94 | ||
95 | rados_shutdown(cluster); | |
96 | } | |
97 | ||
98 | TEST(LibRadosService, StatusFormat) { | |
99 | const int nthreads = 16; | |
100 | std::thread threads[nthreads]; | |
101 | std::mutex lock; | |
102 | std::condition_variable cond; | |
103 | bool stopped = false; | |
104 | int threads_started = 0; | |
105 | ||
106 | // no rlimits on Windows | |
107 | #ifndef _WIN32 | |
108 | // Need a bunch of fd's for this test | |
109 | struct rlimit rold, rnew; | |
110 | ASSERT_EQ(getrlimit(RLIMIT_NOFILE, &rold), 0); | |
111 | rnew = rold; | |
112 | rnew.rlim_cur = rnew.rlim_max; | |
113 | ASSERT_EQ(setrlimit(RLIMIT_NOFILE, &rnew), 0); | |
114 | #endif | |
115 | ||
116 | for (int i = 0; i < nthreads; ++i) | |
117 | threads[i] = std::thread(status_format_func, i, std::ref(lock), | |
118 | std::ref(cond), std::ref(threads_started), | |
119 | std::ref(stopped)); | |
120 | ||
121 | { | |
122 | std::unique_lock<std::mutex> l(lock); | |
123 | cond.wait(l, [&threads_started] { | |
124 | return nthreads == threads_started; | |
125 | }); | |
126 | } | |
127 | ||
128 | int retry = 60; // mon thrashing may make this take a long time | |
129 | while (retry) { | |
130 | rados_t cluster; | |
131 | ||
132 | ASSERT_EQ(0, rados_create(&cluster, "admin")); | |
133 | ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); | |
134 | ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); | |
135 | ||
136 | ASSERT_EQ(0, rados_connect(cluster)); | |
137 | JSONFormatter cmd_f; | |
138 | cmd_f.open_object_section("command"); | |
139 | cmd_f.dump_string("prefix", "status"); | |
140 | cmd_f.close_section(); | |
141 | std::ostringstream cmd_stream; | |
142 | cmd_f.flush(cmd_stream); | |
143 | const std::string serialized_cmd = cmd_stream.str(); | |
144 | const char *cmd[2]; | |
145 | cmd[1] = NULL; | |
146 | cmd[0] = serialized_cmd.c_str(); | |
147 | char *outbuf = NULL; | |
148 | size_t outlen = 0; | |
149 | ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, | |
150 | &outbuf, &outlen, NULL, NULL)); | |
151 | std::string out(outbuf, outlen); | |
152 | cout << out << std::endl; | |
153 | bool success = false; | |
154 | auto r1 = out.find("16 portals active (1 hosts, 3 zones)"); | |
155 | if (std::string::npos != r1) { | |
156 | success = true; | |
157 | } | |
158 | rados_buffer_free(outbuf); | |
159 | rados_shutdown(cluster); | |
160 | ||
161 | if (success || !retry) { | |
162 | break; | |
163 | } | |
164 | ||
165 | // wait for 2 seconds to make sure all the | |
166 | // services have been successfully updated | |
167 | // to ceph mon, then retry it. | |
168 | sleep(2); | |
169 | retry--; | |
170 | } | |
171 | ||
172 | { | |
173 | std::scoped_lock<std::mutex> l(lock); | |
174 | stopped = true; | |
175 | cond.notify_all(); | |
176 | } | |
177 | for (int i = 0; i < nthreads; ++i) | |
178 | threads[i].join(); | |
179 | ||
180 | ASSERT_NE(0, retry); | |
181 | #ifndef _WIN32 | |
182 | ASSERT_EQ(setrlimit(RLIMIT_NOFILE, &rold), 0); | |
183 | #endif | |
184 | } | |
185 | ||
186 | TEST(LibRadosService, Status) { | |
187 | rados_t cluster; | |
188 | ASSERT_EQ(0, rados_create(&cluster, "admin")); | |
189 | ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); | |
190 | ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); | |
191 | ||
192 | ASSERT_EQ(-ENOTCONN, rados_service_update_status(cluster, | |
193 | "testing\0testing\0")); | |
194 | ||
195 | ASSERT_EQ(0, rados_connect(cluster)); | |
196 | string name = string("pid") + stringify(getpid()); | |
197 | ASSERT_EQ(0, rados_service_register(cluster, "laundry", name.c_str(), | |
198 | "foo\0bar\0this\0that\0")); | |
199 | ||
200 | for (int i=0; i<20; ++i) { | |
201 | char buffer[1024]; | |
202 | snprintf(buffer, sizeof(buffer), "%s%c%s%c%s%c%d%c", | |
203 | "testing", '\0', "testing", '\0', | |
204 | "count", '\0', i, '\0'); | |
205 | ASSERT_EQ(0, rados_service_update_status(cluster, buffer)); | |
206 | sleep(1); | |
207 | } | |
208 | rados_shutdown(cluster); | |
209 | } |