Initial support for objects encapsulated into segments.
[cumulus.git] / store.h
1 /* LBS: An LFS-inspired filesystem backup system
2  * Copyright (C) 2006  Michael Vrable
3  *
4  * Backup data is stored in a collection of objects, which are grouped together
5  * into segments for storage purposes.  This file provides interfaces for
6  * reading and writing objects and segments. */
7
8 #ifndef _LBS_STORE_H
9 #define _LBS_STORE_H
10
11 #include <stdint.h>
12
13 #include <exception>
14 #include <map>
15 #include <string>
16 #include <sstream>
17 #include <vector>
18
19 /* In memory datatype to represent key/value pairs of information, such as file
20  * metadata.  Currently implemented as map<string, string>. */
21 typedef std::map<std::string, std::string> dictionary;
22
23 /* IOException will be thrown if an error occurs while reading or writing in
24  * one of the I/O wrappers.  Depending upon the context; this may be fatal or
25  * not--typically, errors reading/writing the store will be serious, but errors
26  * reading an individual file are less so. */
27 class IOException : public std::exception {
28 private:
29     std::string error;
30 public:
31     explicit IOException(const std::string &err) { error = err; }
32     virtual ~IOException() throw () { }
33     std::string getError() const { return error; }
34 };
35
36 /* OutputStream is an abstract interface for writing data without seeking.
37  * Output could be to a file, to an object within a segment, or even to a
38  * memory buffer to help serialize data. */
39 class OutputStream {
40 public:
41     OutputStream();
42     virtual ~OutputStream() { }
43
44     // Write the given data buffer
45     void write(const void *data, size_t len);
46
47     // Return the total number of bytes written so far
48     int64_t get_pos() const { return bytes_written; }
49
50     // Convenience functions for writing other data types.  Values are always
51     // written out in little-endian order.
52     void write_u8(uint8_t val);
53     void write_u16(uint16_t val);
54     void write_u32(uint32_t val);
55     void write_u64(uint64_t val);
56
57     void write_s32(int32_t val) { write_u32((uint32_t)val); }
58     void write_s64(int64_t val) { write_u64((uint64_t)val); }
59
60     void write_varint(uint64_t val);
61
62     void write_string(const std::string &s);
63     void write_dictionary(const dictionary &d);
64
65 protected:
66     // Function which actually causes a write: must be overridden by
67     // implementation.
68     virtual void write_internal(const void *data, size_t len) = 0;
69
70 private:
71     int64_t bytes_written;
72 };
73
74 /* An OutputStream implementation which writes data to memory and returns the
75  * result as a string. */
76 class StringOutputStream : public OutputStream {
77 public:
78     StringOutputStream();
79     std::string contents() const { return buf.str(); }
80
81 protected:
82     virtual void write_internal(const void *data, size_t len);
83
84 private:
85     std::stringstream buf;
86 };
87
88 /* An OutputStream implementation which writes data via the C stdio layer. */
89 class FileOutputStream : public OutputStream {
90 public:
91     explicit FileOutputStream(FILE *file);
92     virtual ~FileOutputStream();
93
94 protected:
95     virtual void write_internal(const void *data, size_t len);
96
97 private:
98     FILE *f;
99 };
100
101 /* An OutputStream which is simply sends writes to another OutputStream, but
102  * does provide separate tracking of bytes written. */
103 class WrapperOutputStream : public OutputStream {
104 public:
105     explicit WrapperOutputStream(OutputStream &o);
106     virtual ~WrapperOutputStream() { }
107
108 protected:
109     virtual void write_internal(const void *data, size_t len);
110
111 private:
112     OutputStream &real;
113 };
114
115 /* Simple wrappers that encode integers using a StringOutputStream and return
116  * the encoded result. */
117 std::string encode_u16(uint16_t val);
118 std::string encode_u32(uint32_t val);
119 std::string encode_u64(uint64_t val);
120
121 struct uuid {
122     uint8_t bytes[16];
123 };
124
125 class SegmentWriter {
126 public:
127     SegmentWriter(OutputStream &output, struct uuid u);
128     ~SegmentWriter();
129
130     struct uuid get_uuid() const { return id; }
131
132     // Start writing out a new object to this segment.
133     OutputStream *new_object();
134     void finish_object();
135
136     // Utility functions for generating and formatting UUIDs for display.
137     static struct uuid generate_uuid();
138     static std::string format_uuid(const struct uuid u);
139
140 private:
141     typedef std::vector<std::pair<int64_t, int64_t> > object_table;
142
143     OutputStream &out;
144     struct uuid id;
145
146     int64_t object_start_offset;
147     OutputStream *object_stream;
148
149     object_table objects;
150 };
151
152 #endif // _LBS_STORE_H