RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
core/agent_configuration/blacklist.cc
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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator