Write out new-style statcache data.
[cumulus.git] / metadata.cc
index 5d30baf..6661f39 100644 (file)
 #include "statcache.h"
 #include "util.h"
 
+using std::list;
 using std::string;
 using std::ostream;
+using std::ostringstream;
 
 static const size_t LBS_METADATA_BLOCK_SIZE = 65536;
 
 /* TODO: Move to header file */
 void add_segment(const string& segment);
 
-MetadataWriter::MetadataWriter(TarSegmentStore *store)
+MetadataWriter::MetadataWriter(TarSegmentStore *store,
+                               const char *path,
+                               const char *snapshot_name,
+                               const char *snapshot_scheme)
 {
+    statcache_path = path;
+    statcache_path += "/statcache2";
+    if (snapshot_scheme != NULL)
+        statcache_path = statcache_path + "-" + snapshot_scheme;
+    statcache_tmp_path = statcache_path + "." + snapshot_name;
+
+    statcache_out = fopen(statcache_tmp_path.c_str(), "w");
+    if (statcache_out == NULL) {
+        fprintf(stderr, "Error opening statcache %s: %m\n",
+                statcache_tmp_path.c_str());
+        throw IOException("Error opening statcache");
+    }
+
     this->store = store;
+    chunk_size = 0;
 }
 
 /* Ensure contents of metadata are flushed to an object. */
 void MetadataWriter::metadata_flush()
 {
+    int offset = 0;
+
+    ostringstream metadata;
+    for (list<MetadataItem>::iterator i = items.begin();
+         i != items.end(); ++i) {
+        metadata << i->text;
+        i->offset = offset;
+        offset += i->text.size();
+    }
     string m = metadata.str();
     if (m.size() == 0)
         return;
@@ -49,16 +77,31 @@ void MetadataWriter::metadata_flush()
 
     delete meta;
 
-    metadata.str("");
+    /* Write these files out to the statcache, and include a reference to where
+     * the metadata lives (so we can re-use it if it has not changed). */
+    for (list<MetadataItem>::const_iterator i = items.begin();
+         i != items.end(); ++i) {
+        ObjectReference r = ref;
+        r.set_range(i->offset, i->text.size());
+
+        string refstr = r.to_string();
+        fprintf(statcache_out, "@@%s\n%s", refstr.c_str(), i->text.c_str());
+    }
+
+    items.clear();
 }
 
 void MetadataWriter::add(const string& path, dictionary info)
 {
-    metadata << "path: " << uri_encode(path) << "\n";
-    metadata << encode_dict(info);
-    metadata << "\n";
+    MetadataItem item;
+    item.offset = 0;
+    item.text = "path: " + uri_encode(path) + "\n";
+    item.text += encode_dict(info) + "\n";
 
-    if (metadata.str().size() > LBS_METADATA_BLOCK_SIZE)
+    items.push_back(item);
+    chunk_size += item.text.size();
+
+    if (chunk_size > LBS_METADATA_BLOCK_SIZE)
         metadata_flush();
 }
 
@@ -76,5 +119,12 @@ ObjectReference MetadataWriter::close()
 
     ObjectReference ref = root->get_ref();
     delete root;
+
+    fclose(statcache_out);
+    if (rename(statcache_tmp_path.c_str(), statcache_path.c_str()) < 0) {
+        fprintf(stderr, "Error renaming statcache from %s to %s: %m\n",
+                statcache_tmp_path.c_str(), statcache_path.c_str());
+    }
+
     return ref;
 }