]> arthur.barton.de Git - bup.git/blob - DESIGN
Update base_version to 0.34~ for 0.34 development
[bup.git] / DESIGN
1
2 The Crazy Hacker's Crazy Guide to Bup Craziness
3 ===============================================
4
5 Despite what you might have heard, bup is not that crazy, and neither are
6 you if you're trying to figure out how it works.  But it's also (as of this
7 writing) rather new and the source code doesn't have a lot of comments, so
8 it can be a little confusing at first glance.  This document is designed to
9 make it easier for you to get started if you want to add a new feature, fix
10 a bug, or just understand how it all works.
11
12
13 Bup Source Code Layout
14 ----------------------
15
16 As you're reading this, you might want to look at different parts of the bup
17 source code to follow along and see what we're talking about.  bup's code is
18 written primarily in python with a bit of C code in speed-sensitive places. 
19 Here are the most important things to know:
20
21  - The main program is a fairly small C program that mostly just
22    initializes the correct Python interpreter and then runs
23    bup.main.main().  This arrangement was chosen in order to give us
24    more flexibility.  For example:
25
26      - It allows us to avoid
27        [crashing on some Unicode-unfriendly command line arguments](https://bugs.python.org/issue35883)
28        which is critical, given that paths can be arbitrary byte
29        sequences.
30
31      - It allows more flexibility in dealing with upstream changes
32        like the breakage of our ability to manipulate the
33        processes arguement list on platforms that support it during
34        the Python 3.9 series.
35
36      - It means that we'll no longer be affected by any changes to the
37        `#!/...` path, i.e. if `/usr/bin/python`, or
38        `/usr/bin/python3`, or whatever we'd previously selected during
39        `./configure` were to change from 2 to 3, or 3.5 to 3.20.
40
41    The version of python bup uses is determined by the `python-config`
42    program selected by `./configure`.  It tries to find a suitable
43    default unless `BUP_PYTHON_CONFIG` is set in the environment.
44
45  - bup supports both internal and external subcommands.  The former
46    are the most common, and are all located in lib/bup/cmd/.  They
47    must be python modules named lib/bup/cmd/COMMAND.py, and must
48    contain a `main(argv)` function that will be passed the *binary*
49    command line arguments (bytes, not strings).  The filename must
50    have underscores for any dashes in the subcommand name.  The
51    external subcommands are in lib/cmd/.
52
53  - The python code is all in lib/bup.
54
55  - lib/bup/\*.py contains the python code (modules) that bup depends on.
56    That directory name seems a little silly (and worse, redundant) but there
57    seemed to be no better way to let programs write "from bup import
58    index" and have it work.  Putting bup in the top level conflicted with
59    the 'bup' command; calling it anything other than 'bup' was fundamentally
60    wrong, and doesn't work when you install bup on your system in /usr/lib
61    somewhere.  So we get the annoyingly long paths.
62
63
64 Repository Structure
65 ====================
66
67 Before you can talk about how bup works, we need to first address what it
68 does.  The purpose of bup is essentially to let you "replicate" data between
69 two main data structures:
70
71 1. Your computer's filesystem;
72
73 2. A bup repository. (Yes, we know, that part also resides in your
74    filesystem.  Stop trying to confuse yourself.  Don't worry, we'll be
75    plenty confusing enough as it is.)
76
77 Essentially, copying data from the filesystem to your repository is called
78 "backing stuff up," which is what bup specializes in.  Normally you initiate
79 a backup using the 'bup save' command, but that's getting ahead of
80 ourselves.
81
82 For the inverse operation, ie. copying from the repository to your
83 filesystem, you have several choices; the main ones are 'bup restore', 'bup
84 ftp', 'bup fuse', and 'bup web'.
85
86 Now, those are the basics of backups.  In other words, we just spent about
87 half a page telling you that bup backs up and restores data.  Are we having
88 fun yet?
89
90 The next thing you'll want to know is the format of the bup repository,
91 because hacking on bup is rather impossible unless you understand that part. 
92 In short, a bup repository is a git repository.  If you don't know about
93 git, you'll want to read about it now.  A really good article to read is
94 "Git for Computer Scientists" - you can find it in Google.  Go read it now. 
95 We'll wait.
96
97 Got it?  Okay, so now you're an expert in blobs, trees, commits, and refs,
98 the four building blocks of a git repository.  bup uses these four things,
99 and they're formatted in exactly the same way as git does it, so you can use
100 git to manipulate the bup repository if you want, and you probably won't
101 break anything.  It's also a comfort to know you can squeeze data out using
102 git, just in case bup fails you, and as a developer, git offers some nice
103 tools (like 'git rev-list' and 'git log' and 'git diff' and 'git show' and
104 so on) that allow you to explore your repository and help debug when things
105 go wrong.
106
107 Now, bup does use these tools a little bit differently than plain git.  We
108 need to do this in order to address two deficiencies in git when used for
109 large backups, namely a) git bogs down and crashes if you give it really
110 large files; b) git is too slow when you give it too many files; and c) git
111 doesn't store detailed filesystem metadata.
112
113 Let's talk about each of those problems in turn.
114
115
116 Handling large files (cmd/split, hashsplit.split_to_blob_or_tree)
117 --------------------
118
119 The primary reason git can't handle huge files is that it runs them through
120 xdelta, which generally means it tries to load the entire contents of a file
121 into memory at once.  If it didn't do this, it would have to store the
122 entire contents of every single revision of every single file, even if you
123 only changed a few bytes of that file.  That would be a terribly inefficient
124 use of disk space, and git is well known for its amazingly efficient
125 repository format.
126
127 Unfortunately, xdelta works great for small files and gets amazingly slow
128 and memory-hungry for large files.  For git's main purpose, ie. managing
129 your source code, this isn't a problem.  But when backing up your
130 filesystem, you're going to have at least a few large files, and so it's a
131 non-starter.  bup has to do something totally different.
132
133 What bup does instead of xdelta is what we call "hashsplitting."  We wanted
134 a general-purpose way to efficiently back up *any* large file that might
135 change in small ways, without storing the entire file every time.  In fact,
136 the original versions of bup could only store a single file at a time;
137 surprisingly enough, this was enough to give us a large part of bup's
138 functionality.  If you just take your entire filesystem and put it in a
139 giant tarball each day, then send that tarball to bup, bup will be able to
140 efficiently store only the changes to that tarball from one day to the next. 
141 For small files, bup's compression won't be as good as xdelta's, but for
142 anything over a few megabytes in size, bup's compression will actually
143 *work*, which is a big advantage over xdelta.
144
145 How does hashsplitting work?  It's deceptively simple.  We read through the
146 file one byte at a time, calculating a rolling checksum of the last 64
147 bytes.  (Why 64?  No reason.  Literally.  We picked it out of the air.
148 Probably some other number is better.  Feel free to join the mailing list
149 and tell us which one and why.)  (The rolling checksum idea is actually
150 stolen from rsync and xdelta, although we use it differently.  And they use
151 some kind of variable window size based on a formula we don't totally
152 understand.)
153
154 The original rolling checksum algorithm we used was called "stupidsum,"
155 because it was based on the only checksum Avery remembered how to calculate at
156 the time.  He also remembered that it was the introductory checksum
157 algorithm in a whole article about how to make good checksums that he read
158 about 15 years ago, and it was thoroughly discredited in that article for
159 being very stupid.  But, as so often happens, Avery couldn't remember any
160 better algorithms from the article.  So what we got is stupidsum.
161
162 Since then, we have replaced the stupidsum algorithm with what we call
163 "rollsum," based on code in librsync.  It's essentially the same as what
164 rsync does, except we use a fixed window size.
165
166 (If you're a computer scientist and can demonstrate that some other rolling
167 checksum would be faster and/or better and/or have fewer screwy edge cases,
168 we need your help!  Avery's out of control!  Join our mailing list!  Please! 
169 Save us! ...  oh boy, I sure hope he doesn't read this)
170
171 In any case, rollsum seems to do pretty well at its job. 
172 You can find it in bupsplit.c.  Basically, it converts the last 64 bytes
173 read into a 32-bit integer.  What we then do is take the lowest 13
174 bits of the rollsum, and if they're all 1's, we consider that to be the end
175 of a chunk.  This happens on average once every 2^13 = 8192 bytes, so the
176 average chunk size is 8192 bytes.
177
178 (Why 13 bits?  Well, we picked the number at random and... eugh.  You're
179 getting the idea, right?  Join the mailing list and tell us why we're
180 wrong.)
181
182 (Incidentally, even though the average chunk size is 8192 bytes, the actual
183 probability distribution of block sizes ends up being non-uniform; if we
184 remember our stats classes correctly, which we probably don't, it's probably
185 an "exponential distribution."  The idea is that for each byte in the block,
186 the probability that it's the last block is one in 8192.  Thus, the
187 block sizes end up being skewed toward the smaller end.  That's not
188 necessarily for the best, but maybe it is.  Computer science to the rescue? 
189 You know the drill.)
190
191 Anyway, so we're dividing up those files into chunks based on the rolling
192 checksum.  Then we store each chunk separately (indexed by its sha1sum) as a
193 git blob.  Why do we split this way?  Well, because the results are actually
194 really nice.  Let's imagine you have a big mysql database dump (produced by
195 mysqldump) and it's basically 100 megs of SQL text.  Tomorrow's database
196 dump adds 100 rows to the middle of the file somewhere, soo it's 100.01 megs
197 of text.
198
199 A naive block splitting algorithm - for example, just dividing the file into
200 8192-byte blocks - would be a disaster.  After the first bit of text has
201 changed, every block after that would have a different boundary, so most of
202 the blocks in the new backup would be different from the previous ones, and
203 you'd have to store the same data all over again.  But with hashsplitting,
204 no matter how much data you add, modify, or remove in the middle of the
205 file, all the chunks *before* and *after* the affected chunk are absolutely
206 the same.  All that matters to the hashsplitting algorithm is the
207 "separator" sequence, and a single change can only affect, at most, one
208 separator sequence or the bytes between two separator sequences.  And
209 because of rollsum, about one in 8192 possible 64-byte sequences is a
210 separator sequence.  Like magic, the hashsplit chunking algorithm will chunk
211 your file the same way every time, even without knowing how it had chunked
212 it previously.
213
214 The next problem is less obvious: after you store your series of chunks as
215 git blobs, how do you store their sequence?  Each blob has a 20-byte sha1
216 identifier, which means the simple list of blobs is going to be 20/8192 =
217 0.25% of the file length.  For a 200GB file, that's 488 megs of just
218 sequence data.
219
220 As an overhead percentage, 0.25% basically doesn't matter.  488 megs sounds
221 like a lot, but compared to the 200GB you have to store anyway, it's
222 irrelevant.  What *is* relevant is that 488 megs is a lot of memory you have
223 to use in order to keep track of the list.  Worse, if you back up an
224 almost-identical file tomorrow, you'll have *another* 488 meg blob to keep
225 track of, and it'll be almost but not quite the same as last time.
226
227 Hmm, big files, each one almost the same as the last... you know where this
228 is going, right?
229
230 Actually no!  Ha!  We didn't split this list in the same way.  We could
231 have, in fact, but it wouldn't have been very "git-like", since we'd like to
232 store the list as a git 'tree' object in order to make sure git's
233 refcounting and reachability analysis doesn't get confused.  Never mind the
234 fact that we want you to be able to 'git checkout' your data without any
235 special tools.
236
237 What we do instead is we extend the hashsplit algorithm a little further
238 using what we call "fanout." Instead of checking just the last 13 bits of
239 the checksum, we use additional checksum bits to produce additional splits.
240 Note that (most likely due to an implementation bug), the next higher bit
241 after the 13 bits (marked 'x'):
242
243   ...... '..x1'1111'1111'1111
244
245 is actually ignored next. Now, let's say we use a 4-bit fanout. That means
246 we'll break a series of chunks into its own tree object whenever the next
247 4 bits of the rolling checksum are 1, in addition to the 13 lowest ones.
248 Since the 13 lowest bits already have to be 1, the boundary of a group of
249 chunks is necessarily also always the boundary of a particular chunk.
250
251 And so on.  Eventually you'll have too many chunk groups, but you can group
252 them into supergroups by using another 4 bits, and continue from there.
253
254 What you end up with is an actual tree of blobs - which git 'tree' objects
255 are ideal to represent.  And if you think about it, just like the original
256 list of chunks, the tree itself is pretty stable across file modifications. 
257 Any one modification will only affect the chunks actually containing the
258 modifications, thus only the groups containing those chunks, and so on up
259 the tree.  Essentially, the number of changed git objects is O(log n)
260 where n is the number of chunks.  Since log 200 GB, using a base of 16 or
261 so, is not a very big number, this is pretty awesome.  Remember, any git
262 object we *don't* change in a new backup is one we can reuse from last time,
263 so the deduplication effect is pretty awesome.
264
265 Better still, the hashsplit-tree format is good for a) random instead of
266 sequential access to data (which you can see in action with 'bup fuse'); and
267 b) quickly showing the differences between huge files (which we haven't
268 really implemented because we don't need it, but you can try 'git diff -M -C
269 -C backup1 backup2 -- filename' for a good start).
270
271 So now we've split out 200 GB file into about 24 million pieces.  That
272 brings us to git limitation number 2.
273
274
275 Handling huge numbers of files (git.PackWriter)
276 ------------------------------
277
278 git is designed for handling reasonably-sized repositories that change
279 relatively infrequently.  (You might think you change your source code
280 "frequently" and that git handles much more frequent changes than, say, svn
281 can handle.  But that's not the same kind of "frequently" we're talking
282 about.  Imagine you're backing up all the files on your disk, and one of
283 those files is a 100 GB database file with hundreds of daily users.  Your
284 disk changes so frequently you can't even back up all the revisions even if
285 you were backing stuff up 24 hours a day.  That's "frequently.")
286
287 git's way of doing things works really nicely for the way software
288 developers write software, but it doesn't really work so well for everything
289 else.  The #1 killer is the way it adds new objects to the repository: it
290 creates one file per blob.  Then you later run 'git gc' and combine those
291 files into a single file (using highly efficient xdelta compression, and
292 ignoring any files that are no longer relevant).
293
294 'git gc' is slow, but for source code repositories, the resulting
295 super-efficient storage (and associated really fast access to the stored
296 files) is worth it.  For backups, it's not; you almost never access your
297 backed-up data, so storage time is paramount, and retrieval time is mostly
298 unimportant.
299
300 To back up that 200 GB file with git and hashsplitting, you'd have to create
301 24 million little 8k files, then copy them into a 200 GB packfile, then
302 delete the 24 million files again.  That would take about 400 GB of disk
303 space to run, require lots of random disk seeks, and require you to go
304 through your data twice.
305
306 So bup doesn't do that.  It just writes packfiles directly.  Luckily, these
307 packfiles are still git-formatted, so git can happily access them once
308 they're written.
309
310 But that leads us to our next problem.
311
312
313 Huge numbers of huge packfiles (midx.py, bloom.py, cmd/midx, cmd/bloom)
314 ------------------------------
315
316 Git isn't actually designed to handle super-huge repositories.  Most git
317 repositories are small enough that it's reasonable to merge them all into a
318 single packfile, which 'git gc' usually does eventually.
319
320 The problematic part of large packfiles isn't the packfiles themselves - git
321 is designed to expect the total size of all packs to be larger than
322 available memory, and once it can handle that, it can handle virtually any
323 amount of data about equally efficiently.  The problem is the packfile
324 indexes (.idx) files.  In bup we call these idx (pronounced "idix") files
325 instead of using the word "index," because the word index is already used
326 for something totally different in git (and thus bup) and we'll become
327 hopelessly confused otherwise.
328
329 Anyway, each packfile (*.pack) in git has an associated idx (*.idx) that's a
330 sorted list of git object hashes and file offsets.  If you're looking for a
331 particular object based on its sha1, you open the idx, binary search it to
332 find the right hash, then take the associated file offset, seek to that
333 offset in the packfile, and read the object contents.
334
335 The performance of the binary search is about O(log n) with the number of
336 hashes in the pack, with an optimized first step (you can read about it
337 elsewhere) that somewhat improves it to O(log(n)-7).
338
339 Unfortunately, this breaks down a bit when you have *lots* of packs.  Say
340 you have 24 million objects (containing around 200 GB of data) spread across
341 200 packfiles of 1GB each.  To look for an object requires you search
342 through about 122000 objects per pack; ceil(log2(122000)-7) = 10, so you'll
343 have to search 10 times.  About 7 of those searches will be confined to a
344 single 4k memory page, so you'll probably have to page in about 3-4 pages
345 per file, times 200 files, which makes 600-800 4k pages (2.4-3.6 megs)...
346 every single time you want to look for an object.
347
348 This brings us to another difference between git's and bup's normal use
349 case.  With git, there's a simple optimization possible here: when looking
350 for an object, always search the packfiles in MRU (most recently used)
351 order.  Related objects are usually clusted together in a single pack, so
352 you'll usually end up searching around 3 pages instead of 600, which is a
353 tremendous improvement.  (And since you'll quickly end up swapping in all
354 the pages in a particular idx file this way, it isn't long before searching
355 for a nearby object doesn't involve any swapping at all.)
356
357 bup isn't so lucky.  git users spend most of their time examining existing
358 objects (looking at logs, generating diffs, checking out branches), which
359 lends itself to the above optimization.  bup, on the other hand, spends most
360 of its time looking for *nonexistent* objects in the repository so that it
361 can back them up.  When you're looking for objects that aren't in the
362 repository, there's no good way to optimize; you have to exhaustively check
363 all the packs, one by one, to ensure that none of them contain the data you
364 want.
365
366 To improve performance of this sort of operation, bup introduces midx
367 (pronounced "midix" and short for "multi-idx") files.  As the name implies,
368 they index multiple packs at a time.
369
370 Imagine you had a midx file for your 200 packs.  midx files are a lot like
371 idx files; they have a lookup table at the beginning that narrows down the
372 initial search, followed by a binary search.  Then unlike idx files (which
373 have a fixed-size 256-entry lookup table) midx tables have a variably-sized
374 table that makes sure the entire binary search can be contained to a single
375 page of the midx file.  Basically, the lookup table tells you which page to
376 load, and then you binary search inside that page.  A typical search thus
377 only requires the kernel to swap in two pages, which is better than results
378 with even a single large idx file.  And if you have lots of RAM, eventually
379 the midx lookup table (at least) will end up cached in memory, so only a
380 single page should be needed for each lookup.
381
382 You generate midx files with 'bup midx'.  The downside of midx files is that
383 generating one takes a while, and you have to regenerate it every time you
384 add a few packs.
385
386 UPDATE: Brandon Low contributed an implementation of "bloom filters", which
387 have even better characteristics than midx for certain uses.  Look it up in
388 Wikipedia.  He also massively sped up both midx and bloom by rewriting the
389 key parts in C.  The nicest thing about bloom filters is we can update them
390 incrementally every time we get a new idx, without regenerating from
391 scratch.  That makes the update phase much faster, and means we can also get
392 away with generating midxes less often.
393
394 midx files are a bup-specific optimization and git doesn't know what to do
395 with them.  However, since they're stored as separate files, they don't
396 interfere with git's ability to read the repository.
397
398
399 Detailed Metadata
400 -----------------
401
402 So that's the basic structure of a bup repository, which is also a git
403 repository.  There's just one more thing we have to deal with:
404 filesystem metadata.  Git repositories are really only intended to
405 store file contents with a small bit of extra information, like
406 symlink targets and executable bits, so we have to store the rest
407 some other way.
408
409 Bup stores more complete metadata in the VFS in a file named .bupm in
410 each tree.  This file contains one entry for each file in the tree
411 object, sorted in the same order as the tree.  The first .bupm entry
412 is for the directory itself, i.e. ".", and its name is the empty
413 string, "".
414
415 Each .bupm entry contains a variable length sequence of records
416 containing the metadata for the corresponding path.  Each record
417 records one type of metadata.  Current types include a common record
418 type (containing the normal stat information), a symlink target type,
419 a hardlink target type, a POSIX1e ACL type, etc.  See metadata.py for
420 the complete list.
421
422 The .bupm file is optional, and when it's missing, bup will behave as
423 it did before the addition of metadata, and restore files using the
424 tree information.
425
426 The nice thing about this design is that you can walk through each
427 file in a tree just by opening the tree and the .bupm contents, and
428 iterating through both at the same time.
429
430 Since the contents of any .bupm file should match the state of the
431 filesystem when it was *indexed*, bup must record the detailed
432 metadata in the index.  To do this, bup records four values in the
433 index, the atime, mtime, and ctime (as timespecs), and an integer
434 offset into a secondary "metadata store" which has the same name as
435 the index, but with ".meta" appended.  This secondary store contains
436 the encoded Metadata object corresponding to each path in the index.
437
438 Currently, in order to decrease the storage required for the metadata
439 store, bup only writes unique values there, reusing offsets when
440 appropriate across the index.  The effectiveness of this approach
441 relies on the expectation that there will be many duplicate metadata
442 records.  Storing the full timestamps in the index is intended to make
443 that more likely, because it makes it unnecessary to record those
444 values in the secondary store.  So bup clears them before encoding the
445 Metadata objects destined for the index, and timestamp differences
446 don't contribute to the uniqueness of the metadata.
447
448 Bup supports recording and restoring hardlinks, and it does so by
449 tracking sets of paths that correspond to the same dev/inode pair when
450 indexing.  This information is stored in an optional file with the
451 same name as the index, but ending with ".hlink".
452
453 If there are multiple index runs, and the hardlinks change, bup will
454 notice this (within whatever subtree it is asked to reindex) and
455 update the .hlink information accordingly.
456
457 The current hardlink implementation will refuse to link to any file
458 that resides outside the restore tree, and if the restore tree spans a
459 different set of filesystems than the save tree, complete sets of
460 hardlinks may not be restored.
461
462
463 Filesystem Interaction
464 ======================
465
466 Storing data is just half of the problem of making a backup; figuring out
467 what to store is the other half.
468
469 At the most basic level, piping the output of 'tar' into 'bup split' is an
470 easy way to offload that decision; just let tar do all the hard stuff.  And
471 if you like tar files, that's a perfectly acceptable way to do it.  But we
472 can do better.
473
474 Backing up with tarballs would totally be the way to go, except for two
475 serious problems:
476
477 1. The result isn't easily "seekable."  Tar files have no index, so if (as
478    commonly happens) you only want to restore one file in a 200 GB backup,
479    you'll have to read up to 200 GB before you can get to the beginning of
480    that file.  tar is short for "tape archive"; on a tape, there was no
481    better way to do it anyway, so they didn't try.  But on a disk, random
482    file access is much, much better when you can figure out how.
483    
484 2. tar doesn't remember which files it backed up last time, so it has to
485    read through the entire file contents again in order to generate the
486    tarball, large parts of which will then be skipped by bup since they've
487    already been stored.  This is much slower than necessary.
488
489 (The second point isn't entirely true for all versions of tar. For example,
490 GNU tar has an "incremental" mode that can somewhat mitigate this problem,
491 if you're smart enough to know how to use it without hurting yourself.  But
492 you still have to decide which backups are "incremental" and which ones will
493 be "full" and so on, so even when it works, it's more error-prone than bup.)
494
495 bup divides the backup process into two major steps: a) indexing the
496 filesystem, and b) saving file contents into the repository.  Let's look at
497 those steps in detail.
498
499
500 Indexing the filesystem (cmd/drecurse, cmd/index, index.py)
501 -----------------------
502
503 Splitting the filesystem indexing phase into its own program is
504 nontraditional, but it gives us several advantages.
505
506 The first advantage is trivial, but might be the most important: you can
507 index files a lot faster than you can back them up.  That means we can
508 generate the index (.bup/bupindex) first, then have a nice, reliable,
509 non-lying completion bar that tells you how much of your filesystem remains
510 to be backed up.  The alternative would be annoying failures like counting
511 the number of *files* remaining (as rsync does), even though one of the
512 files is a virtual machine image of 80 GB, and the 1000 other files are each
513 under 10k.  With bup, the percentage complete is the *real* percentage
514 complete, which is very pleasant.
515
516 Secondly, it makes it easier to debug and test; you can play with the index
517 without actually backing up any files.
518
519 Thirdly, you can replace the 'bup index' command with something else and not
520 have to change anything about the 'bup save' command.  The current 'bup
521 index' implementation just blindly walks the whole filesystem looking for
522 files that have changed since the last time it was indexed; this works fine,
523 but something using inotify instead would be orders of magnitude faster. 
524 Windows and MacOS both have inotify-like services too, but they're totally
525 different; if we want to support them, we can simply write new bup commands
526 that do the job, and they'll never interfere with each other.
527
528 And fourthly, git does it that way, and git is awesome, so who are we to
529 argue?
530
531 So let's look at how the index file works.
532
533 First of all, note that the ".bup/bupindex" file is not the same as git's
534 ".git/index" file.  The latter isn't used in bup; as far as git is
535 concerned, your bup repository is a "bare" git repository and doesn't have a
536 working tree, and thus it doesn't have an index either.
537
538 However, the bupindex file actually serves exactly the same purpose as git's
539 index file, which is why we still call it "the index." We just had to
540 redesign it for the usual bup-vs-git reasons, mostly that git just isn't
541 designed to handle millions of files in a single repository.  (The only way
542 to find a file in git's index is to search it linearly; that's very fast in
543 git-sized repositories, but very slow in bup-sized ones.)
544
545 Let's not worry about the exact format of the bupindex file; it's still not
546 optimal, and will probably change again.  The most important things to know
547 about bupindex are:
548
549  - You can iterate through it much faster than you can iterate through the
550    "real" filesystem (using something like the 'find' command).
551    
552  - If you delete it, you can get it back just by reindexing your filesystem
553    (although that can be annoying to wait for); it's not critical to the
554    repository itself.
555    
556  - You can iterate through only particular subtrees if you want.
557  
558  - There is no need to have more than one index for a particular filesystem,
559    since it doesn't store anything about backups; it just stores file
560    metadata.  It's really just a cache (or 'index') of your filesystem's
561    existing metadata.  You could share the bupindex between repositories, or
562    between multiple users on the same computer.  If you back up your
563    filesystem to multiple remote repositories to be extra safe, you can
564    still use the same bupindex file across all of them, because it's the
565    same filesystem every time.
566    
567  - Filenames in the bupindex are absolute paths, because that's the best way
568    to ensure that you only need one bupindex file and that they're
569    interchangeable.
570    
571
572 A note on file "dirtiness"
573 --------------------------
574
575 The concept on which 'bup save' operates is simple enough; it reads through
576 the index and backs up any file that is "dirty," that is, doesn't already
577 exist in the repository.
578
579 Determination of dirtiness is a little more complicated than it sounds.  The
580 most dirtiness-relevant flag in the bupindex is IX_HASHVALID; if
581 this flag is reset, the file *definitely* is dirty and needs to be backed
582 up.  But a file may be dirty even if IX_HASHVALID is set, and that's the
583 confusing part.
584
585 The index stores a listing of files, their attributes, and
586 their git object ids (sha1 hashes), if known.  The "if known" is what
587 IX_HASHVALID is about.  When 'bup save' backs up a file, it sets
588 the sha1 and sets IX_HASHVALID; when 'bup index' sees that a file has
589 changed, it leaves the sha1 alone and resets IX_HASHVALID.
590
591 Remember that the index can be shared between users, repositories, and
592 backups.  So IX_HASHVALID doesn't mean your repository *has* that sha1 in
593 it; it only means that if you *do* have it, that you don't need to back up
594 the file.  Thus, 'bup save' needs to check every file in the index to make
595 sure its hash exists, not just that it's valid.
596
597 There's an optimization possible, however: if you know a particular tree's
598 hash is valid and exists (say /usr), then you don't need to check the
599 validity of all its children; because of the way git trees and blobs work,
600 if your repository is valid and you have a tree object, then you have all
601 the blobs it points to.  You won't back up a tree object without backing up
602 its blobs first, so you don't need to double check it next time.  (If you
603 really want to double check this, it belongs in a tool like 'bup fsck' or
604 'git fsck'.) So in short, 'bup save' on a "clean" index (all files are
605 marked IX_HASHVALID) can be very fast; we just check our repository and see
606 if the top level IX_HASHVALID sha1 exists.  If it does, then we're done.
607
608 Similarly, if not the entire index is valid, you can still avoid recursing
609 into subtrees if those particular subtrees are IX_HASHVALID and their sha1s
610 are in the repository.  The net result is that, as long as you never lose
611 your index, 'bup save' can always run very fast.
612
613 Another interesting trick is that you can skip backing up files even if
614 IX_HASHVALID *isn't* set, as long as you have that file's sha1 in the
615 repository.  What that means is you've chosen not to backup the latest
616 version of that file; instead, your new backup set just contains the
617 most-recently-known valid version of that file.  This is a good trick if you
618 want to do frequent backups of smallish files and infrequent backups of
619 large ones.  Each of your backups will be "complete," in that they contain
620 all the small files and the large ones, but intermediate ones will just
621 contain out-of-date copies of the large files. Note that this isn't done
622 right now, and 'bup save --smaller' doesn't store bigger files _at all_.
623
624 A final game we can play with the bupindex involves restoring: when you
625 restore a directory from a previous backup, you can update the bupindex
626 right away.  Then, if you want to restore a different backup on top, you can
627 compare the files in the index against the ones in the backup set, and
628 update only the ones that have changed.  (Even more interesting things
629 happen if people are using the files on the restored system and you haven't
630 updated the index yet; the net result would be an automated merge of all
631 non-conflicting files.) This would be a poor man's distributed filesystem. 
632 The only catch is that nobody has written this feature for 'bup restore'
633 yet.  Someday!
634
635
636 How 'bup save' works (cmd/save)
637 --------------------
638
639 This section is too boring and has been omitted.  Once you understand the
640 index, there's nothing special about bup save.
641
642
643 Retrieving backups: the bup vfs layer (vfs.py, cmd/ls, cmd/ftp, cmd/fuse)
644 =====================================
645
646 One of the neat things about bup's storage format, at least compared to most
647 backup tools, is it's easy to read a particular file, or even part of a
648 file.  That means a read-only virtual filesystem is easy to generate and
649 it'll have good performance characteristics.  Because of git's commit
650 structure, you could even use branching and merging to make a transactional
651 read-write filesystem... but that's probably getting a little out of bup's
652 scope.  Who knows what the future might bring, though?
653
654 Read-only filesystems are well within our reach today, however.  The 'bup
655 ls', 'bup ftp', and 'bup fuse' commands all use a "VFS" (virtual filesystem)
656 layer to let you access your repositories.  Feel free to explore the source
657 code for these tools and vfs.py - they're pretty straightforward.  Some
658 things to note:
659
660  - None of these use the bupindex for anything.
661  
662  - For user-friendliness, they present your refs/commits/trees as a single
663    hierarchy (ie.  a filesystem), which isn't really how git repositories
664    are formatted.  So don't get confused!
665
666
667 Handling Python 3's insistence on strings
668 =========================================
669
670 In Python 2 strings were bytes, and bup used them for all kinds of
671 data.  Python 3 made a pervasive backward-incompatible change to treat
672 all strings as Unicode, i.e. in Python 2 'foo' and b'foo' were the
673 same thing, while u'foo' was a Unicode string.  In Python 3 'foo'
674 became synonymous with u'foo', completely changing the type and
675 potential content, depending on the locale.
676
677 In addition, and particularly bad for bup, Python 3 also (initially)
678 insisted that all kinds of things were strings that just aren't (at
679 least not on many platforms), i.e. user names, groups, filesystem
680 paths, etc.  There's no guarantee that any of those are always
681 representable in Unicode.
682
683 Over the years, Python 3 has gradually backed away from that initial
684 position, adding alternate interfaces like os.environb or allowing
685 bytes arguments to many functions like open(b'foo'...), so that in
686 those cases it's at least possible to accurately retrieve the system
687 data.
688
689 After a while, they devised the concept of
690 [bytesmuggling](https://www.python.org/dev/peps/pep-0383/) as a more
691 comprehensive solution.  In theory, this might be sufficient, but our
692 initial randomized testing discovered that some binary arguments would
693 crash Python during startup[1].  Eventually Johannes Berg tracked down
694 the [cause](https://sourceware.org/bugzilla/show_bug.cgi?id=26034),
695 and we hope that the problem will be fixed eventually in glibc or
696 worked around by Python, but in either case, it will be a long time
697 before any fix is widely available.
698
699 Before we tracked down that bug we were pursuing an approach that
700 would let us side step the issue entirely by manipulating the
701 LC_CTYPE, but that approach was somewhat complicated, and once we
702 understood what was causing the crashes, we decided to just let Python
703 3 operate "normally", and work around the issues.
704
705 Consequently, we've had to wrap a number of things ourselves that
706 incorrectly return Unicode strings (libacl, libreadline, hostname,
707 etc.)  and we've had to come up with a way to avoid the fatal crashes
708 caused by some command line arguments (sys.argv) described above.  To
709 fix the latter, for the time being, we just use a trivial sh wrapper
710 to redirect all of the command line arguments through the environment
711 in BUP_ARGV_{0,1,2,...} variables, since the variables are unaffected,
712 and we can access them directly in Python 3 via environb.
713
714 [1] Our randomized argv testing found that the byte smuggling approach
715     was not working correctly for some values (initially discovered in
716     Python 3.7, and observed in other versions).  The interpreter
717     would just crash while starting up like this:
718
719     Fatal Python error: _PyMainInterpreterConfig_Read: memory allocation failed
720     ValueError: character U+134bd2 is not in range [U+0000; U+10ffff]
721
722     Current thread 0x00007f2f0e1d8740 (most recent call first):
723     Traceback (most recent call last):
724       File "t/test-argv", line 28, in <module>
725         out = check_output(cmd)
726       File "/usr/lib/python3.7/subprocess.py", line 395, in check_output
727         **kwargs).stdout
728       File "/usr/lib/python3.7/subprocess.py", line 487, in run
729         output=stdout, stderr=stderr)
730
731 We hope you'll enjoy bup.  Looking forward to your patches!
732
733 -- apenwarr and the rest of the bup team
734
735 Local Variables:
736 mode: markdown
737 End: