From: Dana How <danahow@gmail.com>
To: Junio C Hamano <junkio@cox.net>
Cc: Git Mailing List <git@vger.kernel.org>, danahow@gmail.com
Subject: [PATCH 5/8] get-repack --max-pack-size: write_object() takes 'limit' arg
Date: Sun, 08 Apr 2007 16:24:04 -0700 [thread overview]
Message-ID: <46197994.70009@gmail.com> (raw)
Accept new 'limit' argument and check against it
before each group of writes. Update delta usability rules
for possibility of delta base being in a previously-
written pack. Inline sha1write_compressed() so we know
the exact size of the written data when it needs to be compressed.
Signed-off-by: Dana How <how@deathvalley.cswitch.com>
---
builtin-pack-objects.c | 66 ++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 58 insertions(+), 8 deletions(-)
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 7ab0712..9530008 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -373,7 +373,8 @@ static int revalidate_loose_object(struct object_entry *entry,
}
static off_t write_object(struct sha1file *f,
- struct object_entry *entry)
+ struct object_entry *entry,
+ unsigned long limit)
{
unsigned long size;
enum object_type type;
@@ -407,6 +408,10 @@ static off_t write_object(struct sha1file *f,
if (revalidate_loose_object(entry, map, mapsize))
die("corrupt loose object %s",
sha1_to_hex(entry->sha1));
+ if ( limit && mapsize + 20 >= limit ) {
+ munmap(map, mapsize);
+ return 0;
+ }
sha1write(f, map, mapsize);
munmap(map, mapsize);
written++;
@@ -418,24 +423,51 @@ static off_t write_object(struct sha1file *f,
}
if (!to_reuse) {
+ z_stream stream;
+ unsigned long maxsize;
+ void *out;
+ /* no if no delta */
+ int usable_delta = !entry->delta ? 0 :
+ /* yes if unlimited packfile */
+ !offset_limit ? 1 :
+ /* no if base written to previous pack */
+ entry->delta->prev_pack ? 0 :
+ /* otherwise double-check written to this
+ * pack, like we do below
+ */
+ entry->delta->offset ? 1 : 0;
buf = read_sha1_file(entry->sha1, &type, &size);
if (!buf)
die("unable to read %s", sha1_to_hex(entry->sha1));
if (size != entry->size)
die("object %s size inconsistency (%lu vs %lu)",
sha1_to_hex(entry->sha1), size, entry->size);
- if (entry->delta) {
+ if (usable_delta) {
buf = delta_against(buf, size, entry);
size = entry->delta_size;
obj_type = (allow_ofs_delta && entry->delta->offset) ?
OBJ_OFS_DELTA : OBJ_REF_DELTA;
}
+ /* compress the data to store and put compressed length in datalen */
+ memset(&stream, 0, sizeof(stream));
+ deflateInit(&stream, zlib_compression_level);
+ maxsize = deflateBound(&stream, size);
+ out = xmalloc(maxsize);
+ /* Compress it */
+ stream.next_in = buf;
+ stream.avail_in = size;
+ stream.next_out = out;
+ stream.avail_out = maxsize;
+ while (deflate(&stream, Z_FINISH) == Z_OK)
+ /* nothing */;
+ deflateEnd(&stream);
+ datalen = stream.total_out;
+ deflateEnd(&stream);
/*
* The object header is a byte of 'type' followed by zero or
* more bytes of length.
*/
hdrlen = encode_header(obj_type, size, header);
- sha1write(f, header, hdrlen);
if (obj_type == OBJ_OFS_DELTA) {
/*
@@ -448,6 +480,12 @@ static off_t write_object(struct sha1file *f,
header[pos] = ofs & 127;
while (ofs >>= 7)
header[--pos] = 128 | (--ofs & 127);
+ if ( limit && hdrlen + sizeof(header) - pos + datalen + 20 >= limit ) {
+ free(out);
+ free(buf);
+ return 0;
+ }
+ sha1write(f, header, hdrlen);
sha1write(f, header + pos, sizeof(header) - pos);
hdrlen += sizeof(header) - pos;
} else if (obj_type == OBJ_REF_DELTA) {
@@ -455,10 +493,17 @@ static off_t write_object(struct sha1file *f,
* Deltas with a base reference contain
* an additional 20 bytes for the base sha1.
*/
+ if ( limit && hdrlen + 20 + datalen + 20 >= limit ) {
+ free(out);
+ free(buf);
+ return 0;
+ }
+ sha1write(f, header, hdrlen);
sha1write(f, entry->delta->sha1, 20);
hdrlen += 20;
}
- datalen = sha1write_compressed(f, buf, size);
+ sha1write(f, out, datalen);
+ free(out);
free(buf);
}
else {
@@ -472,23 +517,28 @@ static off_t write_object(struct sha1file *f,
reused_delta++;
}
hdrlen = encode_header(obj_type, entry->size, header);
- sha1write(f, header, hdrlen);
+ datalen = find_packed_object_size(p, entry->in_pack_offset)
+ - entry->in_pack_header_size;
if (obj_type == OBJ_OFS_DELTA) {
off_t ofs = entry->offset - entry->delta->offset;
unsigned pos = sizeof(header) - 1;
header[pos] = ofs & 127;
while (ofs >>= 7)
header[--pos] = 128 | (--ofs & 127);
+ if ( limit && hdrlen + sizeof(header) - pos + datalen + 20 >= limit )
+ return 0;
+ sha1write(f, header, hdrlen);
sha1write(f, header + pos, sizeof(header) - pos);
hdrlen += sizeof(header) - pos;
} else if (obj_type == OBJ_REF_DELTA) {
+ if ( limit && hdrlen + 20 + datalen + 20 >= limit )
+ return 0;
+ sha1write(f, header, hdrlen);
sha1write(f, entry->delta->sha1, 20);
hdrlen += 20;
}
offset = entry->in_pack_offset + entry->in_pack_header_size;
- datalen = find_packed_object_size(p, entry->in_pack_offset)
- - entry->in_pack_header_size;
if (!pack_to_stdout && check_pack_inflate(p, &w_curs,
offset, datalen, entry->size))
die("corrupt delta in pack %s", sha1_to_hex(entry->sha1));
@@ -515,7 +565,7 @@ static off_t write_one(struct sha1file *f,
if (e->delta)
offset = write_one(f, e->delta, offset);
e->offset = offset;
- return offset + write_object(f, e);
+ return offset + write_object(f, e, 0);
}
/*
--
1.5.1.89.g8abf0
next reply other threads:[~2007-04-08 23:24 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-08 23:24 Dana How [this message]
2007-04-09 0:03 ` [PATCH 5/8] get-repack --max-pack-size: write_object() takes 'limit' arg Junio C Hamano
2007-04-09 0:15 ` Junio C Hamano
2007-04-09 2:28 ` Nicolas Pitre
2007-04-09 0:40 ` Nicolas Pitre
2007-04-09 18:51 ` Dana How
2007-04-09 18:59 ` Nicolas Pitre
2007-04-09 19:20 ` Dana How
2007-04-09 19:25 ` Nicolas Pitre
2007-04-09 20:09 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46197994.70009@gmail.com \
--to=danahow@gmail.com \
--cc=git@vger.kernel.org \
--cc=junkio@cox.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.