11
11
#include "progress.h"
12
12
#include "csum-file.h"
13
13
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
+
14
28
static void flush (struct hashfile * f , const void * buf , unsigned int count )
15
29
{
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 );
27
32
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 )
40
35
die ("sha1 file '%s' write error. Out of diskspace" , f -> name );
41
36
die_errno ("sha1 file '%s' write error" , f -> name );
42
37
}
38
+
39
+ f -> total += count ;
40
+ display_throughput (f -> tp , f -> total );
43
41
}
44
42
45
43
void hashflush (struct hashfile * f )
@@ -53,6 +51,13 @@ void hashflush(struct hashfile *f)
53
51
}
54
52
}
55
53
54
+ static void free_hashfile (struct hashfile * f )
55
+ {
56
+ free (f -> buffer );
57
+ free (f -> check_buffer );
58
+ free (f );
59
+ }
60
+
56
61
int finalize_hashfile (struct hashfile * f , unsigned char * result , unsigned int flags )
57
62
{
58
63
int fd ;
@@ -82,20 +87,20 @@ int finalize_hashfile(struct hashfile *f, unsigned char *result, unsigned int fl
82
87
if (close (f -> check_fd ))
83
88
die_errno ("%s: sha1 file error on close" , f -> name );
84
89
}
85
- free (f );
90
+ free_hashfile (f );
86
91
return fd ;
87
92
}
88
93
89
94
void hashwrite (struct hashfile * f , const void * buf , unsigned int count )
90
95
{
91
96
while (count ) {
92
- unsigned left = sizeof ( f -> buffer ) - f -> offset ;
97
+ unsigned left = f -> buffer_len - f -> offset ;
93
98
unsigned nr = count > left ? left : count ;
94
99
95
100
if (f -> do_crc )
96
101
f -> crc32 = crc32 (f -> crc32 , buf , nr );
97
102
98
- if (nr == sizeof ( f -> buffer ) ) {
103
+ if (nr == f -> buffer_len ) {
99
104
/*
100
105
* Flush a full batch worth of data directly
101
106
* from the input, skipping the memcpy() to
@@ -121,11 +126,6 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count)
121
126
}
122
127
}
123
128
124
- struct hashfile * hashfd (int fd , const char * name )
125
- {
126
- return hashfd_throughput (fd , name , NULL );
127
- }
128
-
129
129
struct hashfile * hashfd_check (const char * name )
130
130
{
131
131
int sink , check ;
@@ -139,10 +139,14 @@ struct hashfile *hashfd_check(const char *name)
139
139
die_errno ("unable to open '%s'" , name );
140
140
f = hashfd (sink , name );
141
141
f -> check_fd = check ;
142
+ f -> check_buffer = xmalloc (f -> buffer_len );
143
+
142
144
return f ;
143
145
}
144
146
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 )
146
150
{
147
151
struct hashfile * f = xmalloc (sizeof (* f ));
148
152
f -> fd = fd ;
@@ -153,9 +157,35 @@ struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp
153
157
f -> name = name ;
154
158
f -> do_crc = 0 ;
155
159
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
+
156
165
return f ;
157
166
}
158
167
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
+
159
189
void hashfile_checkpoint (struct hashfile * f , struct hashfile_checkpoint * checkpoint )
160
190
{
161
191
hashflush (f );
0 commit comments