Initial support for efficient sub-file incrementals.
[cumulus.git] / subfile.h
diff --git a/subfile.h b/subfile.h
new file mode 100644 (file)
index 0000000..e80f76c
--- /dev/null
+++ b/subfile.h
@@ -0,0 +1,94 @@
+/* Cumulus: Smart Filesystem Backup to Dumb Servers
+ *
+ * Copyright (C) 2008  The Regents of the University of California
+ * Written by Michael Vrable <mvrable@cs.ucsd.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Allow for sub-file incremental backups: if only a portion of a file changes,
+ * allow the new data to be written out, and the old data to simply be
+ * referenced from the new metadata log. */
+
+#ifndef _LBS_SUBFILE_H
+#define _LBS_SUBFILE_H
+
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "chunk.h"
+#include "localdb.h"
+#include "ref.h"
+#include "store.h"
+
+class Subfile {
+public:
+    Subfile(LocalDb *localdb);
+    ~Subfile();
+
+    // Prepare to compute a subfile incremental by loading signatures for data
+    // in the old file.
+    void load_old_blocks(const std::list<ObjectReference> &blocks);
+
+    // Break a new block of data into small chunks, and compute checksums of
+    // the chunks.  After doing so, a delta can be computed, or the signatures
+    // can be written out to the database.  The caller must not modify the
+    // buffer until all operations referring to it are finished.
+    void analyze_new_block(const char *buf, size_t len);
+
+    std::list<ObjectReference> create_incremental(TarSegmentStore *tss,
+                                                  LbsObject *o,
+                                                  double block_age);
+
+    static const int HASH_SIZE = 20;
+
+private:
+    struct chunk_info {
+        char hash[HASH_SIZE];
+        int offset, len;
+    };
+
+    struct block_summary {
+        ObjectReference ref;
+        int num_chunks;
+        struct chunk_info *chunks;
+    };
+
+    LocalDb *db;
+    bool checksums_loaded;
+    std::set<ObjectReference> old_blocks;
+    std::vector<block_summary> block_list;
+    std::map<std::string, std::pair<int, int> > chunk_index;
+
+    bool new_block_summary_valid;
+    block_summary new_block_summary;
+
+    const char *analyzed_buf;
+    size_t analyzed_len;
+
+    void ensure_signatures_loaded();
+    void index_chunks(ObjectReference ref);
+    void free_analysis();
+    void store_block_signatures(ObjectReference ref, block_summary summary);
+
+    std::string get_algorithm() {
+        return chunk_algorithm_name() + "/sha1";
+    }
+};
+
+#endif // _LBS_SUBFILE_H