1 /* LBS: An LFS-inspired filesystem backup system
2 * Copyright (C) 2007 Michael Vrable
4 * Handling of metadata written to backup snapshots. This manages the writing
5 * of file metadata into new backup snapshots, including breaking the metadata
6 * log apart across separate objects. Eventually this should include unified
7 * handling of the statcache, and re-use of metadata between snapshots.
15 #include "statcache.h"
21 using std::ostringstream;
23 static const size_t LBS_METADATA_BLOCK_SIZE = 65536;
25 /* TODO: Move to header file */
26 void add_segment(const string& segment);
28 MetadataWriter::MetadataWriter(TarSegmentStore *store,
30 const char *snapshot_name,
31 const char *snapshot_scheme)
33 statcache_path = path;
34 statcache_path += "/statcache2";
35 if (snapshot_scheme != NULL)
36 statcache_path = statcache_path + "-" + snapshot_scheme;
37 statcache_tmp_path = statcache_path + "." + snapshot_name;
39 statcache_out = fopen(statcache_tmp_path.c_str(), "w");
40 if (statcache_out == NULL) {
41 fprintf(stderr, "Error opening statcache %s: %m\n",
42 statcache_tmp_path.c_str());
43 throw IOException("Error opening statcache");
50 /* Ensure contents of metadata are flushed to an object. */
51 void MetadataWriter::metadata_flush()
55 ostringstream metadata;
56 for (list<MetadataItem>::iterator i = items.begin();
57 i != items.end(); ++i) {
60 offset += i->text.size();
62 string m = metadata.str();
66 /* Write current metadata information to a new object. */
67 LbsObject *meta = new LbsObject;
68 meta->set_group("metadata");
69 meta->set_data(m.data(), m.size());
73 /* Write a reference to this block in the root. */
74 ObjectReference ref = meta->get_ref();
75 metadata_root << "@" << ref.to_string() << "\n";
76 add_segment(ref.get_segment());
80 /* Write these files out to the statcache, and include a reference to where
81 * the metadata lives (so we can re-use it if it has not changed). */
82 for (list<MetadataItem>::const_iterator i = items.begin();
83 i != items.end(); ++i) {
84 ObjectReference r = ref;
85 r.set_range(i->offset, i->text.size());
87 string refstr = r.to_string();
88 fprintf(statcache_out, "@@%s\n%s", refstr.c_str(), i->text.c_str());
94 void MetadataWriter::add(const string& path, dictionary info)
98 item.text = "path: " + uri_encode(path) + "\n";
99 item.text += encode_dict(info) + "\n";
101 items.push_back(item);
102 chunk_size += item.text.size();
104 if (chunk_size > LBS_METADATA_BLOCK_SIZE)
108 ObjectReference MetadataWriter::close()
111 const string root_data = metadata_root.str();
113 LbsObject *root = new LbsObject;
114 root->set_group("metadata");
115 root->set_data(root_data.data(), root_data.size());
118 add_segment(root->get_ref().get_segment());
120 ObjectReference ref = root->get_ref();
123 fclose(statcache_out);
124 if (rename(statcache_tmp_path.c_str(), statcache_path.c_str()) < 0) {
125 fprintf(stderr, "Error renaming statcache from %s to %s: %m\n",
126 statcache_tmp_path.c_str(), statcache_path.c_str());