Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
5.7 KiB

  1. //
  2. // unbuffered rapid disk i/o class. Provides streaming write to disk using
  3. // unbuffered, overlapped i/o via large buffers. Inter-thread sync
  4. // must be provided elsewhere.
  5. //
  6. #ifndef _DIRECTIO_H_
  7. #define _DIRECTIO_H_
  8. #ifdef _WIN32
  9. #ifdef CHICAGO
  10. #include "disk32.h"
  11. #endif
  12. // all 'tunable' constants now found in CFileStream::EnsureBuffersValid()
  13. // maximum number of buffers that can be requested
  14. #define NR_OF_BUFFERS 4
  15. // min read size
  16. #define MIN_READ_SIZE (12 * 1024)
  17. // --- we use these internally ----
  18. // unbuffered i/o handler class. requires copy of data.
  19. // will round reads and writes to correct sector size, and
  20. // will pre-read if start location of read or write is not in buffer.
  21. // read or write will terminate early if insufficient space or data.
  22. // writes must be explicitly initiated from the buffer to disk
  23. // by calling commit. reads will be initiated by the Read function, or may
  24. // be initiated offline using ReadAhead.
  25. class CFileBuffer {
  26. public:
  27. // initiate to an invalid (no buffer ready) state
  28. CFileBuffer();
  29. // allocate memory and become idle.
  30. #ifdef CHICAGO
  31. BOOL Init(DWORD nBytesPerSector, DWORD buffersize, LPQIO pqio);
  32. #else
  33. BOOL Init(DWORD nBytesPerSector, DWORD buffersize, HANDLE hfile);
  34. #endif
  35. // revert to invalid state (eg when streaming stops)
  36. void FreeMemory();
  37. // write some data to buffer (must be committed separately)
  38. // filesize parameter is the current file size before this write
  39. // (used to control reading of partial sectors).
  40. BOOL Write(DWORD pos, LPBYTE pData, DWORD count, DWORD filesize,
  41. DWORD * pBytesWritten);
  42. // read data from buffer (will seek and read if necessary first)
  43. BOOL Read(DWORD pos, LPBYTE pData, DWORD count,
  44. DWORD filelength, DWORD * pBytesRead);
  45. // does this position occur anywhere within the current buffer ?
  46. // needs to know current eof for some cases (writing beyond eof
  47. // if eof is within this buffer is ok to this buffer).
  48. BOOL QueryPosition(DWORD pos, DWORD filesize);
  49. // what is the first file position after this buffer's valid data
  50. DWORD GetNextPosition();
  51. // initiate a read-ahead
  52. void ReadAhead(DWORD start, DWORD filelength);
  53. // initiate the i/o from the buffer
  54. BOOL Commit();
  55. // wait for any pending commit to complete
  56. BOOL WaitComplete();
  57. // is the buffer idle - FALSE if currently busy or invalid
  58. BOOL IsIdle() {
  59. return (m_State == Idle);
  60. };
  61. // calls commit if dirty before freeing everything.
  62. ~CFileBuffer();
  63. private:
  64. // non-blocking check to see if pending i/o is complete and ok
  65. BOOL CheckComplete();
  66. BOOL ReadIntoBuffer(int offset, DWORD pos, DWORD count);
  67. DWORD_PTR RoundPosToSector(DWORD_PTR pos)
  68. {
  69. // positions round down to the previous sector start
  70. return (pos / m_BytesPerSector) * m_BytesPerSector;
  71. };
  72. DWORD_PTR RoundSizeToSector(DWORD_PTR size)
  73. {
  74. // sizes round up to total sector count
  75. return ((size + m_BytesPerSector - 1) / m_BytesPerSector)
  76. * m_BytesPerSector;
  77. }
  78. // buffer states
  79. enum BufferState { Idle, Busy, Invalid, ErrorOccurred };
  80. BufferState m_State;
  81. BOOL m_bDirty;
  82. LPBYTE m_pBuffer; // buffer with start addr rounded
  83. LPBYTE m_pAllocedMem; // buffer before rounding
  84. DWORD m_TotalSize; // allocated buffer size
  85. DWORD m_DataLength; // bytes of valid data in buffer
  86. DWORD m_Position; // file position of start of buffer
  87. DWORD m_BytesPerSector; // sector boundaries are important
  88. DWORD m_FileLength; // actual file size (not rounded)
  89. #ifdef CHICAGO
  90. QIOBUF m_qiobuf;
  91. LPQIO m_pqio;
  92. #else
  93. OVERLAPPED m_Overlapped;
  94. HANDLE m_hFile;
  95. #endif
  96. };
  97. class CFileStream {
  98. public:
  99. CFileStream(); // does not do much (cannot return error)
  100. BOOL Open(LPTSTR file, BOOL bWrite, BOOL bTruncate);
  101. BOOL Seek(DWORD pos);
  102. BOOL Write(LPBYTE pData, DWORD count, DWORD * pbyteswritten);
  103. BOOL Read(LPBYTE pData, DWORD count, DWORD * pbytesread);
  104. DWORD GetCurrentPosition();
  105. BOOL StartStreaming(); // default (write if opened for write)
  106. BOOL StartWriteStreaming();
  107. BOOL StartReadStreaming();
  108. BOOL StopStreaming();
  109. // wait for all transfers to complete.
  110. BOOL CommitAndWait();
  111. // destructor will call Commit()
  112. ~CFileStream();
  113. private:
  114. // enable extra buffers for streaming
  115. BOOL EnsureBuffersValid();
  116. // advance to next buffer
  117. int NextBuffer(int i) {
  118. return (i + 1) % m_NrValid;
  119. };
  120. // unbuffered i/o is only allowed in multiples of this
  121. DWORD m_SectorSize;
  122. CFileBuffer m_Buffers[NR_OF_BUFFERS];
  123. // how many buffers are valid ?
  124. int m_NrValid;
  125. // which is the current buffer
  126. int m_Current;
  127. // which buffer has the highest position - we will issue the
  128. // readahead when we start using this buffer
  129. int m_HighestBuffer;
  130. // next read/write position within file
  131. DWORD m_Position;
  132. enum StreamingState { Invalid, Stopped, Reading, Writing };
  133. StreamingState m_State;
  134. DWORD m_Size; // current file size
  135. // file handle
  136. #ifdef CHICAGO
  137. QIO m_qio;
  138. #define m_hFile m_qio.hFile
  139. #else
  140. HANDLE m_hFile;
  141. #endif
  142. // if opened for writing, then default streaming mode is write
  143. BOOL m_bWrite;
  144. };
  145. #endif //_WIN32
  146. #endif // _DIRECTIO_H_
  147.