Clone
ixen <ixen@copyhandler.com>
committed
on 16 Oct 16
Various code cleanups (CH-273)
ParallelizeReaderWriter + 4 more
/libchcore/TFilesystemFileFeedbackWrapper.cpp (+16 -38)
26 26
27 27 namespace chcore
28 28 {
29 29         TFilesystemFileFeedbackWrapper::TFilesystemFileFeedbackWrapper(const IFilesystemFilePtr& spFile,
30 30                 const IFeedbackHandlerPtr& spFeedbackHandler, const logger::TLogFileDataPtr& spLogFileData,
31 31                 TWorkerThreadController& rThreadController, const IFilesystemPtr& spFilesystem) :
32 32                 m_spFile(spFile),
33 33                 m_spFeedbackHandler(spFeedbackHandler),
34 34                 m_spLog(std::make_unique<logger::TLogger>(spLogFileData, L"Filesystem-File")),
35 35                 m_rThreadController(rThreadController),
36 36                 m_spFilesystem(spFilesystem)
37 37         {
38 38                 if (!spFeedbackHandler)
39 39                         throw TCoreException(eErr_InvalidArgument, L"spFeedbackHandler is NULL", LOCATION);
40 40                 if (!spFile)
41 41                         throw TCoreException(eErr_InvalidArgument, L"spFile is NULL", LOCATION);
42 42                 if (!spFilesystem)
43 43                         throw TCoreException(eErr_InvalidArgument, L"spFilesystem is NULL", LOCATION);
44 44         }
45 45
46           TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::HandleFileAlreadyExistsFB(const TFileInfoPtr& spSrcFileInfo, bool& bShouldAppend, bool& bSkip)
  46         TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::HandleFileAlreadyExistsFB(const TFileInfoPtr& spSrcFileInfo, bool& bShouldAppend)
47 47         {
48                   bSkip = false;
49 48                 bShouldAppend = false;
50 49
51 50                 // read info about the existing destination file,
52 51                 TFileInfo tDstFileInfo;
53 52                 m_spFile->GetFileInfo(tDstFileInfo);
54 53
55 54                 // src and dst files are the same
56 55                 TFeedbackResult frResult = m_spFeedbackHandler->FileAlreadyExists(*spSrcFileInfo, tDstFileInfo);
57 56                 switch(frResult.GetResult())
58 57                 {
59 58                 case EFeedbackResult::eResult_Overwrite:
60 59                         bShouldAppend = false;
61 60                         return TSubTaskBase::eSubResult_Continue;
62 61
63 62                 case EFeedbackResult::eResult_CopyRest:
64 63                         bShouldAppend = true;
65 64                         return TSubTaskBase::eSubResult_Continue;
66 65
67 66                 case EFeedbackResult::eResult_Skip:
68                           bSkip = true;
69                           return TSubTaskBase::eSubResult_Continue;
  67                         return TSubTaskBase::eSubResult_SkipFile;
70 68
71 69                 case EFeedbackResult::eResult_Cancel:
72 70                 {
73 71                         // log
74 72                         TString strFormat = _T("Cancel request while checking result of dialog before opening source file %path (CustomCopyFileFB)");
75 73                         strFormat.Replace(_T("%path"), m_spFile->GetFilePath().ToString());
76 74                         LOG_INFO(m_spLog) << strFormat.c_str();
77 75
78 76                         return TSubTaskBase::eSubResult_CancelRequest;
79 77                 }
80 78                 case EFeedbackResult::eResult_Pause:
81 79                         return TSubTaskBase::eSubResult_PauseRequest;
82 80
83 81                 default:
84 82                         BOOST_ASSERT(FALSE);            // unknown result
85 83                         throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION);
86 84                 }
87 85         }
88 86
89           TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::TruncateFileFB(file_size_t fsNewSize, bool& bSkip)
  87         TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::TruncateFileFB(file_size_t fsNewSize)
90 88         {
91                   bSkip = false;
92  
93 89                 bool bRetry = false;
94 90                 do
95 91                 {
96 92                         DWORD dwLastError = ERROR_SUCCESS;
97 93
98 94                         try
99 95                         {
100 96                                 m_spFile->Truncate(fsNewSize);
101 97                                 return TSubTaskBase::eSubResult_Continue;
102 98                         }
103 99                         catch (const TFileException& e)
104 100                         {
105 101                                 dwLastError = e.GetNativeError();
106 102                         }
107 103
108 104                         TString strFormat = _T("Error %errno while truncating file %path to 0");
109 105                         strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
110 106                         strFormat.Replace(_T("%path"), m_spFile->GetFilePath().ToString());
111 107                         LOG_ERROR(m_spLog) << strFormat.c_str();
112 108
113 109                         TFeedbackResult frResult = m_spFeedbackHandler->FileError(m_spFile->GetFilePath().ToWString(), TString(), EFileError::eResizeError, dwLastError);
114 110                         switch (frResult.GetResult())
115 111                         {
116 112                         case EFeedbackResult::eResult_Cancel:
117 113                                 return TSubTaskBase::eSubResult_CancelRequest;
118 114
119 115                         case EFeedbackResult::eResult_Retry:
120 116                                 bRetry = true;
121 117                                 break;
122 118
123 119                         case EFeedbackResult::eResult_Pause:
124 120                                 return TSubTaskBase::eSubResult_PauseRequest;
125 121
126 122                         case EFeedbackResult::eResult_Skip:
127                                   bSkip = true;
128                                   return TSubTaskBase::eSubResult_Continue;
  123                                 return TSubTaskBase::eSubResult_SkipFile;
129 124
130 125                         default:
131 126                                 BOOST_ASSERT(FALSE);            // unknown result
132 127                                 throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION);
133 128                         }
134 129
135 130                         if(WasKillRequested(frResult))
136 131                                 return TSubTaskBase::eSubResult_KillRequest;
137 132                 }
138 133                 while(bRetry);
139 134
140 135                 return TSubTaskBase::eSubResult_Continue;
141 136         }
142 137
143           TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::ReadFileFB(TOverlappedDataBuffer& rBuffer, bool& bSkip)
  138         TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::ReadFileFB(TOverlappedDataBuffer& rBuffer)
144 139         {
145                   bSkip = false;
146 140                 bool bRetry = false;
147 141                 do
148 142                 {
149 143                         bRetry = false;
150 144
151 145                         DWORD dwLastError = ERROR_SUCCESS;
152 146
153 147                         try
154 148                         {
155 149                                 m_spFile->ReadFile(rBuffer);
156 150                                 return TSubTaskBase::eSubResult_Continue;
157 151                         }
158 152                         catch (const TFileException& e)
159 153                         {
160 154                                 dwLastError = e.GetNativeError();
161 155                         }
162 156
163 157                         TString strFormat = _T("Error %errno while requesting read of %count bytes from source file %path (CustomCopyFileFB)");
164 158                         strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
165 159                         strFormat.Replace(_T("%count"), boost::lexical_cast<std::wstring>(rBuffer.GetRequestedDataSize()).c_str());
166 160                         strFormat.Replace(_T("%path"), m_spFile->GetFilePath().ToString());
167 161                         LOG_ERROR(m_spLog) << strFormat.c_str();
168 162
169 163                         TFeedbackResult frResult = m_spFeedbackHandler->FileError(m_spFile->GetFilePath().ToWString(), TString(), EFileError::eReadError, dwLastError);
170 164                         switch (frResult.GetResult())
171 165                         {
172 166                         case EFeedbackResult::eResult_Cancel:
173 167                                 return TSubTaskBase::eSubResult_CancelRequest;
174 168
175 169                         case EFeedbackResult::eResult_Retry:
176 170                                 bRetry = true;
177 171                                 break;
178 172
179 173                         case EFeedbackResult::eResult_Pause:
180 174                                 return TSubTaskBase::eSubResult_PauseRequest;
181 175
182 176                         case EFeedbackResult::eResult_Skip:
183                                   bSkip = true;
184                                   return TSubTaskBase::eSubResult_Continue;
  177                                 return TSubTaskBase::eSubResult_SkipFile;
185 178
186 179                         default:
187 180                                 BOOST_ASSERT(FALSE);            // unknown result
188 181                                 throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION);
189 182                         }
190 183
191 184                         if(WasKillRequested(frResult))
192 185                                 return TSubTaskBase::eSubResult_KillRequest;
193 186                 }
194 187                 while(bRetry);
195 188
196 189                 return TSubTaskBase::eSubResult_Continue;
197 190         }
198 191
199           TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::WriteFileFB(TOverlappedDataBuffer& rBuffer, bool& bSkip)
  192         TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::WriteFileFB(TOverlappedDataBuffer& rBuffer)
200 193         {
201                   bSkip = false;
202  
203 194                 bool bRetry = false;
204 195                 do
205 196                 {
206 197                         bRetry = false;
207 198
208 199                         DWORD dwLastError = ERROR_SUCCESS;
209 200
210 201                         try
211 202                         {
212 203                                 m_spFile->WriteFile(rBuffer);
213 204                                 return TSubTaskBase::eSubResult_Continue;
214 205                         }
215 206                         catch (const TFileException& e)
216 207                         {
217 208                                 dwLastError = e.GetNativeError();
218 209                         }
219 210
220 211                         TString strFormat = _T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)");
221 212                         strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
222 213                         strFormat.Replace(_T("%count"), boost::lexical_cast<std::wstring>(rBuffer.GetBytesTransferred()).c_str());
223 214                         strFormat.Replace(_T("%path"), m_spFile->GetFilePath().ToString());
224 215                         LOG_ERROR(m_spLog) << strFormat.c_str();
225 216
226 217                         TFeedbackResult frResult = m_spFeedbackHandler->FileError(m_spFile->GetFilePath().ToWString(), TString(), EFileError::eWriteError, dwLastError);
227 218                         switch (frResult.GetResult())
228 219                         {
229 220                         case EFeedbackResult::eResult_Cancel:
230 221                                 return TSubTaskBase::eSubResult_CancelRequest;
231 222
232 223                         case EFeedbackResult::eResult_Retry:
233 224                                 bRetry = true;
234 225                                 break;
235 226
236 227                         case EFeedbackResult::eResult_Pause:
237 228                                 return TSubTaskBase::eSubResult_PauseRequest;
238 229
239 230                         case EFeedbackResult::eResult_Skip:
240                                   bSkip = true;
241                                   return TSubTaskBase::eSubResult_Continue;
  231                                 return TSubTaskBase::eSubResult_SkipFile;
242 232
243 233                         default:
244 234                                 BOOST_ASSERT(FALSE);            // unknown result
245 235                                 throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION);
246 236                         }
247 237
248 238                         if(WasKillRequested(frResult))
249 239                                 return TSubTaskBase::eSubResult_KillRequest;
250 240                 }
251 241                 while(bRetry);
252 242
253 243                 return TSubTaskBase::eSubResult_Continue;
254 244         }
255 245
256           TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::FinalizeFileFB(TOverlappedDataBuffer& rBuffer, bool& bSkip)
  246         TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::FinalizeFileFB(TOverlappedDataBuffer& rBuffer)
257 247         {
258                   bSkip = false;
259  
260 248                 bool bRetry = false;
261 249                 do
262 250                 {
263 251                         bRetry = false;
264 252
265 253                         DWORD dwLastError = ERROR_SUCCESS;
266 254
267 255                         try
268 256                         {
269 257                                 m_spFile->FinalizeFile(rBuffer);
270 258                                 return TSubTaskBase::eSubResult_Continue;
271 259                         }
272 260                         catch (const TFileException& e)
273 261                         {
274 262                                 dwLastError = e.GetNativeError();
275 263                         }
276 264
277 265                         TString strFormat = _T("Error %errno while trying to finalize file %path (CustomCopyFileFB)");
278 266                         strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
279 267                         strFormat.Replace(_T("%path"), m_spFile->GetFilePath().ToString());
280 268                         LOG_ERROR(m_spLog) << strFormat.c_str();
281 269
282 270                         TFeedbackResult frResult = m_spFeedbackHandler->FileError(m_spFile->GetFilePath().ToWString(), TString(), EFileError::eFinalizeError, dwLastError);
283 271                         switch (frResult.GetResult())
284 272                         {
285 273                         case EFeedbackResult::eResult_Cancel:
286 274                                 return TSubTaskBase::eSubResult_CancelRequest;
287 275
288 276                         case EFeedbackResult::eResult_Retry:
289 277                                 bRetry = true;
290 278                                 break;
291 279
292 280                         case EFeedbackResult::eResult_Pause:
293 281                                 return TSubTaskBase::eSubResult_PauseRequest;
294 282
295 283                         case EFeedbackResult::eResult_Skip:
296                                   bSkip = true;
297                                   return TSubTaskBase::eSubResult_Continue;
  284                                 return TSubTaskBase::eSubResult_SkipFile;
298 285
299 286                         default:
300 287                                 BOOST_ASSERT(FALSE);            // unknown result
301 288                                 throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION);
302 289                         }
303 290
304 291                         if(WasKillRequested(frResult))
305 292                                 return TSubTaskBase::eSubResult_KillRequest;
306 293                 }
307 294                 while(bRetry);
308 295
309 296                 return TSubTaskBase::eSubResult_Continue;
310 297         }
311 298
312           TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::HandleReadError(TOverlappedDataBuffer& rBuffer, bool& bSkip)
  299         TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::HandleReadError(TOverlappedDataBuffer& rBuffer)
313 300         {
314 301                 DWORD dwLastError = rBuffer.GetErrorCode();
315 302
316                   bSkip = false;
317  
318 303                 // log
319 304                 TString strFormat = _T("Error %errno while requesting read of %count bytes from source file %path (CustomCopyFileFB)");
320 305                 strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
321 306                 strFormat.Replace(_T("%count"), boost::lexical_cast<std::wstring>(rBuffer.GetRequestedDataSize()).c_str());
322 307                 strFormat.Replace(_T("%path"), m_spFile->GetFilePath().ToString());
323 308                 LOG_ERROR(m_spLog) << strFormat.c_str();
324 309
325 310                 TFeedbackResult frResult = m_spFeedbackHandler->FileError(m_spFile->GetFilePath().ToWString(), TString(), EFileError::eReadError, dwLastError);
326 311                 switch(frResult.GetResult())
327 312                 {
328 313                 case EFeedbackResult::eResult_Cancel:
329 314                         return TSubTaskBase::eSubResult_CancelRequest;
330 315
331 316                 case EFeedbackResult::eResult_Retry:
332 317                         return TSubTaskBase::eSubResult_Retry;
333 318
334 319                 case EFeedbackResult::eResult_Pause:
335 320                         return TSubTaskBase::eSubResult_PauseRequest;
336 321
337 322                 case EFeedbackResult::eResult_Skip:
338                           bSkip = true;
339                           return TSubTaskBase::eSubResult_Continue;
  323                         return TSubTaskBase::eSubResult_SkipFile;
340 324
341 325                 default:
342 326                         BOOST_ASSERT(FALSE);            // unknown result
343 327                         throw TCoreException(eErr_UnhandledCase, L"Unknown feedback result", LOCATION);
344 328                 }
345 329         }
346 330
347           TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::HandleWriteError(TOverlappedDataBuffer& rBuffer, bool& bSkip)
  331         TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::HandleWriteError(TOverlappedDataBuffer& rBuffer)
348 332         {
349 333                 DWORD dwLastError = rBuffer.GetErrorCode();
350 334
351                   bSkip = false;
352  
353 335                 // log
354 336                 TString strFormat = _T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)");
355 337                 strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(rBuffer.GetErrorCode()).c_str());
356 338                 strFormat.Replace(_T("%count"), boost::lexical_cast<std::wstring>(rBuffer.GetBytesTransferred()).c_str());
357 339                 strFormat.Replace(_T("%path"), m_spFile->GetFilePath().ToString());
358 340                 LOG_ERROR(m_spLog) << strFormat.c_str();
359 341
360 342                 TFeedbackResult frResult = m_spFeedbackHandler->FileError(m_spFile->GetFilePath().ToWString(), TString(), EFileError::eWriteError, dwLastError);
361 343                 switch(frResult.GetResult())
362 344                 {
363 345                 case EFeedbackResult::eResult_Cancel:
364 346                         return TSubTaskBase::eSubResult_CancelRequest;
365 347
366 348                 case EFeedbackResult::eResult_Retry:
367 349                         return TSubTaskBase::eSubResult_Retry;
368 350
369 351                 case EFeedbackResult::eResult_Pause:
370 352                         return TSubTaskBase::eSubResult_PauseRequest;
371 353
372 354                 case EFeedbackResult::eResult_Skip:
373                           bSkip = true;
374                           return TSubTaskBase::eSubResult_Continue;
  355                         return TSubTaskBase::eSubResult_SkipFile;
375 356
376 357                 default:
377 358                         BOOST_ASSERT(FALSE);            // unknown result
378 359                         throw TCoreException(eErr_UnhandledCase, L"Unknown feedback result", LOCATION);
379 360                 }
380 361         }
381 362
382 363         bool TFilesystemFileFeedbackWrapper::IsFreshlyCreated() const
383 364         {
384 365                 return m_spFile->IsFreshlyCreated();
385 366         }
386 367
387 368         TSmartPath TFilesystemFileFeedbackWrapper::GetFilePath() const
388 369         {
389 370                 return m_spFile->GetFilePath();
390 371         }
391 372
392           TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::GetFileSize(file_size_t& fsSize, bool& bSkip) const
  373         TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::GetFileSize(file_size_t& fsSize) const
393 374         {
394                   bSkip = false;
395  
396 375                 bool bRetry = false;
397 376                 do
398 377                 {
399 378                         bRetry = false;
400 379
401 380                         DWORD dwLastError = ERROR_SUCCESS;
402 381
403 382                         try
404 383                         {
405 384                                 fsSize = m_spFile->GetFileSize();
406 385                                 return TSubTaskBase::eSubResult_Continue;
407 386                         }
408 387                         catch(const TFileException& e)
409 388                         {
410 389                                 dwLastError = e.GetNativeError();
411 390                         }
412 391
413 392                         TString strFormat = _T("Error %errno while trying to finalize file %path (CustomCopyFileFB)");
414 393                         strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
415 394                         strFormat.Replace(_T("%path"), m_spFile->GetFilePath().ToString());
416 395                         LOG_ERROR(m_spLog) << strFormat.c_str();
417 396
418 397                         TFeedbackResult frResult = m_spFeedbackHandler->FileError(m_spFile->GetFilePath().ToWString(), TString(), EFileError::eFinalizeError, dwLastError);
419 398                         switch(frResult.GetResult())
420 399                         {
421 400                         case EFeedbackResult::eResult_Cancel:
422 401                                 return TSubTaskBase::eSubResult_CancelRequest;
423 402
424 403                         case EFeedbackResult::eResult_Retry:
425 404                                 bRetry = true;
426 405                                 break;
427 406
428 407                         case EFeedbackResult::eResult_Pause:
429 408                                 return TSubTaskBase::eSubResult_PauseRequest;
430 409
431 410                         case EFeedbackResult::eResult_Skip:
432                                   bSkip = true;
433                                   return TSubTaskBase::eSubResult_Continue;
  411                                 return TSubTaskBase::eSubResult_SkipFile;
434 412
435 413                         default:
436 414                                 BOOST_ASSERT(FALSE);            // unknown result
437 415                                 throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION);
438 416                         }
439 417
440 418                         if(WasKillRequested(frResult))
441 419                                 return TSubTaskBase::eSubResult_KillRequest;
442 420                 }
443 421                 while(bRetry);
444 422
445 423                 return TSubTaskBase::eSubResult_Continue;
446 424         }
447 425
448 426         file_size_t TFilesystemFileFeedbackWrapper::GetSeekPositionForResume(file_size_t fsLastAvailablePosition)
449 427         {
450 428                 return m_spFile->GetSeekPositionForResume(fsLastAvailablePosition);
451 429         }
452 430
453 431         bool TFilesystemFileFeedbackWrapper::WasKillRequested(const TFeedbackResult& rFeedbackResult) const