*/
#include "ImageNameMap.hpp"
-#include <boost/foreach.hpp>
-#include "include/assert.h"
using namespace std;
using namespace rbd_replay;
-static ImageName bad_mapping_abort(ImageName input, string output) {
- assertf(false, "Bad value returned from mapping. Image: '%s', snap: '%s', output: '%s'", input.image().c_str(), input.snap().c_str(), output.c_str());
-}
-
-ImageNameMap::ImageNameMap()
- : m_bad_mapping_fallback(bad_mapping_abort) {
-}
-
bool ImageNameMap::parse_mapping(string mapping_string, Mapping *mapping) const {
- return m_map.parse_mapping(mapping_string, mapping);
+ string fields[2];
+ int field = 0;
+ for (size_t i = 0, n = mapping_string.length(); i < n; i++) {
+ char c = mapping_string[i];
+ switch (c) {
+ case '\\':
+ if (i != n - 1 && mapping_string[i + 1] == '=') {
+ i++;
+ fields[field].push_back('=');
+ } else {
+ fields[field].push_back('\\');
+ }
+ break;
+ case '=':
+ if (field == 1) {
+ return false;
+ }
+ field = 1;
+ break;
+ default:
+ fields[field].push_back(c);
+ }
+ }
+ if (field == 0) {
+ return false;
+ }
+ if (!mapping->first.parse(fields[0])) {
+ return false;
+ }
+ if (!mapping->second.parse(fields[1])) {
+ return false;
+ }
+ return true;
}
-void ImageNameMap::add_mapping(Mapping mapping) {
- m_map.add_mapping(mapping);
+void ImageNameMap::add_mapping(const Mapping& mapping) {
+ m_map.insert(mapping);
}
-ImageName ImageNameMap::map(const ImageName& name) const {
- string in_string(name.str());
- string out_string(m_map.map(in_string));
- ImageName out;
- if (!out.parse(out_string)) {
- return m_bad_mapping_fallback(name, out_string);
+rbd_loc ImageNameMap::map(const rbd_loc& name) const {
+ std::map<rbd_loc, rbd_loc>::const_iterator p(m_map.find(name));
+ if (p == m_map.end()) {
+ return name;
+ } else {
+ return p->second;
}
- return out;
-}
-
-void ImageNameMap::set_bad_mapping_fallback(BadMappingFallback bad_mapping_fallback) {
- m_bad_mapping_fallback = bad_mapping_fallback;
}
#include <map>
#include <string>
-#include <vector>
-#include <boost/function.hpp>
-#include <boost/regex.hpp>
-#include "ImageName.hpp"
-#include "NameMap.hpp"
+#include "rbd_loc.hpp"
namespace rbd_replay {
class ImageNameMap {
public:
- typedef std::pair<boost::regex, std::string> Mapping;
-
- typedef boost::function<rbd_replay::ImageName (const rbd_replay::ImageName& input, std::string output)> BadMappingFallback;
-
- ImageNameMap();
+ typedef std::pair<rbd_loc, rbd_loc> Mapping;
bool parse_mapping(std::string mapping_string, Mapping *mapping) const;
- void add_mapping(Mapping mapping);
+ void add_mapping(const Mapping& mapping);
- rbd_replay::ImageName map(const rbd_replay::ImageName& name) const;
-
- void set_bad_mapping_fallback(BadMappingFallback bad_mapping_fallback);
+ rbd_loc map(const rbd_loc& name) const;
private:
- NameMap m_map;
-
- BadMappingFallback m_bad_mapping_fallback;
+ std::map<rbd_loc, rbd_loc> m_map;
};
}
librbd_replay_la_SOURCES = rbd_replay/actions.cc \
rbd_replay/Deser.cc \
rbd_replay/ImageNameMap.cc \
- rbd_replay/NameMap.cc \
rbd_replay/PendingIO.cc \
rbd_replay/rbd_loc.cc \
rbd_replay/Replayer.cc
rbd_replay/actions.hpp \
rbd_replay/Deser.hpp \
rbd_replay/ImageNameMap.hpp \
- rbd_replay/NameMap.hpp \
rbd_replay/PendingIO.hpp \
rbd_replay/rbd_loc.hpp \
rbd_replay/rbd_replay_debug.hpp \
+++ /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 "NameMap.hpp"
-#include <boost/foreach.hpp>
-#include "include/assert.h"
-
-
-using namespace std;
-using namespace rbd_replay;
-
-
-bool NameMap::parse_mapping(string mapping_string, Mapping *mapping) const {
- boost::smatch what;
- if (boost::regex_match(mapping_string, what, m_keyval)) {
- string pattern(what[1]);
- string replacement(what[2]);
-
- pattern = boost::regex_replace(pattern, m_escaped_equals, "=");
- replacement = boost::regex_replace(replacement, m_escaped_equals, "=");
-
- *mapping = Mapping(boost::regex(pattern), replacement);
- return true;
- } else {
- return false;
- }
-}
-
-void NameMap::add_mapping(Mapping mapping) {
- m_mappings.push_back(mapping);
-}
-
-string NameMap::map(string name) const {
- BOOST_FOREACH(const Mapping &m, m_mappings) {
- boost::smatch what;
- if (boost::regex_match(name, what, m.first)) {
- return what.format(m.second);
- }
- }
- return name;
-}
+++ /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_NAMEMAP_HPP
-#define _INCLUDED_RBD_REPLAY_NAMEMAP_HPP
-
-#include <map>
-#include <string>
-#include <vector>
-#include <boost/regex.hpp>
-
-namespace rbd_replay {
-
-class NameMap {
-public:
- typedef std::pair<boost::regex, std::string> Mapping;
-
- NameMap()
- : m_keyval("((?:[^=\\\\]|\\\\.)*)=((?:[^=\\\\]|\\\\.)*)"),
- m_escaped_equals("\\\\=") {
- }
-
- bool parse_mapping(std::string mapping_string, Mapping *mapping) const;
-
- void add_mapping(Mapping mapping);
-
- std::string map(std::string name) const;
-
-private:
- std::vector<Mapping> m_mappings;
-
- // Split "a=b" into "a" and "b", allowing for escaped equal signs
- boost::regex m_keyval;
-
- // We don't have to worry about an even number of backslahes followed by an equal sign,
- // because that equal sign would have already been matched and removed.
- boost::regex m_escaped_equals;
-};
-
-}
-
-#endif
return m_replayer.readonly();
}
-ImageName Worker::map_image_name(string image_name, string snap_name) const {
- return m_replayer.image_name_map().map(ImageName("", image_name, snap_name));
+rbd_loc Worker::map_image_name(string image_name, string snap_name) const {
+ return m_replayer.image_name_map().map(rbd_loc("", image_name, snap_name));
}
bool readonly() const;
- rbd_replay::ImageName map_image_name(std::string image_name, std::string snap_name) const;
+ rbd_loc map_image_name(std::string image_name, std::string snap_name) const;
private:
void run();
worker.add_pending(io);
librbd::Image *image = new librbd::Image();
librbd::RBD *rbd = worker.rbd();
- ImageName name(worker.map_image_name(m_name, m_snap_name));
+ rbd_loc name(worker.map_image_name(m_name, m_snap_name));
int r;
if (m_readonly || worker.readonly()) {
- r = rbd->open_read_only(*worker.ioctx(), *image, name.image().c_str(), name.snap().c_str());
+ r = rbd->open_read_only(*worker.ioctx(), *image, name.image.c_str(), name.snap.c_str());
} else {
- r = rbd->open(*worker.ioctx(), *image, name.image().c_str(), name.snap().c_str());
+ r = rbd->open(*worker.ioctx(), *image, name.image.c_str(), name.snap.c_str());
}
if (r) {
cerr << "Unable to open image '" << m_name
#include <boost/shared_ptr.hpp>
#include "include/rbd/librbd.hpp"
#include "Deser.hpp"
-#include "ImageName.hpp"
+#include "rbd_loc.hpp"
namespace rbd_replay {
virtual void stop() = 0;
- virtual rbd_replay::ImageName map_image_name(std::string image_name, std::string snap_name) const = 0;
+ virtual rbd_loc map_image_name(std::string image_name, std::string snap_name) const = 0;
};
cout << "image@snap_1 to image_1." << std::endl;
}
-static ImageName bad_mapping(ImageName input, string output) {
- dout(0) << "Bad value returned from mapping. Input: '" << input.str() << "', output: '" << output << "'. Using image: '" << output << ", snap ''." << dendl;
- return ImageName("", output, "");
-}
-
int main(int argc, const char **argv) {
vector<const char*> args;
float latency_multiplier = 1;
bool readonly = false;
ImageNameMap image_name_map;
- image_name_map.set_bad_mapping_fallback(bad_mapping);
std::string val;
std::ostringstream err;
for (i = args.begin(); i != args.end(); ) {
using rbd_replay::ImageNameMap;
-using rbd_replay::NameMap;
using rbd_replay::rbd_loc;
-std::ostream& operator<<(std::ostream& o, const ImageName& name) {
- return o << "('" << name.pool() << "', '" << name.image() << "', '" << name.snap() << "')";
-}
-
-static ImageName bad_mapping(ImageName input, std::string output) {
- return ImageName("xxx", "xxx", "xxx");
+std::ostream& operator<<(std::ostream& o, const rbd_loc& name) {
+ return o << "('" << name.pool << "', '" << name.image << "', '" << name.snap << "')";
}
static void add_mapping(ImageNameMap *map, std::string mapping_string) {
map->add_mapping(mapping);
}
-static void add_mapping(NameMap *map, std::string mapping_string) {
- NameMap::Mapping mapping;
- if (!map->parse_mapping(mapping_string, &mapping)) {
- ASSERT_TRUE(false) << "Failed to parse mapping string '" << mapping_string << "'";
- }
- map->add_mapping(mapping);
-}
-
TEST(RBDReplay, Deser) {
const char data[] = {1, 2, 3, 4, 0, 0, 0, 5, 'h', 'e', 'l', 'l', 'o', 1, 0};
const std::string s(data, sizeof(data));
TEST(RBDReplay, ImageNameMap) {
ImageNameMap m;
- m.set_bad_mapping_fallback(bad_mapping);
add_mapping(&m, "x@y=y@x");
add_mapping(&m, "a\\=b@c=h@i");
add_mapping(&m, "a@b\\=c=j@k");
- add_mapping(&m, "a\\\\@b@c=d@e");
- add_mapping(&m, "a@b\\\\@c=f@g");
- add_mapping(&m, "image@snap_(.*)=image_$1@");
- add_mapping(&m, "bad=@@@");
- EXPECT_EQ(ImageName("", "y", "x"), m.map(ImageName("", "x", "y")));
- EXPECT_EQ(ImageName("", "h", "i"), m.map(ImageName("", "a=b", "c")));
- EXPECT_EQ(ImageName("", "j", "k"), m.map(ImageName("", "a", "b=c")));
- EXPECT_EQ(ImageName("", "d", "e"), m.map(ImageName("", "a@b", "c")));
- EXPECT_EQ(ImageName("", "f", "g"), m.map(ImageName("", "a", "b@c")));
- EXPECT_EQ(ImageName("", "image_1", ""), m.map(ImageName("", "image", "snap_1")));
- EXPECT_EQ(ImageName("xxx", "xxx", "xxx"), m.map(ImageName("", "bad", "")));
-}
-
-TEST(RBDReplay, NameMap) {
- NameMap m;
- add_mapping(&m, "x=y");
- add_mapping(&m, "image_(.*)=$1_image");
- EXPECT_EQ("y", m.map("x"));
- EXPECT_EQ("ab_image", m.map("image_ab"));
- EXPECT_EQ("asdf", m.map("asdf"));
+ add_mapping(&m, "a\\@b@c=d@e");
+ add_mapping(&m, "a@b\\@c=f@g");
+ add_mapping(&m, "image@snap_1=image_1");
+ ImageNameMap::Mapping mapping;
+ EXPECT_EQ(false, m.parse_mapping("bad=@@@", &mapping));
+ EXPECT_EQ(false, m.parse_mapping("bad==stuff", &mapping));
+ EXPECT_EQ(rbd_loc("", "y", "x"), m.map(rbd_loc("", "x", "y")));
+ EXPECT_EQ(rbd_loc("", "h", "i"), m.map(rbd_loc("", "a=b", "c")));
+ EXPECT_EQ(rbd_loc("", "j", "k"), m.map(rbd_loc("", "a", "b=c")));
+ EXPECT_EQ(rbd_loc("", "d", "e"), m.map(rbd_loc("", "a@b", "c")));
+ EXPECT_EQ(rbd_loc("", "f", "g"), m.map(rbd_loc("", "a", "b@c")));
+ EXPECT_EQ(rbd_loc("", "image_1", ""), m.map(rbd_loc("", "image", "snap_1")));
}
TEST(RBDReplay, rbd_loc_str) {