RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* blacklist.cc -*- C++ -*- 00002 Jeremy Barnes, 1 March 2012 00003 Copyright (c) 2012 Datacratic. All rights reserved. 00004 00005 Blacklist functionality. 00006 */ 00007 00008 #include "blacklist.h" 00009 #include "agent_config.h" 00010 00011 namespace RTBKIT { 00012 00013 Date 00014 BlacklistInfo:: 00015 add(const BidRequest & bidRequest, 00016 const std::string & agent, 00017 const AgentConfig & config) 00018 { 00019 Entry entry; 00020 entry.agent = agent; 00021 entry.account = config.account; 00022 entry.site = bidRequest.url.toString(); 00023 entry.expiry = Date::now().plusSeconds(config.blacklistTime); 00024 00025 entries.push_back(entry); 00026 00027 if (entries.size() == 1 || entry.expiry < earliestExpiry) { 00028 earliestExpiry = entry.expiry; 00029 return earliestExpiry; 00030 } 00031 00032 return Date(); // no need to reset the expiry 00033 } 00034 00035 Date 00036 BlacklistInfo:: 00037 expire(Date now) 00038 { 00039 Date result = Date(); 00040 for (unsigned i = 0; i < entries.size(); /* no inc */) { 00041 if (entries[i].expiry <= now) { 00042 std::swap(entries[i], entries.back()); 00043 entries.pop_back(); 00044 // no increment 00045 } 00046 else { 00047 if (result == Date()) 00048 result = entries[i].expiry; 00049 else result = std::min(result, entries[i].expiry); 00050 ++i; 00051 } 00052 } 00053 return result; 00054 } 00055 00056 bool 00057 BlacklistInfo:: 00058 matches(const BidRequest & bidRequest, 00059 const std::string & agent, 00060 const AgentConfig & config) const 00061 { 00062 auto matchesEntry = [&] (const Entry & entry) -> bool 00063 { 00064 switch (config.blacklistScope) { 00065 case BL_AGENT: 00066 return entry.agent == agent; 00067 case BL_ACCOUNT: 00068 return entry.account == config.account; 00069 default: 00070 throw ML::Exception("invalid blacklist scope"); 00071 } 00072 }; 00073 00074 switch (config.blacklistType) { 00075 case BL_OFF: 00076 return false; // shouldn't happen 00077 00078 case BL_USER: // fall through 00079 for (unsigned i = 0; i < entries.size(); ++i) { 00080 const Entry & entry = entries[i]; 00081 if (matchesEntry(entry)) return true; 00082 } 00083 00084 case BL_USER_SITE: 00085 for (unsigned i = 0; i < entries.size(); ++i) { 00086 const Entry & entry = entries[i]; 00087 if (!matchesEntry(entry)) continue; 00088 if (entry.site != "" && entry.site == bidRequest.url.toString()) 00089 return true; 00090 } 00091 return false; 00092 00093 default: 00094 throw ML::Exception("unknown blacklist type"); 00095 } 00096 } 00097 00098 void 00099 Blacklist:: 00100 doExpiries() 00101 { 00102 Date start = Date::now(); 00103 00104 auto onBlacklistFinished = [&] (const Id & userId, 00105 BlacklistInfo & info) 00106 { 00107 return info.expire(start); 00108 }; 00109 00110 entries.expire(onBlacklistFinished, start); 00111 } 00112 00113 bool 00114 Blacklist:: 00115 matches(const BidRequest & bidRequest, const std::string & agentName, 00116 const AgentConfig & config) const 00117 { 00118 bool blocked = false; 00119 const Id & exchangeId = bidRequest.userIds.exchangeId; 00120 if (!blocked && exchangeId) { 00121 // TODO: read lock 00122 auto bit = entries.find(exchangeId); 00123 if (bit != entries.end()) { 00124 const BlacklistInfo & binfo = bit->second; 00125 if (binfo.matches(bidRequest, agentName, config)) 00126 blocked = true; 00127 } 00128 } 00129 const Id & providerId = bidRequest.userIds.providerId; 00130 if (!blocked && providerId) { 00131 // TODO: read lock 00132 auto bit = entries.find(providerId); 00133 if (bit != entries.end()) { 00134 const BlacklistInfo & binfo = bit->second; 00135 if (binfo.matches(bidRequest, agentName, config)) 00136 blocked = true; 00137 } 00138 } 00139 00140 return blocked; 00141 } 00142 00143 void 00144 Blacklist:: 00145 add(const BidRequest & bidRequest, const std::string & agent, 00146 const AgentConfig & agentConfig) 00147 { 00148 auto addToBlacklist = [&] (const Id & id) 00149 { 00150 if (!id) return; 00151 00152 auto it = this->entries.find(id); 00153 if (it != this->entries.end()) { 00154 Date newExpiry 00155 = it->second.add(bidRequest, agent, agentConfig); 00156 if (newExpiry != Date()) 00157 this->entries.updateTimeout(it, newExpiry); 00158 } 00159 else { 00160 BlacklistInfo binfo; 00161 Date timeout = binfo.add(bidRequest, agent, agentConfig); 00162 this->entries.insert(id, binfo, timeout); 00163 } 00164 }; 00165 00166 addToBlacklist(bidRequest.userIds.exchangeId); 00167 addToBlacklist(bidRequest.userIds.providerId); 00168 } 00169 00170 } // namespace RTBKIT