read-cache.c: read prefix-compressed names in index on-disk version v4
Because the entries are sorted by path, adjacent entries in the index tend to share the leading components of them, and it makes sense to only store the differences in later entries. In the v4 on-disk format of the index, each on-disk cache entry stores the number of bytes to be stripped from the end of the previous name, and the bytes to append to the result, to come up with its name. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Apr 3, 2012 at 15:53 UTC
6c9cd161d9d1bee349b1389d661282c92da098bc
1 file changed
+51
-7
read-cache.c
+51
-7
@@ -12,6 +12,8 @@
12
#include "commit.h"
13
#include "blob.h"
14
#include "resolve-undo.h"
15
+#include "strbuf.h"
16
+#include "varint.h"
17
18
static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
19
@@ -1236,6 +1238,7 @@ struct ondisk_cache_entry_extended {
1238
char name[FLEX_ARRAY]; /* more */
1239
};
1240
1241
+/* These are only used for v3 or lower */
1242
#define align_flex_name(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
1243
#define ondisk_cache_entry_size(len) align_flex_name(ondisk_cache_entry,len)
1244
#define ondisk_cache_entry_extended_size(len) align_flex_name(ondisk_cache_entry_extended,len)
@@ -1252,7 +1255,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
1255
if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
1256
return error("bad signature");
1257
hdr_version = ntohl(hdr->hdr_version);
1255
- if (hdr_version < 2 || 3 < hdr_version)
1258
+ if (hdr_version < 2 || 4 < hdr_version)
1259
return error("bad index version %d", hdr_version);
1260
git_SHA1_Init(&c);
1261
git_SHA1_Update(&c, hdr, size - 20);
@@ -1331,8 +1334,30 @@ static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *on
1334
return ce;
1335
}
1336
1337
+/*
1338
+ * Adjacent cache entries tend to share the leading paths, so it makes
1339
+ * sense to only store the differences in later entries. In the v4
1340
+ * on-disk format of the index, each on-disk cache entry stores the
1341
+ * number of bytes to be stripped from the end of the previous name,
1342
+ * and the bytes to append to the result, to come up with its name.
1343
+ */
1344
+static unsigned long expand_name_field(struct strbuf *name, const char *cp_)
1345
+{
1346
+ const unsigned char *ep, *cp = (const unsigned char *)cp_;
1347
+ size_t len = decode_varint(&cp);
1348
+
1349
+ if (name->len < len)
1350
+ die("malformed name field in the index");
1351
+ strbuf_remove(name, name->len - len, len);
1352
+ for (ep = cp; *ep; ep++)
1353
+ ; /* find the end */
1354
+ strbuf_add(name, cp, ep - cp);
1355
+ return (const char *)ep + 1 - cp_;
1356
+}
1357
+
1358
static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk,
1335
- unsigned long *ent_size)
1359
+ unsigned long *ent_size,
1360
+ struct strbuf *previous_name)
1361
{
1362
struct cache_entry *ce;
1363
size_t len;
@@ -1357,10 +1382,22 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk,
1382
else
1383
name = ondisk->name;
1384
1360
- if (len == CE_NAMEMASK)
1361
- len = strlen(name);
1362
- ce = cache_entry_from_ondisk(ondisk, flags, name, len);
1363
- *ent_size = ondisk_ce_size(ce);
1385
+ if (!previous_name) {
1386
+ /* v3 and earlier */
1387
+ if (len == CE_NAMEMASK)
1388
+ len = strlen(name);
1389
+ ce = cache_entry_from_ondisk(ondisk, flags, name, len);
1390
+
1391
+ *ent_size = ondisk_ce_size(ce);
1392
+ } else {
1393
+ unsigned long consumed;
1394
+ consumed = expand_name_field(previous_name, name);
1395
+ ce = cache_entry_from_ondisk(ondisk, flags,
1396
+ previous_name->buf,
1397
+ previous_name->len);
1398
+
1399
+ *ent_size = (name - ((char *)ondisk)) + consumed;
1400
+ }
1401
return ce;
1402
}
1403
@@ -1373,6 +1410,7 @@ int read_index_from(struct index_state *istate, const char *path)
1410
struct cache_header *hdr;
1411
void *mmap;
1412
size_t mmap_size;
1413
+ struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
1414
1415
errno = EBUSY;
1416
if (istate->initialized)
@@ -1410,6 +1448,11 @@ int read_index_from(struct index_state *istate, const char *path)
1448
istate->cache = xcalloc(istate->cache_alloc, sizeof(struct cache_entry *));
1449
istate->initialized = 1;
1450
1451
+ if (hdr->hdr_version == htonl(4))
1452
+ previous_name = &previous_name_buf;
1453
+ else
1454
+ previous_name = NULL;
1455
+
1456
src_offset = sizeof(*hdr);
1457
for (i = 0; i < istate->cache_nr; i++) {
1458
struct ondisk_cache_entry *disk_ce;
@@ -1417,11 +1460,12 @@ int read_index_from(struct index_state *istate, const char *path)
1460
unsigned long consumed;
1461
1462
disk_ce = (struct ondisk_cache_entry *)((char *)mmap + src_offset);
1420
- ce = create_from_disk(disk_ce, &consumed);
1463
+ ce = create_from_disk(disk_ce, &consumed, previous_name);
1464
set_index_entry(istate, i, ce);
1465
1466
src_offset += consumed;
1467
}
1468
+ strbuf_release(&previous_name_buf);
1469
istate->timestamp.sec = st.st_mtime;
1470
istate->timestamp.nsec = ST_MTIME_NSEC(st);
1471