Merge branch 'rs/allocate-cache-entry-individually'

* rs/allocate-cache-entry-individually:
  cache.h: put single NUL at end of struct cache_entry
  read-cache.c: allocate index entries individually

Conflicts:
	read-cache.c
This commit is contained in:
Junio C Hamano 2011-12-09 13:36:56 -08:00
commit ef87690b27
2 changed files with 38 additions and 58 deletions

View File

@ -306,7 +306,7 @@ static inline unsigned int canon_mode(unsigned int mode)
} }
#define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7) #define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
#define cache_entry_size(len) flexible_size(cache_entry,len) #define cache_entry_size(len) (offsetof(struct cache_entry,name) + (len) + 1)
#define ondisk_cache_entry_size(len) flexible_size(ondisk_cache_entry,len) #define ondisk_cache_entry_size(len) flexible_size(ondisk_cache_entry,len)
#define ondisk_cache_entry_extended_size(len) flexible_size(ondisk_cache_entry_extended,len) #define ondisk_cache_entry_extended_size(len) flexible_size(ondisk_cache_entry_extended,len)
@ -316,7 +316,6 @@ struct index_state {
struct string_list *resolve_undo; struct string_list *resolve_undo;
struct cache_tree *cache_tree; struct cache_tree *cache_tree;
struct cache_time timestamp; struct cache_time timestamp;
void *alloc;
unsigned name_hash_initialized : 1, unsigned name_hash_initialized : 1,
initialized : 1; initialized : 1;
struct hash_table name_hash; struct hash_table name_hash;

View File

@ -1224,10 +1224,35 @@ int read_index(struct index_state *istate)
return read_index_from(istate, get_index_file()); return read_index_from(istate, get_index_file());
} }
static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_entry *ce) static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk)
{ {
struct cache_entry *ce;
size_t len; size_t len;
const char *name; const char *name;
unsigned int flags;
/* On-disk flags are just 16 bits */
flags = ntohs(ondisk->flags);
len = flags & CE_NAMEMASK;
if (flags & CE_EXTENDED) {
struct ondisk_cache_entry_extended *ondisk2;
int extended_flags;
ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
extended_flags = ntohs(ondisk2->flags2) << 16;
/* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
if (extended_flags & ~CE_EXTENDED_FLAGS)
die("Unknown index entry format %08x", extended_flags);
flags |= extended_flags;
name = ondisk2->name;
}
else
name = ondisk->name;
if (len == CE_NAMEMASK)
len = strlen(name);
ce = xmalloc(cache_entry_size(len));
ce->ce_ctime.sec = ntohl(ondisk->ctime.sec); ce->ce_ctime.sec = ntohl(ondisk->ctime.sec);
ce->ce_mtime.sec = ntohl(ondisk->mtime.sec); ce->ce_mtime.sec = ntohl(ondisk->mtime.sec);
@ -1239,48 +1264,13 @@ static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_en
ce->ce_uid = ntohl(ondisk->uid); ce->ce_uid = ntohl(ondisk->uid);
ce->ce_gid = ntohl(ondisk->gid); ce->ce_gid = ntohl(ondisk->gid);
ce->ce_size = ntohl(ondisk->size); ce->ce_size = ntohl(ondisk->size);
/* On-disk flags are just 16 bits */ ce->ce_flags = flags;
ce->ce_flags = ntohs(ondisk->flags);
hashcpy(ce->sha1, ondisk->sha1); hashcpy(ce->sha1, ondisk->sha1);
len = ce->ce_flags & CE_NAMEMASK; memcpy(ce->name, name, len);
ce->name[len] = '\0';
if (ce->ce_flags & CE_EXTENDED) { return ce;
struct ondisk_cache_entry_extended *ondisk2;
int extended_flags;
ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
extended_flags = ntohs(ondisk2->flags2) << 16;
/* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
if (extended_flags & ~CE_EXTENDED_FLAGS)
die("Unknown index entry format %08x", extended_flags);
ce->ce_flags |= extended_flags;
name = ondisk2->name;
}
else
name = ondisk->name;
if (len == CE_NAMEMASK)
len = strlen(name);
/*
* NEEDSWORK: If the original index is crafted, this copy could
* go unchecked.
*/
memcpy(ce->name, name, len + 1);
}
static inline size_t estimate_cache_size(size_t ondisk_size, unsigned int entries)
{
size_t fix_size_mem = offsetof(struct cache_entry, name);
size_t fix_size_dsk = offsetof(struct ondisk_cache_entry, name);
long per_entry = (fix_size_mem - fix_size_dsk + 7) & ~7;
/*
* Alignment can cause differences. This should be "alignof", but
* since that's a gcc'ism, just use the size of a pointer.
*/
per_entry += sizeof(void *);
return ondisk_size + entries*per_entry;
} }
/* remember to discard_cache() before reading a different cache! */ /* remember to discard_cache() before reading a different cache! */
@ -1288,7 +1278,7 @@ int read_index_from(struct index_state *istate, const char *path)
{ {
int fd, i; int fd, i;
struct stat st; struct stat st;
unsigned long src_offset, dst_offset; unsigned long src_offset;
struct cache_header *hdr; struct cache_header *hdr;
void *mmap; void *mmap;
size_t mmap_size; size_t mmap_size;
@ -1327,29 +1317,18 @@ int read_index_from(struct index_state *istate, const char *path)
istate->cache_nr = ntohl(hdr->hdr_entries); istate->cache_nr = ntohl(hdr->hdr_entries);
istate->cache_alloc = alloc_nr(istate->cache_nr); istate->cache_alloc = alloc_nr(istate->cache_nr);
istate->cache = xcalloc(istate->cache_alloc, sizeof(struct cache_entry *)); istate->cache = xcalloc(istate->cache_alloc, sizeof(struct cache_entry *));
/*
* The disk format is actually larger than the in-memory format,
* due to space for nsec etc, so even though the in-memory one
* has room for a few more flags, we can allocate using the same
* index size
*/
istate->alloc = xmalloc(estimate_cache_size(mmap_size, istate->cache_nr));
istate->initialized = 1; istate->initialized = 1;
src_offset = sizeof(*hdr); src_offset = sizeof(*hdr);
dst_offset = 0;
for (i = 0; i < istate->cache_nr; i++) { for (i = 0; i < istate->cache_nr; i++) {
struct ondisk_cache_entry *disk_ce; struct ondisk_cache_entry *disk_ce;
struct cache_entry *ce; struct cache_entry *ce;
disk_ce = (struct ondisk_cache_entry *)((char *)mmap + src_offset); disk_ce = (struct ondisk_cache_entry *)((char *)mmap + src_offset);
ce = (struct cache_entry *)((char *)istate->alloc + dst_offset); ce = create_from_disk(disk_ce);
convert_from_disk(disk_ce, ce);
set_index_entry(istate, i, ce); set_index_entry(istate, i, ce);
src_offset += ondisk_ce_size(ce); src_offset += ondisk_ce_size(ce);
dst_offset += ce_size(ce);
} }
istate->timestamp.sec = st.st_mtime; istate->timestamp.sec = st.st_mtime;
istate->timestamp.nsec = ST_MTIME_NSEC(st); istate->timestamp.nsec = ST_MTIME_NSEC(st);
@ -1383,11 +1362,15 @@ unmap:
int is_index_unborn(struct index_state *istate) int is_index_unborn(struct index_state *istate)
{ {
return (!istate->cache_nr && !istate->alloc && !istate->timestamp.sec); return (!istate->cache_nr && !istate->timestamp.sec);
} }
int discard_index(struct index_state *istate) int discard_index(struct index_state *istate)
{ {
int i;
for (i = 0; i < istate->cache_nr; i++)
free(istate->cache[i]);
resolve_undo_clear_index(istate); resolve_undo_clear_index(istate);
istate->cache_nr = 0; istate->cache_nr = 0;
istate->cache_changed = 0; istate->cache_changed = 0;
@ -1396,8 +1379,6 @@ int discard_index(struct index_state *istate)
istate->name_hash_initialized = 0; istate->name_hash_initialized = 0;
free_hash(&istate->name_hash); free_hash(&istate->name_hash);
cache_tree_free(&(istate->cache_tree)); cache_tree_free(&(istate->cache_tree));
free(istate->alloc);
istate->alloc = NULL;
istate->initialized = 0; istate->initialized = 0;
/* no need to throw away allocated active_cache */ /* no need to throw away allocated active_cache */