* Make sure setFlushMaxUs() is honored. */
| 222 | * Make sure setFlushMaxUs() is honored. |
| 223 | */ |
| 224 | void test_flush_max_us_impl(uint32_t flush_us, uint32_t write_us, uint32_t test_us) { |
| 225 | // TFileTransport only calls fsync() if data has been written, |
| 226 | // so make sure the write interval is smaller than the flush interval. |
| 227 | BOOST_WARN(write_us < flush_us); |
| 228 | |
| 229 | TempFile f(tmp_dir, "thrift.TFileTransportTest."); |
| 230 | |
| 231 | // Record calls to fsync() |
| 232 | FsyncLog log; |
| 233 | fsync_log = &log; |
| 234 | |
| 235 | TFileTransport* transport = new TFileTransport(f.getPath()); |
| 236 | // Don't flush because of # of bytes written |
| 237 | transport->setFlushMaxBytes(0xffffffff); |
| 238 | uint8_t buf[] = "a"; |
| 239 | uint32_t buflen = sizeof(buf); |
| 240 | |
| 241 | // Set the flush interval |
| 242 | transport->setFlushMaxUs(flush_us); |
| 243 | |
| 244 | // Make one call to write, to start the writer thread now. |
| 245 | // (If we just let the thread get created during our test loop, |
| 246 | // the thread creation sometimes takes long enough to make the first |
| 247 | // fsync interval fail the check.) |
| 248 | transport->write(buf, buflen); |
| 249 | |
| 250 | // Add one entry to the fsync log, just to mark the start time |
| 251 | log.fsync(-1); |
| 252 | |
| 253 | // Loop doing write(), sleep(), ... |
| 254 | uint32_t total_time = 0; |
| 255 | while (true) { |
| 256 | transport->write(buf, buflen); |
| 257 | if (total_time > test_us) { |
| 258 | break; |
| 259 | } |
| 260 | usleep(write_us); |
| 261 | total_time += write_us; |
| 262 | } |
| 263 | |
| 264 | delete transport; |
| 265 | |
| 266 | // Stop logging new fsync() calls |
| 267 | fsync_log = nullptr; |
| 268 | |
| 269 | // Examine the fsync() log |
| 270 | // |
| 271 | // TFileTransport uses pthread_cond_timedwait(), which only has millisecond |
| 272 | // resolution. In my testing, it normally wakes up about 1 millisecond late. |
| 273 | // However, sometimes it takes a bit longer. Allow 5ms leeway. |
| 274 | int max_allowed_delta = flush_us + 5000; |
| 275 | |
| 276 | const FsyncLog::CallList* calls = log.getCalls(); |
| 277 | // We added 1 fsync call above. |
| 278 | // Make sure TFileTransport called fsync at least once |
| 279 | BOOST_WARN_GE(calls->size(), static_cast<FsyncLog::CallList::size_type>(1)); |
| 280 | |
| 281 | const struct timeval* prev_time = nullptr; |
no test coverage detected