Skip to content

Commit 27051d4

Browse files
author
Edward Thomson
committed
odb: only freshen pack files every 2 seconds
Since writing multiple objects may all already exist in a single packfile, avoid freshening that packfile repeatedly in a tight loop. Instead, only freshen pack files every 2 seconds.
1 parent 8f09a98 commit 27051d4

File tree

6 files changed

+37
-10
lines changed

6 files changed

+37
-10
lines changed

src/fileops.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -837,16 +837,13 @@ int git_futils_cp(const char *from, const char *to, mode_t filemode)
837837
return cp_by_fd(ifd, ofd, true);
838838
}
839839

840-
int git_futils_touch(const char *path)
840+
int git_futils_touch(const char *path, time_t *when)
841841
{
842842
struct p_timeval times[2];
843-
time_t now = time(NULL);
844843
int ret;
845844

846-
times[0].tv_sec = now;
847-
times[0].tv_usec = 0;
848-
times[1].tv_sec = now;
849-
times[1].tv_usec = 0;
845+
times[0].tv_sec = times[1].tv_sec = when ? *when : time(NULL);
846+
times[0].tv_usec = times[1].tv_usec = 0;
850847

851848
ret = p_utimes(path, times);
852849

src/fileops.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,10 @@ extern int git_futils_cp(
185185
mode_t filemode);
186186

187187
/**
188-
* Set the files atime and mtime to the current time.
188+
* Set the files atime and mtime to the given time, or the current time
189+
* if `ts` is NULL.
189190
*/
190-
extern int git_futils_touch(const char *path);
191+
extern int git_futils_touch(const char *path, time_t *when);
191192

192193
/**
193194
* Flags that can be passed to `git_futils_cp_r`.

src/odb_loose.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,7 @@ static int loose_backend__freshen(
929929
if (object_file_name(&path, backend, oid) < 0)
930930
return -1;
931931

932-
error = git_futils_touch(path.ptr);
932+
error = git_futils_touch(path.ptr, NULL);
933933
git_buf_free(&path);
934934

935935
return error;

src/odb_pack.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020

2121
#include "git2/odb_backend.h"
2222

23+
/* re-freshen pack files no more than every 2 seconds */
24+
#define FRESHEN_FREQUENCY 2
25+
2326
struct pack_backend {
2427
git_odb_backend parent;
2528
git_vector packs;
@@ -367,12 +370,22 @@ static int pack_backend__freshen(
367370
git_odb_backend *backend, const git_oid *oid)
368371
{
369372
struct git_pack_entry e;
373+
time_t now;
370374
int error;
371375

372376
if ((error = pack_entry_find(&e, (struct pack_backend *)backend, oid)) < 0)
373377
return error;
374378

375-
return git_futils_touch(e.p->pack_name);
379+
now = time(NULL);
380+
381+
if (e.p->last_freshen > now - FRESHEN_FREQUENCY)
382+
return 0;
383+
384+
if ((error = git_futils_touch(e.p->pack_name, &now)) < 0)
385+
return error;
386+
387+
e.p->last_freshen = now;
388+
return 0;
376389
}
377390

378391
static int pack_backend__read(

src/pack.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ struct git_pack_file {
102102

103103
git_pack_cache bases; /* delta base cache */
104104

105+
time_t last_freshen; /* last time the packfile was freshened */
106+
105107
/* something like ".git/objects/pack/xxxxx.pack" */
106108
char pack_name[GIT_FLEX_ARRAY]; /* more */
107109
};

tests/odb/freshen.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,26 @@ void test_odb_freshen__packed_object(void)
6868
cl_must_pass(p_utimes("testrepo.git/objects/pack/" PACKED_FN, old_times));
6969
cl_must_pass(p_lstat("testrepo.git/objects/pack/" PACKED_FN, &before));
7070

71+
/* ensure that packfile is freshened */
7172
cl_git_pass(git_odb_write(&id, odb, PACKED_STR,
7273
CONST_STRLEN(PACKED_STR), GIT_OBJ_BLOB));
7374
cl_assert_equal_oid(&expected_id, &id);
7475
cl_must_pass(p_lstat("testrepo.git/objects/pack/" PACKED_FN, &after));
7576

7677
cl_assert(before.st_atime < after.st_atime);
7778
cl_assert(before.st_mtime < after.st_mtime);
79+
80+
memcpy(&before, &after, sizeof(struct stat));
81+
82+
/* ensure that the pack file is not freshened again immediately */
83+
cl_git_pass(git_odb_write(&id, odb, PACKED_STR,
84+
CONST_STRLEN(PACKED_STR), GIT_OBJ_BLOB));
85+
cl_assert_equal_oid(&expected_id, &id);
86+
cl_must_pass(p_lstat("testrepo.git/objects/pack/" PACKED_FN, &after));
87+
88+
cl_assert(before.st_atime == after.st_atime);
89+
cl_assert(before.st_atime_nsec == after.st_atime_nsec);
90+
cl_assert(before.st_mtime == after.st_mtime);
91+
cl_assert(before.st_mtime_nsec == after.st_mtime_nsec);
7892
}
7993

0 commit comments

Comments
 (0)