From 429a08918c9737313c7d170a00fb0c5ba21042df Mon Sep 17 00:00:00 2001 From: Adam Crume Date: Wed, 6 Aug 2014 16:39:56 -0700 Subject: [PATCH] rbd-replay: Add rbd_replay::rbd_loc Signed-off-by: Adam Crume --- src/rbd_replay/Makefile.am | 2 + src/rbd_replay/rbd_loc.cc | 130 ++++++++++++++++++++++++++++++++++++ src/rbd_replay/rbd_loc.hpp | 46 +++++++++++++ src/test/test_rbd_replay.cc | 79 ++++++++++++++++++++++ 4 files changed, 257 insertions(+) create mode 100644 src/rbd_replay/rbd_loc.cc create mode 100644 src/rbd_replay/rbd_loc.hpp diff --git a/src/rbd_replay/Makefile.am b/src/rbd_replay/Makefile.am index aa9be69c52336..58c7de3070f0b 100644 --- a/src/rbd_replay/Makefile.am +++ b/src/rbd_replay/Makefile.am @@ -4,6 +4,7 @@ librbd_replay_la_SOURCES = rbd_replay/actions.cc \ rbd_replay/ImageNameMap.cc \ rbd_replay/NameMap.cc \ rbd_replay/PendingIO.cc \ + rbd_replay/rbd_loc.cc \ rbd_replay/Replayer.cc librbd_replay_la_LIBADD = $(LIBRBD) \ $(LIBRADOS) \ @@ -16,6 +17,7 @@ noinst_HEADERS += rbd_replay/BoundedBuffer.hpp \ rbd_replay/ImageNameMap.hpp \ rbd_replay/NameMap.hpp \ rbd_replay/PendingIO.hpp \ + rbd_replay/rbd_loc.hpp \ rbd_replay/rbd_replay_debug.hpp \ rbd_replay/Replayer.hpp diff --git a/src/rbd_replay/rbd_loc.cc b/src/rbd_replay/rbd_loc.cc new file mode 100644 index 0000000000000..86c50ae1a70f0 --- /dev/null +++ b/src/rbd_replay/rbd_loc.cc @@ -0,0 +1,130 @@ +// -*- 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 + * + * 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; +} diff --git a/src/rbd_replay/rbd_loc.hpp b/src/rbd_replay/rbd_loc.hpp new file mode 100644 index 0000000000000..fab159ae7157d --- /dev/null +++ b/src/rbd_replay/rbd_loc.hpp @@ -0,0 +1,46 @@ +// -*- 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 + * + * 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 + +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 diff --git a/src/test/test_rbd_replay.cc b/src/test/test_rbd_replay.cc index 66b476f5528cd..e41a6b09a8916 100644 --- a/src/test/test_rbd_replay.cc +++ b/src/test/test_rbd_replay.cc @@ -18,10 +18,12 @@ #include #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 << "')"; @@ -93,3 +95,80 @@ TEST(RBDReplay, NameMap) { 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")); +} -- 2.39.5