From 3cfc1643082e60fea72539033b7adb094d236b0a Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Thu, 10 May 2007 22:10:26 -0700 Subject: [PATCH] Add a new object-oriented wrapper for building object references. --- Makefile | 2 +- ref.cc | 57 ++++++++++++++++++++++++++++++++++ ref.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ store.cc | 8 ++--- store.h | 6 ++-- 5 files changed, 156 insertions(+), 10 deletions(-) create mode 100644 ref.cc create mode 100644 ref.h diff --git a/Makefile b/Makefile index 9f6892b..f29d2a7 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CXXFLAGS=-O -Wall -D_FILE_OFFSET_BITS=64 $(DEBUG) \ `pkg-config --cflags $(PACKAGES)` LDFLAGS=$(DEBUG) -ltar `pkg-config --libs $(PACKAGES)` -SRCS=format.cc scandir.cc sha1.cc store.cc +SRCS=format.cc ref.cc scandir.cc sha1.cc store.cc OBJS=$(SRCS:.cc=.o) scandir : $(OBJS) diff --git a/ref.cc b/ref.cc new file mode 100644 index 0000000..e996c7d --- /dev/null +++ b/ref.cc @@ -0,0 +1,57 @@ +/* LBS: An LFS-inspired filesystem backup system + * Copyright (C) 2007 Michael Vrable + * + * Backups are structured as a collection of objects, which may refer to other + * objects. Object references are used to name other objects or parts of them. + * This file defines the class for representing object references and the + * textual representation of these references. */ + +#include +#include +#include + +#include + +#include "ref.h" + +using std::string; + +/* Generate a new UUID, and return the text representation of it. This is + * suitable for generating the name for a new segment. */ +string generate_uuid() +{ + uint8_t uuid[16]; + char buf[40]; + + uuid_generate(uuid); + uuid_unparse_lower(uuid, buf); + return string(buf); +} + + +ObjectReference::ObjectReference(const std::string& segment, int sequence) + : segment(segment) +{ + char seq_buf[64]; + sprintf(seq_buf, "%08x", sequence); + object = seq_buf; + + clear_checksum(); + clear_range(); +} + +string ObjectReference::to_string() const +{ + string result = segment + "/" + object; + + if (checksum_valid) + result += "(" + checksum + ")"; + + if (range_valid) { + char buf[64]; + sprintf(buf, "[%zu+%zu]", range_start, range_length); + result += buf; + } + + return result; +} diff --git a/ref.h b/ref.h new file mode 100644 index 0000000..496fdec --- /dev/null +++ b/ref.h @@ -0,0 +1,93 @@ +/* LBS: An LFS-inspired filesystem backup system + * Copyright (C) 2007 Michael Vrable + * + * Backups are structured as a collection of objects, which may refer to other + * objects. Object references are used to name other objects or parts of them. + * This file defines the class for representing object references and the + * textual representation of these references. */ + +#ifndef _LBS_REF_H +#define _LBS_REF_H + +#include + +/* ======================== Object Reference Syntax ======================== + * + * Segments are groups of objects. Segments are named by UUID, which is a + * 128-bit value. The text representation is + * ::= xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxx + * where each is a lowercase hexadecimal digit ([0-9a-f]). + * + * Each object within a segment is assigned a sequence number, which is given + * as a hexadecimal value: + * ::= xxxxxxxx + * + * An object can be uniquely named by the combination of segment name and + * object sequence number: + * ::= "/" + * Example: "cf47429e-a503-43ac-9c31-bb3175fbb820/0000002b" + * + * An object name may optionally be suffixed with a checksum, which allows + * checking the integrity of the referenced object. + * ::= "=" + * Currently the only checksum-alg is "sha1", but others may be defined later. + * is a hexadecimal string. If included, the checksum is + * enclosed in parentheses. + * + * Each object is stored as a string of bytes, and object reference may specify + * a substring rather than the entire string using a range specifier. If no + * range specifier is given, then by default the entire object is used. + * ::= "+" + * Both and are decimal values. If included, the range is + * enclosed in brackets. + * + * When both a checksum and a range are included, note that the checksum is + * taken over the entire original object, before the range is taken into + * account. + * + * The full syntax for an object reference is: + * + * ::= [ "(" ")" ] [ "[" "]" ] + * Example: "cf47429e-a503-43ac-9c31-bb3175fbb820/0000002b(sha1=b9f5d0a21b8d07356723f041f5463dec892654af)[1024+512]" + * + * Finally, in specific circumstances, and indirect reference may be used. In + * cases where data could be listed directly, instead an object reference can + * be given, prefixed with "@", which indicates that the data stored at the + * referenced object should be treated as being included. + * ::= "@" + */ + +/* Generate a fresh UUID, suitable for use as a segment name. */ +std::string generate_uuid(); + +/* Class representing an object reference, which allows it to be manipulated + * and converted to and from the text representation. */ +class ObjectReference { +public: + ObjectReference(const std::string& segment, int sequence); + + std::string to_string() const; + + std::string get_segment() const { return segment; } + void set_segment(const std::string& segment) { this->segment = segment; } + + bool has_checksum() const { return checksum_valid; } + std::string get_checksum() const { return checksum; } + void clear_checksum() { checksum = ""; checksum_valid = false; } + void set_checksum(const std::string& checksum) + { this->checksum = checksum; checksum_valid = true; } + + bool has_range() const { return range_valid; } + size_t get_range_start() const { return range_start; } + size_t get_range_length() const { return range_length; } + void clear_range() { range_start = range_length = 0; range_valid = false; } + void set_range(size_t start, size_t length) + { range_start = start; range_length = length; range_valid = true; } + +private: + std::string segment, object, checksum; + size_t range_start, range_length; + bool checksum_valid, range_valid; +}; + +#endif // _LBS_REF_H diff --git a/store.cc b/store.cc index 49f002a..0533630 100644 --- a/store.cc +++ b/store.cc @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -21,6 +20,7 @@ #include #include "store.h" +#include "ref.h" using std::list; using std::set; @@ -116,11 +116,7 @@ string TarSegmentStore::write_object(const char *data, size_t len, const if (segments.find(group) == segments.end()) { segment = new segment_info; - uint8_t uuid[16]; - char uuid_buf[40]; - uuid_generate(uuid); - uuid_unparse_lower(uuid, uuid_buf); - segment->name = uuid_buf; + segment->name = generate_uuid(); string filename = path + "/" + segment->name + ".tar"; segment->file = new Tarfile(filename, segment->name); diff --git a/store.h b/store.h index 6906d63..6fec763 100644 --- a/store.h +++ b/store.h @@ -6,8 +6,8 @@ * is built on top of libtar, and represents segments as TAR files and objects * as files within them. */ -#ifndef _LBS_TARSTORE_H -#define _LBS_TARSTORE_H +#ifndef _LBS_STORE_H +#define _LBS_STORE_H #include #include @@ -149,4 +149,4 @@ private: std::set refs; }; -#endif // _LBS_TARSTORE_H +#endif // _LBS_STORE_H -- 2.20.1