1 /*
2 * cleaner.cc
3 *
4 * Created on: 05.02.2011
5 * Author: ed
6 */
7
8 #include "debug.h"
9 #include "meta.h"
10
11 #include "cleaner.h"
12
13 #include "fileitem.h"
14 #include "acfg.h"
15 #include "caddrinfo.h"
16 #include "tcpconnect.h"
17
18 #include <limits>
19 #include <cstring>
20 using namespace std;
21
22 #define TERM_VAL (time_t(-1))
23
24 namespace acng
25 {
26
cleaner()27 cleaner::cleaner() : m_thr(0)
28 {
29 Init();
30 }
Init()31 void cleaner::Init()
32 {
33 for(auto&ts : stamps)
34 ts=END_OF_TIME;
35 }
36
~cleaner()37 cleaner::~cleaner()
38 {
39 }
40
WorkLoop()41 void cleaner::WorkLoop()
42 {
43 LOGSTART("cleaner::WorkLoop");
44
45 lockuniq g(this);
46 for(;;)
47 {
48 // XXX: review the flow, is this always safe?
49 eType what = TYPE_EXCONNS;
50 time_t when = END_OF_TIME;
51
52 if(m_terminating)
53 return;
54
55 // ok, who's next?
56 for (unsigned i = 0; i < ETYPE_MAX; ++i)
57 {
58 if (stamps[i] < when)
59 {
60 what = (eType) i;
61 when = stamps[i];
62 }
63 }
64
65 auto now=GetTime();
66 if(when > now)
67 {
68 // work around buggy STL: add some years on top and hope it will be fixed then
69 if(when == END_OF_TIME)
70 when = now | 0x3ffffffe;
71 wait_until(g, when, 111);
72 continue;
73 }
74 stamps[what] = END_OF_TIME;
75 g.unLock();
76
77 // good, do the work now
78 time_t time_nextcand=END_OF_TIME;
79 switch(what)
80 {
81 case TYPE_ACFGHOOKS:
82 time_nextcand = cfg::BackgroundCleanup();
83 USRDBG("acng::cfg:ExecutePostponed, nextRunTime now: " << time_nextcand);
84 break;
85
86 case TYPE_EXCONNS:
87 time_nextcand = g_tcp_con_factory.BackgroundCleanup();
88 USRDBG("tcpconnect::ExpireCache, nextRunTime now: " << time_nextcand);
89 break;
90 case TYPE_EXFILEITEM:
91 time_nextcand = fileItemMgmt::BackgroundCleanup();
92 USRDBG("fileitem::DoDelayedUnregAndCheck, nextRunTime now: " << time_nextcand);
93 break;
94
95 case ETYPE_MAX:
96 return; // heh?
97 }
98
99 if(time_nextcand <= now || time_nextcand < 1)
100 {
101 log::err(tSS() << "ERROR: looping bug candidate on " << (int) what
102 << ", value: " << time_nextcand);
103 time_nextcand=GetTime()+60;
104 }
105
106 g.reLock();
107
108 if (time_nextcand < stamps[what])
109 stamps[what] = time_nextcand;
110 };
111 }
112
CleanerThreadAction(void * pVoid)113 inline void * CleanerThreadAction(void *pVoid)
114 {
115 static_cast<cleaner*>(pVoid)->WorkLoop();
116 return nullptr;
117 }
118
ScheduleFor(time_t when,eType what)119 void cleaner::ScheduleFor(time_t when, eType what)
120 {
121 setLockGuard;
122 if(m_thr == 0)
123 {
124 Init();
125 stamps[what] = when;
126 pthread_create(&m_thr, nullptr, CleanerThreadAction, (void *)this);
127 }
128 else
129 {
130 // already scheduled for an earlier moment or
131 // something else is pointed and this will come earlier anyhow
132
133 if(when > stamps[what])
134 return;
135
136 stamps[what] = when;
137 notifyAll();
138 }
139 }
140
Stop()141 void cleaner::Stop()
142 {
143 {
144 setLockGuard;
145
146 if(!m_thr)
147 return;
148
149 m_terminating = true;
150 notifyAll();
151 }
152 pthread_join(m_thr, nullptr);
153
154 setLockGuard;
155 m_thr = 0;
156 }
157
dump_status()158 void cleaner::dump_status()
159 {
160 setLockGuard;
161 tSS msg;
162 msg << "Cleanup schedule:\n";
163 for(int i=0; i<cleaner::ETYPE_MAX; ++i)
164 msg << stamps[i] << " (in " << (stamps[i]-GetTime()) << " seconds)\n";
165 log::err(msg);
166 }
167
168
dump_handler(int)169 void dump_handler(int) {
170 fileItemMgmt::dump_status();
171 g_victor.dump_status();
172 g_tcp_con_factory.dump_status();
173 cfg::dump_trace();
174 }
175
176
177 }
178