--- /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) 2014 Adam Crume <adamcrume@gmail.com>
+ *
+ * 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 "rbd_loc.hpp"
+#include "include/assert.h"
+
+
+using namespace std;
+using namespace rbd_replay;
+
+
+rbd_loc::rbd_loc() {
+}
+
+rbd_loc::rbd_loc(string pool, string image, string snap)
+ : pool(pool),
+ image(image),
+ snap(snap) {
+}
+
+bool rbd_loc::parse(string name_string) {
+ int field = 0;
+ string fields[3];
+ bool read_slash = false;
+ bool read_at = false;
+ for (size_t i = 0, n = name_string.length(); i < n; i++) {
+ char c = name_string[i];
+ switch (c) {
+ case '/':
+ if (read_slash || read_at) {
+ return false;
+ }
+ assert(field == 0);
+ field++;
+ read_slash = true;
+ break;
+ case '@':
+ if (read_at) {
+ return false;
+ }
+ assert(field < 2);
+ field++;
+ read_at = true;
+ break;
+ case '\\':
+ if (i == n - 1) {
+ return false;
+ }
+ fields[field].push_back(name_string[++i]);
+ break;
+ default:
+ fields[field].push_back(c);
+ }
+ }
+
+ if (read_slash) {
+ pool = fields[0];
+ image = fields[1];
+ // note that if read_at is false, then fields[2] is the empty string,
+ // so this is still correct
+ snap = fields[2];
+ } else {
+ pool = "";
+ image = fields[0];
+ // note that if read_at is false, then fields[1] is the empty string,
+ // so this is still correct
+ snap = fields[1];
+ }
+ return true;
+}
+
+
+static void write(const string &in, string *out) {
+ for (size_t i = 0, n = in.length(); i < n; i++) {
+ char c = in[i];
+ if (c == '@' || c == '/' || c == '\\') {
+ out->push_back('\\');
+ }
+ out->push_back(c);
+ }
+}
+
+string rbd_loc::str() const {
+ string out;
+ if (!pool.empty()) {
+ write(pool, &out);
+ out.push_back('/');
+ }
+ write(image, &out);
+ if (!snap.empty()) {
+ out.push_back('@');
+ write(snap, &out);
+ }
+ return out;
+}
+
+int rbd_loc::compare(const rbd_loc& rhs) const {
+ int c = pool.compare(rhs.pool);
+ if (c) {
+ return c;
+ }
+ c = image.compare(rhs.image);
+ if (c) {
+ return c;
+ }
+ c = snap.compare(rhs.snap);
+ if (c) {
+ return c;
+ }
+ return 0;
+}
+
+bool rbd_loc::operator==(const rbd_loc& rhs) const {
+ return compare(rhs) == 0;
+}
+
+bool rbd_loc::operator<(const rbd_loc& rhs) const {
+ return compare(rhs) < 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) 2014 Adam Crume <adamcrume@gmail.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef _INCLUDED_RBD_REPLAY_RBD_LOC_HPP
+#define _INCLUDED_RBD_REPLAY_RBD_LOC_HPP
+
+#include <string>
+
+namespace rbd_replay {
+
+struct rbd_loc {
+ rbd_loc();
+
+ rbd_loc(std::string pool, std::string image, std::string snap);
+
+ bool parse(std::string name_string);
+
+ std::string str() const;
+
+ int compare(const rbd_loc& rhs) const;
+
+ bool operator==(const rbd_loc& rhs) const;
+
+ bool operator<(const rbd_loc& rhs) const;
+
+ std::string pool;
+
+ std::string image;
+
+ std::string snap;
+};
+
+}
+
+#endif
#include <boost/foreach.hpp>
#include "rbd_replay/Deser.hpp"
#include "rbd_replay/ImageNameMap.hpp"
+#include "rbd_replay/rbd_loc.hpp"
using rbd_replay::ImageNameMap;
using rbd_replay::NameMap;
+using rbd_replay::rbd_loc;
std::ostream& operator<<(std::ostream& o, const ImageNameMap::Name& name) {
return o << "('" << name.first << "', '" << name.second << "')";
EXPECT_EQ("ab_image", m.map("image_ab"));
EXPECT_EQ("asdf", m.map("asdf"));
}
+
+TEST(RBDReplay, rbd_loc_str) {
+ EXPECT_EQ("", rbd_loc("", "", "").str());
+ EXPECT_EQ("a/", rbd_loc("a", "", "").str());
+ EXPECT_EQ("b", rbd_loc("", "b", "").str());
+ EXPECT_EQ("a/b", rbd_loc("a", "b", "").str());
+ EXPECT_EQ("@c", rbd_loc("", "", "c").str());
+ EXPECT_EQ("a/@c", rbd_loc("a", "", "c").str());
+ EXPECT_EQ("b@c", rbd_loc("", "b", "c").str());
+ EXPECT_EQ("a/b@c", rbd_loc("a", "b", "c").str());
+ EXPECT_EQ("a\\@x/b\\@y@c\\@z", rbd_loc("a@x", "b@y", "c@z").str());
+ EXPECT_EQ("a\\/x/b\\/y@c\\/z", rbd_loc("a/x", "b/y", "c/z").str());
+ EXPECT_EQ("a\\\\x/b\\\\y@c\\\\z", rbd_loc("a\\x", "b\\y", "c\\z").str());
+}
+
+TEST(RBDReplay, rbd_loc_parse) {
+ rbd_loc m("x", "y", "z");
+
+ EXPECT_EQ(true, m.parse(""));
+ EXPECT_EQ("", m.pool);
+ EXPECT_EQ("", m.image);
+ EXPECT_EQ("", m.snap);
+
+ EXPECT_EQ(true, m.parse("a/"));
+ EXPECT_EQ("a", m.pool);
+ EXPECT_EQ("", m.image);
+ EXPECT_EQ("", m.snap);
+
+ EXPECT_EQ(true, m.parse("b"));
+ EXPECT_EQ("", m.pool);
+ EXPECT_EQ("b", m.image);
+ EXPECT_EQ("", m.snap);
+
+ EXPECT_EQ(true, m.parse("a/b"));
+ EXPECT_EQ("a", m.pool);
+ EXPECT_EQ("b", m.image);
+ EXPECT_EQ("", m.snap);
+
+ EXPECT_EQ(true, m.parse("@c"));
+ EXPECT_EQ("", m.pool);
+ EXPECT_EQ("", m.image);
+ EXPECT_EQ("c", m.snap);
+
+ EXPECT_EQ(true, m.parse("a/@c"));
+ EXPECT_EQ("a", m.pool);
+ EXPECT_EQ("", m.image);
+ EXPECT_EQ("c", m.snap);
+
+ EXPECT_EQ(true, m.parse("b@c"));
+ EXPECT_EQ("", m.pool);
+ EXPECT_EQ("b", m.image);
+ EXPECT_EQ("c", m.snap);
+
+ EXPECT_EQ(true, m.parse("a/b@c"));
+ EXPECT_EQ("a", m.pool);
+ EXPECT_EQ("b", m.image);
+ EXPECT_EQ("c", m.snap);
+
+ EXPECT_EQ(true, m.parse("a\\@x/b\\@y@c\\@z"));
+ EXPECT_EQ("a@x", m.pool);
+ EXPECT_EQ("b@y", m.image);
+ EXPECT_EQ("c@z", m.snap);
+
+ EXPECT_EQ(true, m.parse("a\\/x/b\\/y@c\\/z"));
+ EXPECT_EQ("a/x", m.pool);
+ EXPECT_EQ("b/y", m.image);
+ EXPECT_EQ("c/z", m.snap);
+
+ EXPECT_EQ(true, m.parse("a\\\\x/b\\\\y@c\\\\z"));
+ EXPECT_EQ("a\\x", m.pool);
+ EXPECT_EQ("b\\y", m.image);
+ EXPECT_EQ("c\\z", m.snap);
+
+ EXPECT_EQ(false, m.parse("a@b@c"));
+ EXPECT_EQ(false, m.parse("a/b/c"));
+ EXPECT_EQ(false, m.parse("a@b/c"));
+}