Merge branch 'jc/racy'

* jc/racy:
  Remove the "delay writing to avoid runtime penalty of racy-git avoidance"
  Add check program "git-check-racy"
  Documentation/technical/racy-git.txt
  avoid nanosleep(2)
This commit is contained in:
Junio C Hamano
2006-08-16 14:00:34 -07:00
4 changed files with 236 additions and 60 deletions

View File

@ -5,7 +5,6 @@
*/
#include "cache.h"
#include "cache-tree.h"
#include <time.h>
/* Index extensions.
*
@ -170,9 +169,11 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
return changed;
}
int ce_match_stat(struct cache_entry *ce, struct stat *st, int ignore_valid)
int ce_match_stat(struct cache_entry *ce, struct stat *st, int options)
{
unsigned int changed;
int ignore_valid = options & 01;
int assume_racy_is_modified = options & 02;
/*
* If it's marked as always valid in the index, it's
@ -201,8 +202,12 @@ int ce_match_stat(struct cache_entry *ce, struct stat *st, int ignore_valid)
*/
if (!changed &&
index_file_timestamp &&
index_file_timestamp <= ntohl(ce->ce_mtime.sec))
changed |= ce_modified_check_fs(ce, st);
index_file_timestamp <= ntohl(ce->ce_mtime.sec)) {
if (assume_racy_is_modified)
changed |= DATA_CHANGED;
else
changed |= ce_modified_check_fs(ce, st);
}
return changed;
}
@ -954,9 +959,7 @@ int write_cache(int newfd, struct cache_entry **cache, int entries)
{
SHA_CTX c;
struct cache_header hdr;
int i, removed, recent;
struct stat st;
time_t now;
int i, removed;
for (i = removed = 0; i < entries; i++)
if (!cache[i]->ce_mode)
@ -994,57 +997,5 @@ int write_cache(int newfd, struct cache_entry **cache, int entries)
return -1;
}
}
/*
* To prevent later ce_match_stat() from always falling into
* check_fs(), if we have too many entries that can trigger
* racily clean check, we are better off delaying the return.
* We arbitrarily say if more than 20 paths or 25% of total
* paths are very new, we delay the return until the index
* file gets a new timestamp.
*
* NOTE! NOTE! NOTE!
*
* This assumes that nobody is touching the working tree while
* we are updating the index.
*/
/* 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);
}