|
7 | 7 |
|
8 | 8 | #include <library/cpp/threading/future/future.h> |
9 | 9 |
|
| 10 | +#include <fcntl.h> |
10 | 11 | #include <util/folder/dirut.h> |
11 | 12 | #include <util/folder/tempdir.h> |
12 | 13 | #include <util/generic/array_ref.h> |
@@ -143,6 +144,105 @@ Y_UNIT_TEST_SUITE(TAioTest) |
143 | 144 | } |
144 | 145 | } |
145 | 146 |
|
| 147 | + Y_UNIT_TEST(ShouldReadWriteWithSyncFlags) |
| 148 | + { |
| 149 | + auto service = CreateAIOService(); |
| 150 | + service->Start(); |
| 151 | + Y_DEFER { service->Stop(); }; |
| 152 | + |
| 153 | + const ui32 blockSize = 4_KB; |
| 154 | + const ui64 blockCount = 1024; |
| 155 | + const auto filePath = TryGetRamDrivePath() / "test_sync_flags"; |
| 156 | + |
| 157 | + // Keep open mode non-sync; sync intent must come from write flags. |
| 158 | + TFileHandle fileData(filePath, OpenAlways | RdWr | DirectAligned); |
| 159 | + fileData.Resize(blockCount * blockSize); |
| 160 | + |
| 161 | + const ui64 requestStartIndex = 20; |
| 162 | + const ui64 requestBlockCount = 16; |
| 163 | + const ui64 length = requestBlockCount * blockSize; |
| 164 | + const i64 offset = requestStartIndex * blockSize; |
| 165 | + |
| 166 | + std::shared_ptr<char> memory { |
| 167 | + static_cast<char*>(std::aligned_alloc(blockSize, length)), |
| 168 | + std::free |
| 169 | + }; |
| 170 | + |
| 171 | + TArrayRef<char> buffer {memory.get(), length}; |
| 172 | + std::memset(buffer.data(), 'X', buffer.size()); |
| 173 | + |
| 174 | + for (const ui32 flags: {ui32(O_SYNC), ui32(O_DSYNC), ui32(O_SYNC | O_DSYNC)}) { |
| 175 | + auto result = service->AsyncWrite(fileData, offset, buffer, flags); |
| 176 | + UNIT_ASSERT_VALUES_EQUAL(buffer.size(), result.GetValueSync()); |
| 177 | + } |
| 178 | + |
| 179 | + std::memset(buffer.data(), '.', buffer.size()); |
| 180 | + { |
| 181 | + auto result = service->AsyncRead(fileData, offset, buffer); |
| 182 | + UNIT_ASSERT_VALUES_EQUAL(buffer.size(), result.GetValueSync()); |
| 183 | + } |
| 184 | + |
| 185 | + for (char val: buffer) { |
| 186 | + UNIT_ASSERT_VALUES_EQUAL('X', val); |
| 187 | + } |
| 188 | + } |
| 189 | + |
| 190 | + Y_UNIT_TEST(ShouldReadWriteVWithSyncFlags) |
| 191 | + { |
| 192 | + auto service = CreateAIOService(); |
| 193 | + service->Start(); |
| 194 | + Y_DEFER { service->Stop(); }; |
| 195 | + |
| 196 | + const ui32 blockSize = 4_KB; |
| 197 | + const ui64 blockCount = 1024; |
| 198 | + const auto filePath = TryGetRamDrivePath() / "test_sync_flags_v"; |
| 199 | + |
| 200 | + // Keep open mode non-sync; sync intent must come from write flags. |
| 201 | + TFileHandle fileData(filePath, OpenAlways | RdWr | DirectAligned); |
| 202 | + fileData.Resize(blockCount * blockSize); |
| 203 | + |
| 204 | + const ui64 requestStartIndex = 20; |
| 205 | + const ui64 requestBlockCount = 16; |
| 206 | + const ui64 length = requestBlockCount * blockSize; |
| 207 | + const i64 offset = requestStartIndex * blockSize; |
| 208 | + |
| 209 | + std::shared_ptr<char> memory { |
| 210 | + static_cast<char*>(std::aligned_alloc(blockSize, length)), |
| 211 | + std::free |
| 212 | + }; |
| 213 | + |
| 214 | + TVector<TArrayRef<char>> buffers; |
| 215 | + buffers.emplace_back(memory.get(), 4 * blockSize); |
| 216 | + buffers.emplace_back(memory.get() + 4 * blockSize, 6 * blockSize); |
| 217 | + buffers.emplace_back(memory.get() + 10 * blockSize, 6 * blockSize); |
| 218 | + |
| 219 | + TVector<TArrayRef<const char>> constBuffers; |
| 220 | + for (auto& buffer: buffers) { |
| 221 | + std::memset(buffer.data(), 'X', buffer.size()); |
| 222 | + constBuffers.emplace_back(buffer.data(), buffer.size()); |
| 223 | + } |
| 224 | + |
| 225 | + for (const ui32 flags: {ui32(O_SYNC), ui32(O_DSYNC), ui32(O_SYNC | O_DSYNC)}) { |
| 226 | + auto result = service->AsyncWriteV(fileData, offset, constBuffers, flags); |
| 227 | + UNIT_ASSERT_VALUES_EQUAL(length, result.GetValueSync()); |
| 228 | + } |
| 229 | + |
| 230 | + for (auto& buffer: buffers) { |
| 231 | + std::memset(buffer.data(), '.', buffer.size()); |
| 232 | + } |
| 233 | + |
| 234 | + { |
| 235 | + auto result = service->AsyncReadV(fileData, offset, buffers); |
| 236 | + UNIT_ASSERT_VALUES_EQUAL(length, result.GetValueSync()); |
| 237 | + } |
| 238 | + |
| 239 | + for (auto& buffer: buffers) { |
| 240 | + for (char val: buffer) { |
| 241 | + UNIT_ASSERT_VALUES_EQUAL('X', val); |
| 242 | + } |
| 243 | + } |
| 244 | + } |
| 245 | + |
146 | 246 | Y_UNIT_TEST(ShouldRetryIoSetupErrors) |
147 | 247 | { |
148 | 248 | const ui32 eventCountLimit = |
|
0 commit comments