@@ -55,7 +55,14 @@ bool FileCreator::setFileSize(int fd, int64_t fileSize) {
55
55
56
56
int FileCreator::openAndSetSize (BlockDetails const *blockDetails) {
57
57
const auto &options = WdtOptions::get ();
58
- int fd = createFile (blockDetails->fileName );
58
+ int fd;
59
+ const bool doCreate = blockDetails->allocationStatus == NOT_EXISTS;
60
+ const bool isTooLarge = (blockDetails->allocationStatus == EXISTS_TOO_LARGE);
61
+ if (doCreate) {
62
+ fd = createFile (blockDetails->fileName );
63
+ } else {
64
+ fd = openExistingFile (blockDetails->fileName );
65
+ }
59
66
if (fd < 0 ) {
60
67
return -1 ;
61
68
}
@@ -67,14 +74,13 @@ int FileCreator::openAndSetSize(BlockDetails const *blockDetails) {
67
74
return -1 ;
68
75
}
69
76
if (options.isLogBasedResumption ()) {
70
- if (blockDetails-> allocationStatus == EXISTS_TOO_LARGE ) {
77
+ if (isTooLarge ) {
71
78
LOG (WARNING) << " File size smaller in the sender side "
72
79
<< blockDetails->fileName
73
80
<< " , marking previous transferred chunks as invalid" ;
74
81
transferLogManager_.addInvalidationEntry (blockDetails->prevSeqId );
75
82
}
76
- if (blockDetails->allocationStatus == EXISTS_TOO_LARGE ||
77
- blockDetails->allocationStatus == NOT_EXISTS) {
83
+ if (isTooLarge || doCreate) {
78
84
transferLogManager_.addFileCreationEntry (
79
85
blockDetails->fileName , blockDetails->seqId , blockDetails->fileSize );
80
86
} else {
@@ -147,11 +153,33 @@ int FileCreator::openForBlocks(int threadIndex,
147
153
return -1 ;
148
154
}
149
155
}
150
- return createFile (blockDetails->fileName );
156
+ return openExistingFile (blockDetails->fileName );
151
157
}
152
158
153
159
using std::string;
154
160
161
+ int FileCreator::openExistingFile (const string &relPathStr) {
162
+ // This should have been validated earlier and errored out
163
+ // instead of crashing here
164
+ WDT_CHECK (!relPathStr.empty ());
165
+ WDT_CHECK (relPathStr[0 ] != ' /' );
166
+ WDT_CHECK (relPathStr.back () != ' /' );
167
+
168
+ string path (rootDir_);
169
+ path.append (relPathStr);
170
+
171
+ int openFlags = O_WRONLY;
172
+ START_PERF_TIMER
173
+ int res = open (path.c_str (), openFlags, 0644 );
174
+ RECORD_PERF_RESULT (PerfStatReport::FILE_OPEN)
175
+ if (res < 0 ) {
176
+ PLOG (ERROR) << " failed opening file " << path;
177
+ return -1 ;
178
+ }
179
+ VLOG (1 ) << " successfully opened file " << path;
180
+ return res;
181
+ }
182
+
155
183
int FileCreator::createFile (const string &relPathStr) {
156
184
CHECK (!relPathStr.empty ());
157
185
CHECK (relPathStr[0 ] != ' /' );
@@ -167,39 +195,62 @@ int FileCreator::createFile(const string &relPathStr) {
167
195
std::string dir;
168
196
if (p) {
169
197
dir.assign (relPathStr.data (), p);
170
- if (!createDirRecursively (dir)) {
198
+ START_PERF_TIMER
199
+ const bool dirSuccess1 = createDirRecursively (dir);
200
+ RECORD_PERF_RESULT (PerfStatReport::DIRECTORY_CREATE)
201
+ if (!dirSuccess1) {
171
202
// retry with force
172
203
LOG (ERROR) << " failed to create dir " << dir << " recursively, "
173
204
<< " trying to force directory creation" ;
174
- if (!createDirRecursively (dir, true /* force */ )) {
205
+ START_PERF_TIMER
206
+ const bool dirSuccess2 = createDirRecursively (dir, true /* force */ );
207
+ RECORD_PERF_RESULT (PerfStatReport::DIRECTORY_CREATE)
208
+ if (!dirSuccess2) {
175
209
LOG (ERROR) << " failed to create dir " << dir << " recursively" ;
176
210
return -1 ;
177
211
}
178
212
}
179
213
}
180
214
int openFlags = O_CREAT | O_WRONLY;
215
+ auto &options = WdtOptions::get ();
216
+ // When doing download resumption we sometime open files that do already
217
+ // exist and we need to overwrite them anyway (files which have been
218
+ // discarded from the log for some reason)
219
+ if (options.overwrite || options.enable_download_resumption ) {
220
+ // Make sure file size resumption will not get messed up if we
221
+ // expect to create this file
222
+ openFlags |= O_TRUNC;
223
+ } else {
224
+ // Make sure open will fail if we don't allow overwriting and
225
+ // the file happens to already exist
226
+ openFlags |= O_EXCL;
227
+ }
181
228
START_PERF_TIMER
182
229
int res = open (path.c_str (), openFlags, 0644 );
230
+ RECORD_PERF_RESULT (PerfStatReport::FILE_OPEN)
183
231
if (res < 0 ) {
184
232
if (dir.empty ()) {
185
233
PLOG (ERROR) << " failed creating file " << path;
186
234
return -1 ;
187
235
}
188
236
PLOG (ERROR) << " failed creating file " << path << " , trying to "
189
237
<< " force directory creation" ;
190
- if (!createDirRecursively (dir, true /* force */ )) {
191
- LOG (ERROR) << " failed to create dir " << dir << " recursively" ;
192
- return -1 ;
238
+ {
239
+ START_PERF_TIMER
240
+ const bool dirSuccess = createDirRecursively (dir, true /* force */ );
241
+ RECORD_PERF_RESULT (PerfStatReport::DIRECTORY_CREATE)
242
+ if (!dirSuccess) {
243
+ LOG (ERROR) << " failed to create dir " << dir << " recursively" ;
244
+ return -1 ;
245
+ }
193
246
}
194
247
START_PERF_TIMER
195
248
res = open (path.c_str (), openFlags, 0644 );
249
+ RECORD_PERF_RESULT (PerfStatReport::FILE_OPEN)
196
250
if (res < 0 ) {
197
251
PLOG (ERROR) << " failed creating file " << path;
198
252
return -1 ;
199
253
}
200
- RECORD_PERF_RESULT (PerfStatReport::FILE_OPEN)
201
- } else {
202
- RECORD_PERF_RESULT (PerfStatReport::FILE_OPEN)
203
254
}
204
255
VLOG (1 ) << " successfully created file " << path;
205
256
return res;
@@ -210,7 +261,7 @@ bool FileCreator::createDirRecursively(const std::string dir, bool force) {
210
261
return true ;
211
262
}
212
263
213
- CHECK (dir.back () == ' /' );
264
+ WDT_CHECK (dir.back () == ' /' );
214
265
215
266
int64_t lastIndex = dir.size () - 1 ;
216
267
while (lastIndex > 0 && dir[lastIndex - 1 ] != ' /' ) {
0 commit comments