]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/ueberbackend.cc
Initialize TCPReceiver#d_tid
[thirdparty/pdns.git] / pdns / ueberbackend.cc
CommitLineData
12c86877
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
e0d84497 3 Copyright (C) 2005 - 2011 PowerDNS.COM BV
12c86877
BH
4
5 This program is free software; you can redistribute it and/or modify
923a2384
BH
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation
12c86877 8
f782fe38
MH
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
12
12c86877
BH
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
06bd9ccf 20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12c86877 21*/
870a0fe4
AT
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
cb433f9c
BH
25#include <boost/archive/binary_iarchive.hpp>
26#include <boost/archive/binary_oarchive.hpp>
27
ba45c866 28#include "packetcache.hh"
12c86877 29#include "utility.hh"
c6566265 30
c6566265 31
12c86877
BH
32#include <string>
33#include <map>
34#include <sys/types.h>
cb433f9c 35#include <sstream>
12c86877
BH
36#include <errno.h>
37#include <iostream>
38#include <sstream>
39#include <functional>
c0273500 40#include <boost/foreach.hpp>
12c86877
BH
41#include "dns.hh"
42#include "arguments.hh"
43#include "dnsbackend.hh"
44#include "ueberbackend.hh"
45#include "dnspacket.hh"
46#include "logger.hh"
47#include "statbag.hh"
13978a71 48#include <boost/serialization/vector.hpp>
ba45c866 49
12c86877
BH
50
51extern StatBag S;
52
53vector<UeberBackend *>UeberBackend::instances;
54pthread_mutex_t UeberBackend::instances_lock=PTHREAD_MUTEX_INITIALIZER;
55
56sem_t UeberBackend::d_dynserialize;
12c86877
BH
57
58// initially we are blocked
59bool UeberBackend::d_go=false;
60pthread_mutex_t UeberBackend::d_mut = PTHREAD_MUTEX_INITIALIZER;
61pthread_cond_t UeberBackend::d_cond = PTHREAD_COND_INITIALIZER;
62
12c86877
BH
63//! Loads a module and reports it to all UeberBackend threads
64bool UeberBackend::loadmodule(const string &name)
65{
74caf870
KM
66 L<<Logger::Warning <<"Loading '"<<name<<"'" << endl;
67
12c86877 68 void *dlib=dlopen(name.c_str(), RTLD_NOW);
74caf870 69
12c86877 70 if(dlib == NULL) {
74caf870 71 L<<Logger::Error <<"Unable to load module '"<<name<<"': "<<dlerror() << endl;
12c86877
BH
72 return false;
73 }
74caf870 74
12c86877 75 return true;
12c86877
BH
76}
77
78void UeberBackend::go(void)
79{
80 pthread_mutex_lock(&d_mut);
81 d_go=true;
82 pthread_cond_broadcast(&d_cond);
83 pthread_mutex_unlock(&d_mut);
84}
85
675fa24c 86bool UeberBackend::getDomainInfo(const DNSName &domain, DomainInfo &di)
12c86877
BH
87{
88 for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
89 if((*i)->getDomainInfo(domain, di))
90 return true;
91 return false;
92}
93
675fa24c 94bool UeberBackend::createDomain(const DNSName &domain)
487cf033
CH
95{
96 BOOST_FOREACH(DNSBackend* mydb, backends) {
97 if(mydb->createDomain(domain)) {
487cf033
CH
98 return true;
99 }
100 }
101 return false;
102}
103
675fa24c 104int UeberBackend::addDomainKey(const DNSName& name, const DNSBackend::KeyData& key)
c0273500 105{
9957cac5 106 int ret;
c0273500 107 BOOST_FOREACH(DNSBackend* db, backends) {
9957cac5
BH
108 if((ret = db->addDomainKey(name, key)) >= 0)
109 return ret;
c0273500 110 }
9957cac5 111 return -1;
c0273500 112}
675fa24c 113bool UeberBackend::getDomainKeys(const DNSName& name, unsigned int kind, std::vector<DNSBackend::KeyData>& keys)
c0273500
BH
114{
115 BOOST_FOREACH(DNSBackend* db, backends) {
116 if(db->getDomainKeys(name, kind, keys))
117 return true;
118 }
119 return false;
120}
121
675fa24c 122bool UeberBackend::getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta)
ac993e0a 123{
ac993e0a
AT
124 BOOST_FOREACH(DNSBackend* db, backends) {
125 if(db->getAllDomainMetadata(name, meta))
126 return true;
127 }
128 return false;
129}
130
675fa24c 131bool UeberBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta)
c0273500
BH
132{
133 BOOST_FOREACH(DNSBackend* db, backends) {
134 if(db->getDomainMetadata(name, kind, meta))
135 return true;
136 }
137 return false;
138}
139
675fa24c 140bool UeberBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta)
c0273500
BH
141{
142 BOOST_FOREACH(DNSBackend* db, backends) {
143 if(db->setDomainMetadata(name, kind, meta))
144 return true;
145 }
146 return false;
147}
148
675fa24c 149bool UeberBackend::activateDomainKey(const DNSName& name, unsigned int id)
4496f66f
BH
150{
151 BOOST_FOREACH(DNSBackend* db, backends) {
152 if(db->activateDomainKey(name, id))
153 return true;
154 }
155 return false;
156}
157
675fa24c 158bool UeberBackend::deactivateDomainKey(const DNSName& name, unsigned int id)
4496f66f
BH
159{
160 BOOST_FOREACH(DNSBackend* db, backends) {
161 if(db->deactivateDomainKey(name, id))
162 return true;
163 }
164 return false;
165}
166
675fa24c 167bool UeberBackend::removeDomainKey(const DNSName& name, unsigned int id)
4496f66f
BH
168{
169 BOOST_FOREACH(DNSBackend* db, backends) {
170 if(db->removeDomainKey(name, id))
171 return true;
172 }
173 return false;
174}
175
c0273500 176
675fa24c 177bool UeberBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content)
78bcb858
BH
178{
179 BOOST_FOREACH(DNSBackend* db, backends) {
180 if(db->getTSIGKey(name, algorithm, content))
181 return true;
182 }
183 return false;
184}
185
186
675fa24c 187bool UeberBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content)
6f872b78
AT
188{
189 BOOST_FOREACH(DNSBackend* db, backends) {
190 if(db->setTSIGKey(name, algorithm, content))
191 return true;
192 }
193 return false;
194}
195
675fa24c 196bool UeberBackend::deleteTSIGKey(const DNSName& name)
6f872b78
AT
197{
198 BOOST_FOREACH(DNSBackend* db, backends) {
199 if(db->deleteTSIGKey(name))
200 return true;
201 }
202 return false;
203}
204
205bool UeberBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys)
206{
207 BOOST_FOREACH(DNSBackend* db, backends) {
208 db->getTSIGKeys(keys);
209 }
210 return true;
211}
212
675fa24c 213bool UeberBackend::getDirectNSECx(uint32_t id, const string &hashed, const QType &qtype, DNSName &before, DNSResourceRecord &rr)
d88babea
KM
214{
215 BOOST_FOREACH(DNSBackend* db, backends) {
996df946 216 if(db->getDirectNSECx(id, hashed, qtype, before, rr))
d88babea
KM
217 return true;
218 }
219 return false;
220}
221
675fa24c 222bool UeberBackend::getDirectRRSIGs(const DNSName &signer, const DNSName &qname, const QType &qtype, vector<DNSResourceRecord> &rrsigs)
d88babea
KM
223{
224 BOOST_FOREACH(DNSBackend* db, backends) {
461a0401 225 if(db->getDirectRRSIGs(signer, qname, qtype, rrsigs))
d88babea
KM
226 return true;
227 }
228 return false;
229}
230
12c86877
BH
231void UeberBackend::reload()
232{
233 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
234 {
235 ( *i )->reload();
236 }
237}
238
973ad2b5 239void UeberBackend::rediscover(string *status)
12c86877 240{
20ca8e7d 241
12c86877
BH
242 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
243 {
973ad2b5
BH
244 string tmpstr;
245 ( *i )->rediscover(&tmpstr);
6242d8a4
KM
246 if(status)
247 *status+=tmpstr + (i!=backends.begin() ? "\n" : "");
12c86877
BH
248 }
249}
250
251
252void UeberBackend::getUnfreshSlaveInfos(vector<DomainInfo>* domains)
253{
254 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
255 {
256 ( *i )->getUnfreshSlaveInfos( domains );
257 }
258}
259
260
261
262void UeberBackend::getUpdatedMasters(vector<DomainInfo>* domains)
263{
264 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
265 {
266 ( *i )->getUpdatedMasters( domains );
267 }
268}
269
675fa24c 270bool UeberBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target)
c14bc34a 271{
d33578f8 272 int best_match_len = -1;
c14bc34a
MZ
273 bool from_cache = false; // Was this result fetched from the cache?
274
c14bc34a
MZ
275 // If not special case of caching explicitly disabled (sd->db = -1), first
276 // find the best match from the cache. If DS then we need to find parent so
277 // dont bother with caching as it confuses matters.
278 if( sd->db != (DNSBackend *)-1 && d_cache_ttl && p->qtype != QType::DS ) {
675fa24c 279 DNSName subdomain(target);
c14bc34a
MZ
280 int cstat, loops = 0;
281 do {
282 d_question.qtype = QType::SOA;
283 d_question.qname = subdomain;
284 d_question.zoneId = -1;
285
286 cstat = cacheHas(d_question,d_answers);
287
288 if(cstat==1 && !d_answers.empty()) {
289 fillSOAData(d_answers[0].content,*sd);
290 sd->domain_id = d_answers[0].domain_id;
291 sd->ttl = d_answers[0].ttl;
292 sd->db = 0;
293 sd->qname = subdomain;
294 //L<<Logger::Error<<"Best cache match: " << sd->qname << " itteration " << loops <<endl;
295
296 // Found first time round this must be the best match
297 if( loops == 0 )
298 return true;
299
300 from_cache = true;
675fa24c 301 best_match_len = sd->qname.countLabels();
c14bc34a
MZ
302
303 break;
304 }
305 loops++;
306 }
675fa24c 307 while( subdomain.chopOff() ); // 'www.powerdns.org' -> 'powerdns.org' -> 'org' -> ''
c14bc34a
MZ
308 }
309
310 for(vector<DNSBackend *>::const_iterator i=backends.begin(); i!=backends.end();++i)
81c486ad 311 if((*i)->getAuth(p, sd, target, best_match_len)) {
3343ad1f 312 best_match_len = sd->qname.countLabels(); // FIXME400
c14bc34a
MZ
313 from_cache = false;
314
315 // Shortcut for the case that we got a direct hit - no need to go
316 // through the other backends then.
675fa24c 317 if( best_match_len == (int)target.countLabels() )
c14bc34a
MZ
318 goto auth_found;
319 }
320
d33578f8 321 if( best_match_len == -1 )
c14bc34a
MZ
322 return false;
323
324auth_found:
325 // Insert into cache. Don't cache if the query was a DS
326 if( d_cache_ttl && ! from_cache && p->qtype != QType::DS ) {
327 //L<<Logger::Error<<"Saving auth cache for " << sd->qname <<endl;
328 d_question.qtype = QType::SOA;
329 d_question.qname = sd->qname;
330 d_question.zoneId = -1;
331
332 DNSResourceRecord rr;
333 rr.qname = sd->qname;
334 rr.qtype = QType::SOA;
335 rr.content = serializeSOAData(*sd);
336 rr.ttl = sd->ttl;
337 rr.domain_id = sd->domain_id;
338 vector<DNSResourceRecord> rrs;
339 rrs.push_back(rr);
340 addCache(d_question, rrs);
341 }
342
343 return true;
344}
345
675fa24c 346bool UeberBackend::getSOA(const DNSName &domain, SOAData &sd, DNSPacket *p)
12c86877
BH
347{
348 d_question.qtype=QType::SOA;
349 d_question.qname=domain;
350 d_question.zoneId=-1;
351
79ba7763
CH
352 int cstat=cacheHas(d_question,d_answers);
353 if(cstat==0) { // negative
354 return false;
12c86877 355 }
79ba7763
CH
356 else if(cstat==1 && !d_answers.empty()) {
357 fillSOAData(d_answers[0].content,sd);
358 sd.domain_id=d_answers[0].domain_id;
359 sd.ttl=d_answers[0].ttl;
360 sd.db=0;
361 return true;
362 }
363
364 // not found in neg. or pos. cache, look it up
365 return getSOAUncached(domain, sd, p);
366}
367
675fa24c 368bool UeberBackend::getSOAUncached(const DNSName &domain, SOAData &sd, DNSPacket *p)
79ba7763
CH
369{
370 d_question.qtype=QType::SOA;
371 d_question.qname=domain;
372 d_question.zoneId=-1;
373
12c86877 374 for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
35933370 375 if((*i)->getSOA(domain, sd, p)) {
f1d64762
MZ
376 if( d_cache_ttl ) {
377 DNSResourceRecord rr;
378 rr.qname=domain;
379 rr.qtype=QType::SOA;
380 rr.content=serializeSOAData(sd);
381 rr.ttl=sd.ttl;
382 rr.domain_id=sd.domain_id;
383 vector<DNSResourceRecord> rrs;
384 rrs.push_back(rr);
385 addCache(d_question, rrs);
386 }
12c86877
BH
387 return true;
388 }
389
79ba7763 390 addNegCache(d_question);
12c86877
BH
391 return false;
392}
393
675fa24c 394bool UeberBackend::superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **db)
12c86877
BH
395{
396 for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
719f9024 397 if((*i)->superMasterBackend(ip, domain, nsset, nameserver, account, db))
12c86877
BH
398 return true;
399 return false;
12c86877
BH
400}
401
12c86877
BH
402UeberBackend::UeberBackend(const string &pname)
403{
12c86877
BH
404 pthread_mutex_lock(&instances_lock);
405 instances.push_back(this); // report to the static list of ourself
406 pthread_mutex_unlock(&instances_lock);
407
f1d64762
MZ
408 d_cache_ttl = ::arg().asNum("query-cache-ttl");
409 d_negcache_ttl = ::arg().asNum("negquery-cache-ttl");
410
12c86877
BH
411 tid=pthread_self();
412 stale=false;
413
e0d84497 414 backends=BackendMakers().all(pname=="key-only");
12c86877
BH
415}
416
12c86877
BH
417void del(DNSBackend* d)
418{
419 delete d;
420}
421
422void UeberBackend::cleanup()
423{
424 pthread_mutex_lock(&instances_lock);
425
426 remove(instances.begin(),instances.end(),this);
427 instances.resize(instances.size()-1);
428
429 pthread_mutex_unlock(&instances_lock);
430
6242d8a4 431 for_each(backends.begin(),backends.end(),del);
12c86877
BH
432}
433
923a2384
BH
434// silly Solaris fix
435#undef PC
436
cb433f9c
BH
437// returns -1 for miss, 0 for negative match, 1 for hit
438int UeberBackend::cacheHas(const Question &q, vector<DNSResourceRecord> &rrs)
12c86877
BH
439{
440 extern PacketCache PC;
1566533a 441 static AtomicCounter *qcachehit=S.getPointer("query-cache-hit");
442 static AtomicCounter *qcachemiss=S.getPointer("query-cache-miss");
12c86877 443
f1d64762 444 if(!d_cache_ttl && ! d_negcache_ttl) {
12c86877
BH
445 (*qcachemiss)++;
446 return -1;
447 }
448
449 string content;
2f24bcd2 450 // L<<Logger::Warning<<"looking up: '"<<q.qname+"'|N|"+q.qtype.getName()+"|"+itoa(q.zoneId)<<endl;
cf71f03f 451
771af01a 452 bool ret=PC.getEntry(q.qname, q.qtype, PacketCache::QUERYCACHE, content, q.zoneId); // think about lowercasing here
12c86877
BH
453 if(!ret) {
454 (*qcachemiss)++;
455 return -1;
456 }
12c86877 457 (*qcachehit)++;
2f24bcd2 458 if(content.empty()) // negatively cached
12c86877 459 return 0;
cb433f9c
BH
460
461 std::istringstream istr(content);
2665f226 462 boost::archive::binary_iarchive boa(istr, boost::archive::no_header);
7d454f5b 463 rrs.clear();
cb433f9c 464 boa >> rrs;
12c86877
BH
465 return 1;
466}
467
468void UeberBackend::addNegCache(const Question &q)
469{
470 extern PacketCache PC;
f1d64762 471 if(!d_negcache_ttl)
12c86877 472 return;
ee5e1751 473 // we should also not be storing negative answers if a pipebackend does scopeMask, but we can't pass a negative scopeMask in an empty set!
f1d64762 474 PC.insert(q.qname, q.qtype, PacketCache::QUERYCACHE, "", d_negcache_ttl, q.zoneId);
12c86877
BH
475}
476
cb433f9c 477void UeberBackend::addCache(const Question &q, const vector<DNSResourceRecord> &rrs)
12c86877
BH
478{
479 extern PacketCache PC;
46c6efbe 480
f1d64762 481 if(!d_cache_ttl)
12c86877 482 return;
f1d64762
MZ
483
484 unsigned int store_ttl = d_cache_ttl;
485
2f24bcd2 486 // L<<Logger::Warning<<"inserting: "<<q.qname+"|N|"+q.qtype.getName()+"|"+itoa(q.zoneId)<<endl;
cb433f9c 487 std::ostringstream ostr;
2665f226 488 boost::archive::binary_oarchive boa(ostr, boost::archive::no_header);
b35ea8ec
PD
489
490 BOOST_FOREACH(DNSResourceRecord rr, rrs) {
f1d64762
MZ
491 if (rr.ttl < d_cache_ttl)
492 store_ttl = rr.ttl;
ee5e1751 493 if (rr.scopeMask)
494 return;
b35ea8ec 495 }
46c6efbe 496
cb433f9c 497 boa << rrs;
f1d64762 498 PC.insert(q.qname, q.qtype, PacketCache::QUERYCACHE, ostr.str(), store_ttl, q.zoneId);
12c86877
BH
499}
500
675fa24c 501void UeberBackend::alsoNotifies(const DNSName &domain, set<string> *ips)
27d94a79
BH
502{
503 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
504 (*i)->alsoNotifies(domain,ips);
505}
12c86877
BH
506
507UeberBackend::~UeberBackend()
508{
509 DLOG(L<<Logger::Error<<"UeberBackend destructor called, removing ourselves from instances, and deleting our backends"<<endl);
510 cleanup();
511}
512
513// this handle is more magic than most
675fa24c 514void UeberBackend::lookup(const QType &qtype,const DNSName &qname, DNSPacket *pkt_p, int zoneId)
12c86877
BH
515{
516 if(stale) {
517 L<<Logger::Error<<"Stale ueberbackend received question, signalling that we want to be recycled"<<endl;
3f81d239 518 throw PDNSException("We are stale, please recycle");
12c86877
BH
519 }
520
f43c4448 521 DLOG(L<<"UeberBackend received question for "<<qtype.getName()<<" of "<<qname<<endl);
12c86877
BH
522 if(!d_go) {
523 pthread_mutex_lock(&d_mut);
524 while (d_go==false) {
525 L<<Logger::Error<<"UeberBackend is blocked, waiting for 'go'"<<endl;
526 pthread_cond_wait(&d_cond, &d_mut);
527 L<<Logger::Error<<"Broadcast received, unblocked"<<endl;
528 }
529 pthread_mutex_unlock(&d_mut);
530 }
531
c27c8d96
PD
532 domain_id=zoneId;
533
12c86877
BH
534 d_handle.i=0;
535 d_handle.qtype=qtype;
536 d_handle.qname=qname;
537 d_handle.pkt_p=pkt_p;
538 d_ancount=0;
539
540 if(!backends.size()) {
541 L<<Logger::Error<<Logger::NTLog<<"No database backends available - unable to answer questions."<<endl;
542 stale=true; // please recycle us!
3f81d239 543 throw PDNSException("We are stale, please recycle");
12c86877
BH
544 }
545 else {
6242d8a4
KM
546 d_question.qtype=qtype;
547 d_question.qname=qname;
548 d_question.zoneId=zoneId;
549 int cstat=cacheHas(d_question, d_answers);
550 if(cstat<0) { // nothing
551 d_negcached=d_cached=false;
552 d_answers.clear();
553 (d_handle.d_hinterBackend=backends[d_handle.i++])->lookup(qtype, qname,pkt_p,zoneId);
554 }
555 else if(cstat==0) {
556 d_negcached=true;
557 d_cached=false;
558 d_answers.clear();
559 }
560 else {
561 d_negcached=false;
562 d_cached=true;
563 d_cachehandleiter = d_answers.begin();
564 }
12c86877
BH
565 }
566
567 d_handle.parent=this;
12c86877
BH
568}
569
cea26350 570void UeberBackend::getAllDomains(vector<DomainInfo> *domains, bool include_disabled) {
1325e8a2
PD
571 for (vector<DNSBackend*>::iterator i = backends.begin(); i != backends.end(); ++i )
572 {
cea26350 573 (*i)->getAllDomains(domains, include_disabled);
1325e8a2
PD
574 }
575}
576
12c86877
BH
577bool UeberBackend::get(DNSResourceRecord &rr)
578{
579 if(d_negcached) {
580 return false;
581 }
582
583 if(d_cached) {
cb433f9c
BH
584 if(d_cachehandleiter != d_answers.end()) {
585 rr=*d_cachehandleiter++;;
586 return true;
587 }
588 return false;
12c86877 589 }
12c86877 590 if(!d_handle.get(rr)) {
675fa24c 591 if(!d_ancount && d_handle.qname.countLabels()) // don't cache axfr
12c86877
BH
592 addNegCache(d_question);
593
cb433f9c
BH
594 addCache(d_question, d_answers);
595 d_answers.clear();
12c86877
BH
596 return false;
597 }
cb433f9c
BH
598 d_ancount++;
599 d_answers.push_back(rr);
12c86877
BH
600 return true;
601}
602
675fa24c 603bool UeberBackend::list(const DNSName &target, int domain_id, bool include_disabled)
12c86877 604{
36d772ab
BH
605 L<<Logger::Error<<"UeberBackend::list called, should NEVER EVER HAPPEN"<<endl;
606 exit(1);
607 return false;
12c86877 608}
36d772ab 609
9f8e226e
AT
610bool UeberBackend::searchRecords(const string& pattern, int maxResults, vector<DNSResourceRecord>& result)
611{
612 bool rc = false;
613 for ( vector< DNSBackend * >::iterator i = backends.begin(); result.size() < static_cast<vector<DNSResourceRecord>::size_type>(maxResults) && i != backends.end(); ++i )
614 if ((*i)->searchRecords(pattern, maxResults - result.size(), result)) rc = true;
615 return rc;
616}
617
618bool UeberBackend::searchComments(const string& pattern, int maxResults, vector<Comment>& result)
619{
620 bool rc = false;
621 for ( vector< DNSBackend * >::iterator i = backends.begin(); result.size() < static_cast<vector<Comment>::size_type>(maxResults) && i != backends.end(); ++i )
622 if ((*i)->searchComments(pattern, maxResults - result.size(), result)) rc = true;
623 return rc;
624}
12c86877 625
16f7d28d 626AtomicCounter UeberBackend::handle::instances(0);
12c86877
BH
627
628UeberBackend::handle::handle()
629{
630 // L<<Logger::Warning<<"Handle instances: "<<instances<<endl;
16f7d28d 631 ++instances;
12c86877
BH
632}
633
634UeberBackend::handle::~handle()
635{
16f7d28d 636 --instances;
12c86877
BH
637}
638
12c86877
BH
639bool UeberBackend::handle::get(DNSResourceRecord &r)
640{
641 DLOG(L << "Ueber get() was called for a "<<qtype.getName()<<" record" << endl);
642 bool isMore=false;
643 while(d_hinterBackend && !(isMore=d_hinterBackend->get(r))) { // this backend out of answers
644 if(i<parent->backends.size()) {
645 DLOG(L<<"Backend #"<<i<<" of "<<parent->backends.size()
4957a608 646 <<" out of answers, taking next"<<endl);
12c86877
BH
647
648 d_hinterBackend=parent->backends[i++];
c27c8d96 649 d_hinterBackend->lookup(qtype,qname,pkt_p,parent->domain_id);
12c86877
BH
650 }
651 else
652 break;
653
654 DLOG(L<<"Now asking backend #"<<i<<endl);
655 }
656
657 if(!isMore && i==parent->backends.size()) {
658 DLOG(L<<"UeberBackend reached end of backends"<<endl);
659 return false;
660 }
661
662 DLOG(L<<"Found an answering backend - will not try another one"<<endl);
663 i=parent->backends.size(); // don't go on to the next backend
664 return true;
665}