From: Eric Wong <e@80x24.org>
To: git@vger.kernel.org
Subject: [PATCH] update-server-info: avoid needless overwrites
Date: Sat, 11 May 2019 01:34:55 +0000 [thread overview]
Message-ID: <20190511013455.5886-1-e@80x24.org> (raw)
Do not change the existing info/refs and objects/info/packs
files if they match the existing content on the filesystem.
This is intended to preserve mtime and make it easier for dumb
HTTP pollers to rely on the If-Modified-Since header.
Combined with stdio and kernel buffering; the kernel should be
able to avoid block layer writes and reduce wear.
Signed-off-by: Eric Wong <e@80x24.org>
---
server-info.c | 61 +++++++++++++++++++++++++++++------
t/t5200-update-server-info.sh | 41 +++++++++++++++++++++++
2 files changed, 92 insertions(+), 10 deletions(-)
create mode 100755 t/t5200-update-server-info.sh
diff --git a/server-info.c b/server-info.c
index 41274d098b..34599e4817 100644
--- a/server-info.c
+++ b/server-info.c
@@ -6,37 +6,78 @@
#include "tag.h"
#include "packfile.h"
#include "object-store.h"
+#include "strbuf.h"
+
+static int files_differ(FILE *fp, const char *path)
+{
+ struct stat st;
+ git_hash_ctx c;
+ struct object_id oid_old, oid_new;
+ struct strbuf tmp = STRBUF_INIT;
+ long new_len = ftell(fp);
+
+ if (new_len < 0 || stat(path, &st) < 0)
+ return 1;
+ if (!S_ISREG(st.st_mode))
+ return 1;
+ if ((off_t)new_len != st.st_size)
+ return 1;
+
+ rewind(fp);
+ if (strbuf_fread(&tmp, (size_t)new_len, fp) != (size_t)new_len)
+ return 1;
+ the_hash_algo->init_fn(&c);
+ the_hash_algo->update_fn(&c, tmp.buf, tmp.len);
+ the_hash_algo->final_fn(oid_new.hash, &c);
+ strbuf_release(&tmp);
+
+ if (strbuf_read_file(&tmp, path, (size_t)st.st_size) < 0)
+ return 1;
+ the_hash_algo->init_fn(&c);
+ the_hash_algo->update_fn(&c, tmp.buf, tmp.len);
+ the_hash_algo->final_fn(oid_old.hash, &c);
+ strbuf_release(&tmp);
+
+ return hashcmp(oid_old.hash, oid_new.hash);
+}
/*
* Create the file "path" by writing to a temporary file and renaming
* it into place. The contents of the file come from "generate", which
* should return non-zero if it encounters an error.
*/
-static int update_info_file(char *path, int (*generate)(FILE *))
+static int update_info_file(char *path, int (*generate)(FILE *), int force)
{
char *tmp = mkpathdup("%s_XXXXXX", path);
int ret = -1;
int fd = -1;
FILE *fp = NULL, *to_close;
+ int do_update;
safe_create_leading_directories(path);
fd = git_mkstemp_mode(tmp, 0666);
if (fd < 0)
goto out;
- to_close = fp = fdopen(fd, "w");
+ to_close = fp = fdopen(fd, "w+");
if (!fp)
goto out;
fd = -1;
ret = generate(fp);
if (ret)
goto out;
+
+ do_update = force || files_differ(fp, path);
fp = NULL;
if (fclose(to_close))
goto out;
- if (adjust_shared_perm(tmp) < 0)
- goto out;
- if (rename(tmp, path) < 0)
- goto out;
+ if (do_update) {
+ if (adjust_shared_perm(tmp) < 0)
+ goto out;
+ if (rename(tmp, path) < 0)
+ goto out;
+ } else {
+ unlink(tmp);
+ }
ret = 0;
out:
@@ -78,10 +119,10 @@ static int generate_info_refs(FILE *fp)
return for_each_ref(add_info_ref, fp);
}
-static int update_info_refs(void)
+static int update_info_refs(int force)
{
char *path = git_pathdup("info/refs");
- int ret = update_info_file(path, generate_info_refs);
+ int ret = update_info_file(path, generate_info_refs, force);
free(path);
return ret;
}
@@ -254,7 +295,7 @@ static int update_info_packs(int force)
int ret;
init_pack_info(infofile, force);
- ret = update_info_file(infofile, write_pack_info_file);
+ ret = update_info_file(infofile, write_pack_info_file, force);
free_pack_info();
free(infofile);
return ret;
@@ -269,7 +310,7 @@ int update_server_info(int force)
*/
int errs = 0;
- errs = errs | update_info_refs();
+ errs = errs | update_info_refs(force);
errs = errs | update_info_packs(force);
/* remove leftover rev-cache file if there is any */
diff --git a/t/t5200-update-server-info.sh b/t/t5200-update-server-info.sh
new file mode 100755
index 0000000000..f1cec46914
--- /dev/null
+++ b/t/t5200-update-server-info.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+test_description='Test git stash show configuration.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' 'test_commit file'
+
+test_expect_success 'create info/refs' '
+ git update-server-info &&
+ test_path_is_file .git/info/refs
+'
+
+test_expect_success 'modify and store mtime' '
+ test-tool chmtime =0 .git/info/refs &&
+ test-tool chmtime --get .git/info/refs >a
+'
+
+test_expect_success 'info/refs is not needlessly overwritten' '
+ git update-server-info &&
+ test-tool chmtime --get .git/info/refs >b &&
+ test_cmp a b
+'
+
+test_expect_success 'info/refs can be forced to update' '
+ git update-server-info -f &&
+ test-tool chmtime --get .git/info/refs >b &&
+ ! test_cmp a b
+'
+
+test_expect_success 'info/refs updates when changes are made' '
+ test-tool chmtime =0 .git/info/refs &&
+ test-tool chmtime --get .git/info/refs >b &&
+ test_cmp a b &&
+ git update-ref refs/heads/foo HEAD &&
+ git update-server-info &&
+ test-tool chmtime --get .git/info/refs >b &&
+ ! test_cmp a b
+'
+
+test_done
--
EW
next reply other threads:[~2019-05-11 1:34 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-11 1:34 Eric Wong [this message]
2019-05-11 7:35 ` [PATCH] update-server-info: avoid needless overwrites Eric Sunshine
2019-05-11 20:47 ` [PATCH v2] " Eric Wong
2019-05-11 21:17 ` [PATCH] " Eric Wong
2019-05-11 23:37 ` Ævar Arnfjörð Bjarmason
2019-05-12 0:38 ` Eric Wong
2019-05-12 4:08 ` Jeff King
2019-05-12 7:16 ` Ævar Arnfjörð Bjarmason
2019-05-14 9:47 ` Jeff King
2019-05-14 10:33 ` Ævar Arnfjörð Bjarmason
2019-05-14 11:24 ` Jeff King
2019-05-14 11:57 ` Ævar Arnfjörð Bjarmason
2019-05-14 11:50 ` Eric Wong
2019-05-14 12:13 ` dumb HTTP things I want to do Eric Wong
2019-05-14 12:27 ` Jeff King
2019-05-14 12:19 ` [PATCH] update-server-info: avoid needless overwrites Ævar Arnfjörð Bjarmason
2019-05-14 12:29 ` Jeff King
2019-05-15 0:45 ` [PATCH 2/1] server-info: conditionally update on fetch Eric Wong
2019-05-15 20:38 ` [WIP] repack leaving stale entries in objects/info/packs Eric Wong
2019-05-15 21:48 ` Jeff King
2019-05-23 8:59 ` [PATCH] server-info: do not list unlinked packs Eric Wong
2019-05-23 10:24 ` Jeff King
2019-05-23 17:27 ` [PATCH v2] " Eric Wong
2019-05-24 6:05 ` Jeff King
2019-05-24 7:34 ` Ævar Arnfjörð Bjarmason
2019-05-13 23:17 ` [PATCH v3] update-server-info: avoid needless overwrites Eric Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190511013455.5886-1-e@80x24.org \
--to=e@80x24.org \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).