]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #include "include/rados/librados.h" | |
16 | ||
17 | #include <assert.h> | |
18 | #include <stdarg.h> | |
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <time.h> | |
22 | ||
23 | static int do_rados_setxattr(rados_ioctx_t io_ctx, const char *oid, | |
24 | const char *key, const char *val) | |
25 | { | |
26 | int ret = rados_setxattr(io_ctx, oid, key, val, strlen(val) + 1); | |
27 | if (ret < 0) { | |
28 | printf("rados_setxattr failed with error %d\n", ret); | |
29 | return 1; | |
30 | } | |
31 | printf("rados_setxattr %s=%s\n", key, val); | |
32 | return 0; | |
33 | } | |
34 | ||
35 | static int do_rados_getxattr(rados_ioctx_t io_ctx, const char *oid, | |
36 | const char *key, const char *expected) | |
37 | { | |
38 | size_t blen = strlen(expected) + 1; | |
39 | char buf[blen]; | |
40 | memset(buf, 0, sizeof(buf)); | |
41 | int r = rados_getxattr(io_ctx, oid, key, buf, blen); | |
42 | if (r < 0) { | |
43 | printf("rados_getxattr(%s) failed with error %d\n", key, r); | |
44 | return 1; | |
45 | } | |
46 | if (strcmp(buf, expected) != 0) { | |
47 | printf("rados_getxattr(%s) got wrong result! " | |
48 | "expected: '%s'. got '%s'\n", key, expected, buf); | |
49 | return 1; | |
50 | } | |
51 | printf("rados_getxattr %s=%s\n", key, buf); | |
52 | return 0; | |
53 | } | |
54 | ||
55 | static int do_rados_getxattrs(rados_ioctx_t io_ctx, const char *oid, | |
56 | const char **exkeys, const char **exvals) | |
57 | { | |
58 | rados_xattrs_iter_t iter; | |
59 | int nval = 0, i, nfound = 0, r = 0, ret = 1; | |
60 | ||
61 | for (i = 0; exvals[i]; ++i) { | |
62 | ++nval; | |
63 | } | |
64 | r = rados_getxattrs(io_ctx, oid, &iter); | |
65 | if (r) { | |
66 | printf("rados_getxattrs(%s) failed with error %d\n", oid, r); | |
67 | return 1; | |
68 | } | |
69 | while (1) { | |
70 | size_t len; | |
71 | const char *key, *val; | |
72 | r = rados_getxattrs_next(iter, &key, &val, &len); | |
73 | if (r) { | |
74 | printf("rados_getxattrs(%s): rados_getxattrs_next " | |
75 | "returned error %d\n", oid, r); | |
76 | goto out_err; | |
77 | } | |
78 | if (!key) | |
79 | break; | |
80 | for (i = 0; i < nval; ++i) { | |
81 | if (strcmp(exkeys[i], key)) | |
82 | continue; | |
83 | if ((len == strlen(exvals[i]) + 1) && (val != NULL) && (!strcmp(exvals[i], val))) { | |
84 | nfound++; | |
85 | break; | |
86 | } | |
87 | printf("rados_getxattrs(%s): got key %s, but the " | |
88 | "value was %s rather than %s.\n", | |
89 | oid, key, val, exvals[i]); | |
90 | goto out_err; | |
91 | } | |
92 | } | |
93 | if (nfound != nval) { | |
94 | printf("rados_getxattrs(%s): only found %d extended attributes. " | |
95 | "Expected %d\n", oid, nfound, nval); | |
96 | goto out_err; | |
97 | } | |
98 | ret = 0; | |
99 | printf("rados_getxattrs(%s)\n", oid); | |
100 | ||
101 | out_err: | |
102 | rados_getxattrs_end(iter); | |
103 | return ret; | |
104 | } | |
105 | ||
106 | static int testrados(void) | |
107 | { | |
108 | char tmp[32]; | |
9f95a23c | 109 | int i, r, safe; |
7c673cae FG |
110 | int ret = 1; //set 1 as error case |
111 | rados_t cl; | |
9f95a23c TL |
112 | const char *oid = "foo_object"; |
113 | const char *exkeys[] = { "a", "b", "c", NULL }; | |
114 | const char *exvals[] = { "1", "2", "3", NULL }; | |
7c673cae FG |
115 | |
116 | if (rados_create(&cl, NULL) < 0) { | |
117 | printf("error initializing\n"); | |
118 | return 1; | |
119 | } | |
120 | ||
121 | if (rados_conf_read_file(cl, NULL)) { | |
122 | printf("error reading configuration file\n"); | |
123 | goto out_err; | |
124 | } | |
125 | ||
126 | // Try to set a configuration option that doesn't exist. | |
127 | // This should fail. | |
128 | if (!rados_conf_set(cl, "config option that doesn't exist", | |
129 | "some random value")) { | |
130 | printf("error: succeeded in setting nonexistent config option\n"); | |
131 | goto out_err; | |
132 | } | |
133 | ||
134 | if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) { | |
135 | printf("error: failed to read log_to_stderr from config\n"); | |
136 | goto out_err; | |
137 | } | |
138 | ||
139 | // Can we change it? | |
140 | if (rados_conf_set(cl, "log to stderr", "true")) { | |
141 | printf("error: error setting log_to_stderr\n"); | |
142 | goto out_err; | |
143 | } | |
144 | if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) { | |
145 | printf("error: failed to read log_to_stderr from config\n"); | |
146 | goto out_err; | |
147 | } | |
148 | if (strcmp(tmp, "true")) { | |
149 | printf("error: new setting for log_to_stderr failed to take effect.\n"); | |
150 | goto out_err; | |
151 | } | |
152 | ||
153 | if (rados_connect(cl)) { | |
154 | printf("error connecting\n"); | |
155 | goto out_err; | |
156 | } | |
157 | if (rados_connect(cl) == 0) { | |
158 | printf("second connect attempt didn't return an error\n"); | |
159 | goto out_err; | |
160 | } | |
161 | ||
162 | /* create an io_ctx */ | |
163 | r = rados_pool_create(cl, "foo"); | |
164 | printf("rados_pool_create = %d\n", r); | |
165 | ||
166 | rados_ioctx_t io_ctx; | |
167 | r = rados_ioctx_create(cl, "foo", &io_ctx); | |
168 | if (r < 0) { | |
169 | printf("error creating ioctx\n"); | |
170 | goto out_err; | |
171 | } | |
172 | printf("rados_ioctx_create = %d, io_ctx = %p\n", r, io_ctx); | |
173 | ||
174 | /* list all pools */ | |
175 | { | |
176 | int buf_sz = rados_pool_list(cl, NULL, 0); | |
177 | printf("need buffer size of %d\n", buf_sz); | |
178 | char buf[buf_sz]; | |
179 | int r = rados_pool_list(cl, buf, buf_sz); | |
180 | if (r != buf_sz) { | |
181 | printf("buffer size mismatch: got %d the first time, but %d " | |
182 | "the second.\n", buf_sz, r); | |
183 | goto out_err_cleanup; | |
184 | } | |
185 | const char *b = buf; | |
186 | printf("begin pools.\n"); | |
187 | while (1) { | |
188 | if (b[0] == '\0') | |
189 | break; | |
190 | printf(" pool: '%s'\n", b); | |
191 | b += strlen(b) + 1; | |
192 | }; | |
193 | printf("end pools.\n"); | |
194 | } | |
195 | ||
196 | ||
197 | /* stat */ | |
198 | struct rados_pool_stat_t st; | |
199 | r = rados_ioctx_pool_stat(io_ctx, &st); | |
200 | printf("rados_ioctx_pool_stat = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects); | |
201 | ||
202 | /* snapshots */ | |
203 | r = rados_ioctx_snap_create(io_ctx, "snap1"); | |
204 | printf("rados_ioctx_snap_create snap1 = %d\n", r); | |
205 | rados_snap_t snaps[10]; | |
206 | r = rados_ioctx_snap_list(io_ctx, snaps, 10); | |
207 | for (i=0; i<r; i++) { | |
208 | char name[100]; | |
209 | rados_ioctx_snap_get_name(io_ctx, snaps[i], name, sizeof(name)); | |
210 | printf("rados_ioctx_snap_list got snap %lld %s\n", (long long)snaps[i], name); | |
211 | } | |
212 | rados_snap_t snapid; | |
213 | r = rados_ioctx_snap_lookup(io_ctx, "snap1", &snapid); | |
214 | printf("rados_ioctx_snap_lookup snap1 got %lld, result %d\n", (long long)snapid, r); | |
215 | r = rados_ioctx_snap_remove(io_ctx, "snap1"); | |
216 | printf("rados_ioctx_snap_remove snap1 = %d\n", r); | |
217 | ||
218 | /* sync io */ | |
219 | time_t tm; | |
220 | char buf[128], buf2[128]; | |
221 | time(&tm); | |
222 | snprintf(buf, 128, "%s", ctime(&tm)); | |
7c673cae FG |
223 | r = rados_write(io_ctx, oid, buf, strlen(buf) + 1, 0); |
224 | printf("rados_write = %d\n", r); | |
225 | r = rados_read(io_ctx, oid, buf2, sizeof(buf2), 0); | |
226 | printf("rados_read = %d\n", r); | |
227 | if (memcmp(buf, buf2, r)) | |
228 | printf("*** content mismatch ***\n"); | |
229 | ||
230 | /* attrs */ | |
231 | if (do_rados_setxattr(io_ctx, oid, "b", "2")) | |
232 | goto out_err_cleanup; | |
233 | if (do_rados_setxattr(io_ctx, oid, "a", "1")) | |
234 | goto out_err_cleanup; | |
235 | if (do_rados_setxattr(io_ctx, oid, "c", "3")) | |
236 | goto out_err_cleanup; | |
237 | if (do_rados_getxattr(io_ctx, oid, "a", "1")) | |
238 | goto out_err_cleanup; | |
239 | if (do_rados_getxattr(io_ctx, oid, "b", "2")) | |
240 | goto out_err_cleanup; | |
241 | if (do_rados_getxattr(io_ctx, oid, "c", "3")) | |
242 | goto out_err_cleanup; | |
7c673cae FG |
243 | if (do_rados_getxattrs(io_ctx, oid, exkeys, exvals)) |
244 | goto out_err_cleanup; | |
245 | ||
246 | uint64_t size; | |
247 | time_t mtime; | |
248 | r = rados_stat(io_ctx, oid, &size, &mtime); | |
249 | printf("rados_stat size = %lld mtime = %d = %d\n", (long long)size, (int)mtime, r); | |
250 | r = rados_stat(io_ctx, "does_not_exist", NULL, NULL); | |
251 | printf("rados_stat(does_not_exist) = %d\n", r); | |
252 | ||
253 | /* exec */ | |
254 | rados_exec(io_ctx, oid, "crypto", "md5", buf, strlen(buf) + 1, buf, 128); | |
255 | printf("exec result=%s\n", buf); | |
256 | r = rados_read(io_ctx, oid, buf2, 128, 0); | |
257 | printf("read result=%s\n", buf2); | |
258 | printf("size=%d\n", r); | |
259 | ||
260 | /* aio */ | |
261 | rados_completion_t a, b; | |
9f95a23c TL |
262 | rados_aio_create_completion2(NULL, NULL, &a); |
263 | rados_aio_create_completion2(NULL, NULL, &b); | |
7c673cae FG |
264 | rados_aio_write(io_ctx, "a", a, buf, 100, 0); |
265 | rados_aio_write(io_ctx, "../b/bb_bb_bb\\foo\\bar", b, buf, 100, 0); | |
9f95a23c | 266 | rados_aio_wait_for_complete(a); |
7c673cae | 267 | printf("a safe\n"); |
9f95a23c | 268 | rados_aio_wait_for_complete(b); |
7c673cae FG |
269 | printf("b safe\n"); |
270 | rados_aio_release(a); | |
271 | rados_aio_release(b); | |
272 | ||
273 | /* test flush */ | |
274 | printf("testing aio flush\n"); | |
275 | rados_completion_t c; | |
9f95a23c | 276 | rados_aio_create_completion2(NULL, NULL, &c); |
7c673cae | 277 | rados_aio_write(io_ctx, "c", c, buf, 100, 0); |
9f95a23c | 278 | safe = rados_aio_is_safe(c); |
7c673cae FG |
279 | printf("a should not yet be safe and ... %s\n", safe ? "is":"is not"); |
280 | assert(!safe); | |
281 | rados_aio_flush(io_ctx); | |
282 | safe = rados_aio_is_safe(c); | |
283 | printf("a should be safe and ... %s\n", safe ? "is":"is not"); | |
284 | assert(safe); | |
285 | rados_aio_release(c); | |
286 | ||
287 | rados_read(io_ctx, "../b/bb_bb_bb\\foo\\bar", buf2, 128, 0); | |
288 | ||
289 | /* list objects */ | |
290 | rados_list_ctx_t h; | |
291 | r = rados_nobjects_list_open(io_ctx, &h); | |
292 | printf("rados_nobjects_list_open = %d, h = %p\n", r, h); | |
293 | const char *poolname; | |
294 | while (rados_nobjects_list_next(h, &poolname, NULL, NULL) == 0) | |
295 | printf("rados_nobjects_list_next got object '%s'\n", poolname); | |
296 | rados_nobjects_list_close(h); | |
297 | ||
298 | /* stat */ | |
299 | r = rados_ioctx_pool_stat(io_ctx, &st); | |
300 | printf("rados_stat_pool = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects); | |
301 | ||
302 | ret = 0; | |
303 | ||
304 | out_err_cleanup: | |
305 | /* delete a pool */ | |
306 | rados_ioctx_destroy(io_ctx); | |
307 | ||
308 | r = rados_pool_delete(cl, "foo"); | |
309 | printf("rados_delete_pool = %d\n", r); | |
310 | ||
311 | out_err: | |
312 | rados_shutdown(cl); | |
313 | return ret; | |
314 | } | |
315 | ||
316 | int main(int argc, const char **argv) | |
317 | { | |
318 | return testrados(); | |
319 | } |