Ensure metadata file is written prior to calculating checksum.
[cumulus.git] / subfile.h
1 /* Cumulus: Efficient Filesystem Backup to the Cloud
2  * Copyright (C) 2008 The Cumulus Developers
3  * See the AUTHORS file for a list of contributors.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 /* Allow for sub-file incremental backups: if only a portion of a file changes,
21  * allow the new data to be written out, and the old data to simply be
22  * referenced from the new metadata log. */
23
24 #ifndef _LBS_SUBFILE_H
25 #define _LBS_SUBFILE_H
26
27 #include <list>
28 #include <map>
29 #include <set>
30 #include <string>
31 #include <vector>
32
33 #include "localdb.h"
34 #include "ref.h"
35 #include "store.h"
36 #include "third_party/chunk.h"
37
38 class Subfile {
39 public:
40     Subfile(LocalDb *localdb);
41     ~Subfile();
42
43     // Prepare to compute a subfile incremental by loading signatures for data
44     // in the old file.
45     void load_old_blocks(const std::list<ObjectReference> &blocks);
46
47     // Break a new block of data into small chunks, and compute checksums of
48     // the chunks.  After doing so, a delta can be computed, or the signatures
49     // can be written out to the database.  The caller must not modify the
50     // buffer until all operations referring to it are finished.
51     void analyze_new_block(const char *buf, size_t len);
52
53     // Store the signatures for the most recently-analyzed block in the local
54     // database (linked to the specified object), if the block is sufficiently
55     // large.  If signatures already exist, they will be overwritten.
56     void store_analyzed_signatures(ObjectReference ref);
57
58     std::list<ObjectReference> create_incremental(TarSegmentStore *tss,
59                                                   LbsObject *o,
60                                                   double block_age);
61
62     static const int HASH_SIZE = 20;
63
64 private:
65     std::string algorithm_name;
66     size_t hash_size;
67
68     struct chunk_info {
69         int offset, len;
70         std::string hash;
71     };
72
73     struct block_summary {
74         ObjectReference ref;
75         int num_chunks;
76         struct chunk_info *chunks;
77     };
78
79     LocalDb *db;
80     bool checksums_loaded;
81     std::set<ObjectReference> old_blocks;
82     std::vector<block_summary> block_list;
83     std::map<std::string, std::pair<int, int> > chunk_index;
84
85     bool new_block_summary_valid;
86     block_summary new_block_summary;
87
88     const char *analyzed_buf;
89     size_t analyzed_len;
90
91     void ensure_signatures_loaded();
92     void index_chunks(ObjectReference ref);
93     void free_analysis();
94     void store_block_signatures(ObjectReference ref, block_summary summary);
95 };
96
97 #endif // _LBS_SUBFILE_H