Skip to content

Commit 419a597

Browse files
kbleesgitster
authored andcommitted
name-hash.c: remove cache entries instead of marking them CE_UNHASHED
The new hashmap implementation supports remove, so really remove unused cache entries from the name hashmap instead of just marking them. The CE_UNHASHED flag and CE_STATE_MASK are no longer needed. Keep the CE_HASHED flag to prevent adding entries twice. Signed-off-by: Karsten Blees <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8b01378 commit 419a597

File tree

4 files changed

+26
-30
lines changed

4 files changed

+26
-30
lines changed

cache.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ struct cache_entry {
160160
#define CE_ADDED (1 << 19)
161161

162162
#define CE_HASHED (1 << 20)
163-
#define CE_UNHASHED (1 << 21)
164163
#define CE_WT_REMOVE (1 << 22) /* remove in work directory */
165164
#define CE_CONFLICTED (1 << 23)
166165

@@ -196,19 +195,18 @@ struct pathspec;
196195
* Copy the sha1 and stat state of a cache entry from one to
197196
* another. But we never change the name, or the hash state!
198197
*/
199-
#define CE_STATE_MASK (CE_HASHED | CE_UNHASHED)
200198
static inline void copy_cache_entry(struct cache_entry *dst,
201199
const struct cache_entry *src)
202200
{
203-
unsigned int state = dst->ce_flags & CE_STATE_MASK;
201+
unsigned int state = dst->ce_flags & CE_HASHED;
204202

205203
/* Don't copy hash chain and name */
206204
memcpy(&dst->ce_stat_data, &src->ce_stat_data,
207205
offsetof(struct cache_entry, name) -
208206
offsetof(struct cache_entry, ce_stat_data));
209207

210208
/* Restore the hash state */
211-
dst->ce_flags = (dst->ce_flags & ~CE_STATE_MASK) | state;
209+
dst->ce_flags = (dst->ce_flags & ~CE_HASHED) | state;
212210
}
213211

214212
static inline unsigned create_ce_flags(unsigned stage)

name-hash.c

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,29 @@ static void hash_index_entry(struct index_state *istate, struct cache_entry *ce)
106106
hashmap_entry_init(ce, memihash(ce->name, ce_namelen(ce)));
107107
hashmap_add(&istate->name_hash, ce);
108108

109-
if (ignore_case && !(ce->ce_flags & CE_UNHASHED))
109+
if (ignore_case)
110110
add_dir_entry(istate, ce);
111111
}
112112

113+
static int cache_entry_cmp(const struct cache_entry *ce1,
114+
const struct cache_entry *ce2, const void *remove)
115+
{
116+
/*
117+
* For remove_name_hash, find the exact entry (pointer equality); for
118+
* index_name_exists, find all entries with matching hash code and
119+
* decide whether the entry matches in same_name.
120+
*/
121+
return remove ? !(ce1 == ce2) : 0;
122+
}
123+
113124
static void lazy_init_name_hash(struct index_state *istate)
114125
{
115126
int nr;
116127

117128
if (istate->name_hash_initialized)
118129
return;
119-
hashmap_init(&istate->name_hash, NULL, istate->cache_nr);
130+
hashmap_init(&istate->name_hash, (hashmap_cmp_fn) cache_entry_cmp,
131+
istate->cache_nr);
120132
hashmap_init(&istate->dir_hash, (hashmap_cmp_fn) dir_entry_cmp, 0);
121133
for (nr = 0; nr < istate->cache_nr; nr++)
122134
hash_index_entry(istate, istate->cache[nr]);
@@ -125,31 +137,19 @@ static void lazy_init_name_hash(struct index_state *istate)
125137

126138
void add_name_hash(struct index_state *istate, struct cache_entry *ce)
127139
{
128-
/* if already hashed, add reference to directory entries */
129-
if (ignore_case && (ce->ce_flags & CE_STATE_MASK) == CE_STATE_MASK)
130-
add_dir_entry(istate, ce);
131-
132-
ce->ce_flags &= ~CE_UNHASHED;
133140
if (istate->name_hash_initialized)
134141
hash_index_entry(istate, ce);
135142
}
136143

137-
/*
138-
* We don't actually *remove* it, we can just mark it invalid so that
139-
* we won't find it in lookups.
140-
*
141-
* Not only would we have to search the lists (simple enough), but
142-
* we'd also have to rehash other hash buckets in case this makes the
143-
* hash bucket empty (common). So it's much better to just mark
144-
* it.
145-
*/
146144
void remove_name_hash(struct index_state *istate, struct cache_entry *ce)
147145
{
148-
/* if already hashed, release reference to directory entries */
149-
if (ignore_case && (ce->ce_flags & CE_STATE_MASK) == CE_HASHED)
150-
remove_dir_entry(istate, ce);
146+
if (!istate->name_hash_initialized || !(ce->ce_flags & CE_HASHED))
147+
return;
148+
ce->ce_flags &= ~CE_HASHED;
149+
hashmap_remove(&istate->name_hash, ce, ce);
151150

152-
ce->ce_flags |= CE_UNHASHED;
151+
if (ignore_case)
152+
remove_dir_entry(istate, ce);
153153
}
154154

155155
static int slow_same_name(const char *name1, int len1, const char *name2, int len2)
@@ -220,10 +220,8 @@ struct cache_entry *index_file_exists(struct index_state *istate, const char *na
220220
hashmap_entry_init(&key, memihash(name, namelen));
221221
ce = hashmap_get(&istate->name_hash, &key, NULL);
222222
while (ce) {
223-
if (!(ce->ce_flags & CE_UNHASHED)) {
224-
if (same_name(ce, name, namelen, icase))
225-
return ce;
226-
}
223+
if (same_name(ce, name, namelen, icase))
224+
return ce;
227225
ce = hashmap_get_next(&istate->name_hash, ce);
228226
}
229227
return NULL;

read-cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n
5858

5959
new = xmalloc(cache_entry_size(namelen));
6060
copy_cache_entry(new, old);
61-
new->ce_flags &= ~CE_STATE_MASK;
61+
new->ce_flags &= ~CE_HASHED;
6262
new->ce_namelen = namelen;
6363
memcpy(new->name, new_name, namelen + 1);
6464

unpack-trees.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
105105
static void do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
106106
unsigned int set, unsigned int clear)
107107
{
108-
clear |= CE_HASHED | CE_UNHASHED;
108+
clear |= CE_HASHED;
109109

110110
if (set & CE_REMOVE)
111111
set |= CE_WT_REMOVE;

0 commit comments

Comments
 (0)