1 /*
2 * lftp - file transfer program
3 *
4 * Copyright (c) 1996-2013 by Alexander V. Lukyanov (lav@yars.free.net)
5 *
6 * This program 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 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <config.h>
21 #include "SMTask.h"
22 #include "Timer.h"
23 #include "xstring.h"
24 #include "misc.h"
25
26 #define now SMTask::now
27
28 xlist_head<Timer> Timer::all_timers;
29 xheap<Timer> Timer::running_timers;
30 int Timer::infty_count;
31
GetTimeoutTV()32 timeval Timer::GetTimeoutTV()
33 {
34 Timer *t;
35 while((t=running_timers.get_min())!=0 && t->Stopped())
36 running_timers.pop_min();
37 if(!t) {
38 timeval tv={infty_count?HOUR:-1, 0};
39 return tv;
40 }
41 TimeDiff remains(t->stop,now);
42 return remains.toTimeval();
43 }
44
TimeLeft() const45 TimeInterval Timer::TimeLeft() const
46 {
47 if(IsInfty())
48 return TimeInterval();
49 if(now>=stop)
50 return TimeInterval(0,0);
51 return TimeInterval(stop-now);
52 }
set_last_setting(const TimeInterval & i)53 void Timer::set_last_setting(const TimeInterval &i)
54 {
55 infty_count-=IsInfty();
56 last_setting=i;
57 infty_count+=IsInfty();
58 re_set();
59 }
add_random()60 void Timer::add_random()
61 {
62 if(random_max>0.0001) {
63 stop+=TimeDiff::valueOf(random_max*random01());
64 }
65 }
re_set()66 void Timer::re_set()
67 {
68 stop=start;
69 stop+=last_setting;
70 add_random();
71 re_sort();
72 }
AddRandom(double r)73 void Timer::AddRandom(double r) {
74 random_max=r;
75 add_random();
76 re_sort();
77 }
Set(const TimeInterval & i)78 void Timer::Set(const TimeInterval &i)
79 {
80 resource.unset();
81 closure.unset();
82 start=SMTask::now;
83 set_last_setting(i);
84 }
Reset(const Time & t)85 void Timer::Reset(const Time &t)
86 {
87 if(start>=t && stop>t)
88 return;
89 start=t;
90 re_set();
91 }
ResetDelayed(int s)92 void Timer::ResetDelayed(int s)
93 {
94 Reset(SMTask::now+TimeDiff(s,0));
95 }
StopDelayed(int s)96 void Timer::StopDelayed(int s)
97 {
98 stop=SMTask::now+TimeDiff(s,0);
99 re_sort();
100 }
SetResource(const char * r,const char * c)101 void Timer::SetResource(const char *r,const char *c)
102 {
103 if(resource!=r || closure!=c)
104 {
105 resource.set(r);
106 closure.set(c);
107 start=now;
108 reconfig(r);
109 }
110 else
111 {
112 Reset();
113 }
114 }
Stopped() const115 bool Timer::Stopped() const
116 {
117 if(IsInfty())
118 return false;
119 return now>=stop;
120 }
reconfig(const char * r)121 void Timer::reconfig(const char *r)
122 {
123 if(resource && (!r || !strcmp(r,resource)))
124 set_last_setting(TimeIntervalR(ResMgr::Query(resource,closure)));
125 }
init()126 void Timer::init()
127 {
128 random_max=0;
129 all_timers.add(all_timers_node);
130 }
~Timer()131 Timer::~Timer()
132 {
133 running_timers.remove(running_timers_node);
134 all_timers_node.remove();
135 infty_count-=IsInfty();
136 }
Timer()137 Timer::Timer() : last_setting(1,0),
138 all_timers_node(this), running_timers_node(this)
139 {
140 init();
141 }
Timer(const TimeInterval & d)142 Timer::Timer(const TimeInterval &d) : last_setting(d),
143 all_timers_node(this), running_timers_node(this)
144 {
145 init();
146 infty_count+=IsInfty();
147 re_set();
148 }
Timer(const char * r,const char * c)149 Timer::Timer(const char *r,const char *c) : last_setting(0,0),
150 all_timers_node(this), running_timers_node(this)
151 {
152 init();
153 resource.set(r);
154 closure.set(c);
155 start=now;
156 reconfig(r);
157 }
Timer(int s,int ms)158 Timer::Timer(int s,int ms) :
159 all_timers_node(this), running_timers_node(this)
160 {
161 init();
162 Set(TimeInterval(s,ms));
163 }
re_sort()164 void Timer::re_sort()
165 {
166 running_timers.remove(running_timers_node);
167 if(now<stop && !IsInfty())
168 running_timers.add(running_timers_node);
169 }
ReconfigAll(const char * r)170 void Timer::ReconfigAll(const char *r)
171 {
172 xlist_for_each(Timer,all_timers,node,scan)
173 scan->reconfig(r);
174 }
175
operator <(const Timer & a,const Timer & b)176 bool operator<(const Timer& a,const Timer& b)
177 {
178 return a.TimeLeft()<b.TimeLeft();
179 }
180