RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
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 }