|
@@ -65,6 +65,8 @@
|
|
|
|
|
|
// #define REMOTE_DISCONNECT_ON_DESTRUCTOR // enable to disconnect on IFile destructor
|
|
|
// this should not be enabled in WindowRemoteDirectory used
|
|
|
+//#define CHECK_FILE_IO // If enabled, reads and writes are checked for sensible parameters
|
|
|
+
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
#define ASSERTEX(e) assertex(e);
|
|
@@ -1731,7 +1733,13 @@ IFileIO * CFile::openShared(IFOmode mode,IFSHmode share,IFEflags extraFlags)
|
|
|
#endif
|
|
|
if (stdh>=0)
|
|
|
return new CSequentialFileIO(handle,mode,share,extraFlags);
|
|
|
- return new CFileIO(handle,mode,share,extraFlags);
|
|
|
+
|
|
|
+ Owned<IFileIO> io = new CFileIO(handle,mode,share,extraFlags);
|
|
|
+#ifdef CHECK_FILE_IO
|
|
|
+ return new CCheckingFileIO(filename, io);
|
|
|
+#else
|
|
|
+ return io.getClear();
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
|
|
@@ -2087,6 +2095,86 @@ size32_t CFileRangeIO::write(offset_t pos, size32_t len, const void * data)
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
+CCheckingFileIO::~CCheckingFileIO()
|
|
|
+{
|
|
|
+ if (lastWriteSize && !closed)
|
|
|
+ report("FileCheck: IO for File %s destroyed before closing", filename.str());
|
|
|
+}
|
|
|
+
|
|
|
+size32_t CCheckingFileIO::read(offset_t pos, size32_t len, void * data)
|
|
|
+{
|
|
|
+ CriticalBlock block(cs);
|
|
|
+ if ((pos == lastReadPos) && (len < minSeqReadSize) && (pos + len != size()))
|
|
|
+ report("FileCheck: Sequential read [%s] of %u is < %u", filename.str(), len, minSeqReadSize);
|
|
|
+
|
|
|
+ size32_t numRead = io->read(pos, len, data);
|
|
|
+ lastReadPos = pos + numRead;
|
|
|
+ return numRead;
|
|
|
+}
|
|
|
+
|
|
|
+offset_t CCheckingFileIO::size()
|
|
|
+{
|
|
|
+ return io->size();
|
|
|
+}
|
|
|
+
|
|
|
+size32_t CCheckingFileIO::write(offset_t pos, size32_t len, const void * data)
|
|
|
+{
|
|
|
+ CriticalBlock block(cs);
|
|
|
+ if (len != 0)
|
|
|
+ {
|
|
|
+ if ((lastWriteSize != 0) && (lastWriteSize < minWriteSize))
|
|
|
+ report("FileCheck: Sequential write to [%s] of size %u before offset %" I64F "u of %u is < %u", filename.str(), lastWriteSize, pos, len, minWriteSize);
|
|
|
+ lastWriteSize = len;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ report("FileCheck: Unexpected zero byte write on %s at offset %" I64F "u", filename.str(), pos);
|
|
|
+
|
|
|
+ return io->write(pos, len, data);
|
|
|
+}
|
|
|
+
|
|
|
+void CCheckingFileIO::setSize(offset_t size)
|
|
|
+{
|
|
|
+ io->setSize(size);
|
|
|
+}
|
|
|
+
|
|
|
+offset_t CCheckingFileIO::appendFile(IFile *file,offset_t pos,offset_t len)
|
|
|
+{
|
|
|
+ return io->appendFile(file, pos, len);
|
|
|
+}
|
|
|
+
|
|
|
+void CCheckingFileIO::flush()
|
|
|
+{
|
|
|
+ io->flush();
|
|
|
+}
|
|
|
+
|
|
|
+void CCheckingFileIO::close()
|
|
|
+{
|
|
|
+ io->close();
|
|
|
+ closed = true;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned __int64 CCheckingFileIO::getStatistic(StatisticKind kind)
|
|
|
+{
|
|
|
+ return io->getStatistic(kind);
|
|
|
+}
|
|
|
+
|
|
|
+void CCheckingFileIO::report(const char * format, ...)
|
|
|
+{
|
|
|
+ va_list args;
|
|
|
+ va_start(args, format);
|
|
|
+ VALOG(MCinternalError, unknownJob, format, args);
|
|
|
+ va_end(args);
|
|
|
+ if (!traced)
|
|
|
+ {
|
|
|
+ printStackReport();
|
|
|
+ traced = true;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+//--------------------------------------------------------------------------
|
|
|
+
|
|
|
CFileAsyncIO::~CFileAsyncIO()
|
|
|
{
|
|
|
try
|