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