Randomly issue AllocateBuffer(), FreeBuffer(), CreatePage(), Pin(), Unpin(), and DestroyPage() calls. All calls made are legal - error conditions are not expected. When executed in single-threaded mode 'tid' should be SINGLE_THREADED_TID. If 'multiple_pins' is true, pages can be pinned multiple times (useful to test this functionality). Otherwise they are only pinned once (useful to test the case
| 2149 | /// functionality). Otherwise they are only pinned once (useful to test the case when |
| 2150 | /// memory is more committed). |
| 2151 | void BufferPoolTest::TestRandomInternalImpl(BufferPool* pool, TmpFileGroup* file_group, |
| 2152 | MemTracker* parent_mem_tracker, mt19937* rng, int tid, bool multiple_pins) { |
| 2153 | // Encrypting and decrypting is expensive - reduce iterations when encryption is on. |
| 2154 | int num_iterations = FLAGS_disk_spill_encryption ? 5000 : 50000; |
| 2155 | // All the existing pages and buffers along with the sentinel values written to them. |
| 2156 | vector<pair<PageHandle, int>> pages; |
| 2157 | vector<pair<BufferHandle, int>> buffers; |
| 2158 | |
| 2159 | /// Pick a power-of-two buffer sizes that are up to 2^4 times the minimum buffer length. |
| 2160 | uniform_int_distribution<int> buffer_exponent_dist(0, 4); |
| 2161 | |
| 2162 | ClientHandle client; |
| 2163 | ASSERT_OK(pool->RegisterClient(Substitute("$0", tid), file_group, &global_reservations_, |
| 2164 | obj_pool_.Add(new MemTracker(-1, "", parent_mem_tracker)), 1L << 48, NewProfile(), |
| 2165 | &client)); |
| 2166 | |
| 2167 | for (int i = 0; i < num_iterations; ++i) { |
| 2168 | if ((i % 10000) == 0) LOG(ERROR) << " Iteration " << i << endl; |
| 2169 | // Pick an operation. |
| 2170 | // New page: 15% |
| 2171 | // Pin a page and block waiting for the result: 20% |
| 2172 | // Pin a page and let it continue asynchronously: 10% |
| 2173 | // Unpin a pinned page: 25% (< Pin prob. so that memory consumption increases). |
| 2174 | // Destroy page: 10% (< New page prob. so that number of pages grows over time). |
| 2175 | // Allocate buffer: 10% |
| 2176 | // Free buffer: 9.9% |
| 2177 | // Switch core that the thread is executing on: 0.1% |
| 2178 | double p = uniform_real_distribution<double>(0.0, 1.0)(*rng); |
| 2179 | if (p < 0.15) { |
| 2180 | // Create a new page. |
| 2181 | int64_t page_len = pool->min_buffer_len() << (buffer_exponent_dist)(*rng); |
| 2182 | if (!client.IncreaseReservationToFit(page_len)) continue; |
| 2183 | PageHandle new_page; |
| 2184 | ASSERT_OK(pool->CreatePage(&client, page_len, &new_page)); |
| 2185 | int data = (*rng)(); |
| 2186 | WriteData(new_page, data); |
| 2187 | pages.emplace_back(move(new_page), data); |
| 2188 | } else if (p < 0.45) { |
| 2189 | // Pin a page asynchronously. |
| 2190 | if (pages.empty()) continue; |
| 2191 | int rand_pick = uniform_int_distribution<int>(0, pages.size() - 1)(*rng); |
| 2192 | PageHandle* page = &pages[rand_pick].first; |
| 2193 | if (!client.IncreaseReservationToFit(page->len())) continue; |
| 2194 | if (!page->is_pinned() || multiple_pins) { |
| 2195 | ASSERT_OK(pool->Pin(&client, page)); |
| 2196 | } |
| 2197 | // Block on the pin and verify data for sync pins. |
| 2198 | if (p < 0.35) VerifyData(*page, pages[rand_pick].second); |
| 2199 | } else if (p < 0.70) { |
| 2200 | // Unpin a pinned page. |
| 2201 | if (pages.empty()) continue; |
| 2202 | int rand_pick = uniform_int_distribution<int>(0, pages.size() - 1)(*rng); |
| 2203 | PageHandle* page = &pages[rand_pick].first; |
| 2204 | if (page->is_pinned()) { |
| 2205 | VerifyData(*page, pages[rand_pick].second); |
| 2206 | pool->Unpin(&client, page); |
| 2207 | } |
| 2208 | } else if (p < 0.80) { |
nothing calls this directly
no test coverage detected