Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_fs_fs/structure view on Meta::CPAN
Packing revision properties (format 6+)
---------------------------
Similarly to the revision data, packing will concatenate multiple
revprops into a single file. Since they are mutable data, we put an
upper limit to the size of these files: We will concatenate the data
up to the limit and then use a new file for the following revisions.
The limit can be set and changed at will in the configuration file.
It is 64kB by default. Because a pack file must contain at least one
complete property list, files containing just one revision may exceed
that limit.
Furthermore, pack files can be compressed which saves about 75% of
disk space. A configuration file flag enables the compression; it is
off by default and may be switched on and off at will. The pack size
limit is always applied to the uncompressed data. For this reason,
the default is 256kB while compression has been enabled.
Files are named after their start revision as "<rev>.<counter>" where
counter will be increased whenever we rewrite a pack file due to a
revprop change. The manifest file contains the list of pack file
names, one line for each revision.
Many tools track repository global data in revision properties at
revision 0. To minimize I/O overhead for those applications, we
will never pack that revision, i.e. its data is always being kept
in revprops/0/0.
Pack file format
Top level: <packed container>
We always apply data compression to the pack file - using the
SVN_DELTA_COMPRESSION_LEVEL_NONE level if compression is disabled.
(Note that compression at SVN_DELTA_COMPRESSION_LEVEL_NONE is not
a no-op stream transformation although most of the data will remain
human readable.)
container := header '\n' (revprops)+
header := start_rev '\n' rev_count '\n' (size '\n')+
All numbers in the header are given as ASCII decimals. rev_count
is the number of revisions packed into this container. There must
be exactly as many "size" and serialized "revprops". The "size"
values in the list are the length in bytes of the serialized
revprops of the respective revision.
Writing to packed revprops
The old pack file is being read and the new revprops serialized.
If they fit into the same pack file, a temp file with the new
content gets written and moved into place just like an non-packed
revprop file would. No name change or manifest update required.
If they don't fit into the same pack file, i.e. exceed the pack
size limit, the pack will be split into 2 or 3 new packs just
before and / or after the modified revision.
In the current implementation, they will never be merged again.
To minimize fragmentation, the initial packing process will only
use about 90% of the limit, i.e. leave some room for growth.
When a pack file gets split, its counter is being increased
creating a new file and leaving the old content in place and
available for concurrent readers. Only after the new manifest
file got moved into place, will the old pack files be deleted.
Write access to revprops is being serialized by the global
filesystem write lock. We only need to build a few retries into
the reader code to gracefully handle manifest changes and pack
file deletions.
Node-revision IDs
-----------------
A node-rev ID consists of the following three fields:
node_revision_id ::= node_id '.' copy_id '.' txn_id
At this level, the form of the ID is the same as for BDB - see the
section called "ID's" in <../libsvn_fs_base/notes/structure>.
In order to support efficient lookup of node-revisions by their IDs
and to simplify the allocation of fresh node-IDs during a transaction,
we treat the fields of a node-rev ID in new and interesting ways.
Within a new transaction:
New node-revision IDs assigned within a transaction have a txn-id
field of the form "t<txnid>".
When a new node-id or copy-id is assigned in a transaction, the ID
used is a "_" followed by a base36 number unique to the transaction.
Within a revision:
Within a revision file, node-revs have a txn-id field of the form
"r<rev>/<offset>", to support easy lookup. The <offset> is the (ASCII
decimal) number of bytes from the start of the revision file to the
start of the node-rev.
During the final phase of a commit, node-revision IDs are rewritten
to have repository-wide unique node-ID and copy-ID fields, and to have
"r<rev>/<offset>" txn-id fields.
In Format 3 and above, this uniqueness is done by changing a temporary
id of "_<base36>" to "<base36>-<rev>". Note that this means that the
originating revision of a line of history or a copy can be determined
by looking at the node ID.
In Format 2 and below, the "current" file contains global base36
node-ID and copy-ID counters; during the commit, the counter value is
added to the transaction-specific base36 ID, and the value in
"current" is adjusted.
(It is legal for Format 3 repositories to contain Format 2-style IDs;
this just prevents I/O-less node-origin-rev lookup for those nodes.)
The temporary assignment of node-ID and copy-ID fields has
( run in 0.739 second using v1.01-cache-2.11-cpan-b16cb0d3907 )