Skip to content

Commit

Permalink
SERVER-19359 implement setAlarm() for NetworkInterfaceASIO
Browse files Browse the repository at this point in the history
  • Loading branch information
samantharitter committed Aug 14, 2015
1 parent a925e26 commit f075019
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
14 changes: 13 additions & 1 deletion src/mongo/executor/network_interface_asio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
#include "mongo/stdx/memory.h"
#include "mongo/util/log.h"
#include "mongo/util/net/sock.h"
#include "mongo/util/net/ssl_manager.h"
#include "mongo/util/time_support.h"

namespace mongo {
namespace executor {
Expand Down Expand Up @@ -141,7 +143,17 @@ void NetworkInterfaceASIO::cancelCommand(const TaskExecutor::CallbackHandle& cbH
}

void NetworkInterfaceASIO::setAlarm(Date_t when, const stdx::function<void()>& action) {
MONGO_UNREACHABLE;
// "alarm" must stay alive until it expires, hence the shared_ptr.
auto alarm = std::make_shared<asio::steady_timer>(_io_service, when - now());
alarm->async_wait([alarm, this, action](std::error_code ec) {
if (!ec) {
return action();
} else if (ec != asio::error::operation_aborted) {
// When the network interface is shut down, it will cancel all pending
// alarms, raising an "operation_aborted" error here, which we ignore.
warning() << "setAlarm() received an error: " << ec.message();
}
});
};

bool NetworkInterfaceASIO::inShutdown() const {
Expand Down
34 changes: 33 additions & 1 deletion src/mongo/executor/network_interface_asio_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ class NetworkInterfaceASIOTest : public mongo::unittest::Test {
}

void tearDown() override {
_net->shutdown();
if (!_net->inShutdown()) {
_net->shutdown();
}
}

NetworkInterface& net() {
Expand Down Expand Up @@ -222,6 +224,36 @@ TEST_F(NetworkInterfaceASIOTest, StartCommand) {
ASSERT_EQ(res.metadata, expectedMetadata);
}

TEST_F(NetworkInterfaceASIOTest, setAlarm) {
stdx::promise<bool> nearFuture;
stdx::future<bool> executed = nearFuture.get_future();

// set a first alarm, to execute after "expiration"
Date_t expiration = net().now() + Milliseconds(100);
net().setAlarm(
expiration,
[this, expiration, &nearFuture]() { nearFuture.set_value(net().now() >= expiration); });

// wait enough time for first alarm to execute
auto status = executed.wait_for(Milliseconds(5000));

// assert that not only did it execute, but executed after "expiration"
ASSERT(status == stdx::future_status::ready);
ASSERT(executed.get());

// set an alarm for the future, kill interface, ensure it didn't execute
stdx::promise<bool> farFuture;
stdx::future<bool> executed2 = farFuture.get_future();

expiration = net().now() + Milliseconds(99999999);
net().setAlarm(expiration, [this, &farFuture]() { farFuture.set_value(true); });

net().shutdown();

status = executed2.wait_for(Milliseconds(0));
ASSERT(status == stdx::future_status::timeout);
}

} // namespace
} // namespace executor
} // namespace mongo

0 comments on commit f075019

Please sign in to comment.