{"thread":{"id":"8414","subject":"[PATCH] pack-check: Sort entries by pack offset before unpacking them.","startedAt":"2007-06-03T18:21:41Z","lastAt":"2007-06-03T18:21:41Z","messageCount":1,"participants":["Alexandre Julliard"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"43893","messageId":"87ps4csxu2.fsf@wine.dyndns.org","threadId":"8414","inReplyTo":null,"subject":"[PATCH] pack-check: Sort entries by pack offset before unpacking them.","fromName":"Alexandre Julliard","fromEmail":"julliard@winehq.org","sentAt":"2007-06-03T18:21:41Z","receivedAt":"2007-06-03T18:21:41Z","isPatch":true,"sender":{"key":"julliard@winehq.org","avatar":null},"body":"Because of the way objects are sorted in a pack, unpacking them in\ndisk order is much more efficient than random access. Tests on the\nWine repository show a gain in pack validation time of about 35%.\n\nSigned-off-by: Alexandre Julliard <julliard@winehq.org>\n---\n pack-check.c |   47 +++++++++++++++++++++++++++++++++++------------\n 1 files changed, 35 insertions(+), 12 deletions(-)\n\ndiff --git a/pack-check.c b/pack-check.c\nindex 3623c71..d7dd62b 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -1,6 +1,23 @@\n #include \"cache.h\"\n #include \"pack.h\"\n \n+struct idx_entry\n+{\n+\tconst unsigned char *sha1;\n+\toff_t                offset;\n+};\n+\n+static int compare_entries(const void *e1, const void *e2)\n+{\n+\tconst struct idx_entry *entry1 = e1;\n+\tconst struct idx_entry *entry2 = e2;\n+\tif (entry1->offset < entry2->offset)\n+\t\treturn -1;\n+\tif (entry1->offset > entry2->offset)\n+\t\treturn 1;\n+\treturn 0;\n+}\n+\n static int verify_packfile(struct packed_git *p,\n \t\tstruct pack_window **w_curs)\n {\n@@ -11,6 +28,7 @@ static int verify_packfile(struct packed_git *p,\n \toff_t offset = 0, pack_sig = p->pack_size - 20;\n \tuint32_t nr_objects, i;\n \tint err;\n+\tstruct idx_entry *entries;\n \n \t/* Note that the pack header checks are actually performed by\n \t * use_pack when it first opens the pack file.  If anything\n@@ -41,33 +59,38 @@ static int verify_packfile(struct packed_git *p,\n \t * we do not do scan-streaming check on the pack file.\n \t */\n \tnr_objects = p->num_objects;\n+\tentries = xmalloc(nr_objects * sizeof(*entries));\n+\t/* first sort entries by pack offset, since unpacking them is more efficient that way */\n+\tfor (i = 0; i < nr_objects; i++) {\n+\t\tentries[i].sha1 = nth_packed_object_sha1(p, i);\n+\t\tif (!entries[i].sha1)\n+\t\t\tdie(\"internal error pack-check nth-packed-object\");\n+\t\tentries[i].offset = find_pack_entry_one(entries[i].sha1, p);\n+\t\tif (!entries[i].offset)\n+\t\t\tdie(\"internal error pack-check find-pack-entry-one\");\n+\t}\n+\tqsort(entries, nr_objects, sizeof(*entries), compare_entries);\n+\n \tfor (i = 0, err = 0; i < nr_objects; i++) {\n-\t\tconst unsigned char *sha1;\n \t\tvoid *data;\n \t\tenum object_type type;\n \t\tunsigned long size;\n-\t\toff_t offset;\n \n-\t\tsha1 = nth_packed_object_sha1(p, i);\n-\t\tif (!sha1)\n-\t\t\tdie(\"internal error pack-check nth-packed-object\");\n-\t\toffset = find_pack_entry_one(sha1, p);\n-\t\tif (!offset)\n-\t\t\tdie(\"internal error pack-check find-pack-entry-one\");\n-\t\tdata = unpack_entry(p, offset, &type, &size);\n+\t\tdata = unpack_entry(p, entries[i].offset, &type, &size);\n \t\tif (!data) {\n \t\t\terr = error(\"cannot unpack %s from %s\",\n-\t\t\t\t    sha1_to_hex(sha1), p->pack_name);\n+\t\t\t\t    sha1_to_hex(entries[i].sha1), p->pack_name);\n \t\t\tcontinue;\n \t\t}\n-\t\tif (check_sha1_signature(sha1, data, size, typename(type))) {\n+\t\tif (check_sha1_signature(entries[i].sha1, data, size, typename(type))) {\n \t\t\terr = error(\"packed %s from %s is corrupt\",\n-\t\t\t\t    sha1_to_hex(sha1), p->pack_name);\n+\t\t\t\t    sha1_to_hex(entries[i].sha1), p->pack_name);\n \t\t\tfree(data);\n \t\t\tcontinue;\n \t\t}\n \t\tfree(data);\n \t}\n+\tfree(entries);\n \n \treturn err;\n }\n-- \n1.5.2.156.gb09c8\n\n-- \nAlexandre Julliard\njulliard@winehq.org\n"}]}