RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
core/banker/testing/redis_banker_deadlock_test.cc
00001 /* redis_banker_race_test.cc
00002    Jeremy Barnes, 2 November 2012
00003    Copyright (c) 2012 Datacratic.  All rights reserved.
00004    
00005    Test for the banker class.
00006 */
00007 
00008 #define BOOST_TEST_MAIN
00009 #define BOOST_TEST_DYN_LINK
00010 #include <boost/test/unit_test.hpp>
00011 #include "jml/arch/format.h"
00012 #include "jml/arch/exception_handler.h"
00013 #include "jml/utils/guard.h"
00014 #include "rtbkit/plugins/bidding_agent/bidding_agent.h"
00015 #include "rtbkit/core/banker/redis_banker.h"
00016 #include "rtbkit/common/auction.h"
00017 #include "rtbkit/core/router/router.h"
00018 #include "jml/utils/environment.h"
00019 #include "jml/arch/timers.h"
00020 #include "jml/utils/testing/watchdog.h"
00021 #include "dataflow/work_scheduler.h"
00022 #include <future>
00023 #include "soa/service/testing/redis_temporary_server.h"
00024 #include <boost/thread/thread.hpp>
00025 
00026 
00027 using namespace std;
00028 using namespace ML;
00029 using namespace Datacratic;
00030 using namespace RTBKIT;
00031 using namespace Redis;
00032 
00033 
00034 BOOST_AUTO_TEST_CASE( test_banker_deadlock )
00035 {
00036     auto s = std::make_shared<ServiceProxies>();
00037     RedisTemporaryServer redis;
00038 
00039     // Create a campaign with a budget and a strategy
00040     {
00041         RedisBudgetController controller("bankerTest", redis);
00042         controller.addCampaignSync("testCampaign");
00043         controller.addStrategySync("testCampaign", "testStrategy");
00044         controller.setBudgetSync("testCampaign", MicroUSD(100000000));
00045         controller.topupTransferSync("testCampaign", "testStrategy",
00046                                                MicroUSD(90000000));
00047     }
00048 
00049     // Do 1,000 topup transfers of one micro
00050 
00051     int nSyncThreads = 10;
00052     int nBidThreads = 1; // for the moment, we don't support multiple;
00053 
00054     RedisBanker banker("bankerTest", "b", s, redis);
00055 
00056     volatile bool finished = false;
00057 
00058     auto runSyncThread = [&] ()
00059         {
00060             while (!finished) {
00061                 banker.sync();
00062             }
00063         };
00064     
00065     uint64_t numBidsCommitted = 0;
00066 
00067     auto runBidThread = [&] (int threadNum)
00068         {
00069 
00070             string item = "thread" + to_string(threadNum);
00071 
00072             while (!finished) {
00073                 // Authorize 10
00074                 if (!banker.authorizeBid("testCampaign", "testStrategy", item,
00075                                          MicroUSD(1))) {
00076                     banker.sync();
00077                     continue;
00078                 }
00079 
00080                 // Commit 1
00081                 banker.commitBid("testCampaign", "testStrategy", item,
00082                                  MicroUSD(1));
00083 
00084                 ML::atomic_inc(numBidsCommitted);
00085             }
00086 
00087             banker.sync();
00088         };
00089 
00090     boost::thread_group threads;
00091     for (unsigned i = 0;  i < nSyncThreads;  ++i)
00092         threads.create_thread(runSyncThread);
00093     for (unsigned i = 0;  i < nBidThreads;  ++i)
00094         threads.create_thread(std::bind(runBidThread, i));
00095 
00096     // Test for ADGR-213; the expected behaviour is no deadlock and we print
00097     // one message per second and succeed.  If we deadlock the watchdog will
00098     // catch us and we will fail.
00099     ML::Watchdog watchdog(10.0);
00100     
00101     for (unsigned i = 0;  i < 3;  ++i) {
00102         ML::sleep(1.0);
00103         Json::Value status = banker.getCampaignStatusJson("testCampaign", "");
00104         cerr << "status " << status << endl;
00105     }
00106     finished = true;
00107 
00108     cerr << "finished; waiting to join" << endl;
00109     threads.join_all();
00110     cerr << "done" << endl;
00111 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator