10
This document describes the proposed container format for streaming and
11
storing collections of data in Bazaar. Initially this will be used for
12
streaming revision data for incremental push/pull in the smart server for
13
0.18, but the intention is that this will be the basis for much more
14
than just that use case.
16
In particular, this document currently focuses almost exclusively on the
17
streaming case, and not the on-disk storage case. It also does not
18
discuss the APIs used to manipulate containers and their records.
27
To create a low-level file format which is suitable for solving the smart
28
server latency problem and whose layout and requirements are extendable in
29
future versions of Bazaar, and with no requirements that the smart server
36
A **container** is a streamable file that contains a series of
37
**records**. Records may have **names**, and consist of bytes.
43
Here's a brief description of use cases this format is intended to
46
Streaming data between a smart server and client
47
------------------------------------------------
49
It would be nice if we could combine multiple containers into a single
50
stream by something no more expensive than concatenation (e.g. by omitting
51
end/start marker pairs).
53
This doesn't imply that such a combination necessarily produces a valid
54
container (e.g. care must be taken to ensure that names are still unique
55
in the combined container), or even a useful container. It is simply that
56
the cost of assembling a new combined container is practically as cheap as
59
Incremental push or pull
60
~~~~~~~~~~~~~~~~~~~~~~~~
62
Consider the use case of incremental push/pull, which is currently (0.16)
63
very slow on high-latency links due to the large number of round trips.
64
What we'd like is something like the following.
66
A client will make a request meaning "give me the knit contents for these
67
revision IDs" (how the client determines which revision IDs it needs is
68
unimportant here). In response, the server streams a single container of:
70
* one record per file-id:revision-id knit gzip contents and graph data,
71
* one record per inventory:revision-id knit gzip contents and graph
73
* one record per revision knit gzip contents,
74
* one record per revision signature,
79
Persistent storage on disk
80
--------------------------
82
We want a storage format that allows lock-free writes, which suggests a
83
format that uses *rename into place*, and *do not modify after writing*.
85
Usable before deep model changes to Bazaar
86
------------------------------------------
88
We want a format we can use and refine sooner rather than later. So it
89
should be usable before the anticipated model changes for Bazaar "1.0"
90
land, while not conflicting with those changes either.
92
Specifically, we'd like to have this format in Bazaar 0.18.
94
Examples of possible record content
95
-----------------------------------
97
* full texts of file versions
98
* deltas of full texts
101
* inventory as tree items e.g. the inventory data for 20 files
102
* revision signatures
103
* per-file graph data
110
Some key aspects of the described format are discussed in this section.
112
No length-prefixing of entire container
113
---------------------------------------
115
The overall container is not length-prefixed. Instead there is an end
116
marker so that readers can determine when they have read the entire
117
container. This also does not conflict with the goal of allowing
120
Structured as a self-contained series of records
121
------------------------------------------------
123
The container contains a series of *records*. Each record is
124
self-delimiting. Record markers are lightweight. The overhead in terms
125
of bytes and processing for records in this container vs. the raw contents
126
of those records is minimal.
131
There is a requirement that each object can be given an arbitrary name.
132
Some version control systems address all content by the SHA-1 digest of
133
that content, but this scheme is unsatisfactory for Bazaar's revision
134
objects. We can still allow addressing by SHA-1 digest for those content
135
types where it makes sense.
137
Some proposed object names:
139
* to name a revision: "``revision:``\ *revision-id*". e.g.,
140
`revision:pqm@pqm.ubuntu.com-20070531210833-8ptk86ocu822hjd5`.
141
* to name an inventory delta: "``inventory.delta:``\ *revision-id*". e.g.,
142
`inventory.delta:pqm@pqm.ubuntu.com-20070531210833-8ptk86ocu822hjd5`.
144
It seems likely that we may want to have multiple names for an object.
145
This format allows that (by allowing multiple ``name`` headers in a Bytes
148
Although records are in principle addressable by name, this specification
149
alone doesn't provide for efficient access to a particular record given
150
its name. It is intended that separate indexes will be maintained to
153
It is acceptable to have records with no explicit name, if the expected
154
use of them does not require them. For example:
156
* a record's content could be self-describing in the context of a
157
particular container, or
158
* a record could be accessed via an index based on SHA-1, or
159
* when streaming, the first record could be treated specially.
161
Reasonably cheap for small records
162
----------------------------------
164
The overhead for storing fairly short records (tens of bytes, rather than
165
thousands or millions) is minimal. The minimum overhead is 3 bytes plus
166
the length of the decimal representation of the *length* value (for a
167
record with no name).
173
This describes just a basic layer for storing a simple series of
174
"records". This layer has no intrinsic understanding of the contents of
179
* a **container lead-in**, "``Bazaar pack format 1 (introduced in 0.18)\n``",
180
* followed by one or more **records**.
184
* a 1 byte **kind marker**.
185
* 0 or more bytes of record content, depending on the record type.
193
An **End Marker** record:
195
* has a kind marker of "``E``",
198
End Marker records signal the end of a container.
205
* has a kind marker of "``B``",
206
* followed by a mandatory **content length** [1]_:
207
"*number*\ ``\n``", where *number* is in decimal, e.g::
211
* followed by zero or more optional **names**:
212
"*name*\ ``\n``", e.g.::
214
revision:pqm@pqm.ubuntu.com-20070531210833-8ptk86ocu822hjd5
216
* followed by an **end of headers** byte: "``\n``",
217
* followed by some **bytes**, exactly as many as specified by the length
220
So a Bytes record is a series of lines encoding the length and names (if
221
any) followed by a body.
223
For example, this is a possible Bytes record (including the kind marker)::
229
abcdefghijklmnopqrstuvwxyz
235
Names should be UTF-8 encoded strings, with no whitespace. Names should
236
be unique within a single container, but no guarantee of uniqueness
237
outside of the container is made by this layer. Names need to be at least
241
.. [1] This requires that the writer of a record knows the full length of
242
the record up front, which typically means it will need to buffer an
243
entire record in memory. For the first version of this format this is
244
considered to be acceptable.