1 /*
2  * Copyright (C) 2011 Stefan Sayer
3  *
4  * This file is part of SEMS, a free SIP media server.
5  *
6  * SEMS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * For a license to use the sems software under conditions
12  * other than those described here, or to purchase support for this
13  * software, please contact iptel.org by e-mail at the following addresses:
14  *    info@iptel.org
15  *
16  * SEMS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25 
26 #ifndef _RegistrationTimer_h_
27 #define _RegistrationTimer_h_
28 
29 #include <list>
30 #include <vector>
31 
32 #include <sys/time.h>
33 
34 #include "log.h"
35 #include "AmThread.h"
36 
37 #define TIMER_BUCKET_LENGTH 10     // 10 sec
38 #define TIMER_BUCKETS       40000  // 40000 buckets (400000 sec, 111 hrs)
39 
40 // 100 ms == 100000 us
41 #define TIMER_RESOLUTION 100000
42 
43 class RegTimer;
44 typedef void (*timer_cb)(RegTimer*, long /*data1*/,int /*data2*/);
45 
46 class RegTimerBucket;
47 
48 class RegTimer {
49  public:
50     time_t expires;
51 
52     timer_cb       cb;
53     long           data1;
54     int            data2;
55 
RegTimer()56     RegTimer()
57       : expires(0), cb(0), data1(0), data2(0) { }
58 };
59 
60 class RegTimerBucket {
61  public:
62   std::list<RegTimer*> timers;
63 
RegTimerBucket()64  RegTimerBucket() { }
65 };
66 
67 /**
68   Additionally to normal timer operation (setting and removing timer,
69   fire the timer when it is expired), this RegistrationTimer timers
70   class needs to support insert_timer_leastloaded() which should insert
71   the timer in some least loaded interval between from_time and to_time
72   in order to flatten out re-register spikes (due to restart etc).
73 
74   Timer granularity is seconds.
75 
76   Timers are saved in buckets of TIMER_BUCKET_LENGTH seconds. the buckets
77   array is a circular one, the current bucket starts from the time
78   current_bucket_start (in seconds as in time(2)).
79 
80   The timer object is owned by the caller, and MUST be valid until it is
81   fired or removed.
82  */
83 
84 class RegistrationTimer
85 : public AmThread
86 {
87   time_t current_bucket_start;
88   // every bucket contains TIMER_BUCKET_LENGTH seconds of timers
89   RegTimerBucket buckets[TIMER_BUCKETS];
90   unsigned int current_bucket;
91   AmMutex buckets_mut;
92 
93   int get_bucket_index(time_t tv);
94   void place_timer(RegTimer* timer, int bucket_index);
95   void fire_timer(RegTimer* timer);
96   void run_timers();
97 
98  protected:
99   void run();
100   void on_stop();
101 
102  public:
103   bool insert_timer(RegTimer* timer);
104   bool remove_timer(RegTimer* timer);
105 
106   bool insert_timer_leastloaded(RegTimer* timer,
107 				time_t from_time,
108 				time_t to_time);
109 
110   RegistrationTimer();
111   bool _timer_thread_running;
112   bool _shutdown_finished;
113 };
114 
115 #endif
116