Re: [RFH] CE_REMOVE conversion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Thu, 21 Feb 2008, Junio C Hamano wrote:
> 
> And we probably should unhash the entry instead of just removing
> it?  Come to think of it, I am starting to wonder if the
> entries unpack-trees add to and drop from the index are hashed
> and unhashed correctly...

Heh. This was exactly what I was working on, and here's an early patch.

I say "early" just because I haven't really gone through it more than 
once, and testing that it passes all the tests.

It includes your "continue" fix, since that was actually related to the 
"remove_index_entry()" addition this needs. It also contains the hash next 
pointer initialization.

The bulk of the patch is moving (and renaming) the "remove_index_entry()" 
function (used to be remove_hash_entry, but it's very specific to the 
index, not to general hashes), and the comment that goes with it.

I also made that "copy a cache entry" thing use a function of its own, and 
made sure it saves/restores the hash pointer rather than using a naked 
"memcpy()" with offsetof etc. At least it's abstracted away, even if the 
function itself is ugly as sin.

Everything else is really just one-liners.

But I'm still looking at this. In particular, I want to add some 
assertions to make sure the index state matches the name hash state, but 
your lazy patch makes that less convenient.

		Linus

---
 builtin-read-tree.c |    3 ++-
 cache.h             |   21 +++++++++++++++++++++
 read-cache.c        |   19 +++----------------
 unpack-trees.c      |    2 +-
 4 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/builtin-read-tree.c b/builtin-read-tree.c
index 5785401..7bdc312 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -41,11 +41,12 @@ static int read_cache_unmerged(void)
 	for (i = 0; i < active_nr; i++) {
 		struct cache_entry *ce = active_cache[i];
 		if (ce_stage(ce)) {
+			remove_index_entry(ce);
 			if (last && !strcmp(ce->name, last->name))
 				continue;
 			cache_tree_invalidate_path(active_cache_tree, ce->name);
 			last = ce;
-			ce->ce_flags |= CE_REMOVE;
+			continue;
 		}
 		*dst++ = ce;
 	}
diff --git a/cache.h b/cache.h
index e1000bc..32fa6da 100644
--- a/cache.h
+++ b/cache.h
@@ -135,6 +135,27 @@ struct cache_entry {
 #define CE_UPTODATE  (0x40000)
 #define CE_UNHASHED  (0x80000)
 
+static inline void copy_cache_entry(struct cache_entry *dst, struct cache_entry *src)
+{
+	struct cache_entry *next = dst->next;
+	memcpy(dst, src, offsetof(struct cache_entry, name));
+	dst->next = next;
+}
+
+/*
+ * We don't actually *remove* it, we can just mark it invalid so that
+ * we won't find it in lookups.
+ *
+ * Not only would we have to search the lists (simple enough), but
+ * we'd also have to rehash other hash buckets in case this makes the
+ * hash bucket empty (common). So it's much better to just mark
+ * it.
+ */
+static inline void remove_index_entry(struct cache_entry *ce)
+{
+	ce->ce_flags |= CE_UNHASHED;
+}
+
 static inline unsigned create_ce_flags(size_t len, unsigned stage)
 {
 	if (len >= CE_NAMEMASK)
diff --git a/read-cache.c b/read-cache.c
index e45f4b3..e8e2be8 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -39,6 +39,7 @@ static void hash_index_entry(struct index_state *istate, struct cache_entry *ce)
 	void **pos;
 	unsigned int hash = hash_name(ce->name, ce_namelen(ce));
 
+	ce->next = NULL;
 	pos = insert_hash(hash, ce, &istate->name_hash);
 	if (pos) {
 		ce->next = *pos;
@@ -64,26 +65,12 @@ static void set_index_entry(struct index_state *istate, int nr, struct cache_ent
 		hash_index_entry(istate, ce);
 }
 
-/*
- * We don't actually *remove* it, we can just mark it invalid so that
- * we won't find it in lookups.
- *
- * Not only would we have to search the lists (simple enough), but
- * we'd also have to rehash other hash buckets in case this makes the
- * hash bucket empty (common). So it's much better to just mark
- * it.
- */
-static void remove_hash_entry(struct index_state *istate, struct cache_entry *ce)
-{
-	ce->ce_flags |= CE_UNHASHED;
-}
-
 static void replace_index_entry(struct index_state *istate, int nr, struct cache_entry *ce)
 {
 	struct cache_entry *old = istate->cache[nr];
 
 	if (ce != old) {
-		remove_hash_entry(istate, old);
+		remove_index_entry(old);
 		set_index_entry(istate, nr, ce);
 	}
 	istate->cache_changed = 1;
@@ -413,7 +400,7 @@ int remove_index_entry_at(struct index_state *istate, int pos)
 {
 	struct cache_entry *ce = istate->cache[pos];
 
-	remove_hash_entry(istate, ce);
+	remove_index_entry(ce);
 	istate->cache_changed = 1;
 	istate->cache_nr--;
 	if (pos >= istate->cache_nr)
diff --git a/unpack-trees.c b/unpack-trees.c
index ec558f9..07c4c28 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -590,7 +590,7 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
 		 * a match.
 		 */
 		if (same(old, merge)) {
-			memcpy(merge, old, offsetof(struct cache_entry, name));
+			copy_cache_entry(merge, old);
 		} else {
 			verify_uptodate(old, o);
 			invalidate_ce_path(old);
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux