]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/communicator.hh
if we don't AXFR a domain during a slave cycle, don't add it to the AXFR list again!
[thirdparty/pdns.git] / pdns / communicator.hh
CommitLineData
12c86877
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
84f3c217 3 Copyright (C) 2002-2010 PowerDNS.COM BV
12c86877
BH
4
5 This program is free software; you can redistribute it and/or modify
22dc646a
BH
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
8
12c86877
BH
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
06bd9ccf 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12c86877
BH
18*/
19#ifndef PDNS_COMMUNICATOR_HH
20#define PDNS_COMMUNICATOR_HH
21
22#include <pthread.h>
23#include <string>
24#include <semaphore.h>
25#include <queue>
26#include <list>
f1a8bee5 27#include <limits>
84f3c217
BH
28#include <boost/multi_index_container.hpp>
29#include <boost/multi_index/identity.hpp>
30#include <boost/multi_index/sequenced_index.hpp>
31using namespace boost::multi_index;
1258abe0
BH
32
33#ifndef WIN32
34# include <unistd.h>
35# include <fcntl.h>
36# include <netdb.h>
37#endif // WIN32
38
12c86877
BH
39#include "lock.hh"
40#include "packethandler.hh"
41
42using namespace std;
43
44struct SuckRequest
45{
46 string domain;
47 string master;
84f3c217
BH
48 bool operator<(const SuckRequest& b) const
49 {
50 return tie(domain, master) < tie(b.domain, b.master);
51 }
12c86877
BH
52};
53
84f3c217
BH
54typedef multi_index_container<
55 SuckRequest,
56 indexed_by<
57 sequenced<>,
58 ordered_unique<identity<SuckRequest> >
59 >
60> UniQueue;
61
12c86877
BH
62class NotificationQueue
63{
64public:
65 void add(const string &domain, const string &ip)
66 {
1258abe0
BH
67 NotificationRequest nr;
68 nr.domain = domain;
69 nr.ip = ip;
70 nr.attempts = 0;
71 nr.id = Utility::random()%0xffff;
72 nr.next = time(0);
12c86877
BH
73
74 d_nqueue.push_back(nr);
75 }
76
092f210a 77 bool removeIf(const string &remote, uint16_t id, const string &domain)
12c86877
BH
78 {
79 for(d_nqueue_t::iterator i=d_nqueue.begin();i!=d_nqueue.end();++i) {
20ca8e7d
BH
80 // cout<<i->id<<" "<<id<<endl;
81 //cout<<i->ip<<" "<<remote<<endl;
82 //cout<<i->domain<<" "<<domain<<endl;
12c86877
BH
83
84 if(i->id==id && i->ip==remote && i->domain==domain) {
57025e6a
BH
85 d_nqueue.erase(i);
86 return true;
12c86877
BH
87 }
88 }
89 return false;
90 }
91
092f210a 92 bool getOne(string &domain, string &ip, uint16_t *id, bool &purged)
12c86877
BH
93 {
94 for(d_nqueue_t::iterator i=d_nqueue.begin();i!=d_nqueue.end();++i)
95 if(i->next <= time(0)) {
57025e6a
BH
96 i->attempts++;
97 purged=false;
98 i->next=time(0)+1+(1<<i->attempts);
99 domain=i->domain;
100 ip=i->ip;
101 *id=i->id;
102 purged=false;
103 if(i->attempts>4) {
104 purged=true;
105 d_nqueue.erase(i);
106 }
107 return true;
12c86877
BH
108 }
109 return false;
110 }
111
112 time_t earliest()
113 {
f1a8bee5 114 time_t early=numeric_limits<time_t>::max() - 1;
12c86877
BH
115 for(d_nqueue_t::const_iterator i=d_nqueue.begin();i!=d_nqueue.end();++i)
116 early=min(early,i->next);
117 return early-time(0);
118 }
119
120private:
121 struct NotificationRequest
122 {
123 string domain;
124 string ip;
125 int attempts;
092f210a 126 uint16_t id;
12c86877
BH
127 time_t next;
128 };
129
130 typedef list<NotificationRequest>d_nqueue_t;
131 d_nqueue_t d_nqueue;
132
133};
134
135/** this class contains a thread that communicates with other nameserver and does housekeeping.
136 Initially, it is notified only of zones that need to be pulled in because they have been updated. */
137
138class CommunicatorClass
139{
140public:
141 CommunicatorClass()
142 {
143 pthread_mutex_init(&d_lock,0);
144 pthread_mutex_init(&d_holelock,0);
145// sem_init(&d_suck_sem,0,0);
146// sem_init(&d_any_sem,0,0);
147 d_tickinterval=60;
bd11bd1d 148 d_masterschanged=d_slaveschanged=true;
12c86877 149 }
88c0425a 150 time_t doNotifications();
12c86877
BH
151 void go()
152 {
153 pthread_t tid;
154 pthread_create(&tid,0,&launchhelper,this);
155 }
156
157 void drillHole(const string &domain, const string &ip);
158 bool justNotified(const string &domain, const string &ip);
98e05fce 159 void addSuckRequest(const string &domain, const string &master, bool priority=false);
12c86877
BH
160 void notify(const string &domain, const string &ip);
161 void mainloop();
162 static void *launchhelper(void *p)
163 {
164 static_cast<CommunicatorClass *>(p)->mainloop();
165 return 0;
166 }
167 bool notifyDomain(const string &domain);
168private:
169 void makeNotifySocket();
170 void queueNotifyDomain(const string &domain, DNSBackend *B);
171 int d_nsock;
172 map<pair<string,string>,time_t>d_holes;
173 pthread_mutex_t d_holelock;
174 void suck(const string &domain, const string &remote);
175 void slaveRefresh(PacketHandler *P);
176 void masterUpdateCheck(PacketHandler *P);
177 pthread_mutex_t d_lock;
84f3c217
BH
178
179 UniQueue d_suckdomains;
180
98e05fce 181 bool d_havepriosuckrequest;
12c86877
BH
182 Semaphore d_suck_sem;
183 Semaphore d_any_sem;
88c0425a 184 time_t d_tickinterval;
12c86877 185 NotificationQueue d_nq;
bd11bd1d 186 bool d_masterschanged, d_slaveschanged;
12c86877
BH
187};
188
189#endif