summaryrefslogtreecommitdiff
path: root/fast-import.c
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2007-01-15 13:00:49 (GMT)
committerShawn O. Pearce <spearce@spearce.org>2007-01-15 13:00:49 (GMT)
commitd9ee53ce45b0f1c26285417b900b3c5735721f7e (patch)
treefabba64d27ab1c18d96fd6c973a2e5e1c9167b43 /fast-import.c
parent2fce1f3c862845d23b2bd8305f97abb115623192 (diff)
downloadgit-d9ee53ce45b0f1c26285417b900b3c5735721f7e.zip
git-d9ee53ce45b0f1c26285417b900b3c5735721f7e.tar.gz
git-d9ee53ce45b0f1c26285417b900b3c5735721f7e.tar.bz2
Implemented automatic checkpoints within fast-import.
When the number of objects or number of bytes gets close to the limit allowed by the packfile format (or configured on the command line by our caller) we should automatically checkpoint the current packfile and start a new one before writing the object out. This does however require that we abandon the delta (if we had one) as its not valid in a new packfile. I also added the simple rule that if we got a delta back but the delta itself is the same size as or larger than the uncompressed object to ignore the delta and just store the object data. This should avoid some really bad behavior caused by our current delta strategy. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'fast-import.c')
-rw-r--r--fast-import.c96
1 files changed, 68 insertions, 28 deletions
diff --git a/fast-import.c b/fast-import.c
index cfadda0..c19567f 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -217,6 +217,8 @@ struct hash_list
/* Stats and misc. counters */
static unsigned long max_depth = 10;
+static unsigned long max_objects = -1;
+static unsigned long max_packsize = -1;
static unsigned long alloc_count;
static unsigned long branch_count;
static unsigned long branch_load_count;
@@ -303,7 +305,6 @@ static struct object_entry* new_object(unsigned char *sha1)
alloc_objects(object_entry_alloc);
e = blocks->next_free++;
- e->pack_id = pack_id;
hashcpy(e->sha1, sha1);
return e;
}
@@ -678,12 +679,9 @@ static void write_index(const char *idx_name)
idx = xmalloc(object_count * sizeof(struct object_entry*));
c = idx;
for (o = blocks; o; o = o->next_pool)
- for (e = o->next_free; e-- != o->entries;) {
- if (pack_id != e->pack_id)
- goto sort_index;
- *c++ = e;
- }
-sort_index:
+ for (e = o->next_free; e-- != o->entries;)
+ if (pack_id == e->pack_id)
+ *c++ = e;
last = idx + object_count;
if (c != last)
die("internal consistency error creating the index");
@@ -746,6 +744,12 @@ static void end_packfile()
last_blob.depth = 0;
}
+static void checkpoint()
+{
+ end_packfile();
+ start_packfile();
+}
+
static size_t encode_header(
enum object_type type,
size_t size,
@@ -800,20 +804,64 @@ static int store_object(
duplicate_count_by_type[type]++;
return 1;
}
- e->type = type;
- e->offset = pack_size;
- object_count++;
- object_count_by_type[type]++;
- if (last && last->data && last->depth < max_depth)
+ if (last && last->data && last->depth < max_depth) {
delta = diff_delta(last->data, last->len,
dat, datlen,
&deltalen, 0);
- else
- delta = 0;
+ if (delta && deltalen >= datlen) {
+ free(delta);
+ delta = NULL;
+ }
+ } else
+ delta = NULL;
memset(&s, 0, sizeof(s));
deflateInit(&s, zlib_compression_level);
+ if (delta) {
+ s.next_in = delta;
+ s.avail_in = deltalen;
+ } else {
+ s.next_in = dat;
+ s.avail_in = datlen;
+ }
+ s.avail_out = deflateBound(&s, s.avail_in);
+ s.next_out = out = xmalloc(s.avail_out);
+ while (deflate(&s, Z_FINISH) == Z_OK)
+ /* nothing */;
+ deflateEnd(&s);
+
+ /* Determine if we should auto-checkpoint. */
+ if ((object_count + 1) > max_objects
+ || (object_count + 1) < object_count
+ || (pack_size + 60 + s.total_out) > max_packsize
+ || (pack_size + 60 + s.total_out) < pack_size) {
+
+ /* This new object needs to *not* have the current pack_id. */
+ e->pack_id = pack_id + 1;
+ checkpoint();
+
+ /* We cannot carry a delta into the new pack. */
+ if (delta) {
+ free(delta);
+ delta = NULL;
+ }
+ memset(&s, 0, sizeof(s));
+ deflateInit(&s, zlib_compression_level);
+ s.next_in = dat;
+ s.avail_in = datlen;
+ s.avail_out = deflateBound(&s, s.avail_in);
+ s.next_out = out;
+ while (deflate(&s, Z_FINISH) == Z_OK)
+ /* nothing */;
+ deflateEnd(&s);
+ }
+
+ e->type = type;
+ e->pack_id = pack_id;
+ e->offset = pack_size;
+ object_count++;
+ object_count_by_type[type]++;
if (delta) {
unsigned long ofs = e->offset - last->offset;
@@ -821,8 +869,6 @@ static int store_object(
delta_count_by_type[type]++;
last->depth++;
- s.next_in = delta;
- s.avail_in = deltalen;
hdrlen = encode_header(OBJ_OFS_DELTA, deltalen, hdr);
write_or_die(pack_fd, hdr, hdrlen);
@@ -836,19 +882,11 @@ static int store_object(
} else {
if (last)
last->depth = 0;
- s.next_in = dat;
- s.avail_in = datlen;
hdrlen = encode_header(type, datlen, hdr);
write_or_die(pack_fd, hdr, hdrlen);
pack_size += hdrlen;
}
- s.avail_out = deflateBound(&s, s.avail_in);
- s.next_out = out = xmalloc(s.avail_out);
- while (deflate(&s, Z_FINISH) == Z_OK)
- /* nothing */;
- deflateEnd(&s);
-
write_or_die(pack_fd, out, s.total_out);
pack_size += s.total_out;
@@ -1754,10 +1792,8 @@ static void cmd_reset_branch()
static void cmd_checkpoint()
{
- if (object_count) {
- end_packfile();
- start_packfile();
- }
+ if (object_count)
+ checkpoint();
read_next_command();
}
@@ -1780,6 +1816,10 @@ int main(int argc, const char **argv)
break;
else if (!strncmp(a, "--objects=", 10))
est_obj_cnt = strtoul(a + 10, NULL, 0);
+ else if (!strncmp(a, "--max-objects-per-pack=", 23))
+ max_objects = strtoul(a + 23, NULL, 0);
+ else if (!strncmp(a, "--max-pack-size=", 16))
+ max_packsize = strtoul(a + 16, NULL, 0) * 1024 * 1024;
else if (!strncmp(a, "--depth=", 8))
max_depth = strtoul(a + 8, NULL, 0);
else if (!strncmp(a, "--active-branches=", 18))