using namespace rbd_replay;
-static ImageNameMap::Name bad_mapping_abort(ImageNameMap::Name input, string output) {
- assertf(false, "Bad value returned from mapping. Image: '%s', snap: '%s', output: '%s'", input.first.c_str(), input.second.c_str(), output.c_str());
+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_name("((?:[^@\\\\]|\\\\.)*)@((?:[^@\\\\]|\\\\.)*)"),
- m_escaped_at("\\\\@"),
- m_escaped_backslash("\\\\\\\\"),
- m_at("@"),
- m_backslash("\\\\"),
- m_bad_mapping_fallback(bad_mapping_abort) {
+ : m_bad_mapping_fallback(bad_mapping_abort) {
}
bool ImageNameMap::parse_mapping(string mapping_string, Mapping *mapping) const {
m_map.add_mapping(mapping);
}
-string ImageNameMap::unescape_at(string s) const {
- s = boost::regex_replace(s, m_escaped_at, "@");
- return boost::regex_replace(s, m_escaped_backslash, "\\\\");
-}
-
-string ImageNameMap::escape_at(string s) const {
- string result = boost::regex_replace(s, m_backslash, "\\\\");
- return boost::regex_replace(result, m_at, "\\\\@");
-}
-
-bool ImageNameMap::parse_name(string name_string, Name *name) const {
- boost::smatch what;
- if (boost::regex_match(name_string, what, m_name)) {
- string image(unescape_at(what[1]));
- string snap(unescape_at(what[2]));
- *name = Name(image, snap);
- return true;
- } else {
- return false;
- }
-}
-
-string ImageNameMap::format_name(ImageNameMap::Name name) const {
- return escape_at(name.first) + "@" + escape_at(name.second);
-}
-
-ImageNameMap::Name ImageNameMap::map(ImageNameMap::Name name) const {
- string in_string(format_name(name));
+ImageName ImageNameMap::map(const ImageName& name) const {
+ string in_string(name.str());
string out_string(m_map.map(in_string));
- Name out;
- if (!parse_name(out_string, &out)) {
+ ImageName out;
+ if (!out.parse(out_string)) {
return m_bad_mapping_fallback(name, out_string);
}
return out;
#include <vector>
#include <boost/function.hpp>
#include <boost/regex.hpp>
+#include "ImageName.hpp"
#include "NameMap.hpp"
namespace rbd_replay {
public:
typedef std::pair<boost::regex, std::string> Mapping;
- typedef std::pair<std::string, std::string> Name;
-
- typedef boost::function<Name (Name input, std::string output)> BadMappingFallback;
+ typedef boost::function<rbd_replay::ImageName (const rbd_replay::ImageName& input, std::string output)> BadMappingFallback;
ImageNameMap();
void add_mapping(Mapping mapping);
- bool parse_name(std::string name_string, Name *name) const;
-
- std::string format_name(Name name) const;
-
- Name map(Name name) const;
+ rbd_replay::ImageName map(const rbd_replay::ImageName& name) const;
void set_bad_mapping_fallback(BadMappingFallback bad_mapping_fallback);
private:
- std::string escape_at(std::string s) const;
-
- std::string unescape_at(std::string s) const;
-
NameMap m_map;
- // Split "a@b" into "a" and "b", allowing for escaped at sign
- boost::regex m_name;
-
- // We don't have to worry about an even number of backslahes followed by an at sign,
- // because that at sign would have already been matched and removed.
- boost::regex m_escaped_at;
-
- boost::regex m_escaped_backslash;
-
- boost::regex m_at;
-
- boost::regex m_backslash;
-
BadMappingFallback m_bad_mapping_fallback;
};
return m_replayer.readonly();
}
-pair<string, string> Worker::map_image_name(string image_name, string snap_name) const {
- return m_replayer.image_name_map().map(pair<string,string>(image_name, snap_name));
+ImageName Worker::map_image_name(string image_name, string snap_name) const {
+ return m_replayer.image_name_map().map(ImageName("", image_name, snap_name));
}
bool readonly() const;
- std::pair<std::string, std::string> map_image_name(std::string image_name, std::string snap_name) const;
+ rbd_replay::ImageName 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();
- pair<string, string> name(worker.map_image_name(m_name, m_snap_name));
+ ImageName 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.first.c_str(), name.second.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.first.c_str(), name.second.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
<< "' with snap '" << m_snap_name
- << "' (mapped to '" << name.first
- << "' and '" << name.second
+ << "' (mapped to '" << name.str()
<< "') and readonly " << m_readonly
<< ": (" << -r << ") " << strerror(-r) << std::endl;
exit(1);
#include <boost/shared_ptr.hpp>
#include "include/rbd/librbd.hpp"
#include "Deser.hpp"
+#include "ImageName.hpp"
namespace rbd_replay {
virtual void stop() = 0;
- virtual std::pair<std::string, std::string> map_image_name(std::string image_name, std::string snap_name) const = 0;
+ virtual rbd_replay::ImageName map_image_name(std::string image_name, std::string snap_name) const = 0;
};
cout << std::endl;
cout << "Image mapping rules:" << std::endl;
cout << "A rule of image1@snap1=image2@snap2 would map snap1 of image1 to snap2 of" << std::endl;
- cout << "image2. Regular expressions are used, so image@snap_(.*)=image_$1@ would map" << std::endl;
- cout << "image@snap_1 to image_1@. (Note that an un-snapshotted image has the empty" << std::endl;
- cout << "string for the snapshot name.)" << std::endl;
+ cout << "image2. Regular expressions are used, so image@snap_(.*)=image_$1 would map" << std::endl;
+ cout << "image@snap_1 to image_1." << std::endl;
}
-static ImageNameMap::Name bad_mapping(ImageNameMap::Name input, string output) {
- dout(0) << "Bad value returned from mapping. Image: '" << input.first << "', snap '" << input.second << "', output: '" << output << "'. Using image: '" << output << ", snap ''." << dendl;
- return ImageNameMap::Name(output, "");
+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) {
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 << "')";
+std::ostream& operator<<(std::ostream& o, const ImageName& name) {
+ return o << "('" << name.pool() << "', '" << name.image() << "', '" << name.snap() << "')";
}
-static ImageNameMap::Name bad_mapping(ImageNameMap::Name input, std::string output) {
- return ImageNameMap::Name("xxx", "xxx");
+static ImageName bad_mapping(ImageName input, std::string output) {
+ return ImageName("xxx", "xxx", "xxx");
}
static void add_mapping(ImageNameMap *map, std::string mapping_string) {
}
TEST(RBDReplay, ImageNameMap) {
- typedef ImageNameMap::Name Name;
ImageNameMap m;
m.set_bad_mapping_fallback(bad_mapping);
add_mapping(&m, "x@y=y@x");
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(Name("y", "x"), m.map(Name("x", "y")));
- EXPECT_EQ(Name("h", "i"), m.map(Name("a=b", "c")));
- EXPECT_EQ(Name("j", "k"), m.map(Name("a", "b=c")));
- EXPECT_EQ(Name("d", "e"), m.map(Name("a@b", "c")));
- EXPECT_EQ(Name("f", "g"), m.map(Name("a", "b@c")));
- EXPECT_EQ(Name("image_1", ""), m.map(Name("image", "snap_1")));
- EXPECT_EQ(Name("xxx", "xxx"), m.map(Name("bad", "")));
+ 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) {