| 169 | } |
| 170 | |
| 171 | size_t TDirectIOBufferedFile::ReadFromFile(void* buffer, size_t byteCount, ui64 offset) { |
| 172 | SetDirectIO(true); |
| 173 | |
| 174 | ui64 bytesRead = 0; |
| 175 | |
| 176 | while (byteCount) { |
| 177 | if (!Alignment || IsAligned(buffer) && IsAligned(byteCount) && IsAligned(offset)) { |
| 178 | if (const ui64 fromFile = PreadSafe(buffer, byteCount, offset)) { |
| 179 | buffer = (char*)buffer + fromFile; |
| 180 | byteCount -= fromFile; |
| 181 | offset += fromFile; |
| 182 | bytesRead += fromFile; |
| 183 | } else { |
| 184 | return bytesRead; |
| 185 | } |
| 186 | } else { |
| 187 | break; |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | if (!byteCount) { |
| 192 | return bytesRead; |
| 193 | } |
| 194 | |
| 195 | ui64 bufSize = AlignUp(Min<size_t>(BufferStorage.Size(), byteCount + (Alignment << 1)), Alignment); |
| 196 | TBuffer readBufferStorage(bufSize + Alignment); |
| 197 | char* readBuffer = AlignUp((char*)readBufferStorage.Data(), Alignment); |
| 198 | |
| 199 | while (byteCount) { |
| 200 | ui64 begin = AlignDown(offset, (ui64)Alignment); |
| 201 | ui64 end = AlignUp(offset + byteCount, (ui64)Alignment); |
| 202 | ui64 toRead = Min(end - begin, bufSize); |
| 203 | ui64 fromFile = PreadSafe(readBuffer, toRead, begin); |
| 204 | |
| 205 | if (!fromFile) { |
| 206 | break; |
| 207 | } |
| 208 | |
| 209 | ui64 delta = offset - begin; |
| 210 | ui64 count = Min<ui64>(fromFile - delta, byteCount); |
| 211 | |
| 212 | memcpy(buffer, readBuffer + delta, count); |
| 213 | buffer = (char*)buffer + count; |
| 214 | byteCount -= count; |
| 215 | offset += count; |
| 216 | bytesRead += count; |
| 217 | } |
| 218 | return bytesRead; |
| 219 | } |
| 220 | |
| 221 | size_t TDirectIOBufferedFile::Read(void* buffer, size_t byteCount) { |
| 222 | size_t bytesRead = Pread(buffer, byteCount, ReadPosition); |