]> arthur.barton.de Git - bup.git/blob - DESIGN
DESIGN: update mentions of stupidsum to reflect new rollsum algorithm.
[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  - bup (symlinked to main.py) is the main program that runs when you type
22    'bup'.
23  
24  - cmd/bup-* (mostly symlinked to cmd/*-cmd.py) are the individual
25    subcommands, in a way similar to how git breaks all its subcommands into
26    separate programs.  Not all the programs have to be written in python;
27    they could be in any language, as long as they end up named cmd/bup-*. 
28    We might end up re-coding large parts of bup in C eventually so that it
29    can be even faster and (perhaps) more portable.
30
31  - lib/bup/*.py are python library files used by the cmd/*.py commands. 
32    That directory name seems a little silly (and worse, redundant) but there
33    seemed to be no better way to let programs write "from bup import
34    index" and have it work.  Putting bup in the top level conflicted with
35    the 'bup' command; calling it anything other than 'bup' was fundamentally
36    wrong, and doesn't work when you install bup on your system in /usr/lib
37    somewhere.  So we get the annoyingly long paths.
38
39
40 Repository Structure
41 ====================
42
43 Before you can talk about how bup works, we need to first address what it
44 does.  The purpose of bup is essentially to let you "replicate" data between
45 two main data structures:
46
47 1. Your computer's filesystem;
48
49 2. A bup repository. (Yes, we know, that part also resides in your
50    filesystem.  Stop trying to confuse yourself.  Don't worry, we'll be
51    plenty confusing enough as it is.)
52
53 Essentially, copying data from the filesystem to your repository is called
54 "backing stuff up," which is what bup specializes in.  Normally you initiate
55 a backup using the 'bup save' command, but that's getting ahead of
56 ourselves.
57
58 As most backup experts know, backing stuff up is normally about 100x more
59 common than restoring stuff, ie.  copying from the repository to your
60 filesystem.  For that reason, and also because bup is so new, there is no
61 actual 'bup restore' command that does the obvious inverse operation to 'bup
62 save'.  There are 'bup ftp' and 'bup fuse', which let you access your
63 backed-up data, but they aren't as efficient as a fully optimized restore
64 tool intended for high-volume restores.  There's nothing stopping us from
65 writing one; we just haven't written it yet.  Feel free to pester us about
66 it on the bup mailing list (see the README to find out about the list).
67
68 Now, those are the basics of backups.  In other words, we just spent about
69 half a page telling you that bup backs up and restores data.  Are we having
70 fun yet?
71
72 The next thing you'll want to know is the format of the bup repository,
73 because hacking on bup is rather impossible unless you understand that part. 
74 In short, a bup repository is a git repository.  If you don't know about
75 git, you'll want to read about it now.  A really good article to read is
76 "Git for Computer Scientists" - you can find it in Google.  Go read it now. 
77 We'll wait.
78
79 Got it?  Okay, so now you're an expert in blobs, trees, commits, and refs,
80 the four building blocks of a git repository.  bup uses these four things,
81 and they're formatted in exactly the same way as git does it, so you can use
82 git to manipulate the bup repository if you want, and you probably won't
83 break anything.  It's also a comfort to know you can squeeze data out using
84 git, just in case bup fails you, and as a developer, git offers some nice
85 tools (like 'git rev-list' and 'git log' and 'git diff' and 'git show' and
86 so on) that allow you to explore your repository and help debug when things
87 go wrong.
88
89 Now, bup does use these tools a little bit differently than plain git.  We
90 need to do this in order to address two deficiencies in git when used for
91 large backups, namely a) git bogs down and crashes if you give it really
92 large files; b) git is too slow when you give it too many files; and c) git
93 doesn't store detailed filesystem metadata.
94
95 Let's talk about each of those problems in turn.
96
97
98 Handling large files (cmd/split, hashsplit.split_to_blob_or_tree)
99 --------------------
100
101 The primary reason git can't handle huge files is that it runs them through
102 xdelta, which generally means it tries to load the entire contents of a file
103 into memory at once.  If it didn't do this, it would have to store the
104 entire contents of every single revision of every single file, even if you
105 only changed a few bytes of that file.  That would be a terribly inefficient
106 use of disk space, and git is well known for its amazingly efficient
107 repository format.
108
109 Unfortunately, xdelta works great for small files and gets amazingly slow
110 and memory-hungry for large files.  For git's main purpose, ie. managing
111 your source code, this isn't a problem.  But when backing up your
112 filesystem, you're going to have at least a few large files, and so it's a
113 non-starter.  bup has to do something totally different.
114
115 What bup does instead of xdelta is what we call "hashsplitting."  We wanted
116 a general-purpose way to efficiently back up *any* large file that might
117 change in small ways, without storing the entire file every time.  In fact,
118 the original versions of bup could only store a single file at a time;
119 surprisingly enough, this was enough to give us a large part of bup's
120 functionality.  If you just take your entire filesystem and put it in a
121 giant tarball each day, then send that tarball to bup, bup will be able to
122 efficiently store only the changes to that tarball from one day to the next. 
123 For small files, bup's compression won't be as good as xdelta's, but for
124 anything over a few megabytes in size, bup's compression will actually
125 *work*, which is a bit advantage over xdelta.
126
127 How does hashsplitting work?  It's deceptively simple.  We read through the
128 file one byte at a time, calculating a rolling checksum of the last 128
129 bytes.  (Why 128?  No reason.  Literally.  We picked it out of the air. 
130 Probably some other number is better.  Feel free to join the mailing list
131 and tell us which one and why.)  (The rolling checksum idea is actually
132 stolen from rsync and xdelta, although we use it differently.  And they use
133 some kind of variable window size based on a formula we don't totally
134 understand.)
135
136 The original rolling checksum algorithm we used was called "stupidsum,"
137 because it was based on the only checksum Avery remembered how to calculate at
138 the time.  He also remembered that it was the introductory checksum
139 algorithm in a whole article about how to make good checksums that he read
140 about 15 years ago, and it was thoroughly discredited in that article for
141 being very stupid.  But, as so often happens, Avery couldn't remember any
142 better algorithms from the article.  So what we got is stupidsum.
143
144 Since then, we have replaced the stupidsum algorithm with what we call
145 "rollsum," based on code in librsync.  It's essentially the same as what
146 rsync does, except we use a fixed window size.
147
148 (If you're a computer scientist and can demonstrate that some other rolling
149 checksum would be faster and/or better and/or have fewer screwy edge cases,
150 we need your help!  Avery's out of control!  Join our mailing list!  Please! 
151 Save us! ...  oh boy, I sure hope he doesn't read this)
152
153 In any case, rollsum seems to do pretty well at its job. 
154 You can find it in bupsplit.c.  Basically, it converts the last 128 bytes
155 read into a 32-bit integer.  What we then do is take the lowest 13
156 bits of the rollsum, and if they're all 1's, we consider that to be the end
157 of a chunk.  This happens on average once every 2^13 = 8192 bytes, so the
158 average chunk size is 8192 bytes.
159
160 (Why 13 bits?  Well, we picked the number at random and... eugh.  You're
161 getting the idea, right?  Join the mailing list and tell us why we're
162 wrong.)
163
164 (Incidentally, even though the average chunk size is 8192 bytes, the actual
165 probability distribution of block sizes ends up being non-uniform; if we
166 remember our stats classes correctly, which we probably don't, it's probably
167 an "exponential distribution."  The idea is that for each byte in the block,
168 the probability that it's the last block is one in 8192.  Thus, the
169 block sizes end up being skewed toward the smaller end.  That's not
170 necessarily for the best, but maybe it is.  Computer science to the rescue? 
171 You know the drill.)
172
173 Anyway, so we're dividing up those files into chunks based on the rolling
174 checksum.  Then we store each chunk separately (indexed by its sha1sum) as a
175 git blob.  Why do we split this way?  Well, because the results are actually
176 really nice.  Let's imagine you have a big mysql database dump (produced by
177 mysqldump) and it's basically 100 megs of SQL text.  Tomorrow's database
178 dump adds 100 rows to the middle of the file somewhere, soo it's 100.01 megs
179 of text.
180
181 A naive block splitting algorithm - for example, just dividing the file into
182 8192-byte blocks - would be a disaster.  After the first bit of text has
183 changed, every block after that would have a different boundary, so most of
184 the blocks in the new backup would be different from the previous ones, and
185 you'd have to store the same data all over again.  But with hashsplitting,
186 no matter how much data you add, modify, or remove in the middle of the
187 file, all the chunks *before* and *after* the affected chunk are absolutely
188 the same.  All that matters to the hashsplitting algorithm is the 32-byte
189 "separator" sequence, and a single change can only affect, at most, one
190 separator sequence or the bytes between two separator sequences.  And
191 because of rollsum, about one in 8192 possible 128-byte sequences is a
192 separator sequence.  Like magic, the hashsplit chunking algorithm will chunk
193 your file the same way every time, even without knowing how it had chunked
194 it previously.
195
196 The next problem is less obvious: after you store your series of chunks as
197 git blobs, how do you store their sequence?  Each blob has a 20-byte sha1
198 identifier, which means the simple list of blobs is going to be 20/8192 =
199 0.25% of the file length.  For a 200GB file, that's 488 megs of just
200 sequence data.
201
202 As an overhead percentage, 0.25% basically doesn't matter.  488 megs sounds
203 like a lot, but compared to the 200GB you have to store anyway, it's
204 irrelevant.  What *is* relevant is that 488 megs is a lot of memory you have
205 to use in order to to keep track of the list.  Worse, if you back up an
206 almost-identical file tomorrow, you'll have *another* 488 meg blob to keep
207 track of, and it'll be almost but not quite the same as last time.
208
209 Hmm, big files, each one almost the same as the last... you know where this
210 is going, right?
211
212 Actually no!  Ha!  We didn't split this list in the same way.  We could
213 have, in fact, but it wouldn't have been very "git-like", since we'd like to
214 store the list as a git 'tree' object in order to make sure git's
215 refcounting and reachability analysis doesn't get confused.  Never mind the
216 fact that we want you to be able to 'git checkout' your data without any
217 special tools.
218
219 What we do instead is we extend the hashsplit algorithm a little further
220 using what we call "fanout." Instead of checking just the last 13 bits of
221 the checksum, we use additional checksum bits to produce additional splits. 
222 For example, let's say we use a 4-bit fanout.  That means we'll break a
223 series of chunks into its own tree object whenever the last 13+4 = 17 bits
224 of the rolling checksum are 1.  Naturally, whenever the lowest 17 bits are
225 1, the lowest 13 bits are *also* 1, so the boundary of a chunk group is
226 always also the boundary of a particular chunk.
227
228 And so on.  Eventually you'll have too many chunk groups, but you can group
229 them into supergroups by using another 4 bits, and continue from there.
230
231 What you end up with is an actual tree of blobs - which git 'tree' objects
232 are ideal to represent.  And if you think about it, just like the original
233 list of chunks, the tree itself is pretty stable across file modifications. 
234 Any one modification will only affect the chunks actually containing the
235 modifications, thus only the groups containing those chunks, and so on up
236 the tree.  Essentially, the number of changed git objects is O(log n)
237 where n is the number of chunks.  Since log 200 GB, using a base of 16 or
238 so, is not a very big number, this is pretty awesome.  Remember, any git
239 object we *don't* change in a new backup is one we can reuse from last time,
240 so the deduplication effect is pretty awesome.
241
242 Better still, the hashsplit-tree format is good for a) random instead of
243 sequential access to data (which you can see in action with 'bup fuse'); and
244 b) quickly showing the differences between huge files (which we haven't
245 really implemented because we don't need it, but you can try 'git diff -M -C
246 -C backup1 backup2 -- filename' for a good start).
247
248 So now we've split out 200 GB file into about 24 million pieces.  That
249 brings us to git limitation number 2.
250
251
252 Handling huge numbers of files (git.PackWriter)
253 ------------------------------
254
255 git is designed for handling reasonably-sized repositories that change
256 relatively infrequently.  (You might think you change your source code
257 "frequently" and that git handles much more frequent changes than, say, svn
258 can handle.  But that's not the same kind of "frequently" we're talking
259 about.  Imagine you're backing up all the files on your disk, and one of
260 those files is a 100 GB database file with hundreds of daily users.  You
261 disk changes so frequently you can't even back up all the revisions even if
262 you were backing stuff up 24 hours a day.  That's "frequently.")
263
264 git's way of doing things works really nicely for the way software
265 developers write software, but it doesn't really work so well for everything
266 else.  The #1 killer is the way it adds new objects to the repository: it
267 creates one file per blob.  Then you later run 'git gc' and combine those
268 files into a single file (using highly efficient xdelta compression, and
269 ignoring any files that are no longer relevant).
270
271 'git gc' is slow, but for source code repositories, the resulting
272 super-efficient storage (and associated really fast access to the stored
273 files) is worth it.  For backups, it's not; you almost never access your
274 backed-up data, so storage time is paramount, and retrieval time is mostly
275 unimportant.
276
277 To back up that 200 GB file with git and hashsplitting, you'd have to create
278 24 million little 8k files, then copy them into a 200 GB packfile, then
279 delete the 24 million files again.  That would take about 400 GB of disk
280 space to run, require lots of random disk seeks, and require you to go
281 through your data twice.
282
283 So bup doesn't do that.  It just writes packfiles directly.  Luckily, these
284 packfiles are still git-formatted, so git can happily access them once
285 they're written.
286
287 But that leads us to our next problem.
288
289
290 Huge numbers of huge packfiles (git.PackMidx, cmd/midx)
291 ------------------------------
292
293 Git isn't actually designed to handle super-huge repositories.  Most git
294 repositories are small enough that it's reasonable to merge them all into a
295 single packfile, which 'git gc' usually does eventually.
296
297 The problematic part of large packfiles isn't the packfiles themselves - git
298 is designed to expect the total size of all packs to be larger than
299 available memory, and once it can handle that, it can handle virtually any
300 amount of data about equally efficiently.  The problem is the packfile
301 indexes (.idx) files.  In bup we call these idx (pronounced "idix") files
302 instead of using the word "index," because the word index is already used
303 for something totally different in git (and thus bup) and we'll become
304 hopelessly confused otherwise.
305
306 Anyway, each packfile (*.pack) in git has an associated idx (*.idx) that's a
307 sorted list of git object hashes and file offsets.  If you're looking for a
308 particular object based on its sha1, you open the idx, binary search it to
309 find the right hash, then take the associated file offset, seek to that
310 offset in the packfile, and read the object contents.
311
312 The performance of the binary search is about O(log n) with the number of
313 hashes in the pack, with an optimized first step (you can read about it
314 elsewhere) that somewhat improves it to O(log(n)-7).
315
316 Unfortunately, this breaks down a bit when you have *lots* of packs.  Say
317 you have 24 million objects (containing around 200 GB of data) spread across
318 200 packfiles of 1GB each.  To look for an object requires you search
319 through about 122000 objects per pack; ceil(log2(122000)-7) = 10, so you'll
320 have to search 10 times.  About 7 of those searches will be confined to a
321 single 4k memory page, so you'll probably have to page in about 3-4 pages
322 per file, times 200 files, which makes 600-800 4k pages (2.4-3.6 megs)...
323 every single time you want to look for an object.
324
325 This brings us to another difference between git's and bup's normal use
326 case.  With git, there's a simple optimization possible here: when looking
327 for an object, always search the packfiles in MRU (most recently used)
328 order.  Related objects are usually clusted together in a single pack, so
329 you'll usually end up searching around 3 pages instead of 600, which is a
330 tremendous improvement.  (And since you'll quickly end up swapping in all
331 the pages in a particular idx file this way, it isn't long before searching
332 for a nearby object doesn't involve any swapping at all.)
333
334 bup isn't so lucky.  git users spend most of their time examining existing
335 objects (looking at logs, generating diffs, checking out branches), which
336 lends itself to the above optimization.  bup, on the other hand, spends most
337 of its time looking for *nonexistent* objects in the repository so that it
338 can back them up.  When you're looking for objects that aren't in the
339 repository, there's no good way to optimize; you have to exhaustively check
340 all the packs, one by one, to ensure that none of them contain the data you
341 want.
342
343 To improve performance of this sort of operation, bup introduces midx
344 (pronounced "midix" and short for "multi-idx") files.  As the name implies,
345 they index multiple packs at a time.
346
347 Imagine you had a midx file for your 200 packs.  midx files are a lot like
348 idx files; they have a lookup table at the beginning that narrows down the
349 initial search, followed by a binary search.  The unlike idx files (which
350 have a fixed-size 256-entry lookup table) midx tables have a variably-sized
351 table that makes sure the entire binary search can be contained to a single
352 page of the midx file.  Basically, the lookup table tells you which page to
353 load, and then you binary search inside that page.  A typical search thus
354 only requires the kernel to swap in two pages, which is better than results
355 with even a single large idx file.  And if you have lots of RAM, eventually
356 the midx lookup table (at least) will end up cached in memory, so only a
357 single page should be needed for each lookup.
358
359 You generate midx files with 'bup midx'.  The downside of midx files is that
360 generating one takes a while, and you have to regenerate it every time you
361 add a few packs.
362
363 (Computer Sciency observers will note that there are some interesting data
364 structures out there that could help make things even better.  A very
365 promising sounding one is called a "bloom filter." Look it up in Wikipedia.)
366
367 midx files are a bup-specific optimization and git doesn't know what to do
368 with them.  However, since they're stored as separate files, they don't
369 interfere with git's ability to read the repository.
370
371
372 Detailed Metadata
373 -----------------
374
375 So that's the basic structure of a bup repository, which is also a git
376 repository.  There's one more thing we have to deal with in bup: filesystem
377 metadata.  git repositories are really only intended to store file contents
378 with a small bit of extra information, like symlink support and
379 differentiating between executable and non-executable files.  For the rest,
380 we'll have to store it some other way.
381
382 As of this writing, bup's support for metadata is... pretty much
383 nonexistent.  People are working on it.  But the plan goes like this:
384
385  - Each git tree will contain a file called .bupmeta.
386  
387  - .bupmeta contains an entry for every entry in the tree object, sorted in
388    the same order as in the tree.
389  
390  - the .bupmeta entry lists information like modification times, attributes,
391    file ownership, and so on for each file in the tree.
392    
393  - for backward compatibility with pre-metadata versions of bup (and git,
394    for that matter) the .bupmeta file for each tree is optional, and if it's
395    missing, files will be assumed to have default permissions.
396    
397  The nice thing about this design is that you can walk through each file in
398  a tree just by opening the tree and the .bupmeta contents, and iterating
399  through both at the same time.
400  
401  Trust us, it'll be awesome.  
402
403
404 Filesystem Interaction
405 ======================
406
407 Storing data is just half of the problem of making a backup; figuring out
408 what to store is the other half.
409
410 At the most basic level, piping the output of 'tar' into 'bup split' is an
411 easy way to offload that decision; just let tar do all the hard stuff.  And
412 if you like tar files, that's a perfectly acceptable way to do it.  But we
413 can do better.
414
415 Backing up with tarballs would totally be the way to go, except for two
416 serious problems:
417
418 1. The result isn't easily "seekable."  Tar files have no index, so if (as
419    commonly happens) you only want to restore one file in a 200 GB backup,
420    you'll have to read up to 200 GB before you can get to the beginning of
421    that file.  tar is short for "tape archive"; on a tape, there was no
422    better way to do it anyway, so they didn't try.  But on a disk, random
423    file access is much, much better when you can figure out how.
424    
425 2. tar doesn't remember which files it backed up last time, so it has to
426    read through the entire file contents again in order to generate the
427    tarball, large parts of which will then be skipped by bup since they've
428    already been stored.  This is much slower than necessary.
429
430 (The second point isn't entirely true for all versions of tar. For example,
431 GNU tar has an "incremental" mode that can somewhat mitigate this problem,
432 if you're smart enough to know how to use it without hurting yourself.  But
433 you still have to decide which backups are "incremental" and which ones will
434 be "full" and so on, so even when it works, it's more error-prone than bup.)
435
436 bup divides the backup process into two major steps: a) indexing the
437 filesystem, and b) saving file contents into the repository.  Let's look at
438 those steps in detail.
439
440
441 Indexing the filesystem (cmd/drecurse, cmd/index, index.py)
442 -----------------------
443
444 Splitting the filesystem indexing phase into its own program is
445 nontraditional, but it gives us several advantages.
446
447 The first advantage is trivial, but might be the most important: you can
448 index files a lot faster than you can back them up.  That means we can
449 generate the index (.bup/bupindex) first, then have a nice, reliable,
450 non-lying completion bar that tells you how much of your filesystem remains
451 to be backed up.  The alternative would be annoying failures like counting
452 the number of *files* remaining (as rsync does), even though one of the
453 files is a virtual machine image of 80 GB, and the 1000 other files are each
454 under 10k.  With bup, the percentage complete is the *real* percentage
455 complete, which is very pleasant.
456
457 Secondly, it makes it easier to debug and test; you can play with the index
458 without actually backing up any files.
459
460 Thirdly, you can replace the 'bup index' command with something else and not
461 have to change anything about the 'bup save' command.  The current 'bup
462 index' implementation just blindly walks the whole filesystem looking for
463 files that have changed since the last time it was indexed; this works fine,
464 but something using inotify instead would be orders of magnitude faster. 
465 Windows and MacOS both have inotify-like services too, but they're totally
466 different; if we want to support them, we can simply write new bup commands
467 that do the job, and they'll never interfere with each other.
468
469 And fourthly, git does it that way, and git is awesome, so who are we to
470 argue?
471
472 So let's look at how the index file works.
473
474 First of all, note that the ".bup/bupindex" file is not the same as git's
475 ".git/index" file.  The latter isn't used in bup; as far as git is
476 concerned, your bup repository is a "bare" git repository and doesn't have a
477 working tree, and thus it doesn't have an index either.
478
479 However, the bupindex file actually serves exactly the same purpose as git's
480 index file, which is why we still call it "the index." We just had to
481 redesign it for the usual bup-vs-git reasons, mostly that git just isn't
482 designed to handle millions of files in a single repository.  (The only way
483 to find a file in git's index is to search it linearly; that's very fast in
484 git-sized repositories, but very slow in bup-sized ones.)
485
486 Let's not worry about the exact format of the bupindex file; it's still not
487 optimal, and will probably change again.  The most important things to know
488 about bupindex are:
489
490  - You can iterate through it much faster than you can iterate through the
491    "real" filesystem (using something like the 'find' command).
492    
493  - If you delete it, you can get it back just by reindexing your filesystem
494    (although that can be annoying to wait for); it's not critical to the
495    repository itself.
496    
497  - You can iterate through only particular subtrees if you want.
498  
499  - There is no need to have more than one index for a particular filesystem,
500    since it doesn't store anything about backups; it just stores file
501    metadata.  It's really just a cache (or 'index') of your filesystem's
502    existing metadata.  You could share the bupindex between repositories, or
503    between multiple users on the same computer.  If you back up your
504    filesystem to multiple remote repositories to be extra safe, you can
505    still use the same bupindex file across all of them, because it's the
506    same filesystem every time.
507    
508  - Filenames in the bupindex are absolute paths, because that's the best way
509    to ensure that you only need one bupindex file and that they're
510    interchangeable.
511    
512
513 A note on file "dirtiness"
514 --------------------------
515
516 The concept on which 'bup save' operates is simple enough; it reads through
517 the index and backs up any file that is "dirty," that is, doesn't already
518 exist in the repository.
519
520 Determination of dirtiness is a little more complicated than it sounds.  The
521 most dirtiness-relevant relevant flag in the bupindex is IX_HASHVALID; if
522 this flag is reset, the file *definitely* is dirty and needs to be backed
523 up.  But a file may be dirty even if IX_HASHVALID is set, and that's the
524 confusing part.
525
526 The index stores a listing of files, their attributes, and
527 their git object ids (sha1 hashes), if known.  The "if known" is what
528 IX_HASHVALID is about.  When 'bup save' backs up a file, it sets
529 the sha1 and sets IX_HASHVALID; when 'bup index' sees that a file has
530 changed, it leaves the sha1 alone and resets IX_HASHVALID.
531
532 Remember that the index can be shared between users, repositories, and
533 backups.  So IX_HASHVALID doesn't mean your repository *has* that sha1 in
534 it; it only means that if you *do* have it, that you don't need to back up
535 the file.  Thus, 'bup save' needs to check every file in the index to make
536 sure its hash exists, not just that it's valid.
537
538 There's an optimization possible, however: if you know a particular tree's
539 hash is valid and exists (say /usr), then you don't need to check the
540 validity of all its children; because of the way git trees and blobs work,
541 if your repository is valid and you have a tree object, then you have all
542 the blobs it points to.  You won't back up a tree object without backing up
543 its blobs first, so you don't need to double check it next time.  (If you
544 really want to double check this, it belongs in a tool like 'bup fsck' or
545 'git fsck'.) So in short, 'bup save' on a "clean" index (all files are
546 marked IX_HASHVALID) can be very fast; we just check our repository and see
547 if the top level IX_HASHVALID sha1 exists.  If it does, then we're done.
548
549 Similarly, if not the entire index is valid, you can still avoid recursing
550 into subtrees if those particular subtrees are IX_HASHVALID and their sha1s
551 are in the repository.  The net result is that, as long as you never lose
552 your index, 'bup save' can always run very fast.
553
554 Another interesting trick is that you can skip backing up files even if
555 IX_HASHVALID *isn't* set, as long as you have that file's sha1 in the
556 repository.  What that means is you've chosen not to backup the latest
557 version of that file; instead, your new backup set just contains the
558 most-recently-known valid version of that file.  This is a good trick if you
559 want to do frequent backups of smallish files and infrequent backups of
560 large ones (as in 'bup save --smaller').  Each of your backups will be
561 "complete," in that they contain all the small files and the large ones, but
562 intermediate ones will just contain out-of-date copies of the large files.
563
564 A final game we can play with the bupindex involves restoring: when you
565 restore a directory from a previous backup, you can update the bupindex
566 right away.  Then, if you want to restore a different backup on top, you can
567 compare the files in the index against the ones in the backup set, and
568 update only the ones that have changed.  (Even more interesting things
569 happen if people are using the files on the restored system and you haven't
570 updated the index yet; the net result would be an automated merge of all
571 non-conflicting files.)  This would be a poor man's distributed filesystem. 
572 The only catch is that nobody has written 'bup restore' yet.  Someday!
573
574
575 How 'bup save' works (cmd/save)
576 --------------------
577
578 This section is too boring and has been omitted.  Once you understand the
579 index, there's nothing special about bup save.
580
581
582 Retrieving backups: the bup vfs layer (vfs.py, cmd/ls, cmd/ftp, cmd/fuse)
583 =====================================
584
585 One of the neat things about bup's storage format, at least compared to most
586 backup tools, is it's easy to read a particular file, or even part of a
587 file.  That means a read-only virtual filesystem is easy to generate and
588 it'll have good performance characteristics.  Because of git's commit
589 structure, you could even use branching and merging to make a transactional
590 read-write filesystem... but that's probably getting a little out of bup's
591 scope.  Who knows what the future might bring, though?
592
593 Read-only filesystems are well within our reach today, however.  The 'bup
594 ls', 'bup ftp', and 'bup fuse' commands all use a "VFS" (virtual filesystem)
595 layer to let you access your repositories.  Feel free to explore the source
596 code for these tools and vfs.py - they're pretty straightforward.  Some
597 things to note:
598
599  - None of these use the bupindex for anything.
600  
601  - For user-friendliness, they present your refs/commits/trees as a single
602    hierarchy (ie.  a filesystem), which isn't really how git repositories
603    are formatted.  So don't get confused!
604
605
606 We hope you'll enjoy bup.  Looking forward to your patches!
607
608 -- apenwarr and the rest of the bup team