Clone
ixen <ixen@copyhandler.com>
committed
on 20 Dec 15
Changed the way attributes are retrieved for file being overwritten (CH-196).
LoggerImprovements + 5 more
src/libchcore/TLocalFilesystemFile.cpp (+16 -16)
10 10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12 //  GNU General Public License for more details.
13 13 //
14 14 //  You should have received a copy of the GNU Library General Public
15 15 //  License along with this program; if not, write to the
16 16 //  Free Software Foundation, Inc.,
17 17 //  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 18 // ============================================================================
19 19 #include "stdafx.h"
20 20 #include "TLocalFilesystemFile.h"
21 21 #include "TBufferSizes.h"
22 22 #include "TCoreException.h"
23 23 #include "ErrorCodes.h"
24 24 #include <boost/numeric/conversion/cast.hpp>
25 25 #include "RoundingFunctions.h"
26 26 #include "TLocalFilesystem.h"
27 27 #include "TFileException.h"
28 28 #include "TFileInfo.h"
29 29 #include "StreamingHelpers.h"
30   #include "TOverlappedDataBufferQueue.h"
  30 #include "TOverlappedMemoryPool.h"
31 31 #include "OverlappedCallbacks.h"
32 32
33 33 namespace chcore
34 34 {
35 35         // compile-time check - ensure the buffer granularity used for transfers are bigger than expected sector size
36 36         static_assert(TLocalFilesystemFile::MaxSectorSize <= TBufferSizes::BufferGranularity, "Buffer granularity must be equal to or bigger than the max sector size");
37 37
38 38         TLocalFilesystemFile::TLocalFilesystemFile(const TSmartPath& pathFile, bool bNoBuffering, const logger::TLogFileDataPtr& spLogFileData) :
39 39                 m_pathFile(TLocalFilesystem::PrependPathExtensionIfNeeded(pathFile)),
40 40                 m_hFile(INVALID_HANDLE_VALUE),
41 41                 m_bNoBuffering(bNoBuffering),
42 42                 m_spLog(logger::MakeLogger(spLogFileData, L"Filesystem-File"))
43 43         {
44 44                 if (pathFile.IsEmpty())
45 45                         throw TCoreException(eErr_InvalidArgument, L"pathFile", LOCATION);
46 46         }
47 47
48 48         TLocalFilesystemFile::~TLocalFilesystemFile()
49 49         {
50 50                 try
 
170 170                 if(!::SetEndOfFile(m_hFile))
171 171                 {
172 172                         DWORD dwLastError = GetLastError();
173 173                         LOG_ERROR(m_spLog) << L"Setting EOF failed" << GetFileInfoForLog(m_bNoBuffering);
174 174                         throw TFileException(eErr_CannotTruncate, dwLastError, m_pathFile, L"Cannot mark the end of file", LOCATION);
175 175                 }
176 176
177 177                 // close the file that was open in inappropriate mode
178 178                 if(bFileSettingsChanged)
179 179                 {
180 180                         LOG_DEBUG(m_spLog) << L"Closing file due to mode change in truncate function" << GetFileInfoForLog(m_bNoBuffering);
181 181
182 182                         Close();
183 183                 }
184 184         }
185 185
186 186         void TLocalFilesystemFile::ReadFile(TOverlappedDataBuffer& rBuffer)
187 187         {
188 188                 LOG_TRACE(m_spLog) << L"Requesting read of " << rBuffer.GetRequestedDataSize() <<
189 189                         L" bytes at position " << rBuffer.GetFilePosition() <<
190                           L"; buffer-order: " << rBuffer.GetBufferOrder() <<
  190                         L"; buffer-order: " << rBuffer.GetFilePosition() <<
191 191                         GetFileInfoForLog(m_bNoBuffering);
192 192
193 193                 if (!IsOpen())
194 194                 {
195                           LOG_ERROR(m_spLog) << L"Read request failed - file not open" << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  195                         LOG_ERROR(m_spLog) << L"Read request failed - file not open" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
196 196                         throw TFileException(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"Cannot read from closed file", LOCATION);
197 197                 }
198 198
199 199                 if (!::ReadFileEx(m_hFile, rBuffer.GetBufferPtr(), rBuffer.GetRequestedDataSize(), &rBuffer, OverlappedReadCompleted))
200 200                 {
201 201                         DWORD dwLastError = GetLastError();
202 202                         switch (dwLastError)
203 203                         {
204 204                         case ERROR_IO_PENDING:
205                                   LOG_TRACE(m_spLog) << L"Read requested and is pending" << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  205                                 LOG_TRACE(m_spLog) << L"Read requested and is pending" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
206 206                                 return;
207 207
208 208                         case ERROR_HANDLE_EOF:
209 209                                 {
210                                           LOG_TRACE(m_spLog) << L"Read request marked as EOF" << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  210                                         LOG_TRACE(m_spLog) << L"Read request marked as EOF" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
211 211
212 212                                         rBuffer.SetBytesTransferred(0);
213 213                                         rBuffer.SetStatusCode(0);
214 214                                         rBuffer.SetErrorCode(ERROR_SUCCESS);
215 215                                         rBuffer.SetLastPart(true);
216 216
217 217                                         OverlappedReadCompleted(rBuffer.GetErrorCode(), 0, &rBuffer);
218 218
219 219                                         break;
220 220                                 }
221 221
222 222                         default:
223 223                                 {
224                                           LOG_ERROR(m_spLog) << L"Read request failed with error " << dwLastError << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  224                                         LOG_ERROR(m_spLog) << L"Read request failed with error " << dwLastError << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
225 225
226 226                                         throw TFileException(eErr_CannotReadFile, dwLastError, m_pathFile, L"Error reading data from file", LOCATION);
227 227                                 }
228 228                         }
229 229                 }
230 230                 else
231                           LOG_TRACE(m_spLog) << L"Read request succeeded" << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  231                         LOG_TRACE(m_spLog) << L"Read request succeeded" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
232 232         }
233 233
234 234         void TLocalFilesystemFile::WriteFile(TOverlappedDataBuffer& rBuffer)
235 235         {
236 236                 LOG_TRACE(m_spLog) << L"Requesting writing of " << rBuffer.GetRealDataSize() <<
237 237                         L" bytes at position " << rBuffer.GetFilePosition() <<
238                           L"; buffer-order: " << rBuffer.GetBufferOrder() <<
  238                         L"; buffer-order: " << rBuffer.GetFilePosition() <<
239 239                         GetFileInfoForLog(m_bNoBuffering);
240 240
241 241                 if (!IsOpen())
242 242                 {
243                           LOG_ERROR(m_spLog) << L"Write request failed - file not open" << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  243                         LOG_ERROR(m_spLog) << L"Write request failed - file not open" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
244 244                         throw TFileException(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"Cannot write to closed file", LOCATION);
245 245                 }
246 246
247 247                 DWORD dwToWrite = boost::numeric_cast<DWORD>(rBuffer.GetRealDataSize());
248 248
249 249                 if (m_bNoBuffering && rBuffer.IsLastPart())
250 250                 {
251 251                         dwToWrite = RoundUp<DWORD>(dwToWrite, MaxSectorSize);
252                           LOG_TRACE(m_spLog) << L"Writing last part of file in no-buffering mode. Rounding up last write to " << dwToWrite << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  252                         LOG_TRACE(m_spLog) << L"Writing last part of file in no-buffering mode. Rounding up last write to " << dwToWrite << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
253 253                 }
254 254
255 255                 if (!::WriteFileEx(m_hFile, rBuffer.GetBufferPtr(), dwToWrite, &rBuffer, OverlappedWriteCompleted))
256 256                 {
257 257                         DWORD dwLastError = GetLastError();
258 258                         if (dwLastError != ERROR_IO_PENDING)
259 259                         {
260                                   LOG_ERROR(m_spLog) << L"Write request failed with error " << dwLastError << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  260                                 LOG_ERROR(m_spLog) << L"Write request failed with error " << dwLastError << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
261 261                                 throw TFileException(eErr_CannotWriteFile, dwLastError, m_pathFile, L"Error while writing to file", LOCATION);
262 262                         }
263 263
264                           LOG_TRACE(m_spLog) << L"Write requested and is pending" << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  264                         LOG_TRACE(m_spLog) << L"Write requested and is pending" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
265 265                 }
266 266                 else
267                           LOG_TRACE(m_spLog) << L"Write request succeeded" << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  267                         LOG_TRACE(m_spLog) << L"Write request succeeded" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
268 268         }
269 269
270 270         void TLocalFilesystemFile::FinalizeFile(TOverlappedDataBuffer& rBuffer)
271 271         {
272 272                 LOG_TRACE(m_spLog) << L"Finalizing file" <<
273                           L"; buffer-order: " << rBuffer.GetBufferOrder() <<
  273                         L"; buffer-order: " << rBuffer.GetFilePosition() <<
274 274                         GetFileInfoForLog(m_bNoBuffering);
275 275
276 276                 if (!IsOpen())
277 277                 {
278                           LOG_ERROR(m_spLog) << L"Cannot finalize file - file not open" << L"; buffer-order: " << rBuffer.GetBufferOrder() << GetFileInfoForLog(m_bNoBuffering);
  278                         LOG_ERROR(m_spLog) << L"Cannot finalize file - file not open" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering);
279 279                         throw TFileException(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"Cannot write to closed file", LOCATION);
280 280                 }
281 281
282 282                 if (m_bNoBuffering && rBuffer.IsLastPart())
283 283                 {
284 284                         DWORD dwToWrite = boost::numeric_cast<DWORD>(rBuffer.GetRealDataSize());
285 285                         DWORD dwReallyWritten = RoundUp<DWORD>(dwToWrite, MaxSectorSize);
286 286
287 287                         if (dwToWrite != dwReallyWritten)
288 288                         {
289 289                                 file_size_t fsNewFileSize = rBuffer.GetFilePosition() + dwToWrite;      // new size
290 290
291 291                                 LOG_TRACE(m_spLog) << L"File need truncating - really written " << dwReallyWritten <<
292 292                                         L", should write " << dwToWrite <<
293 293                                         L". Truncating file to " << fsNewFileSize <<
294                                           L"; buffer-order: " << rBuffer.GetBufferOrder() <<
  294                                         L"; buffer-order: " << rBuffer.GetFilePosition() <<
295 295                                         GetFileInfoForLog(m_bNoBuffering);
296 296
297 297                                 Truncate(fsNewFileSize);
298 298                         }
299 299                 }
300 300         }
301 301
302 302         void TLocalFilesystemFile::InternalClose()
303 303         {
304 304                 if (m_hFile != INVALID_HANDLE_VALUE)
305 305                 {
306 306                         LOG_DEBUG(m_spLog) << L"Closing file" << GetFileInfoForLog(m_bNoBuffering);
307 307                         ::CloseHandle(m_hFile);
308 308                 }
309 309                 m_hFile = INVALID_HANDLE_VALUE;
310 310         }
311 311
312 312         std::wstring TLocalFilesystemFile::GetFileInfoForLog(bool bNoBuffering) const
313 313         {
314 314                 std::wstringstream wss;