summaryrefslogtreecommitdiff
path: root/p2pvr/daemon/maintenance.cpp
blob: 6abad00410d7a6e04a9e2f93885bef035801f4f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <logger.h>
#include <thread>
#include "maintenance.h"
#include <Ice/Ice.h>
#include "bindTimerTask.h"
#include <linux/dvb/frontend.h>
#include <cxxabi.h>
#include <scopeExit.h>

namespace po = boost::program_options;

namespace P2PVR {
MaintenanceI::Options::Options() : IceTray::Options("P2PVR Maintenance options") { }
ICETRAY_OPTIONS(MaintenanceI::Options,
		("p2pvr.maintenance.periodUpdateNetwork", po::value(&periodUpdateNetwork)->default_value(86400 * 7),
		 "Period between automated updates of DVB network (1 week)")
		("p2pvr.maintenance.periodUpdateServices", po::value(&periodUpdateServices)->default_value(86400 * 7),
		 "Period between automated updates of DVB services (1 week)")
		("p2pvr.maintenance.periodUpdateEvents", po::value(&periodUpdateEvents)->default_value(3600 * 12),
		 "Period between automated updates of DVB events (12 hours)")
		("p2pvr.maintenance.scanOnStart", po::value(&scanOnStart)->default_value(false),
		 "Perform the maintenance circle on start-up (false)")
);

IceTray::Logging::LoggerPtr MaintenanceI::logger(LOGMANAGER()->getLogger<MaintenanceI>());

MaintenanceI::MaintenanceI(IceTray::DatabasePoolPtr db, Ice::ObjectAdapterPtr a, IceUtil::TimerPtr t) :
	IceTray::AbstractDatabaseClient(db),
	adapter(a),
	timer(t),
	clientCheck(new BindTimerTask(boost::bind(&MaintenanceI::ScheduledUpdate, this))),
	lastUpdateNetwork(0),
	lastUpdateServices(0),
	lastUpdateEvents(0),
	updateRunning(false)
{
	if (timer) {
		timer->scheduleRepeated(clientCheck, IceUtil::Time::seconds(5 * 60));
	}
	if (options->scanOnStart) {
		ScheduledUpdate();
	}
}

void
MaintenanceI::UpdateAll(const Ice::Current & ice)
{
	UpdateAll(FE_OFDM, ice);
	UpdateAll(FE_QPSK, ice);
	UpdateAll(FE_ATSC, ice);
	UpdateAll(FE_QAM, ice);
}

void
MaintenanceI::UpdateAll(short type, const Ice::Current & ice)
{
	UpdateNetwork(type, ice);
	UpdateServices(ice);
	UpdateEvents(ice);
}

void
MaintenanceI::ScheduledUpdate()
{
	logger->messagebf(LOG::DEBUG, "%s: triggered", __PRETTY_FUNCTION__);
	if (!updateRunning) {
		std::thread update([this] {
			try {
				AdHoc::ScopeExit notRunning([this]{ updateRunning = false; });
				updateRunning = true;
				time_t now = time(NULL);
				if (lastUpdateNetwork < now - options->periodUpdateNetwork) {
					logger->messagebf(LOG::INFO, "%s: updating network", __PRETTY_FUNCTION__);
					this->UpdateNetwork(FE_OFDM, Ice::Current());
					time(&lastUpdateNetwork);
				}
				if (lastUpdateServices < now - options->periodUpdateServices) {
					logger->messagebf(LOG::INFO, "%s: updating services", __PRETTY_FUNCTION__);
					this->UpdateServices(Ice::Current());
					time(&lastUpdateServices);
				}
				if (lastUpdateEvents < now - options->periodUpdateEvents) {
					logger->messagebf(LOG::INFO, "%s: updating events", __PRETTY_FUNCTION__);
					this->UpdateEvents(Ice::Current());
					time(&lastUpdateEvents);
				}
				logger->messagebf(LOG::DEBUG, "%s: completed", __PRETTY_FUNCTION__);
			}
			catch (const std::exception & ex) {
				char * buf = __cxxabiv1::__cxa_demangle(typeid(ex).name(), NULL, NULL, NULL);
				logger->messagebf(LOG::ERR, "%s: failed %s: %s", __PRETTY_FUNCTION__, buf, ex.what());
				free(buf);
			}
			catch (...) {
				logger->messagebf(LOG::ERR, "%s: failed (unknown exception)", __PRETTY_FUNCTION__);
			}
		});
		update.detach();
	}
}
}