git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH/RFC v4 02/13] read-cache.c: Re-read index if index file changed

From
Thomas Gummerer <t.gummerer@gmail.com>
Date
Aug 16, 2012, 09:58 UTC
Message-ID
<1345111129-6925-3-git-send-email-t.gummerer@gmail.com>
In-Reply-To
<1345111129-6925-1-git-send-email-t.gummerer@gmail.com>

Add the possibility of re-reading the index file, if it changed while reading.

The index file might change during the read, causing outdated information to be displayed. We check if the index file changed by using its stat data as heuristic.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 read-cache.c | 87 +++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 60 insertions(+), 27 deletions(-)
diff --git a/read-cache.c b/read-cache.c
index 6a8b4b1..cdd8480 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1170,11 +1170,34 @@ int read_index(struct index_state *istate)
 	return read_index_from(istate, get_index_file());
 }
 
+static int index_changed(struct stat st_old, struct stat st_new)
+{
+	int changed = 0;
+
+	if (st_old.st_mtime != st_new.st_mtime ||
+	    st_old.st_uid   != st_new.st_uid ||
+	    st_old.st_gid   != st_new.st_gid ||
+	    st_old.st_ino   != st_new.st_ino ||
+	    st_old.st_size  != st_new.st_size)
+		changed = 1;
+#ifdef USE_NSEC
+	if (ST_MTIME_NSEC(st_old) != ST_MTIME_NSEC(st_new))
+		changed = 1;
+#endif
+
+#ifdef USE_STDEV
+	if (st_old.st_dev != st_new.st_dev)
+		changed = 1;
+#endif
+
+	return changed;
+}
+
 /* remember to discard_cache() before reading a different cache! */
 int read_index_from(struct index_state *istate, const char *path)
 {
-	int fd;
-	struct stat st;
+	int fd, err, i = 0;
+	struct stat st_old, st_new;
 	struct cache_version_header *hdr;
 	void *mmap;
 	size_t mmap_size;
@@ -1186,38 +1209,48 @@ int read_index_from(struct index_state *istate, const char *path)
 	errno = ENOENT;
 	istate->timestamp.sec = 0;
 	istate->timestamp.nsec = 0;
-	fd = open(path, O_RDONLY);
-	if (fd < 0) {
-		if (errno == ENOENT)
-			return 0;
-		die_errno("index file open failed");
-	}
+	do {
+		err = 0;
+		fd = open(path, O_RDONLY);
+		if (fd < 0) {
+			if (errno == ENOENT)
+				return 0;
+			die_errno("index file open failed");
+		}
 
-	if (fstat(fd, &st))
-		die_errno("cannot stat the open index");
+		if (fstat(fd, &st_old))
+			die_errno("cannot stat the open index");
 
-	errno = EINVAL;
-	mmap_size = xsize_t(st.st_size);
-	mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
-	close(fd);
-	if (mmap == MAP_FAILED)
-		die_errno("unable to map index file");
+		errno = EINVAL;
+		mmap_size = xsize_t(st_old.st_size);
+		mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+		close(fd);
+		if (mmap == MAP_FAILED)
+			die_errno("unable to map index file");
 
-	hdr = mmap;
-	if (verify_hdr_version(istate, hdr, mmap_size) < 0)
-		goto unmap;
+		hdr = mmap;
+		if (verify_hdr_version(istate, hdr, mmap_size) < 0)
+			err = 1;
 
-	if (istate->ops->verify_hdr(mmap, mmap_size) < 0)
-		goto unmap;
+		if (istate->ops->verify_hdr(mmap, mmap_size) < 0)
+			err = 1;
 
-	istate->ops->read_index(istate, mmap, mmap_size);
-	istate->timestamp.sec = st.st_mtime;
-	istate->timestamp.nsec = ST_MTIME_NSEC(st);
+		if (istate->ops->read_index(istate, mmap, mmap_size) < 0)
+			err = 1;
+		istate->timestamp.sec = st_old.st_mtime;
+		istate->timestamp.nsec = ST_MTIME_NSEC(st_old);
+		if (lstat(path, &st_new))
+			die_errno("cannot stat the open index");
 
-	munmap(mmap, mmap_size);
-	return istate->cache_nr;
+		munmap(mmap, mmap_size);
+
+		if (!index_changed(st_old, st_new) && !err)
+			return istate->cache_nr;
+
+		usleep(10*1000);
+		i++;
+	} while ((err || index_changed(st_old, st_new)) && i < 50);
 
-unmap:
 	munmap(mmap, mmap_size);
 	die("index file corrupt");
 }
-- 
1.7.11.2
Previous: Thomas GummererNext: Thomas Gummerer
Message 3 of 14 in “Introduce index file format version 5”
  1. 0/13 Introduce index file format version 5Thomas Gummerer, Aug 16, 2012
  2. 01/13 Move index v2 specific functions to their own fileThomas Gummerer, Aug 16, 2012
  3. 02/13 read-cache.c: Re-read index if index file changedThomas Gummerer, Aug 16, 2012
  4. 03/13 t2104: Don't fail for index versions other than [23]Thomas Gummerer, Aug 16, 2012
  5. 04/13 Add documentation of the index-v5 file formatThomas Gummerer, Aug 16, 2012
  6. 05/13 Make in-memory format aware of stat_crcThomas Gummerer, Aug 16, 2012
  7. 06/13 Read index-v5Thomas Gummerer, Aug 16, 2012
  8. 07/13 Read resolve-undo dataThomas Gummerer, Aug 16, 2012
  9. 08/13 Read cache-tree in index-v5Thomas Gummerer, Aug 16, 2012
  10. 09/13 Write index-v5Thomas Gummerer, Aug 16, 2012
  11. 10/13 Write index-v5 cache-tree dataThomas Gummerer, Aug 16, 2012
  12. 11/13 Write resolve-undo data for index-v5Thomas Gummerer, Aug 16, 2012
  13. 12/13 update-index.c: rewrite index when index-version is givenThomas Gummerer, Aug 16, 2012
  14. 13/13 p0002-index.sh: add perf test for the index formatsThomas Gummerer, Aug 16, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.