Initial refactoring of metadata logging.
[cumulus.git] / metadata.cc
1 /* LBS: An LFS-inspired filesystem backup system
2  * Copyright (C) 2007  Michael Vrable
3  *
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.
8  */
9
10 #include <string>
11 #include <iostream>
12
13 #include "metadata.h"
14 #include "store.h"
15 #include "statcache.h"
16 #include "util.h"
17
18 using std::string;
19 using std::ostream;
20
21 static const size_t LBS_METADATA_BLOCK_SIZE = 65536;
22
23 /* TODO: Move to header file */
24 void add_segment(const string& segment);
25
26 MetadataWriter::MetadataWriter(TarSegmentStore *store)
27 {
28     this->store = store;
29 }
30
31 /* Ensure contents of metadata are flushed to an object. */
32 void MetadataWriter::metadata_flush()
33 {
34     string m = metadata.str();
35     if (m.size() == 0)
36         return;
37
38     /* Write current metadata information to a new object. */
39     LbsObject *meta = new LbsObject;
40     meta->set_group("metadata");
41     meta->set_data(m.data(), m.size());
42     meta->write(store);
43     meta->checksum();
44
45     /* Write a reference to this block in the root. */
46     ObjectReference ref = meta->get_ref();
47     metadata_root << "@" << ref.to_string() << "\n";
48     add_segment(ref.get_segment());
49
50     delete meta;
51
52     metadata.str("");
53 }
54
55 void MetadataWriter::add(const string& path, dictionary info)
56 {
57     metadata << "path: " << uri_encode(path) << "\n";
58     metadata << encode_dict(info);
59     metadata << "\n";
60
61     if (metadata.str().size() > LBS_METADATA_BLOCK_SIZE)
62         metadata_flush();
63 }
64
65 ObjectReference MetadataWriter::close()
66 {
67     metadata_flush();
68     const string root_data = metadata_root.str();
69
70     LbsObject *root = new LbsObject;
71     root->set_group("metadata");
72     root->set_data(root_data.data(), root_data.size());
73     root->write(store);
74     root->checksum();
75     add_segment(root->get_ref().get_segment());
76
77     ObjectReference ref = root->get_ref();
78     delete root;
79     return ref;
80 }