/src/ntopng/src/ThreadedActivity.cpp
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * (C) 2013-26 - ntop.org |
4 | | * |
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, write to the Free Software Foundation, |
18 | | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
19 | | * |
20 | | */ |
21 | | |
22 | | #include "ntop_includes.h" |
23 | | |
24 | | // #define THREAD_DEBUG |
25 | | |
26 | | /* ******************************************* */ |
27 | | |
28 | | ThreadedActivity::ThreadedActivity(const char *_path, bool delayed_activity, |
29 | | u_int32_t _periodicity_seconds, |
30 | | u_int32_t _max_duration_seconds, |
31 | | bool _align_to_localtime, |
32 | | bool _exclude_viewed_interfaces, |
33 | | bool _exclude_pcap_dump_interfaces, |
34 | 0 | ThreadPool *_pool) { |
35 | 0 | if(trace_new_delete) ntop->getTrace()->traceEvent(TRACE_NORMAL, "[new] %s", __FILE__); |
36 | 0 | periodic_script = new (std::nothrow) PeriodicScript(_path, _periodicity_seconds, _max_duration_seconds, _align_to_localtime, |
37 | 0 | _exclude_viewed_interfaces, _exclude_pcap_dump_interfaces, _pool); |
38 | 0 | randomDelaySchedule = delayed_activity; |
39 | 0 | setDeadlineApproachingSecs(); |
40 | 0 | force_run = false; |
41 | 0 | updateNextSchedule((u_int32_t)time(NULL)); |
42 | 0 | } |
43 | | |
44 | | /* ******************************************* */ |
45 | | |
46 | 0 | ThreadedActivity::~ThreadedActivity() { |
47 | | /* |
48 | | NOTE: |
49 | | terminateEnqueueLoop should have already been called by the |
50 | | PeriodicActivities destructor. |
51 | | */ |
52 | |
|
53 | 0 | for (std::map<std::string, ThreadedActivityStats *>::iterator it = |
54 | 0 | threaded_activity_stats.begin(); |
55 | 0 | it != threaded_activity_stats.end(); ++it) { |
56 | 0 | delete it->second; |
57 | 0 | } |
58 | |
|
59 | 0 | if (periodic_script) delete periodic_script; |
60 | 0 | } |
61 | | |
62 | | /* ******************************************* */ |
63 | | |
64 | 0 | void ThreadedActivity::updateNextSchedule(u_int32_t now) { |
65 | 0 | if (getPeriodicity()) { |
66 | 0 | next_schedule = Utils::roundTime(now, getPeriodicity(), |
67 | 0 | alignToLocalTime() ? ntop->get_time_offset() : 0); |
68 | |
|
69 | 0 | if (randomDelaySchedule) { |
70 | 0 | u_int max_randomness = ndpi_min(120 /* 2 mins */, 0.75 /* 75% */ * getPeriodicity()); |
71 | 0 | u_int randomness = rand() % max_randomness; |
72 | | /* |
73 | | Add some schedule randomness to avoid all scripts |
74 | | to be executed at the same time |
75 | | */ |
76 | | |
77 | 0 | if (randomness < 5) randomness = 5; /* Add at least 5 sec */ |
78 | 0 | next_schedule += randomness; |
79 | 0 | } |
80 | 0 | } else |
81 | 0 | next_schedule = 0; |
82 | 0 | } |
83 | | |
84 | | /* ******************************************* */ |
85 | | |
86 | 0 | void ThreadedActivity::setDeadlineApproachingSecs() { |
87 | 0 | if (getPeriodicity() <= 1) |
88 | 0 | deadline_approaching_secs = 0; |
89 | 0 | else if (getPeriodicity() <= 5) |
90 | 0 | deadline_approaching_secs = 1; |
91 | 0 | else if (getPeriodicity() <= 60) |
92 | 0 | deadline_approaching_secs = 5; |
93 | 0 | else /* > 60 secs */ |
94 | 0 | deadline_approaching_secs = 10; |
95 | 0 | } |
96 | | |
97 | | /* ******************************************* */ |
98 | | |
99 | 0 | bool ThreadedActivity::isTerminating() { |
100 | 0 | return (ntop->getGlobals()->isShutdownRequested() || |
101 | 0 | ntop->getGlobals()->isShutdown()); |
102 | 0 | }; |
103 | | |
104 | | /* ******************************************* */ |
105 | | |
106 | | ThreadedActivityState ThreadedActivity::getThreadedActivityState( |
107 | 0 | NetworkInterface *iface, char *script_name) { |
108 | 0 | if (iface) { |
109 | 0 | ThreadedActivityStats *s = getThreadedActivityStats(iface, script_name, false); |
110 | |
|
111 | 0 | if (s) return (s->getState()); |
112 | 0 | } else |
113 | 0 | ntop->getTrace()->traceEvent(TRACE_ERROR, |
114 | 0 | "Internal error. NULL interface."); |
115 | | |
116 | 0 | return (threaded_activity_state_unknown); |
117 | 0 | } |
118 | | |
119 | | /* ******************************************* */ |
120 | | |
121 | 0 | static bool skipExecution(const char *path) { |
122 | | #if 0 |
123 | | if((ntop->getPrefs()->getTimeseriesDriver() != ts_driver_influxdb) && |
124 | | (strcmp(path, TIMESERIES_SCRIPT_PATH) == 0)) |
125 | | return(true); |
126 | | #endif |
127 | | |
128 | | // Always execute periodic activities, thread timeseries.lua |
129 | | // is now also used by rrds to dequeue writes |
130 | 0 | return (false); |
131 | 0 | } |
132 | | |
133 | | /* ******************************************* */ |
134 | | |
135 | | void ThreadedActivity::set_state(NetworkInterface *iface, char *script_name, |
136 | 0 | ThreadedActivityState ta_state) { |
137 | 0 | ThreadedActivityStats *s = |
138 | 0 | getThreadedActivityStats(iface, script_name, false); |
139 | |
|
140 | 0 | if (s) s->setState(ta_state); |
141 | 0 | } |
142 | | |
143 | | /* ******************************************* */ |
144 | | |
145 | | ThreadedActivityState ThreadedActivity::get_state(NetworkInterface *iface, |
146 | 0 | char *script_name) { |
147 | 0 | ThreadedActivityStats *s = |
148 | 0 | getThreadedActivityStats(iface, script_name, false); |
149 | |
|
150 | 0 | if (s) return s->getState(); |
151 | | |
152 | 0 | return threaded_activity_state_unknown; |
153 | 0 | } |
154 | | |
155 | | /* ******************************************* */ |
156 | | |
157 | | void ThreadedActivity::set_state_sleeping(NetworkInterface *iface, |
158 | 0 | char *script_name) { |
159 | 0 | set_state(iface, script_name, threaded_activity_state_sleeping); |
160 | 0 | } |
161 | | |
162 | | /* ******************************************* */ |
163 | | |
164 | | void ThreadedActivity::set_state_queued(NetworkInterface *iface, |
165 | 0 | char *script_name) { |
166 | 0 | ThreadedActivityStats *s = |
167 | 0 | getThreadedActivityStats(iface, script_name, false); |
168 | |
|
169 | 0 | set_state(iface, script_name, threaded_activity_state_queued); |
170 | |
|
171 | 0 | if (s) |
172 | 0 | s->updateStatsQueuedTime(time(NULL)); |
173 | 0 | } |
174 | | |
175 | | /* ******************************************* */ |
176 | | |
177 | | void ThreadedActivity::set_state_running(NetworkInterface *iface, |
178 | 0 | char *script_name) { |
179 | 0 | set_state(iface, script_name, threaded_activity_state_running); |
180 | 0 | } |
181 | | |
182 | | /* ******************************************* */ |
183 | | |
184 | 0 | bool ThreadedActivity::isDeadlineApproaching(time_t deadline) { |
185 | | /* |
186 | | The deadline is approaching if the current time is closer than |
187 | | deadline_approaching_secs with reference to the deadline passed as parameter |
188 | | */ |
189 | 0 | bool res = deadline - time(NULL) <= deadline_approaching_secs; |
190 | |
|
191 | 0 | return res; |
192 | 0 | } |
193 | | |
194 | | /* ******************************************* */ |
195 | | |
196 | | ThreadedActivityStats *ThreadedActivity::getThreadedActivityStats(NetworkInterface *iface, |
197 | | char *script_name, |
198 | 0 | bool allocate_if_missing) { |
199 | 0 | ThreadedActivityStats *ta = NULL; |
200 | |
|
201 | 0 | if (!isTerminating() && iface) { |
202 | 0 | std::string key = std::to_string(iface->get_id()) + "/" + std::string(script_name); |
203 | 0 | std::map<std::string, ThreadedActivityStats *>::iterator it = threaded_activity_stats.find(key); |
204 | |
|
205 | | #ifdef THREAD_DEBUG |
206 | | // ntop->getTrace()->traceEvent(TRACE_WARNING, "%s() [%s]", __FUNCTION__, |
207 | | // key.c_str()); |
208 | | #endif |
209 | |
|
210 | 0 | if (it == threaded_activity_stats.end()) { |
211 | | /* Not found */ |
212 | 0 | if (allocate_if_missing) { |
213 | 0 | try { |
214 | 0 | ta = new ThreadedActivityStats(this); |
215 | 0 | } catch (std::bad_alloc &ba) { |
216 | 0 | return NULL; |
217 | 0 | } |
218 | | |
219 | 0 | threaded_activity_stats[key] = ta; |
220 | 0 | } |
221 | | |
222 | 0 | return (ta); |
223 | 0 | } else { |
224 | 0 | return (it->second); |
225 | 0 | } |
226 | 0 | } |
227 | | |
228 | 0 | return ta; |
229 | 0 | } |
230 | | |
231 | | /* ******************************************* */ |
232 | | |
233 | | void ThreadedActivity::updateThreadedActivityStatsBegin(NetworkInterface *iface, |
234 | | char *script_name, |
235 | 0 | struct timeval *begin) { |
236 | 0 | ThreadedActivityStats *ta = getThreadedActivityStats( |
237 | 0 | iface, script_name, true /* Allocate if missing */); |
238 | |
|
239 | 0 | if (ta) ta->updateStatsBegin(begin); |
240 | 0 | } |
241 | | |
242 | | /* ******************************************* */ |
243 | | |
244 | | void ThreadedActivity::updateThreadedActivityStatsEnd(NetworkInterface *iface, |
245 | | char *script_name, |
246 | 0 | u_long latest_duration) { |
247 | 0 | ThreadedActivityStats *ta = getThreadedActivityStats( |
248 | 0 | iface, script_name, true /* Allocate if missing */); |
249 | |
|
250 | 0 | if (ta) ta->updateStatsEnd(latest_duration); |
251 | 0 | } |
252 | | |
253 | | /* ******************************************* */ |
254 | | |
255 | | /* Run a one-shot script / accurate (e.g. second) periodic script */ |
256 | 0 | void ThreadedActivity::runSystemScript(time_t now) { |
257 | 0 | struct stat buf; |
258 | 0 | char script_path[MAX_PATH]; |
259 | |
|
260 | 0 | snprintf(script_path, sizeof(script_path), "%s/system/%s", |
261 | 0 | ntop->get_callbacks_dir(), activityPath()); |
262 | |
|
263 | 0 | if (stat(script_path, &buf) == 0) { |
264 | 0 | set_state_running(ntop->getSystemInterface(), script_path); |
265 | 0 | runScript(now, script_path, ntop->getSystemInterface(), |
266 | 0 | now + getMaxDuration() /* this is the deadline */); |
267 | 0 | set_state_sleeping(ntop->getSystemInterface(), script_path); |
268 | 0 | } else |
269 | 0 | ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to find script %s", |
270 | 0 | activityPath()); |
271 | 0 | } |
272 | | |
273 | | /* ******************************************* */ |
274 | | |
275 | | /* Run a script - both periodic and one-shot scripts are called here */ |
276 | | void ThreadedActivity::runScript(time_t now, char *script_name, |
277 | 0 | NetworkInterface *iface, time_t deadline) { |
278 | 0 | LuaEngine *l = NULL; |
279 | 0 | u_long msec_diff; |
280 | 0 | struct timeval begin, end; |
281 | 0 | ThreadedActivityStats *thstats = |
282 | 0 | getThreadedActivityStats(iface, script_name, true); |
283 | |
|
284 | 0 | if (!iface) return; |
285 | | |
286 | 0 | if (strcmp((activityPath()), SHUTDOWN_SCRIPT_PATH) && isTerminating()) return; |
287 | | |
288 | 0 | if (iface->isViewed() && excludeViewedIfaces()) return; |
289 | | |
290 | | #ifdef THREAD_DEBUG |
291 | | // ntop->getTrace()->traceEvent(TRACE_WARNING, "[%p] Running %s", this, |
292 | | // activityPath()); |
293 | | #endif |
294 | | |
295 | 0 | l = loadVM(script_name, iface, now); |
296 | 0 | if (!l) { |
297 | 0 | ntop->getTrace()->traceEvent(TRACE_ERROR, |
298 | 0 | "Unable to load the Lua vm [%s][vm: %s][script: %s]", |
299 | 0 | iface->get_name(), activityPath(), script_name); |
300 | 0 | return; |
301 | 0 | } |
302 | | |
303 | | #ifdef TRACE_VM_ENGINES |
304 | | ntop->getTrace()->traceEvent(TRACE_NORMAL, "Running %s (iface=%p) [# LuaVMs: %u]", |
305 | | script_name, iface, ntop->getNumActiveLuaVMs()); |
306 | | #endif |
307 | | |
308 | 0 | l->setAsSystemVM(); /* Privileged VM used by the ntopng engine (no GUI) */ |
309 | | |
310 | | /* Set the deadline and the threaded activity in the vm so they can be |
311 | | * accessed */ |
312 | 0 | l->setThreadedActivityData(this, thstats, deadline); |
313 | |
|
314 | 0 | if (thstats) { |
315 | 0 | thstats->setDeadline(deadline); |
316 | 0 | thstats->setCurrentProgress(0); |
317 | | |
318 | | /* Reset the internal state for the current execution */ |
319 | 0 | thstats->setNotExecutedActivity(false); |
320 | 0 | thstats->setSlowPeriodicActivity(false); |
321 | 0 | } |
322 | |
|
323 | 0 | gettimeofday(&begin, NULL); |
324 | 0 | updateThreadedActivityStatsBegin(iface, script_name, &begin); |
325 | | |
326 | | /* Set the current time globally */ |
327 | 0 | lua_pushinteger(l->getState(), now); |
328 | 0 | lua_setglobal(l->getState(), "_now"); |
329 | 0 | l->run_loaded_script(); |
330 | |
|
331 | 0 | gettimeofday(&end, NULL); |
332 | 0 | msec_diff = (end.tv_sec - begin.tv_sec) * 1000 + (end.tv_usec - begin.tv_usec) / 1000; |
333 | 0 | updateThreadedActivityStatsEnd(iface, script_name, msec_diff); |
334 | |
|
335 | 0 | if (thstats && isDeadlineApproaching(deadline)) |
336 | 0 | thstats->setSlowPeriodicActivity(true); |
337 | |
|
338 | 0 | delete l; |
339 | 0 | } |
340 | | |
341 | | /* ******************************************* */ |
342 | | |
343 | | LuaEngine *ThreadedActivity::loadVM(char *script_name, |
344 | 0 | NetworkInterface *iface, time_t when) { |
345 | 0 | LuaEngine *l = NULL; |
346 | |
|
347 | | #if defined(NTOPNG_PRO) && defined(TRACE_SCRIPTS) |
348 | | ntop->getTrace()->traceEvent( |
349 | | TRACE_NORMAL, "Running %s [is_pro: %s][demo_end_in: %d]", script_name, |
350 | | ntop->getPrefs()->is_pro_edition() ? "YES" : "NO", |
351 | | (ntop->getPro()->demo_ends_at() == 0) |
352 | | ? 0 : (ntop->getPro()->demo_ends_at() - time(NULL))); |
353 | | #endif |
354 | |
|
355 | 0 | try { |
356 | | /* NOTE: this needs to be deallocated by the caller */ |
357 | 0 | l = new LuaEngine(); |
358 | |
|
359 | 0 | if (l->load_script(script_name, lua_engine_mode_callback, iface) != 0) { |
360 | 0 | delete l; |
361 | 0 | l = NULL; |
362 | 0 | } |
363 | 0 | } catch (std::bad_alloc &ba) { |
364 | 0 | l = NULL; |
365 | 0 | } |
366 | |
|
367 | 0 | return (l); |
368 | 0 | } |
369 | | |
370 | | /* ******************************************* */ |
371 | | |
372 | 0 | bool ThreadedActivity::schedule(PeriodicActivities *pa, u_int32_t now, bool hourly_daily_activity) { |
373 | 0 | bool scheduled = false; |
374 | | |
375 | 0 | if(force_run || (now >= next_schedule)) { |
376 | 0 | u_int32_t next_deadline = now + getMaxDuration(); /* deadline is max_duration_secs from now */ |
377 | | |
378 | 0 | if(force_run) |
379 | 0 | ntop->getTrace()->traceEvent(TRACE_NORMAL, "Forcing activity schedule run"); |
380 | | |
381 | 0 | updateNextSchedule(now); |
382 | |
|
383 | 0 | if (!skipExecution(activityPath())) { |
384 | 0 | schedulePeriodicActivity(getPool(), now, next_deadline, pa, hourly_daily_activity); |
385 | 0 | scheduled = true; |
386 | 0 | } |
387 | | |
388 | 0 | force_run = false; /* Just in case */ |
389 | 0 | } |
390 | |
|
391 | | #ifdef THREAD_DEBUG |
392 | | if (1) { |
393 | | int tdiff = next_schedule - now; |
394 | | |
395 | | ntop->getTrace()->traceEvent(TRACE_NORMAL, "Next schedule: %d [%s]", tdiff, |
396 | | activityPath()); |
397 | | } |
398 | | #endif |
399 | |
|
400 | 0 | return(scheduled); |
401 | 0 | } |
402 | | |
403 | | /* ******************************************* */ |
404 | | |
405 | 0 | bool ThreadedActivity::isValidScript(char *dir, char *path) { |
406 | 0 | u_int len; |
407 | 0 | char *suffix; |
408 | | |
409 | | /* Discard names starting with . */ |
410 | 0 | if (path[0] == '.') return (false); |
411 | | |
412 | 0 | #ifndef HAVE_NEDGE |
413 | | /* Discard scripts that start with nedge_... that are nEdge-only files */ |
414 | 0 | if (strncmp(path, NEDGE_HEADER, 6 /* strlen(NEDGE_HEADER) */) == 0) |
415 | 0 | return (false); |
416 | 0 | #endif |
417 | | |
418 | | /* Discard files non ending with .lua suffix */ |
419 | 0 | len = strlen(path); |
420 | 0 | if (len <= 4) |
421 | 0 | return (false); |
422 | 0 | else |
423 | 0 | suffix = &path[len - 4]; |
424 | | |
425 | | // ntop->getTrace()->traceEvent(TRACE_NORMAL, "%s / %s [%s]", dir, path, |
426 | | // suffix); |
427 | | |
428 | 0 | if ((ntop->getPrefs()->getTimeseriesDriver() != ts_driver_influxdb) && |
429 | 0 | (strstr(path, "influxdb") != NULL)) { |
430 | 0 | ntop->getTrace()->traceEvent(TRACE_INFO, "Skipping %s%s", dir, path); |
431 | 0 | return (false); |
432 | 0 | } |
433 | | |
434 | 0 | if ((!ntop->getPrefs()->do_dump_flows_on_clickhouse()) && |
435 | 0 | (strstr(path, "clickhouse") != NULL)) { |
436 | 0 | ntop->getTrace()->traceEvent(TRACE_INFO, "Skipping %s%s", dir, path); |
437 | 0 | return (false); |
438 | 0 | } |
439 | | |
440 | 0 | return (strcmp(suffix, LUA_TRAILER) == 0 ? true : false); |
441 | 0 | } |
442 | | |
443 | | /* ******************************************* */ |
444 | | |
445 | | /* This function enqueues the periodic activity job into the ThreadPool. |
446 | | * The ThreadPool, running into another thread, will dequeue the job and call |
447 | | * ThreadedActivity::runScript. */ |
448 | | void ThreadedActivity::schedulePeriodicActivity(ThreadPool *pool, |
449 | | time_t scheduled_time, |
450 | | time_t deadline, |
451 | | PeriodicActivities *pa, |
452 | 0 | bool hourly_daily_activity) { |
453 | | /* Schedule per system / interface */ |
454 | 0 | char dir_path[MAX_PATH]; |
455 | 0 | struct stat buf; |
456 | 0 | DIR *dir_struct; |
457 | 0 | struct dirent *ent; |
458 | 0 | u_int num_loops; |
459 | |
|
460 | | #ifdef THREAD_DEBUG |
461 | | ntop->getTrace()->traceEvent(TRACE_NORMAL, "Scheduling %s", activityPath()); |
462 | | #endif |
463 | |
|
464 | | #ifdef NTOPNG_PRO |
465 | | if (ntop->getPrefs()->is_pro_edition() == false) |
466 | | num_loops = 1; /* Skip pro scripts in community edition */ |
467 | | else { |
468 | | num_loops = 2; |
469 | | |
470 | | if (ntop->getPro()->demo_ends_at() != 0 /* demo mode */) { |
471 | | int remaining_time = ntop->getPro()->demo_ends_at() - (u_int32_t)time(NULL); |
472 | | |
473 | | if (remaining_time < 60 /* 1 min */) |
474 | | num_loops = 1; /* Demo is ending: stop running pro scripts */ |
475 | | } |
476 | | } |
477 | | #else |
478 | 0 | num_loops = 1; |
479 | 0 | #endif |
480 | |
|
481 | 0 | for (u_int l_i = 0; l_i < num_loops; l_i++) { |
482 | 0 | if (l_i == 0) { |
483 | | /* Schedule system script */ |
484 | 0 | snprintf(dir_path, sizeof(dir_path), "%s/%s/system/", |
485 | 0 | ntop->get_callbacks_dir(), activityPath()); |
486 | 0 | } else { |
487 | | #ifdef NTOPNG_PRO |
488 | | /* Attempt to locate and execute the callback under the pro callbacks */ |
489 | | snprintf(dir_path, sizeof(dir_path), "%s/%s/system/", |
490 | | ntop->get_pro_callbacks_dir(), activityPath()); |
491 | | #else |
492 | 0 | break; |
493 | 0 | #endif |
494 | 0 | } |
495 | | |
496 | 0 | if (stat(dir_path, &buf) == 0) { |
497 | | #ifdef THREAD_DEBUG |
498 | | ntop->getTrace()->traceEvent(TRACE_NORMAL, "Running scripts in %s", dir_path); |
499 | | #endif |
500 | | |
501 | | /* Open the directory and run all the scripts inside it */ |
502 | 0 | if ((dir_struct = opendir(dir_path)) != NULL) { |
503 | 0 | while ((ent = readdir(dir_struct)) != NULL) { |
504 | 0 | if (isValidScript(dir_path, ent->d_name)) { |
505 | 0 | char script_path[2 * MAX_PATH]; |
506 | | |
507 | | /* Schedule interface script, one for each interface */ |
508 | 0 | snprintf(script_path, sizeof(script_path), "%s%s", dir_path, |
509 | 0 | ent->d_name); |
510 | |
|
511 | | #ifdef THREAD_DEBUG |
512 | | ntop->getTrace()->traceEvent(TRACE_INFO, "Processing %s", script_path); |
513 | | #endif |
514 | |
|
515 | 0 | if (pool->queueJob(this, script_path, ntop->getSystemInterface(), |
516 | 0 | scheduled_time, deadline, pa, hourly_daily_activity)) { |
517 | | #ifdef THREAD_DEBUG |
518 | | ntop->getTrace()->traceEvent(TRACE_NORMAL, "Queued system job %s", |
519 | | script_path); |
520 | | #endif |
521 | 0 | } |
522 | 0 | } |
523 | 0 | } |
524 | |
|
525 | 0 | closedir(dir_struct); |
526 | 0 | } |
527 | 0 | } |
528 | 0 | } /* for */ |
529 | |
|
530 | 0 | for (u_int l_i = 0; l_i < num_loops; l_i++) { |
531 | 0 | if (l_i == 0) { |
532 | | /* Schedule interface script, one for each interface */ |
533 | 0 | snprintf(dir_path, sizeof(dir_path), "%s/%s/interface/", |
534 | 0 | ntop->get_callbacks_dir(), activityPath()); |
535 | 0 | } else { |
536 | | #ifdef NTOPNG_PRO |
537 | | /* Attempt at locating and executing the callback under the pro callbacks |
538 | | */ |
539 | | snprintf(dir_path, sizeof(dir_path), "%s/%s/interface/", |
540 | | ntop->get_pro_callbacks_dir(), activityPath()); |
541 | | #else |
542 | 0 | break; |
543 | 0 | #endif |
544 | 0 | } |
545 | | |
546 | 0 | if (stat(dir_path, &buf) == 0) { |
547 | | #ifdef THREAD_DEBUG |
548 | | ntop->getTrace()->traceEvent(TRACE_NORMAL, "Running scripts in %s", |
549 | | dir_path); |
550 | | #endif |
551 | | |
552 | | /* Open the directory e run all the scripts inside it */ |
553 | 0 | if ((dir_struct = opendir(dir_path)) != NULL) { |
554 | 0 | while ((ent = readdir(dir_struct)) != NULL) { |
555 | 0 | if (isValidScript(dir_path, ent->d_name)) { |
556 | 0 | for (int ifId = 0; ifId < ntop->get_num_interfaces(); ifId++) { |
557 | 0 | NetworkInterface *iface = ntop->getInterface(ifId); |
558 | | |
559 | | /* Running the script for each interface if it's not a PCAP */ |
560 | 0 | if (iface && (iface->getIfType() != interface_type_PCAP_DUMP |
561 | 0 | || (!excludePcap()))) { |
562 | 0 | char script_path[2 * MAX_PATH]; |
563 | | |
564 | | /* Schedule interface script, one for each interface */ |
565 | 0 | snprintf(script_path, sizeof(script_path), "%s%s", dir_path, |
566 | 0 | ent->d_name); |
567 | |
|
568 | 0 | if (pool->queueJob(this, script_path, iface, |
569 | 0 | scheduled_time, deadline, |
570 | 0 | pa, hourly_daily_activity)) { |
571 | | #ifdef THREAD_DEBUG |
572 | | ntop->getTrace()->traceEvent(TRACE_NORMAL, |
573 | | "Queued interface job %s [%s]", |
574 | | script_path, iface->get_name()); |
575 | | #endif |
576 | 0 | } |
577 | 0 | } |
578 | 0 | } |
579 | 0 | } |
580 | 0 | } |
581 | |
|
582 | 0 | closedir(dir_struct); |
583 | 0 | } |
584 | 0 | } |
585 | 0 | } /* for */ |
586 | 0 | } |
587 | | |
588 | | /* ******************************************* */ |
589 | | |
590 | 0 | void ThreadedActivity::lua(NetworkInterface *iface, lua_State *vm) { |
591 | 0 | ThreadedActivityStats *ta; |
592 | 0 | std::map<std::string, ThreadedActivityStats *>::iterator it; |
593 | | |
594 | 0 | it = threaded_activity_stats.begin(); |
595 | |
|
596 | 0 | if (it != threaded_activity_stats.end()) |
597 | 0 | ta = it->second; |
598 | 0 | else |
599 | 0 | ta = NULL; |
600 | |
|
601 | 0 | if (ta) { |
602 | 0 | lua_newtable(vm); |
603 | |
|
604 | 0 | ta->lua(vm); |
605 | |
|
606 | 0 | lua_push_str_table_entry(vm, "state", |
607 | 0 | Utils::get_state_label(ta->getState())); |
608 | 0 | lua_push_uint64_table_entry(vm, "periodicity", getPeriodicity()); |
609 | 0 | lua_push_uint64_table_entry(vm, "max_duration_secs", getMaxDuration()); |
610 | 0 | lua_push_uint64_table_entry(vm, "deadline_secs", deadline_approaching_secs); |
611 | |
|
612 | 0 | lua_pushstring(vm, activityPath() ? activityPath() : ""); |
613 | 0 | lua_insert(vm, -2); |
614 | 0 | lua_settable(vm, -3); |
615 | 0 | } |
616 | 0 | } |
617 | | |
618 | | /* ******************************************* */ |
619 | | |
620 | 0 | const char *ThreadedActivity::activityPath() { |
621 | 0 | return (periodic_script ? periodic_script->getPath() : ""); |
622 | 0 | } |
623 | | |
624 | | /* ******************************************* */ |
625 | | |
626 | 0 | u_int32_t ThreadedActivity::getPeriodicity() { |
627 | 0 | return (periodic_script ? periodic_script->getPeriodicity() : 0); |
628 | 0 | } |
629 | | |
630 | | /* ******************************************* */ |
631 | | |
632 | 0 | u_int32_t ThreadedActivity::getMaxDuration() { |
633 | 0 | return (periodic_script ? periodic_script->getMaxDuration() : 0); |
634 | 0 | } |
635 | | |
636 | | /* ******************************************* */ |
637 | | |
638 | 0 | bool ThreadedActivity::excludePcap() { |
639 | 0 | return (periodic_script ? periodic_script->excludePcap() : false); |
640 | 0 | } |
641 | | |
642 | | /* ******************************************* */ |
643 | | |
644 | 0 | bool ThreadedActivity::excludeViewedIfaces() { |
645 | 0 | return (periodic_script ? periodic_script->excludeViewedIfaces() : false); |
646 | 0 | } |
647 | | |
648 | | /* ******************************************* */ |
649 | | |
650 | 0 | bool ThreadedActivity::alignToLocalTime() { |
651 | 0 | return (periodic_script ? periodic_script->alignToLocalTime() : false); |
652 | 0 | } |
653 | | |
654 | | /* ******************************************* */ |
655 | | |
656 | 0 | ThreadPool *ThreadedActivity::getPool() { |
657 | 0 | return (periodic_script ? periodic_script->getPool() : NULL); |
658 | 0 | } |