destroy_mock_cookie(cookie);
}
+// Verify that when a DELETE_BUCKET event occurs, we correctly notify any
+// DCP connections which are currently in ewouldblock state, so the frontend
+// can correctly close the connection.
+// If we don't notify then front-end connections can hang for a long period of
+// time).
+TEST_F(ConnectionTest, test_mb20716_connmap_notify_on_delete) {
+ MockDcpConnMap connMap(*engine);
+ connMap.initialize(DCP_CONN_NOTIFIER);
+ const void *cookie = create_mock_cookie();
+ // Create a new Dcp producer.
+ dcp_producer_t producer = connMap.newProducer(cookie, "mb_20716r",
+ /*notifyOnly*/false);
+
+ // Check preconditions.
+ EXPECT_TRUE(producer->isPaused());
+
+ // Hook into notify_io_complete.
+ // We (ab)use the engine_specific API to pass a pointer to a count of
+ // how many times notify_io_complete has been called.
+ size_t notify_count = 0;
+ SERVER_COOKIE_API* scapi = get_mock_server_api()->cookie;
+ scapi->store_engine_specific(cookie, ¬ify_count);
+ auto orig_notify_io_complete = scapi->notify_io_complete;
+ scapi->notify_io_complete = [](const void *cookie,
+ ENGINE_ERROR_CODE status) {
+ auto* notify_ptr = reinterpret_cast<size_t*>(
+ get_mock_server_api()->cookie->get_engine_specific(cookie));
+ (*notify_ptr)++;
+ };
+
+ // 0. Should start with no notifications.
+ ASSERT_EQ(0, notify_count);
+
+ // 1. Check that the periodic connNotifier (notifyAllPausedConnections)
+ // isn't sufficient to notify (it shouldn't be, as our connection has
+ // no notification pending).
+ connMap.notifyAllPausedConnections();
+ ASSERT_EQ(0, notify_count);
+
+ // 1. Simulate a bucket deletion.
+ connMap.shutdownAllConnections();
+
+ EXPECT_EQ(1, notify_count)
+ << "expected one notify after shutting down all connections";
+
+ // Restore notify_io_complete callback.
+ scapi->notify_io_complete = orig_notify_io_complete;
+ destroy_mock_cookie(cookie);
+}
class NotifyTest : public DCPTest {
protected: