fix log errors
[Pman.Core] / DataObjects / Core_notify_server.php
1 <?php
2 /**
3  * Table Definition for core_notify_server
4  */
5 class_exists('DB_DataObject') ? '' : require_once 'DB/DataObject.php';
6
7 class Pman_Core_DataObjects_Core_notify_server extends DB_DataObject 
8 {
9     ###START_AUTOCODE
10     /* the code below is auto generated do not remove the above tag */
11
12     public $__table = 'core_notify_server';    // table name
13     public $id;                              // int(11)  not_null primary_key auto_increment
14     public $hostname;
15     public $helo;
16     public $poolname;
17     public $is_active;
18     public $last_send;
19     
20     // most services should call this first..
21     
22     function getCurrent($notify)
23     {
24         static $current = false;;
25         
26         if ($current !== false) {
27             return $current;
28         }
29         
30         $ns = DB_DataObject::factory('core_notify_server');
31         $ns->poolname = $notify->poolname;
32         $ns->is_active = 1;
33         $ns->hostname = gethostname();
34         if (!$ns->count()) {
35             $notify->jerr("Server not found for this server " .  gethostname() . " in core_notify_server" );
36         }
37         $ns->find(true);
38         $current = $ns;
39         return $ns;
40     }
41     
42     
43     function isFirstServer()
44     {
45         $servers = $this->availableServers();
46         if (empty($servers)) {
47             return false;
48         }
49         // only run this on the first server...
50         return $this->id == $servers[0]->id;
51     }
52     
53     
54     // called on current server.
55     function assignQueues($notify)
56     {
57          
58         
59         $servers = $this->availableServers();
60         $ids = array();
61         foreach($servers as $s) {
62             $ids[] = $s->id;
63         }
64         
65         
66         if (empty($ids)) {
67             $notify->jerr("no configured servers in core_notify_server for poolname = {$notify->poolname}");
68             
69         }
70          
71         // only run this on the first server...
72         if ($this->id != $ids[0]) {
73             return; 
74         }
75         foreach($ids as $rn) {
76             $up[$rn]  = array();
77         }
78         
79         $num_servers = count($ids);
80         
81         if ($num_servers == 1) {
82             $p = DB_DataObject::factory($notify->table);
83             $p->query("
84                 UPDATE
85                     {$notify->table}
86                 SET
87                     server_id = {$ids[0]}
88                 WHERE
89                     sent < '2000-01-01'
90                     and
91                     event_id = 0
92                     and
93                     act_start < NOW() +  INTERVAL 3 HOUR 
94                     and
95                     server_id != {$ids[0]}
96             ");
97             return;
98         }
99         
100         // ((@row_number := CASE WHEN @row_number IS NULL THEN 0 ELSE @row_number END  +1) % {$num_servers})
101         
102         
103         
104         $p = DB_DataObject::factory($notify->table);
105         $p->whereAdd("
106                 sent < '2000-01-01'
107                 and
108                 event_id = 0
109                 and
110                 act_start < NOW() +  INTERVAL 3 HOUR 
111                 and
112                 server_id NOT IN (" . implode(",", $ids) . ")
113         ");
114         if ($p->count() < 1) {
115             return;
116         }
117         
118         $p->selectAdd();
119         $p->selectAdd("id, ((@row_number := CASE WHEN @row_number IS NULL THEN 0 ELSE @row_number END  +1) % {$num_servers})  as rn");
120         $kv = $p->fetchAll('id','rn');
121         foreach($kv as $id => $r) {
122             $up[ $ids[$r] ][] = $id;
123         }
124         foreach($up as $sid => $nids) {
125             if (empty($nids)) {
126                 continue;
127             }
128             $p = DB_DataObject::factory($notify->table);
129             $p->query("
130                 UPDATE
131                     {$notify->table}
132                 SET
133                     server_id = $sid
134                 WHERE
135                     id IN (". implode(',', $nids). ')'
136             );
137         }
138          
139         DB_DataObject::factory("core_notify_blacklist")->prune();
140         
141     }
142         // called on current server.
143
144     function availableServers()
145     {
146         $ns = DB_DataObject::factory('core_notify_server');
147         $ns->poolname = $this->poolname;
148         $ns->is_active = 1;
149         $ns->orderBy('id ASC');
150         return  $ns->fetchAll();
151         
152     }
153     
154     function updateNotifyToNextServer( $cn , $when = false, $allow_same = false)
155     {
156         // fixme - this should take into account blacklisted - and return false if no more servers are available
157         $email = empty($cn->to_email) ? ($cn->person() ? $cn->person()->email : $cn->to_email) : $cn->to_email;
158
159         $w = DB_DataObject::factory($cn->tableName());
160         $w->get($cn->id);
161         
162         $servers = $this->availableServers();
163         $start = 0;
164         foreach($servers as $i => $s) {
165             if ($s->id == $this->id) {
166                 $start = $i;
167             }
168         }
169         
170         $offset = ($start + 1)  % count($servers);
171         $good = false;
172         while ($offset  != $start) {
173             $s = $servers[$offset];
174             if (!$s->isBlacklisted($email)) {
175                 $good = $s;
176                 break;
177             }
178         }
179         if ($good == false && $allow_same) {
180             $good = $this;
181         }
182         
183         if ($good == false) {
184             return false;
185         }
186         
187         
188         // next server..
189         $pp = clone($w);
190         $w->server_id = $good->id;   
191         $w->act_when = $when === false ? $w->sqlValue('NOW() + INTERVAL 1 MINUTE') : $when;
192         $w->update($pp);
193         return true;
194     }
195     
196     
197     function isBlacklisted($email)
198     {
199         // return current server id..
200         static $cache = array();
201         
202         // get the domain..
203         $ea = explode('@',$email);
204         $dom = strtolower(array_pop($ea));
205         if (isset($cache[$dom])) {
206             return $cache[$dom];
207         }
208         
209         $cd = DB_DataObject::factory('core_domain')->loadOrCreate($dom);
210         
211         $bl = DB_DataObject::factory('core_notify_blacklist');
212         $bl->server_id = $this->id;
213         $bl->domain_id = $cd->id;
214         if ($bl->count()) {
215             $cache[$dom] = true;
216             return true;
217         }
218         
219         return false; 
220     }
221     function initHelo()
222     {
223         $ff = HTML_FlexyFramework::get();
224         $ff->Mail['helo'] = $this->helo;
225         
226     }
227     function checkSmtpResponse($errmsg, $core_domain)
228     {
229         $bl = DB_DataObject::factory('core_notify_blacklist');
230         $bl->server_id = $this->id;
231         $bl->domain_id = $core_domain->id;
232         if ($bl->count()) {
233             return true;
234         }
235         // is it a blacklist message
236         if (!$bl->messageIsBlacklisted($errmsg)) {
237             return false;
238         }
239         $bl->error_str = $errmsg;
240         $bl->added_dt = $bl->sqlValue("NOW()");
241         $bl->insert();
242         return true;
243         
244     }
245     
246 }