| 1353 | } |
| 1354 | |
| 1355 | void StreamStateTest::TestDeferAdvancingReadPage() { |
| 1356 | int num_rows = 1024; |
| 1357 | int buffer_size = 4 * 1024; |
| 1358 | // Only give 2 * buffer_size for the stream initial read and write page reservation. |
| 1359 | Init(2 * buffer_size); |
| 1360 | |
| 1361 | bool eos; |
| 1362 | bool got_reservation; |
| 1363 | Status status; |
| 1364 | RowBatch* write_batch = CreateIntBatch(0, num_rows, false); |
| 1365 | |
| 1366 | { |
| 1367 | // Test unpinning a stream when the read page has been attached to the output batch |
| 1368 | // and the output batch has NOT been reset. |
| 1369 | BufferedTupleStream stream( |
| 1370 | runtime_state_, int_desc_, &client_, buffer_size, buffer_size); |
| 1371 | ASSERT_OK(stream.Init("StreamStateTest::DeferAdvancingReadPage", true)); |
| 1372 | ASSERT_OK(stream.PrepareForReadWrite(true, &got_reservation)); |
| 1373 | ASSERT_TRUE(got_reservation); |
| 1374 | |
| 1375 | // Add rows to stream. |
| 1376 | for (int i = 0; i < write_batch->num_rows(); ++i) { |
| 1377 | EXPECT_TRUE(stream.AddRow(write_batch->GetRow(i), &status)); |
| 1378 | ASSERT_OK(status); |
| 1379 | } |
| 1380 | |
| 1381 | // Read until the read page is attached to the output. |
| 1382 | RowBatch read_batch(int_desc_, num_rows, &tracker_); |
| 1383 | ASSERT_OK(stream.GetNext(&read_batch, &eos)); |
| 1384 | // If GetNext did hit the capacity of the RowBatch, then the read page should have |
| 1385 | // been attached to read_batch. |
| 1386 | ASSERT_TRUE(read_batch.num_rows() < num_rows); |
| 1387 | ASSERT_TRUE(!eos); |
| 1388 | |
| 1389 | // We continue adding rows into the stream without releasing the read_batch. We expect |
| 1390 | // that reservation limit will be hit and stream will need to be unpinned. We also |
| 1391 | // expect that, after unpinning the stream, subsequent AddRow is always successful |
| 1392 | // even if we're not immediately releasing the read_batch. We insert write_batch twice |
| 1393 | // to ensure that we're inserting both in pinned and unpinned mode. |
| 1394 | ASSERT_TRUE(stream.is_pinned()); |
| 1395 | for (int j = 0; j < 2; ++j) { |
| 1396 | for (int i = 0; i < write_batch->num_rows(); ++i) { |
| 1397 | bool succeed = stream.AddRow(write_batch->GetRow(i), &status); |
| 1398 | ASSERT_TRUE(succeed || stream.is_pinned()); |
| 1399 | if (!succeed) { |
| 1400 | // Unpin the stream. |
| 1401 | status = stream.UnpinStream(BufferedTupleStream::UNPIN_ALL_EXCEPT_CURRENT); |
| 1402 | ASSERT_OK(status); |
| 1403 | ASSERT_FALSE(stream.is_pinned()); |
| 1404 | ASSERT_EQ(stream.bytes_unpinned(), 0); |
| 1405 | ASSERT_EQ(stream.pages_.size(), 2); |
| 1406 | ASSERT_EQ(stream.num_pages_, 2); |
| 1407 | // Retry inserting this row by decreasing the index. |
| 1408 | // After stream get into unpinned mode, further inserts should be successful, |
| 1409 | // even if we're not immediately cleaning up the read_batch. |
| 1410 | // Stream should be able to unpin the previous write page to reclaim some |
| 1411 | // memory reservation to allocate new write page. |
| 1412 | --i; |
nothing calls this directly
no test coverage detected