rados_LDADD = libglobal.la librados.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
bin_PROGRAMS += rados
-testrados_SOURCES = testrados.c
-testrados_LDADD = librados.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
-testradospp_SOURCES = testradospp.cc
-testradospp_LDADD = librados.la -lpthread -lm
+scratchtool_SOURCES = scratchtool.c
+scratchtool_LDADD = librados.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
+scratchtoolpp_SOURCES = scratchtoolpp.cc
+scratchtoolpp_LDADD = librados.la -lpthread -lm
radosacl_SOURCES = radosacl.cc
radosacl_LDADD = librados.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
-bin_DEBUGPROGRAMS += testrados testradospp radosacl
+bin_DEBUGPROGRAMS += scratchtool scratchtoolpp radosacl
rbd_SOURCES = rbd.cc common/fiemap.cc common/secret.c
rbd_CXXFLAGS = ${AM_CXXFLAGS}
--- /dev/null
+// -*- 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-2006 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 "include/rados/librados.h"
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+static int do_rados_setxattr(rados_ioctx_t io_ctx, const char *oid,
+ const char *key, const char *val)
+{
+ int ret = rados_setxattr(io_ctx, oid, key, val, strlen(val) + 1);
+ if (ret < 0) {
+ printf("rados_setxattr failed with error %d\n", ret);
+ return 1;
+ }
+ printf("rados_setxattr %s=%s\n", key, val);
+ return 0;
+}
+
+static int do_rados_getxattr(rados_ioctx_t io_ctx, const char *oid,
+ const char *key, const char *expected)
+{
+ size_t blen = strlen(expected) + 1;
+ char buf[blen];
+ memset(buf, 0, sizeof(buf));
+ int r = rados_getxattr(io_ctx, oid, key, buf, blen);
+ if (r < 0) {
+ printf("rados_getxattr(%s) failed with error %d\n", key, r);
+ return 1;
+ }
+ if (strcmp(buf, expected) != 0) {
+ printf("rados_getxattr(%s) got wrong result! "
+ "expected: '%s'. got '%s'\n", key, expected, buf);
+ return 1;
+ }
+ printf("rados_getxattr %s=%s\n", key, buf);
+ return 0;
+}
+
+static int do_rados_getxattrs(rados_ioctx_t io_ctx, const char *oid,
+ const char **exkeys, const char **exvals)
+{
+ rados_xattrs_iter_t iter;
+ int nval = 0, i, nfound = 0, ret = 0;
+
+ for (i = 0; exvals[i]; ++i) {
+ ++nval;
+ }
+ ret = rados_getxattrs(io_ctx, oid, &iter);
+ if (ret) {
+ printf("rados_getxattrs(%s) failed with error %d\n", oid, ret);
+ return 1;
+ }
+ while (1) {
+ size_t len;
+ const char *key, *val;
+ ret = rados_getxattrs_next(iter, &key, &val, &len);
+ if (ret) {
+ printf("rados_getxattrs(%s): rados_getxattrs_next "
+ "returned error %d\n", oid, ret);
+ return 1;
+ }
+ if (!key)
+ break;
+ for (i = 0; i < nval; ++i) {
+ if (strcmp(exkeys[i], key))
+ continue;
+ if ((len == strlen(exvals[i]) + 1) && (!strcmp(exvals[i], val))) {
+ nfound++;
+ break;
+ }
+ printf("rados_getxattrs(%s): got key %s, but the "
+ "value was %s rather than %s.\n",
+ oid, key, val, exvals[i]);
+ return 1;
+ }
+ }
+ if (nfound != nval) {
+ printf("rados_getxattrs(%s): only found %d extended attributes. "
+ "Expected %d\n", oid, nfound, nval);
+ return 1;
+ }
+ rados_getxattrs_end(iter);
+ printf("rados_getxattrs(%s)\n", oid);
+ return 0;
+}
+
+static int testrados(void)
+{
+ char tmp[32];
+ int i, r;
+ rados_t cl;
+
+ if (rados_create(&cl, NULL) < 0) {
+ printf("error initializing\n");
+ return 1;
+ }
+
+ if (rados_conf_read_file(cl, NULL)) {
+ printf("error reading configuration file\n");
+ return 1;
+ }
+
+ // Try to set a configuration option that doesn't exist.
+ // This should fail.
+ if (!rados_conf_set(cl, "config option that doesn't exist",
+ "some random value")) {
+ printf("error: succeeded in setting nonexistent config option\n");
+ return 1;
+ }
+
+ if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) {
+ printf("error: failed to read log_to_stderr from config\n");
+ return 1;
+ }
+
+ // Can we change it?
+ if (rados_conf_set(cl, "log to stderr", "2")) {
+ printf("error: error setting log_to_stderr\n");
+ return 1;
+ }
+ if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) {
+ printf("error: failed to read log_to_stderr from config\n");
+ return 1;
+ }
+ if (tmp[0] != '2') {
+ printf("error: new setting for log_to_stderr failed to take effect.\n");
+ return 1;
+ }
+
+ if (rados_connect(cl)) {
+ printf("error connecting\n");
+ return 1;
+ }
+ if (rados_connect(cl) == 0) {
+ printf("second connect attempt didn't return an error\n");
+ return 1;
+ }
+
+ /* create an io_ctx */
+ r = rados_pool_create(cl, "foo");
+ printf("rados_pool_create = %d\n", r);
+
+ rados_ioctx_t io_ctx;
+ r = rados_ioctx_create(cl, "foo", &io_ctx);
+ printf("rados_ioctx_create = %d, io_ctx = %p\n", r, io_ctx);
+
+ /* list all pools */
+ {
+ int buf_sz = rados_pool_list(cl, NULL, 0);
+ printf("need buffer size of %d\n", buf_sz);
+ char buf[buf_sz];
+ int r = rados_pool_list(cl, buf, buf_sz);
+ if (r != buf_sz) {
+ printf("buffer size mismatch: got %d the first time, but %d "
+ "the second.\n", buf_sz, r);
+ return 1;
+ }
+ const char *b = buf;
+ printf("begin pools.\n");
+ while (1) {
+ if (b[0] == '\0')
+ break;
+ printf(" pool: '%s'\n", b);
+ b += strlen(b) + 1;
+ };
+ printf("end pools.\n");
+ }
+
+
+ /* stat */
+ struct rados_pool_stat_t st;
+ r = rados_ioctx_pool_stat(io_ctx, &st);
+ printf("rados_ioctx_pool_stat = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects);
+
+ /* snapshots */
+ r = rados_ioctx_snap_create(io_ctx, "snap1");
+ printf("rados_ioctx_snap_create snap1 = %d\n", r);
+ rados_snap_t snaps[10];
+ r = rados_ioctx_snap_list(io_ctx, snaps, 10);
+ for (i=0; i<r; i++) {
+ char name[100];
+ rados_ioctx_snap_get_name(io_ctx, snaps[i], name, sizeof(name));
+ printf("rados_ioctx_snap_list got snap %lld %s\n", (long long)snaps[i], name);
+ }
+ rados_snap_t snapid;
+ r = rados_ioctx_snap_lookup(io_ctx, "snap1", &snapid);
+ printf("rados_ioctx_snap_lookup snap1 got %lld, result %d\n", (long long)snapid, r);
+ r = rados_ioctx_snap_remove(io_ctx, "snap1");
+ printf("rados_ioctx_snap_remove snap1 = %d\n", r);
+
+ /* sync io */
+ time_t tm;
+ char buf[128], buf2[128];
+ time(&tm);
+ snprintf(buf, 128, "%s", ctime(&tm));
+ const char *oid = "foo_object";
+ r = rados_write(io_ctx, oid, buf, strlen(buf) + 1, 0);
+ printf("rados_write = %d\n", r);
+ r = rados_read(io_ctx, oid, buf2, sizeof(buf2), 0);
+ printf("rados_read = %d\n", r);
+ if (memcmp(buf, buf2, r))
+ printf("*** content mismatch ***\n");
+
+ /* attrs */
+ if (do_rados_setxattr(io_ctx, oid, "b", "2"))
+ return 1;
+ if (do_rados_setxattr(io_ctx, oid, "a", "1"))
+ return 1;
+ if (do_rados_setxattr(io_ctx, oid, "c", "3"))
+ return 1;
+ if (do_rados_getxattr(io_ctx, oid, "a", "1"))
+ return 1;
+ if (do_rados_getxattr(io_ctx, oid, "b", "2"))
+ return 1;
+ if (do_rados_getxattr(io_ctx, oid, "c", "3"))
+ return 1;
+ const char *exkeys[] = { "a", "b", "c", NULL };
+ const char *exvals[] = { "1", "2", "3", NULL };
+ if (do_rados_getxattrs(io_ctx, oid, exkeys, exvals))
+ return 1;
+
+ uint64_t size;
+ time_t mtime;
+ r = rados_stat(io_ctx, oid, &size, &mtime);
+ printf("rados_stat size = %lld mtime = %d = %d\n", (long long)size, (int)mtime, r);
+ r = rados_stat(io_ctx, "does_not_exist", NULL, NULL);
+ printf("rados_stat(does_not_exist) = %d\n", r);
+
+ /* exec */
+ rados_exec(io_ctx, oid, "crypto", "md5", buf, strlen(buf) + 1, buf, 128);
+ printf("exec result=%s\n", buf);
+ r = rados_read(io_ctx, oid, buf2, 128, 0);
+ printf("read result=%s\n", buf2);
+ printf("size=%d\n", r);
+
+ /* aio */
+ rados_completion_t a, b;
+ rados_aio_create_completion(0, 0, 0, &a);
+ rados_aio_create_completion(0, 0, 0, &b);
+ rados_aio_write(io_ctx, "a", a, buf, 100, 0);
+ rados_aio_write(io_ctx, "../b/bb_bb_bb\\foo\\bar", b, buf, 100, 0);
+ rados_aio_wait_for_safe(a);
+ printf("a safe\n");
+ rados_aio_wait_for_safe(b);
+ printf("b safe\n");
+ rados_aio_release(a);
+ rados_aio_release(b);
+
+ /* test flush */
+ printf("testing aio flush\n");
+ rados_completion_t c;
+ rados_aio_create_completion(0, 0, 0, &c);
+ rados_aio_write(io_ctx, "c", c, buf, 100, 0);
+ int safe = rados_aio_is_safe(c);
+ printf("a should not yet be safe and ... %s\n", safe ? "is":"is not");
+ assert(!safe);
+ rados_aio_flush(io_ctx);
+ safe = rados_aio_is_safe(c);
+ printf("a should be safe and ... %s\n", safe ? "is":"is not");
+ assert(safe);
+ rados_aio_release(c);
+
+ rados_read(io_ctx, "../b/bb_bb_bb\\foo\\bar", buf2, 128, 0);
+
+ /* list objects */
+ rados_list_ctx_t h;
+ r = rados_objects_list_open(io_ctx, &h);
+ printf("rados_list_objects_open = %d, h = %p\n", r, h);
+ const char *poolname;
+ while (rados_objects_list_next(h, &poolname) == 0)
+ printf("rados_list_objects_next got object '%s'\n", poolname);
+ rados_objects_list_close(h);
+
+ /* stat */
+ r = rados_ioctx_pool_stat(io_ctx, &st);
+ printf("rados_stat_pool = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects);
+
+ /* delete a pool */
+ printf("rados_delete_pool = %d\n", r);
+ rados_ioctx_destroy(io_ctx);
+
+ r = rados_pool_delete(cl, "foo");
+ printf("rados_ioctx_pool_delete = %d\n", r);
+
+ rados_shutdown(cl);
+ return 0;
+}
+
+int main(int argc, const char **argv)
+{
+ return testrados();
+}
--- /dev/null
+// -*- 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-2006 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 "include/types.h"
+#include "include/rados/librados.hpp"
+
+using namespace librados;
+
+#include <iostream>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+
+void buf_to_hex(const unsigned char *buf, int len, char *str)
+{
+ str[0] = '\0';
+ for (int i = 0; i < len; i++) {
+ sprintf(&str[i*2], "%02x", (int)buf[i]);
+ }
+}
+
+class C_Watch : public WatchCtx {
+public:
+ C_Watch() {}
+ void notify(uint8_t opcode, uint64_t ver, bufferlist& bl) {
+ cout << "C_Watch::notify() opcode=" << (int)opcode << " ver=" << ver << std::endl;
+ }
+};
+
+void testradospp_milestone(void)
+{
+ cout << "*** press enter to continue ***" << std::endl;
+ getchar();
+}
+
+int main(int argc, const char **argv)
+{
+ Rados rados;
+ if (rados.init(NULL) < 0) {
+ cerr << "couldn't initialize rados!" << std::endl;
+ exit(1);
+ }
+
+ if (rados.conf_read_file(NULL)) {
+ cerr << "couldn't read configuration file." << std::endl;
+ exit(1);
+ }
+ rados.conf_parse_argv(argc, argv);
+
+ if (!rados.conf_set("config option that doesn't exist",
+ "some random value")) {
+ printf("error: succeeded in setting nonexistent config option\n");
+ exit(1);
+ }
+ if (rados.conf_set("log to stderr", "2")) {
+ printf("error: error setting log_to_stderr\n");
+ exit(1);
+ }
+ std::string tmp;
+ if (rados.conf_get("log to stderr", tmp)) {
+ printf("error: failed to read log_to_stderr from config\n");
+ exit(1);
+ }
+ if (tmp[0] != '2') {
+ printf("error: new setting for log_to_stderr failed to take effect.\n");
+ exit(1);
+ }
+
+ if (rados.connect()) {
+ printf("error connecting\n");
+ exit(1);
+ }
+
+ cout << "rados_initialize completed" << std::endl;
+ testradospp_milestone();
+
+ time_t tm;
+ bufferlist bl, bl2, blf;
+ char buf[128];
+
+ time(&tm);
+ snprintf(buf, 128, "%s", ctime(&tm));
+ bl.append(buf, strlen(buf));
+ blf.append(buf, 16);
+
+ const char *oid = "bar";
+
+ IoCtx io_ctx;
+ int r = rados.ioctx_create("data", io_ctx);
+ cout << "ioctx_create result = " << r << std::endl;
+
+ r = io_ctx.write(oid, bl, bl.length(), 0);
+ uint64_t objver = io_ctx.get_last_version();
+ assert(objver > 0);
+ cout << "io_ctx.write returned " << r << " last_ver=" << objver << std::endl;
+
+ uint64_t stat_size;
+ time_t stat_mtime;
+ r = io_ctx.stat(oid, &stat_size, &stat_mtime);
+ cout << "io_ctx.stat size = " << stat_size << " mtime = " << stat_mtime << std::endl;
+
+ r = io_ctx.stat(oid, NULL, NULL);
+ cout << "io_ctx.stat(does_not_exist) = " << r;
+
+ uint64_t handle;
+ C_Watch wc;
+ r = io_ctx.watch(oid, objver, &handle, &wc);
+ cout << "io_ctx.watch returned " << r << std::endl;
+
+ testradospp_milestone();
+ io_ctx.set_notify_timeout(7);
+ bufferlist notify_bl;
+ r = io_ctx.notify(oid, objver, notify_bl);
+ cout << "io_ctx.notify returned " << r << std::endl;
+ testradospp_milestone();
+
+ r = io_ctx.notify(oid, objver, notify_bl);
+ cout << "io_ctx.notify returned " << r << std::endl;
+ testradospp_milestone();
+
+ r = io_ctx.unwatch(oid, handle);
+ cout << "io_ctx.unwatch returned " << r << std::endl;
+ cout << "*** press enter to continue ***" << std::endl;
+ testradospp_milestone();
+
+ r = io_ctx.notify(oid, objver, notify_bl);
+ cout << "io_ctx.notify returned " << r << std::endl;
+ cout << "*** press enter to continue ***" << std::endl;
+ testradospp_milestone();
+ io_ctx.set_assert_version(objver);
+
+ r = io_ctx.write(oid, bl, bl.length() - 1, 0);
+ cout << "io_ctx.write returned " << r << std::endl;
+
+ r = io_ctx.write(oid, bl, bl.length() - 2, 0);
+ cout << "io_ctx.write returned " << r << std::endl;
+ r = io_ctx.write(oid, bl, bl.length() - 3, 0);
+ cout << "rados.write returned " << r << std::endl;
+ r = io_ctx.append(oid, bl, bl.length());
+ cout << "rados.write returned " << r << std::endl;
+ r = io_ctx.write_full(oid, blf);
+ cout << "rados.write_full returned " << r << std::endl;
+ r = io_ctx.read(oid, bl, bl.length(), 0);
+ cout << "rados.read returned " << r << std::endl;
+ r = io_ctx.trunc(oid, 8);
+ cout << "rados.trunc returned " << r << std::endl;
+ r = io_ctx.read(oid, bl, bl.length(), 0);
+ cout << "rados.read returned " << r << std::endl;
+ r = io_ctx.exec(oid, "crypto", "md5", bl, bl2);
+ cout << "exec returned " << r << " buf size=" << bl2.length() << std::endl;
+ const unsigned char *md5 = (const unsigned char *)bl2.c_str();
+ char md5_str[bl2.length()*2 + 1];
+ buf_to_hex(md5, bl2.length(), md5_str);
+ cout << "md5 result=" << md5_str << std::endl;
+
+ // test assert_version
+ r = io_ctx.read(oid, bl, 0, 1);
+ assert(r >= 0);
+ uint64_t v = io_ctx.get_last_version();
+ cout << oid << " version is " << v << std::endl;
+ assert(v > 0);
+ io_ctx.set_assert_version(v);
+ r = io_ctx.read(oid, bl, 0, 1);
+ assert(r >= 0);
+ io_ctx.set_assert_version(v - 1);
+ r = io_ctx.read(oid, bl, 0, 1);
+ assert(r == -ERANGE);
+ io_ctx.set_assert_version(v + 1);
+ r = io_ctx.read(oid, bl, 0, 1);
+ assert(r == -EOVERFLOW);
+
+ // test assert_src_version
+ const char *dest = "baz";
+ r = io_ctx.read(oid, bl, 0, 1);
+ assert(r >= 0);
+ v = io_ctx.get_last_version();
+ cout << oid << " version is " << v << std::endl;
+ io_ctx.set_assert_src_version(oid, v);
+ r = io_ctx.clone_range(dest, 0, oid, 0, 1);
+ assert(r >= 0);
+ io_ctx.set_assert_src_version(oid, v-1);
+ r = io_ctx.clone_range(dest, 0, oid, 0, 1);
+ assert(r == -ERANGE);
+ io_ctx.set_assert_src_version(oid, v+1);
+ r = io_ctx.clone_range(dest, 0, oid, 0, 1);
+ assert(r == -EOVERFLOW);
+
+ r = io_ctx.exec(oid, "crypto", "sha1", bl, bl2);
+ cout << "exec returned " << r << std::endl;
+ const unsigned char *sha1 = (const unsigned char *)bl2.c_str();
+ char sha1_str[bl2.length()*2 + 1];
+ buf_to_hex(sha1, bl2.length(), sha1_str);
+ cout << "sha1 result=" << sha1_str << std::endl;
+
+ r = io_ctx.exec(oid, "acl", "set", bl, bl2);
+ r = io_ctx.exec(oid, "acl", "get", bl, bl2);
+ cout << "exec returned " << r << std::endl;
+ if (bl2.length() > 0) {
+ cout << "attr=" << bl2.c_str() << std::endl;
+ }
+
+ int size = io_ctx.read(oid, bl2, 128, 0);
+ if (size <= 0) {
+ cout << "failed to read oid " << oid << "." << std::endl;
+ exit(1);
+ }
+ if (size > 4096) {
+ cout << "read too many bytes from oid " << oid << "." << std::endl;
+ exit(1);
+ }
+ char rbuf[size + 1];
+ memcpy(rbuf, bl2.c_str(), size);
+ rbuf[size] = '\0';
+ cout << "read result='" << rbuf << "'" << std::endl;
+ cout << "size=" << size << std::endl;
+
+ const char *oid2 = "jjj10.rbd";
+ r = io_ctx.exec(oid2, "rbd", "snap_list", bl, bl2);
+ cout << "snap_list result=" << r << std::endl;
+ r = io_ctx.exec(oid2, "rbd", "snap_add", bl, bl2);
+ cout << "snap_add result=" << r << std::endl;
+
+ if (r > 0) {
+ char *s = bl2.c_str();
+ for (int i=0; i<r; i++, s += strlen(s) + 1)
+ cout << s << std::endl;
+ }
+
+ cout << "compound operation..." << std::endl;
+ ObjectWriteOperation o;
+ o.write(0, bl);
+ o.setxattr("foo", bl2);
+ r = io_ctx.operate(oid, &o);
+ cout << "operate result=" << r << std::endl;
+
+ cout << "cmpxattr" << std::endl;
+ bufferlist val;
+ val.append("foo");
+ r = io_ctx.setxattr(oid, "foo", val);
+ assert(r >= 0);
+ {
+ ObjectReadOperation o;
+ o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
+ r = io_ctx.operate(oid, &o, &bl2);
+ cout << " got " << r << " wanted >= 0" << std::endl;
+ assert(r >= 0);
+ }
+ val.append("...");
+ {
+ ObjectReadOperation o;
+ o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
+ r = io_ctx.operate(oid, &o, &bl2);
+ cout << " got " << r << " wanted ECANCELED" << std::endl;
+ assert(r == -ECANCELED);
+ }
+
+ cout << "src_cmpxattr" << std::endl;
+ const char *oidb = "bar-clone";
+ {
+ ObjectWriteOperation o;
+ o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
+ io_ctx.locator_set_key(oid);
+ o.write_full(val);
+ r = io_ctx.operate(oidb, &o);
+ cout << " got " << r << " wanted ECANCELED" << std::endl;
+ assert(r == -ECANCELED);
+ }
+ {
+ ObjectWriteOperation o;
+ o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_NE, val);
+ io_ctx.locator_set_key(oid);
+ o.write_full(val);
+ r = io_ctx.operate(oidb, &o);
+ cout << " got " << r << " wanted >= 0" << std::endl;
+ assert(r >= 0);
+ }
+ io_ctx.locator_set_key(string());
+
+
+ cout << "iterating over objects..." << std::endl;
+ int num_objs = 0;
+ for (ObjectIterator iter = io_ctx.objects_begin();
+ iter != io_ctx.objects_end(); ++iter) {
+ num_objs++;
+ cout << "'" << *iter << "'" << std::endl;
+ }
+ cout << "iterated over " << num_objs << " objects." << std::endl;
+ map<string, bufferlist> attrset;
+ io_ctx.getxattrs(oid, attrset);
+
+ map<string, bufferlist>::iterator it;
+ for (it = attrset.begin(); it != attrset.end(); ++it) {
+ cout << "xattr: " << it->first << std::endl;
+ }
+
+ r = io_ctx.remove(oid);
+ cout << "remove result=" << r << std::endl;
+ rados.shutdown();
+
+ return 0;
+}
+
+++ /dev/null
-// -*- 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-2006 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 "include/rados/librados.h"
-
-#include <assert.h>
-#include <pthread.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-
-static int do_rados_setxattr(rados_ioctx_t io_ctx, const char *oid,
- const char *key, const char *val)
-{
- int ret = rados_setxattr(io_ctx, oid, key, val, strlen(val) + 1);
- if (ret < 0) {
- printf("rados_setxattr failed with error %d\n", ret);
- return 1;
- }
- printf("rados_setxattr %s=%s\n", key, val);
- return 0;
-}
-
-static int do_rados_getxattr(rados_ioctx_t io_ctx, const char *oid,
- const char *key, const char *expected)
-{
- size_t blen = strlen(expected) + 1;
- char buf[blen];
- memset(buf, 0, sizeof(buf));
- int r = rados_getxattr(io_ctx, oid, key, buf, blen);
- if (r < 0) {
- printf("rados_getxattr(%s) failed with error %d\n", key, r);
- return 1;
- }
- if (strcmp(buf, expected) != 0) {
- printf("rados_getxattr(%s) got wrong result! "
- "expected: '%s'. got '%s'\n", key, expected, buf);
- return 1;
- }
- printf("rados_getxattr %s=%s\n", key, buf);
- return 0;
-}
-
-static int do_rados_getxattrs(rados_ioctx_t io_ctx, const char *oid,
- const char **exkeys, const char **exvals)
-{
- rados_xattrs_iter_t iter;
- int nval = 0, i, nfound = 0, ret = 0;
-
- for (i = 0; exvals[i]; ++i) {
- ++nval;
- }
- ret = rados_getxattrs(io_ctx, oid, &iter);
- if (ret) {
- printf("rados_getxattrs(%s) failed with error %d\n", oid, ret);
- return 1;
- }
- while (1) {
- size_t len;
- const char *key, *val;
- ret = rados_getxattrs_next(iter, &key, &val, &len);
- if (ret) {
- printf("rados_getxattrs(%s): rados_getxattrs_next "
- "returned error %d\n", oid, ret);
- return 1;
- }
- if (!key)
- break;
- for (i = 0; i < nval; ++i) {
- if (strcmp(exkeys[i], key))
- continue;
- if ((len == strlen(exvals[i]) + 1) && (!strcmp(exvals[i], val))) {
- nfound++;
- break;
- }
- printf("rados_getxattrs(%s): got key %s, but the "
- "value was %s rather than %s.\n",
- oid, key, val, exvals[i]);
- return 1;
- }
- }
- if (nfound != nval) {
- printf("rados_getxattrs(%s): only found %d extended attributes. "
- "Expected %d\n", oid, nfound, nval);
- return 1;
- }
- rados_getxattrs_end(iter);
- printf("rados_getxattrs(%s)\n", oid);
- return 0;
-}
-
-static int testrados(void)
-{
- char tmp[32];
- int i, r;
- rados_t cl;
-
- if (rados_create(&cl, NULL) < 0) {
- printf("error initializing\n");
- return 1;
- }
-
- if (rados_conf_read_file(cl, NULL)) {
- printf("error reading configuration file\n");
- return 1;
- }
-
- // Try to set a configuration option that doesn't exist.
- // This should fail.
- if (!rados_conf_set(cl, "config option that doesn't exist",
- "some random value")) {
- printf("error: succeeded in setting nonexistent config option\n");
- return 1;
- }
-
- if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) {
- printf("error: failed to read log_to_stderr from config\n");
- return 1;
- }
-
- // Can we change it?
- if (rados_conf_set(cl, "log to stderr", "2")) {
- printf("error: error setting log_to_stderr\n");
- return 1;
- }
- if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) {
- printf("error: failed to read log_to_stderr from config\n");
- return 1;
- }
- if (tmp[0] != '2') {
- printf("error: new setting for log_to_stderr failed to take effect.\n");
- return 1;
- }
-
- if (rados_connect(cl)) {
- printf("error connecting\n");
- return 1;
- }
- if (rados_connect(cl) == 0) {
- printf("second connect attempt didn't return an error\n");
- return 1;
- }
-
- /* create an io_ctx */
- r = rados_pool_create(cl, "foo");
- printf("rados_pool_create = %d\n", r);
-
- rados_ioctx_t io_ctx;
- r = rados_ioctx_create(cl, "foo", &io_ctx);
- printf("rados_ioctx_create = %d, io_ctx = %p\n", r, io_ctx);
-
- /* list all pools */
- {
- int buf_sz = rados_pool_list(cl, NULL, 0);
- printf("need buffer size of %d\n", buf_sz);
- char buf[buf_sz];
- int r = rados_pool_list(cl, buf, buf_sz);
- if (r != buf_sz) {
- printf("buffer size mismatch: got %d the first time, but %d "
- "the second.\n", buf_sz, r);
- return 1;
- }
- const char *b = buf;
- printf("begin pools.\n");
- while (1) {
- if (b[0] == '\0')
- break;
- printf(" pool: '%s'\n", b);
- b += strlen(b) + 1;
- };
- printf("end pools.\n");
- }
-
-
- /* stat */
- struct rados_pool_stat_t st;
- r = rados_ioctx_pool_stat(io_ctx, &st);
- printf("rados_ioctx_pool_stat = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects);
-
- /* snapshots */
- r = rados_ioctx_snap_create(io_ctx, "snap1");
- printf("rados_ioctx_snap_create snap1 = %d\n", r);
- rados_snap_t snaps[10];
- r = rados_ioctx_snap_list(io_ctx, snaps, 10);
- for (i=0; i<r; i++) {
- char name[100];
- rados_ioctx_snap_get_name(io_ctx, snaps[i], name, sizeof(name));
- printf("rados_ioctx_snap_list got snap %lld %s\n", (long long)snaps[i], name);
- }
- rados_snap_t snapid;
- r = rados_ioctx_snap_lookup(io_ctx, "snap1", &snapid);
- printf("rados_ioctx_snap_lookup snap1 got %lld, result %d\n", (long long)snapid, r);
- r = rados_ioctx_snap_remove(io_ctx, "snap1");
- printf("rados_ioctx_snap_remove snap1 = %d\n", r);
-
- /* sync io */
- time_t tm;
- char buf[128], buf2[128];
- time(&tm);
- snprintf(buf, 128, "%s", ctime(&tm));
- const char *oid = "foo_object";
- r = rados_write(io_ctx, oid, buf, strlen(buf) + 1, 0);
- printf("rados_write = %d\n", r);
- r = rados_read(io_ctx, oid, buf2, sizeof(buf2), 0);
- printf("rados_read = %d\n", r);
- if (memcmp(buf, buf2, r))
- printf("*** content mismatch ***\n");
-
- /* attrs */
- if (do_rados_setxattr(io_ctx, oid, "b", "2"))
- return 1;
- if (do_rados_setxattr(io_ctx, oid, "a", "1"))
- return 1;
- if (do_rados_setxattr(io_ctx, oid, "c", "3"))
- return 1;
- if (do_rados_getxattr(io_ctx, oid, "a", "1"))
- return 1;
- if (do_rados_getxattr(io_ctx, oid, "b", "2"))
- return 1;
- if (do_rados_getxattr(io_ctx, oid, "c", "3"))
- return 1;
- const char *exkeys[] = { "a", "b", "c", NULL };
- const char *exvals[] = { "1", "2", "3", NULL };
- if (do_rados_getxattrs(io_ctx, oid, exkeys, exvals))
- return 1;
-
- uint64_t size;
- time_t mtime;
- r = rados_stat(io_ctx, oid, &size, &mtime);
- printf("rados_stat size = %lld mtime = %d = %d\n", (long long)size, (int)mtime, r);
- r = rados_stat(io_ctx, "does_not_exist", NULL, NULL);
- printf("rados_stat(does_not_exist) = %d\n", r);
-
- /* exec */
- rados_exec(io_ctx, oid, "crypto", "md5", buf, strlen(buf) + 1, buf, 128);
- printf("exec result=%s\n", buf);
- r = rados_read(io_ctx, oid, buf2, 128, 0);
- printf("read result=%s\n", buf2);
- printf("size=%d\n", r);
-
- /* aio */
- rados_completion_t a, b;
- rados_aio_create_completion(0, 0, 0, &a);
- rados_aio_create_completion(0, 0, 0, &b);
- rados_aio_write(io_ctx, "a", a, buf, 100, 0);
- rados_aio_write(io_ctx, "../b/bb_bb_bb\\foo\\bar", b, buf, 100, 0);
- rados_aio_wait_for_safe(a);
- printf("a safe\n");
- rados_aio_wait_for_safe(b);
- printf("b safe\n");
- rados_aio_release(a);
- rados_aio_release(b);
-
- /* test flush */
- printf("testing aio flush\n");
- rados_completion_t c;
- rados_aio_create_completion(0, 0, 0, &c);
- rados_aio_write(io_ctx, "c", c, buf, 100, 0);
- int safe = rados_aio_is_safe(c);
- printf("a should not yet be safe and ... %s\n", safe ? "is":"is not");
- assert(!safe);
- rados_aio_flush(io_ctx);
- safe = rados_aio_is_safe(c);
- printf("a should be safe and ... %s\n", safe ? "is":"is not");
- assert(safe);
- rados_aio_release(c);
-
- rados_read(io_ctx, "../b/bb_bb_bb\\foo\\bar", buf2, 128, 0);
-
- /* list objects */
- rados_list_ctx_t h;
- r = rados_objects_list_open(io_ctx, &h);
- printf("rados_list_objects_open = %d, h = %p\n", r, h);
- const char *poolname;
- while (rados_objects_list_next(h, &poolname) == 0)
- printf("rados_list_objects_next got object '%s'\n", poolname);
- rados_objects_list_close(h);
-
- /* stat */
- r = rados_ioctx_pool_stat(io_ctx, &st);
- printf("rados_stat_pool = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects);
-
- /* delete a pool */
- printf("rados_delete_pool = %d\n", r);
- rados_ioctx_destroy(io_ctx);
-
- r = rados_pool_delete(cl, "foo");
- printf("rados_ioctx_pool_delete = %d\n", r);
-
- rados_shutdown(cl);
- return 0;
-}
-
-int main(int argc, const char **argv)
-{
- return testrados();
-}
+++ /dev/null
-// -*- 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-2006 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 "include/types.h"
-#include "include/rados/librados.hpp"
-
-using namespace librados;
-
-#include <iostream>
-
-#include <errno.h>
-#include <stdlib.h>
-#include <time.h>
-
-void buf_to_hex(const unsigned char *buf, int len, char *str)
-{
- str[0] = '\0';
- for (int i = 0; i < len; i++) {
- sprintf(&str[i*2], "%02x", (int)buf[i]);
- }
-}
-
-class C_Watch : public WatchCtx {
-public:
- C_Watch() {}
- void notify(uint8_t opcode, uint64_t ver, bufferlist& bl) {
- cout << "C_Watch::notify() opcode=" << (int)opcode << " ver=" << ver << std::endl;
- }
-};
-
-void testradospp_milestone(void)
-{
- cout << "*** press enter to continue ***" << std::endl;
- getchar();
-}
-
-int main(int argc, const char **argv)
-{
- Rados rados;
- if (rados.init(NULL) < 0) {
- cerr << "couldn't initialize rados!" << std::endl;
- exit(1);
- }
-
- if (rados.conf_read_file(NULL)) {
- cerr << "couldn't read configuration file." << std::endl;
- exit(1);
- }
- rados.conf_parse_argv(argc, argv);
-
- if (!rados.conf_set("config option that doesn't exist",
- "some random value")) {
- printf("error: succeeded in setting nonexistent config option\n");
- exit(1);
- }
- if (rados.conf_set("log to stderr", "2")) {
- printf("error: error setting log_to_stderr\n");
- exit(1);
- }
- std::string tmp;
- if (rados.conf_get("log to stderr", tmp)) {
- printf("error: failed to read log_to_stderr from config\n");
- exit(1);
- }
- if (tmp[0] != '2') {
- printf("error: new setting for log_to_stderr failed to take effect.\n");
- exit(1);
- }
-
- if (rados.connect()) {
- printf("error connecting\n");
- exit(1);
- }
-
- cout << "rados_initialize completed" << std::endl;
- testradospp_milestone();
-
- time_t tm;
- bufferlist bl, bl2, blf;
- char buf[128];
-
- time(&tm);
- snprintf(buf, 128, "%s", ctime(&tm));
- bl.append(buf, strlen(buf));
- blf.append(buf, 16);
-
- const char *oid = "bar";
-
- IoCtx io_ctx;
- int r = rados.ioctx_create("data", io_ctx);
- cout << "ioctx_create result = " << r << std::endl;
-
- r = io_ctx.write(oid, bl, bl.length(), 0);
- uint64_t objver = io_ctx.get_last_version();
- assert(objver > 0);
- cout << "io_ctx.write returned " << r << " last_ver=" << objver << std::endl;
-
- uint64_t stat_size;
- time_t stat_mtime;
- r = io_ctx.stat(oid, &stat_size, &stat_mtime);
- cout << "io_ctx.stat size = " << stat_size << " mtime = " << stat_mtime << std::endl;
-
- r = io_ctx.stat(oid, NULL, NULL);
- cout << "io_ctx.stat(does_not_exist) = " << r;
-
- uint64_t handle;
- C_Watch wc;
- r = io_ctx.watch(oid, objver, &handle, &wc);
- cout << "io_ctx.watch returned " << r << std::endl;
-
- testradospp_milestone();
- io_ctx.set_notify_timeout(7);
- bufferlist notify_bl;
- r = io_ctx.notify(oid, objver, notify_bl);
- cout << "io_ctx.notify returned " << r << std::endl;
- testradospp_milestone();
-
- r = io_ctx.notify(oid, objver, notify_bl);
- cout << "io_ctx.notify returned " << r << std::endl;
- testradospp_milestone();
-
- r = io_ctx.unwatch(oid, handle);
- cout << "io_ctx.unwatch returned " << r << std::endl;
- cout << "*** press enter to continue ***" << std::endl;
- testradospp_milestone();
-
- r = io_ctx.notify(oid, objver, notify_bl);
- cout << "io_ctx.notify returned " << r << std::endl;
- cout << "*** press enter to continue ***" << std::endl;
- testradospp_milestone();
- io_ctx.set_assert_version(objver);
-
- r = io_ctx.write(oid, bl, bl.length() - 1, 0);
- cout << "io_ctx.write returned " << r << std::endl;
-
- r = io_ctx.write(oid, bl, bl.length() - 2, 0);
- cout << "io_ctx.write returned " << r << std::endl;
- r = io_ctx.write(oid, bl, bl.length() - 3, 0);
- cout << "rados.write returned " << r << std::endl;
- r = io_ctx.append(oid, bl, bl.length());
- cout << "rados.write returned " << r << std::endl;
- r = io_ctx.write_full(oid, blf);
- cout << "rados.write_full returned " << r << std::endl;
- r = io_ctx.read(oid, bl, bl.length(), 0);
- cout << "rados.read returned " << r << std::endl;
- r = io_ctx.trunc(oid, 8);
- cout << "rados.trunc returned " << r << std::endl;
- r = io_ctx.read(oid, bl, bl.length(), 0);
- cout << "rados.read returned " << r << std::endl;
- r = io_ctx.exec(oid, "crypto", "md5", bl, bl2);
- cout << "exec returned " << r << " buf size=" << bl2.length() << std::endl;
- const unsigned char *md5 = (const unsigned char *)bl2.c_str();
- char md5_str[bl2.length()*2 + 1];
- buf_to_hex(md5, bl2.length(), md5_str);
- cout << "md5 result=" << md5_str << std::endl;
-
- // test assert_version
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r >= 0);
- uint64_t v = io_ctx.get_last_version();
- cout << oid << " version is " << v << std::endl;
- assert(v > 0);
- io_ctx.set_assert_version(v);
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r >= 0);
- io_ctx.set_assert_version(v - 1);
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r == -ERANGE);
- io_ctx.set_assert_version(v + 1);
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r == -EOVERFLOW);
-
- // test assert_src_version
- const char *dest = "baz";
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r >= 0);
- v = io_ctx.get_last_version();
- cout << oid << " version is " << v << std::endl;
- io_ctx.set_assert_src_version(oid, v);
- r = io_ctx.clone_range(dest, 0, oid, 0, 1);
- assert(r >= 0);
- io_ctx.set_assert_src_version(oid, v-1);
- r = io_ctx.clone_range(dest, 0, oid, 0, 1);
- assert(r == -ERANGE);
- io_ctx.set_assert_src_version(oid, v+1);
- r = io_ctx.clone_range(dest, 0, oid, 0, 1);
- assert(r == -EOVERFLOW);
-
- r = io_ctx.exec(oid, "crypto", "sha1", bl, bl2);
- cout << "exec returned " << r << std::endl;
- const unsigned char *sha1 = (const unsigned char *)bl2.c_str();
- char sha1_str[bl2.length()*2 + 1];
- buf_to_hex(sha1, bl2.length(), sha1_str);
- cout << "sha1 result=" << sha1_str << std::endl;
-
- r = io_ctx.exec(oid, "acl", "set", bl, bl2);
- r = io_ctx.exec(oid, "acl", "get", bl, bl2);
- cout << "exec returned " << r << std::endl;
- if (bl2.length() > 0) {
- cout << "attr=" << bl2.c_str() << std::endl;
- }
-
- int size = io_ctx.read(oid, bl2, 128, 0);
- if (size <= 0) {
- cout << "failed to read oid " << oid << "." << std::endl;
- exit(1);
- }
- if (size > 4096) {
- cout << "read too many bytes from oid " << oid << "." << std::endl;
- exit(1);
- }
- char rbuf[size + 1];
- memcpy(rbuf, bl2.c_str(), size);
- rbuf[size] = '\0';
- cout << "read result='" << rbuf << "'" << std::endl;
- cout << "size=" << size << std::endl;
-
- const char *oid2 = "jjj10.rbd";
- r = io_ctx.exec(oid2, "rbd", "snap_list", bl, bl2);
- cout << "snap_list result=" << r << std::endl;
- r = io_ctx.exec(oid2, "rbd", "snap_add", bl, bl2);
- cout << "snap_add result=" << r << std::endl;
-
- if (r > 0) {
- char *s = bl2.c_str();
- for (int i=0; i<r; i++, s += strlen(s) + 1)
- cout << s << std::endl;
- }
-
- cout << "compound operation..." << std::endl;
- ObjectWriteOperation o;
- o.write(0, bl);
- o.setxattr("foo", bl2);
- r = io_ctx.operate(oid, &o);
- cout << "operate result=" << r << std::endl;
-
- cout << "cmpxattr" << std::endl;
- bufferlist val;
- val.append("foo");
- r = io_ctx.setxattr(oid, "foo", val);
- assert(r >= 0);
- {
- ObjectReadOperation o;
- o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
- r = io_ctx.operate(oid, &o, &bl2);
- cout << " got " << r << " wanted >= 0" << std::endl;
- assert(r >= 0);
- }
- val.append("...");
- {
- ObjectReadOperation o;
- o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
- r = io_ctx.operate(oid, &o, &bl2);
- cout << " got " << r << " wanted ECANCELED" << std::endl;
- assert(r == -ECANCELED);
- }
-
- cout << "src_cmpxattr" << std::endl;
- const char *oidb = "bar-clone";
- {
- ObjectWriteOperation o;
- o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
- io_ctx.locator_set_key(oid);
- o.write_full(val);
- r = io_ctx.operate(oidb, &o);
- cout << " got " << r << " wanted ECANCELED" << std::endl;
- assert(r == -ECANCELED);
- }
- {
- ObjectWriteOperation o;
- o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_NE, val);
- io_ctx.locator_set_key(oid);
- o.write_full(val);
- r = io_ctx.operate(oidb, &o);
- cout << " got " << r << " wanted >= 0" << std::endl;
- assert(r >= 0);
- }
- io_ctx.locator_set_key(string());
-
-
- cout << "iterating over objects..." << std::endl;
- int num_objs = 0;
- for (ObjectIterator iter = io_ctx.objects_begin();
- iter != io_ctx.objects_end(); ++iter) {
- num_objs++;
- cout << "'" << *iter << "'" << std::endl;
- }
- cout << "iterated over " << num_objs << " objects." << std::endl;
- map<string, bufferlist> attrset;
- io_ctx.getxattrs(oid, attrset);
-
- map<string, bufferlist>::iterator it;
- for (it = attrset.begin(); it != attrset.end(); ++it) {
- cout << "xattr: " << it->first << std::endl;
- }
-
- r = io_ctx.remove(oid);
- cout << "remove result=" << r << std::endl;
- rados.shutdown();
-
- return 0;
-}
-