Skip to content

Commit

Permalink
read-cache: tweak racy-git delay logic
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Junio C Hamano committed Aug 9, 2006
1 parent b7e58b1 commit 6015c28
Showing 1 changed file with 52 additions and 21 deletions.
73 changes: 52 additions & 21 deletions read-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,18 @@ int read_cache_from(const char *path)
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) {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 6015c28

Please sign in to comment.