X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=metadata.cc;h=c27278bccb14ce539064eb0d72de766e039de611;hb=722040937d7709a7b976bf57b045dac6d703c893;hp=2517d7341fb1b9d5c4b04402a750d65123ed8836;hpb=bae7cf459803abce603c8b3d3009153936378b42;p=cumulus.git diff --git a/metadata.cc b/metadata.cc index 2517d73..c27278b 100644 --- a/metadata.cc +++ b/metadata.cc @@ -9,6 +9,7 @@ #include #include +#include #include "metadata.h" #include "ref.h" @@ -16,6 +17,7 @@ #include "util.h" using std::list; +using std::map; using std::string; using std::ostream; using std::ostringstream; @@ -63,6 +65,27 @@ static int pathcmp(const char *path1, const char *path2) return pathcmp(slash1 + 1, slash2 + 1); } +/* Encode a dictionary of string key/value pairs into a sequence of lines of + * the form "key: value". If it exists, the key "name" is treated specially + * and will be listed first. */ +static string encode_dict(const map& dict) +{ + string result; + + if (dict.find("name") != dict.end()) { + result += "name: " + dict.at("name") + "\n"; + } + + for (map::const_iterator i = dict.begin(); + i != dict.end(); ++i) { + if (i->first == "name") + continue; + result += i->first + ": " + i->second + "\n"; + } + + return result; +} + MetadataWriter::MetadataWriter(TarSegmentStore *store, const char *path, const char *snapshot_name, @@ -83,7 +106,6 @@ MetadataWriter::MetadataWriter(TarSegmentStore *store, throw IOException("Error opening statcache"); } - found_match = false; old_metadata_eof = false; this->store = store; @@ -162,30 +184,27 @@ bool MetadataWriter::find(const string& path) { const char *path_str = path.c_str(); while (!old_metadata_eof) { - string old_path = uri_decode(old_metadata["path"]); + string old_path = uri_decode(old_metadata["name"]); int cmp = pathcmp(old_path.c_str(), path_str); - if (cmp == 0) { - found_match = true; + if (cmp == 0) return true; - } else if (cmp > 0) { - found_match = false; + else if (cmp > 0) return false; - } else { + else read_statcache(); - } } - found_match = false; return false; } /* Does a file appear to be unchanged from the previous time it was backed up, - * based on stat information? - * - * TODO: Notice files that were modified as they were being backed up the last - * time. */ + * based on stat information? */ bool MetadataWriter::is_unchanged(const struct stat *stat_buf) { + if (old_metadata.find("volatile") != old_metadata.end() + && parse_int(old_metadata["volatile"]) != 0) + return false; + if (old_metadata.find("ctime") == old_metadata.end()) return false; if (stat_buf->st_ctime != parse_int(old_metadata["ctime"])) @@ -233,11 +252,9 @@ list MetadataWriter::get_blocks() s++; } - ObjectReference *r = ObjectReference::parse(ref); - if (r != NULL) { - blocks.push_back(*r); - delete r; - } + ObjectReference r = ObjectReference::parse(ref); + if (!r.is_null()) + blocks.push_back(r); } return blocks; @@ -252,6 +269,11 @@ void MetadataWriter::metadata_flush() ObjectReference indirect; for (list::iterator i = items.begin(); i != items.end(); ++i) { + // If indirectly referencing any other metadata logs, be sure those + // segments are properly referenced. + if (i->reused) + add_segment(i->ref.get_segment()); + // Write out an indirect reference to any previous objects which could // be reused if (!i->reused || !indirect.merge(i->ref)) { @@ -327,11 +349,10 @@ void MetadataWriter::add(dictionary info) item.text += encode_dict(info) + "\n"; if (info == old_metadata) { - ObjectReference *ref = ObjectReference::parse(old_metadata_loc); - if (ref != NULL) { + ObjectReference ref = ObjectReference::parse(old_metadata_loc); + if (!ref.is_null()) { item.reused = true; - item.ref = *ref; - delete ref; + item.ref = ref; } }