Ensure metadata file is written prior to calculating checksum.
[cumulus.git] / ref.h
1 /* Cumulus: Efficient Filesystem Backup to the Cloud
2  * Copyright (C) 2007-2008 The Cumulus Developers
3  * See the AUTHORS file for a list of contributors.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 /* Backups are structured as a collection of objects, which may refer to other
21  * objects.  Object references are used to name other objects or parts of them.
22  * This file defines the class for representing object references and the
23  * textual representation of these references. */
24
25 #ifndef _LBS_REF_H
26 #define _LBS_REF_H
27
28 #include <string>
29
30 /* ======================== Object Reference Syntax ========================
31  *
32  * Segments are groups of objects.  Segments are named by UUID, which is a
33  * 128-bit value.  The text representation is
34  *    <segment> ::= xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxx
35  * where each <x> is a lowercase hexadecimal digit ([0-9a-f]).
36  *
37  * Each object within a segment is assigned a sequence number, which is given
38  * as a hexadecimal value:
39  *    <object-seq> ::= xxxxxxxx
40  *
41  * An object can be uniquely named by the combination of segment name and
42  * object sequence number:
43  *    <object-name> ::= <segment> "/" <object-seq>
44  * Example: "cf47429e-a503-43ac-9c31-bb3175fbb820/0000002b"
45  *
46  * An object name may optionally be suffixed with a checksum, which allows
47  * checking the integrity of the referenced object.
48  *    <checksum> ::= <checksum-alg> "=" <checksum-value>
49  * Currently the only checksum-alg is "sha1", but others may be defined later.
50  * <checksum-value> is a hexadecimal string.  If included, the checksum is
51  * enclosed in parentheses.
52  *
53  * Each object is stored as a string of bytes, and object reference may specify
54  * a substring rather than the entire string using a range specifier.  If no
55  * range specifier is given, then by default the entire object is used.
56  *    <range> ::= <start> "+" <length>
57  *                | <length>
58  *                | "=" <length>
59  * Both <start> and <length> are decimal values.  If included, the range is
60  * enclosed in brackets.  As an abbreviation, if <start> is 0 then the range
61  * can be given as just <length> (no "+" needed).  The "=<length>" form asserts
62  * that the underlying object is exactly <length> bytes in size.
63  *
64  * When both a checksum and a range are included, note that the checksum is
65  * taken over the entire original object, before the range is taken into
66  * account.
67  *
68  * The full syntax for an object reference is:
69  *    <object-reference>
70  *      ::= <object-name> [ "(" <checksum> ")" ] [ "[" <range> "]" ]
71  * Example: "cf47429e-a503-43ac-9c31-bb3175fbb820/0000002b(sha1=b9f5d0a21b8d07356723f041f5463dec892654af)[1024+512]"
72  *
73  * Finally, in specific circumstances, and indirect reference may be used.  In
74  * cases where data could be listed directly, instead an object reference can
75  * be given, prefixed with "@", which indicates that the data stored at the
76  * referenced object should be treated as being included.
77  *    <indirect-reference> ::= "@" <object-reference>
78  */
79
80 /* Generate a fresh UUID, suitable for use as a segment name. */
81 std::string generate_uuid();
82
83 /* Class representing an object reference, which allows it to be manipulated
84  * and converted to and from the text representation. */
85 class ObjectReference {
86 public:
87     enum RefType { REF_NULL, REF_ZERO, REF_NORMAL };
88
89     ObjectReference();
90     ObjectReference(RefType t);
91     ObjectReference(const std::string& segment, int sequence);
92     ObjectReference(const std::string& segment, const std::string& sequence);
93
94     bool is_null() const { return type == REF_NULL; }
95     bool is_normal() const { return type == REF_NORMAL; }
96     std::string to_string() const;
97     static ObjectReference parse(const std::string& s);
98
99     std::string get_segment() const { return segment; }
100     std::string get_sequence() const { return object; }
101     std::string get_basename() const { return segment + "/" + object; }
102     ObjectReference base() const { return ObjectReference(segment, object); }
103
104     bool has_checksum() const { return checksum_valid; }
105     std::string get_checksum() const { return checksum; }
106     void clear_checksum() { checksum = ""; checksum_valid = false; }
107     void set_checksum(const std::string& checksum)
108         { this->checksum = checksum; checksum_valid = true; }
109
110     bool has_range() const { return range_valid; }
111     size_t get_range_start() const { return range_start; }
112     size_t get_range_length() const { return range_length; }
113     bool range_is_exact() const { return range_exact; }
114     void clear_range()
115         { range_start = range_length = 0;
116           range_valid = false; range_exact = false; }
117     void set_range(size_t start, size_t length, bool exact = false)
118         { range_start = start; range_length = length;
119           range_valid = true; range_exact = exact; }
120
121     bool merge(ObjectReference ref);
122
123     // Maybe provide non-string implementations?
124     bool operator==(const ObjectReference &x) const
125         { return to_string() == x.to_string(); }
126     bool operator<(const ObjectReference &x) const
127         { return to_string() < x.to_string(); }
128
129 private:
130     RefType type;
131     std::string segment, object, checksum;
132     size_t range_start, range_length;
133     bool checksum_valid, range_valid, range_exact;
134 };
135
136 #endif // _LBS_REF_H