Skip to content

Commit 0dd2fd1

Browse files
committed
Merge branch 'ds/write-index-with-hashfile-api'
Use the hashfile API in the codepath that writes the index file to reduce code duplication. * ds/write-index-with-hashfile-api: read-cache: delete unused hashing methods read-cache: use hashfile instead of git_hash_ctx csum-file.h: increase hashfile buffer size hashfile: use write_in_full()
2 parents f4f7304 + f6e2cd0 commit 0dd2fd1

File tree

4 files changed

+134
-167
lines changed

4 files changed

+134
-167
lines changed

chunk-format.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,11 @@ void add_chunk(struct chunkfile *cf,
5858

5959
int write_chunkfile(struct chunkfile *cf, void *data)
6060
{
61-
int i;
61+
int i, result = 0;
6262
uint64_t cur_offset = hashfile_total(cf->f);
6363

64+
trace2_region_enter("chunkfile", "write", the_repository);
65+
6466
/* Add the table of contents to the current offset */
6567
cur_offset += (cf->chunks_nr + 1) * CHUNK_TOC_ENTRY_SIZE;
6668

@@ -77,18 +79,20 @@ int write_chunkfile(struct chunkfile *cf, void *data)
7779

7880
for (i = 0; i < cf->chunks_nr; i++) {
7981
off_t start_offset = hashfile_total(cf->f);
80-
int result = cf->chunks[i].write_fn(cf->f, data);
82+
result = cf->chunks[i].write_fn(cf->f, data);
8183

8284
if (result)
83-
return result;
85+
goto cleanup;
8486

8587
if (hashfile_total(cf->f) - start_offset != cf->chunks[i].size)
8688
BUG("expected to write %"PRId64" bytes to chunk %"PRIx32", but wrote %"PRId64" instead",
8789
cf->chunks[i].size, cf->chunks[i].id,
8890
hashfile_total(cf->f) - start_offset);
8991
}
9092

91-
return 0;
93+
cleanup:
94+
trace2_region_leave("chunkfile", "write", the_repository);
95+
return result;
9296
}
9397

9498
int read_table_of_contents(struct chunkfile *cf,

csum-file.c

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,33 @@
1111
#include "progress.h"
1212
#include "csum-file.h"
1313

14+
static void verify_buffer_or_die(struct hashfile *f,
15+
const void *buf,
16+
unsigned int count)
17+
{
18+
ssize_t ret = read_in_full(f->check_fd, f->check_buffer, count);
19+
20+
if (ret < 0)
21+
die_errno("%s: sha1 file read error", f->name);
22+
if (ret != count)
23+
die("%s: sha1 file truncated", f->name);
24+
if (memcmp(buf, f->check_buffer, count))
25+
die("sha1 file '%s' validation error", f->name);
26+
}
27+
1428
static void flush(struct hashfile *f, const void *buf, unsigned int count)
1529
{
16-
if (0 <= f->check_fd && count) {
17-
unsigned char check_buffer[8192];
18-
ssize_t ret = read_in_full(f->check_fd, check_buffer, count);
19-
20-
if (ret < 0)
21-
die_errno("%s: sha1 file read error", f->name);
22-
if (ret != count)
23-
die("%s: sha1 file truncated", f->name);
24-
if (memcmp(buf, check_buffer, count))
25-
die("sha1 file '%s' validation error", f->name);
26-
}
30+
if (0 <= f->check_fd && count)
31+
verify_buffer_or_die(f, buf, count);
2732

28-
for (;;) {
29-
int ret = xwrite(f->fd, buf, count);
30-
if (ret > 0) {
31-
f->total += ret;
32-
display_throughput(f->tp, f->total);
33-
buf = (char *) buf + ret;
34-
count -= ret;
35-
if (count)
36-
continue;
37-
return;
38-
}
39-
if (!ret)
33+
if (write_in_full(f->fd, buf, count) < 0) {
34+
if (errno == ENOSPC)
4035
die("sha1 file '%s' write error. Out of diskspace", f->name);
4136
die_errno("sha1 file '%s' write error", f->name);
4237
}
38+
39+
f->total += count;
40+
display_throughput(f->tp, f->total);
4341
}
4442

4543
void hashflush(struct hashfile *f)
@@ -53,6 +51,13 @@ void hashflush(struct hashfile *f)
5351
}
5452
}
5553

54+
static void free_hashfile(struct hashfile *f)
55+
{
56+
free(f->buffer);
57+
free(f->check_buffer);
58+
free(f);
59+
}
60+
5661
int finalize_hashfile(struct hashfile *f, unsigned char *result, unsigned int flags)
5762
{
5863
int fd;
@@ -82,20 +87,20 @@ int finalize_hashfile(struct hashfile *f, unsigned char *result, unsigned int fl
8287
if (close(f->check_fd))
8388
die_errno("%s: sha1 file error on close", f->name);
8489
}
85-
free(f);
90+
free_hashfile(f);
8691
return fd;
8792
}
8893

8994
void hashwrite(struct hashfile *f, const void *buf, unsigned int count)
9095
{
9196
while (count) {
92-
unsigned left = sizeof(f->buffer) - f->offset;
97+
unsigned left = f->buffer_len - f->offset;
9398
unsigned nr = count > left ? left : count;
9499

95100
if (f->do_crc)
96101
f->crc32 = crc32(f->crc32, buf, nr);
97102

98-
if (nr == sizeof(f->buffer)) {
103+
if (nr == f->buffer_len) {
99104
/*
100105
* Flush a full batch worth of data directly
101106
* from the input, skipping the memcpy() to
@@ -121,11 +126,6 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count)
121126
}
122127
}
123128

124-
struct hashfile *hashfd(int fd, const char *name)
125-
{
126-
return hashfd_throughput(fd, name, NULL);
127-
}
128-
129129
struct hashfile *hashfd_check(const char *name)
130130
{
131131
int sink, check;
@@ -139,10 +139,14 @@ struct hashfile *hashfd_check(const char *name)
139139
die_errno("unable to open '%s'", name);
140140
f = hashfd(sink, name);
141141
f->check_fd = check;
142+
f->check_buffer = xmalloc(f->buffer_len);
143+
142144
return f;
143145
}
144146

145-
struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp)
147+
static struct hashfile *hashfd_internal(int fd, const char *name,
148+
struct progress *tp,
149+
size_t buffer_len)
146150
{
147151
struct hashfile *f = xmalloc(sizeof(*f));
148152
f->fd = fd;
@@ -153,9 +157,35 @@ struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp
153157
f->name = name;
154158
f->do_crc = 0;
155159
the_hash_algo->init_fn(&f->ctx);
160+
161+
f->buffer_len = buffer_len;
162+
f->buffer = xmalloc(buffer_len);
163+
f->check_buffer = NULL;
164+
156165
return f;
157166
}
158167

168+
struct hashfile *hashfd(int fd, const char *name)
169+
{
170+
/*
171+
* Since we are not going to use a progress meter to
172+
* measure the rate of data passing through this hashfile,
173+
* use a larger buffer size to reduce fsync() calls.
174+
*/
175+
return hashfd_internal(fd, name, NULL, 128 * 1024);
176+
}
177+
178+
struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp)
179+
{
180+
/*
181+
* Since we are expecting to report progress of the
182+
* write into this hashfile, use a smaller buffer
183+
* size so the progress indicators arrive at a more
184+
* frequent rate.
185+
*/
186+
return hashfd_internal(fd, name, tp, 8 * 1024);
187+
}
188+
159189
void hashfile_checkpoint(struct hashfile *f, struct hashfile_checkpoint *checkpoint)
160190
{
161191
hashflush(f);

csum-file.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ struct hashfile {
1616
const char *name;
1717
int do_crc;
1818
uint32_t crc32;
19-
unsigned char buffer[8192];
19+
size_t buffer_len;
20+
unsigned char *buffer;
21+
unsigned char *check_buffer;
2022
};
2123

2224
/* Checkpoint */

0 commit comments

Comments
 (0)