+std::string encode_objref(const struct uuid &segment, uint32_t object);
+
+/* A class which is used to pack multiple objects into a single segment, with a
+ * lookup table to quickly locate each object. Call new_object() to get an
+ * OutputStream to which a new object may be written, and optionally
+ * finish_object() when finished writing the current object. Only one object
+ * may be written to a segment at a time; if multiple objects must be written
+ * concurrently, they must be to different segments. */
+class SegmentWriter {
+public:
+ SegmentWriter(OutputStream *output, struct uuid u);
+ ~SegmentWriter();
+
+ struct uuid get_uuid() const { return id; }
+
+ // Start writing out a new object to this segment.
+ OutputStream *new_object(int *id);
+ void finish_object();
+
+ // Determine size of segment data written out so far.
+ size_t get_size() const { return raw_out->get_pos(); }
+
+ // Utility functions for generating and formatting UUIDs for display.
+ static struct uuid generate_uuid();
+ static std::string format_uuid(const struct uuid u);
+
+private:
+ typedef std::vector<std::pair<int64_t, int64_t> > object_table;
+
+ ChecksumOutputStream *out; // Output stream with checksumming enabled
+ OutputStream *raw_out; // Raw output stream, without checksumming
+ struct uuid id;
+
+ int64_t object_start_offset;
+ OutputStream *object_stream;
+
+ object_table objects;
+};
+
+/* A SegmentStore, as the name suggests, is used to store the contents of many
+ * segments. The SegmentStore internally tracks where data should be placed
+ * (such as a local directory or remote storage), and allows new segments to be
+ * easily created as needed. */
+class SegmentStore {
+public:
+ // New segments will be stored in the given directory.
+ SegmentStore(const std::string &path);
+
+ SegmentWriter *new_segment();
+
+private:
+ std::string directory;
+};
+
+/* A SegmentPartitioner helps to divide objects up among a collection of
+ * segments to meet a rough size limit per segment. Like a SegmentWriter, only
+ * one object should be written at a time; however, multiple
+ * SegmentPartitioners can be created using the same base SegmentStore. */
+class SegmentPartitioner {
+public:
+ explicit SegmentPartitioner(SegmentStore *s);
+ ~SegmentPartitioner();
+
+ OutputStream *new_object(struct uuid *uuid, int *id);
+
+private:
+ size_t target_size;
+
+ SegmentStore *store;
+ SegmentWriter *segment;
+ OutputStream *object;
+};