aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-08-08 14:47:32 -0700
committerJunio C Hamano <junkio@cox.net>2006-08-08 17:17:04 -0700
commit6015c28b1d6163f124332769989326ee470afbb6 (patch)
tree876b7cd3df0448f735bdbfc967089f2b068de9c9
parentb7e58b17b50bbbf00299fc89c480efd7cc92c1bd (diff)
downloadgit-6015c28b1d6163f124332769989326ee470afbb6.tar.gz
git-6015c28b1d6163f124332769989326ee470afbb6.tar.xz
read-cache: tweak racy-git delay logic
Instead of looping over the entries and writing out, use a separate loop after all entries have been written out to check how many entries are racily clean. Make sure that the newly created index file gets the right timestamp when we check by flushing the buffered data by ce_write(). Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r--read-cache.c73
1 files changed, 52 insertions, 21 deletions
diff --git a/read-cache.c b/read-cache.c
index ce76c20f3..c923a3270 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -841,6 +841,18 @@ unmap:
static unsigned char write_buffer[WRITE_BUFFER_SIZE];
static unsigned long write_buffer_len;
+static int ce_write_flush(SHA_CTX *context, int fd)
+{
+ unsigned int buffered = write_buffer_len;
+ if (buffered) {
+ SHA1_Update(context, write_buffer, buffered);
+ if (write(fd, write_buffer, buffered) != buffered)
+ return -1;
+ write_buffer_len = 0;
+ }
+ return 0;
+}
+
static int ce_write(SHA_CTX *context, int fd, void *data, unsigned int len)
{
while (len) {
@@ -851,8 +863,8 @@ static int ce_write(SHA_CTX *context, int fd, void *data, unsigned int len)
memcpy(write_buffer + buffered, data, partial);
buffered += partial;
if (buffered == WRITE_BUFFER_SIZE) {
- SHA1_Update(context, write_buffer, WRITE_BUFFER_SIZE);
- if (write(fd, write_buffer, WRITE_BUFFER_SIZE) != WRITE_BUFFER_SIZE)
+ write_buffer_len = buffered;
+ if (ce_write_flush(context, fd))
return -1;
buffered = 0;
}
@@ -962,19 +974,15 @@ int write_cache(int newfd, struct cache_entry **cache, int entries)
if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
return -1;
- now = fstat(newfd, &st) ? 0 : st.st_mtime;
- recent = 0;
for (i = 0; i < entries; i++) {
struct cache_entry *ce = cache[i];
- time_t entry_time = (time_t) ntohl(ce->ce_mtime.sec);
if (!ce->ce_mode)
continue;
- if (index_file_timestamp && index_file_timestamp <= entry_time)
+ if (index_file_timestamp &&
+ index_file_timestamp <= ntohl(ce->ce_mtime.sec))
ce_smudge_racily_clean_entry(ce);
if (ce_write(&c, newfd, ce, ce_size(ce)) < 0)
return -1;
- if (now && now <= entry_time)
- recent++;
}
/* Write extension data here */
@@ -1004,19 +1012,42 @@ int write_cache(int newfd, struct cache_entry **cache, int entries)
* This assumes that nobody is touching the working tree while
* we are updating the index.
*/
- if (20 < recent || entries <= recent * 4) {
- now = fstat(newfd, &st) ? 0 : st.st_mtime;
- while (now && !fstat(newfd, &st) && st.st_mtime <= now) {
- struct timespec rq, rm;
- off_t where = lseek(newfd, 0, SEEK_CUR);
- rq.tv_sec = 0;
- rq.tv_nsec = 250000000;
- nanosleep(&rq, &rm);
- if ((where == (off_t) -1) ||
- (write(newfd, "", 1) != 1) ||
- (lseek(newfd, -1, SEEK_CUR) != where) ||
- ftruncate(newfd, where))
- break;
+
+ /* Make sure that the new index file has st_mtime
+ * that is current enough -- ce_write() batches the data
+ * so it might not have written anything yet.
+ */
+ ce_write_flush(&c, newfd);
+
+ now = fstat(newfd, &st) ? 0 : st.st_mtime;
+ if (now) {
+ recent = 0;
+ for (i = 0; i < entries; i++) {
+ struct cache_entry *ce = cache[i];
+ time_t entry_time = (time_t) ntohl(ce->ce_mtime.sec);
+ if (!ce->ce_mode)
+ continue;
+ if (now && now <= entry_time)
+ recent++;
+ }
+ if (20 < recent && entries <= recent * 4) {
+#if 0
+ fprintf(stderr, "entries %d\n", entries);
+ fprintf(stderr, "recent %d\n", recent);
+ fprintf(stderr, "now %lu\n", now);
+#endif
+ while (!fstat(newfd, &st) && st.st_mtime <= now) {
+ struct timespec rq, rm;
+ off_t where = lseek(newfd, 0, SEEK_CUR);
+ rq.tv_sec = 0;
+ rq.tv_nsec = 250000000;
+ nanosleep(&rq, &rm);
+ if ((where == (off_t) -1) ||
+ (write(newfd, "", 1) != 1) ||
+ (lseek(newfd, -1, SEEK_CUR) != where) ||
+ ftruncate(newfd, where))
+ break;
+ }
}
}
return ce_flush(&c, newfd);