mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
Implemented strict locking of global lists
This commit is contained in:
326
timers.c
326
timers.c
@@ -4,18 +4,18 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: timers.c 3.1 2013/12/28 11:33:08 kls Exp $
|
||||
* $Id: timers.c 4.1 2015/08/31 10:45:13 kls Exp $
|
||||
*/
|
||||
|
||||
#include "timers.h"
|
||||
#include <ctype.h>
|
||||
#include "channels.h"
|
||||
#include "device.h"
|
||||
#include "i18n.h"
|
||||
#include "libsi/si.h"
|
||||
#include "recording.h"
|
||||
#include "remote.h"
|
||||
#include "status.h"
|
||||
#include "svdrp.h"
|
||||
|
||||
// IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
|
||||
// format characters in order to allow any number of blanks after a numeric
|
||||
@@ -23,19 +23,21 @@
|
||||
|
||||
// --- cTimer ----------------------------------------------------------------
|
||||
|
||||
cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel)
|
||||
cTimer::cTimer(bool Instant, bool Pause, const cChannel *Channel)
|
||||
{
|
||||
startTime = stopTime = 0;
|
||||
lastSetEvent = 0;
|
||||
scheduleState = -1;
|
||||
deferred = 0;
|
||||
recording = pending = inVpsMargin = false;
|
||||
pending = inVpsMargin = false;
|
||||
flags = tfNone;
|
||||
*file = 0;
|
||||
aux = NULL;
|
||||
remote = NULL;
|
||||
event = NULL;
|
||||
if (Instant)
|
||||
SetFlags(tfActive | tfInstant);
|
||||
channel = Channel ? Channel : Channels.GetByNumber(cDevice::CurrentChannel());
|
||||
LOCK_CHANNELS_READ;
|
||||
channel = Channel ? Channel : Channels->GetByNumber(cDevice::CurrentChannel());
|
||||
time_t t = time(NULL);
|
||||
struct tm tm_r;
|
||||
struct tm *now = localtime_r(&t, &tm_r);
|
||||
@@ -44,27 +46,25 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel)
|
||||
start = now->tm_hour * 100 + now->tm_min;
|
||||
stop = 0;
|
||||
if (!Setup.InstantRecordTime && channel && (Instant || Pause)) {
|
||||
cSchedulesLock SchedulesLock;
|
||||
if (const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock)) {
|
||||
if (const cSchedule *Schedule = Schedules->GetSchedule(channel)) {
|
||||
if (const cEvent *Event = Schedule->GetPresentEvent()) {
|
||||
time_t tstart = Event->StartTime();
|
||||
time_t tstop = Event->EndTime();
|
||||
if (Event->Vps() && Setup.UseVps) {
|
||||
SetFlags(tfVps);
|
||||
tstart = Event->Vps();
|
||||
}
|
||||
else {
|
||||
tstop += Setup.MarginStop * 60;
|
||||
tstart -= Setup.MarginStart * 60;
|
||||
}
|
||||
day = SetTime(tstart, 0);
|
||||
struct tm *time = localtime_r(&tstart, &tm_r);
|
||||
start = time->tm_hour * 100 + time->tm_min;
|
||||
time = localtime_r(&tstop, &tm_r);
|
||||
stop = time->tm_hour * 100 + time->tm_min;
|
||||
SetEvent(Event);
|
||||
LOCK_SCHEDULES_READ;
|
||||
if (const cSchedule *Schedule = Schedules->GetSchedule(channel)) {
|
||||
if (const cEvent *Event = Schedule->GetPresentEvent()) {
|
||||
time_t tstart = Event->StartTime();
|
||||
time_t tstop = Event->EndTime();
|
||||
if (Event->Vps() && Setup.UseVps) {
|
||||
SetFlags(tfVps);
|
||||
tstart = Event->Vps();
|
||||
}
|
||||
else {
|
||||
tstop += Setup.MarginStop * 60;
|
||||
tstart -= Setup.MarginStart * 60;
|
||||
}
|
||||
day = SetTime(tstart, 0);
|
||||
struct tm *time = localtime_r(&tstart, &tm_r);
|
||||
start = time->tm_hour * 100 + time->tm_min;
|
||||
time = localtime_r(&tstop, &tm_r);
|
||||
stop = time->tm_hour * 100 + time->tm_min;
|
||||
SetEvent(Event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,16 +83,18 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel)
|
||||
cTimer::cTimer(const cEvent *Event)
|
||||
{
|
||||
startTime = stopTime = 0;
|
||||
lastSetEvent = 0;
|
||||
scheduleState = -1;
|
||||
deferred = 0;
|
||||
recording = pending = inVpsMargin = false;
|
||||
pending = inVpsMargin = false;
|
||||
flags = tfActive;
|
||||
*file = 0;
|
||||
aux = NULL;
|
||||
remote = NULL;
|
||||
event = NULL;
|
||||
if (Event->Vps() && Setup.UseVps)
|
||||
SetFlags(tfVps);
|
||||
channel = Channels.GetByChannelID(Event->ChannelID(), true);
|
||||
LOCK_CHANNELS_READ;
|
||||
channel = Channels->GetByChannelID(Event->ChannelID(), true);
|
||||
time_t tstart = (flags & tfVps) ? Event->Vps() : Event->StartTime();
|
||||
time_t tstop = tstart + Event->Duration();
|
||||
if (!(HasFlags(tfVps))) {
|
||||
@@ -120,6 +122,7 @@ cTimer::cTimer(const cTimer &Timer)
|
||||
{
|
||||
channel = NULL;
|
||||
aux = NULL;
|
||||
remote = NULL;
|
||||
event = NULL;
|
||||
flags = tfNone;
|
||||
*this = Timer;
|
||||
@@ -127,7 +130,10 @@ cTimer::cTimer(const cTimer &Timer)
|
||||
|
||||
cTimer::~cTimer()
|
||||
{
|
||||
if (event)
|
||||
event->DecNumTimers();
|
||||
free(aux);
|
||||
free(remote);
|
||||
}
|
||||
|
||||
cTimer& cTimer::operator= (const cTimer &Timer)
|
||||
@@ -136,9 +142,8 @@ cTimer& cTimer::operator= (const cTimer &Timer)
|
||||
uint OldFlags = flags & tfRecording;
|
||||
startTime = Timer.startTime;
|
||||
stopTime = Timer.stopTime;
|
||||
lastSetEvent = 0;
|
||||
deferred = 0;
|
||||
recording = Timer.recording;
|
||||
scheduleState = -1;
|
||||
deferred = 0;
|
||||
pending = Timer.pending;
|
||||
inVpsMargin = Timer.inVpsMargin;
|
||||
flags = Timer.flags | OldFlags;
|
||||
@@ -152,7 +157,13 @@ cTimer& cTimer::operator= (const cTimer &Timer)
|
||||
strncpy(file, Timer.file, sizeof(file));
|
||||
free(aux);
|
||||
aux = Timer.aux ? strdup(Timer.aux) : NULL;
|
||||
event = NULL;
|
||||
free(remote);
|
||||
remote = Timer.remote ? strdup(Timer.remote) : NULL;
|
||||
if (event)
|
||||
event->DecNumTimers();
|
||||
event = Timer.event;
|
||||
if (event)
|
||||
event->IncNumTimers();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -178,7 +189,7 @@ cString cTimer::ToText(bool UseChannelID) const
|
||||
|
||||
cString cTimer::ToDescr(void) const
|
||||
{
|
||||
return cString::sprintf("%d (%d %04d-%04d %s'%s')", Index() + 1, Channel()->Number(), start, stop, HasFlags(tfVps) ? "VPS " : "", file);
|
||||
return cString::sprintf("%d%s%s (%d %04d-%04d %s'%s')", Index() + 1, remote ? "@" : "", remote ? remote : "", Channel()->Number(), start, stop, HasFlags(tfVps) ? "VPS " : "", file);
|
||||
}
|
||||
|
||||
int cTimer::TimeToInt(int t)
|
||||
@@ -313,7 +324,6 @@ bool cTimer::Parse(const char *s)
|
||||
}
|
||||
bool result = false;
|
||||
if (8 <= sscanf(s, "%u :%m[^:]:%m[^:]:%d :%d :%d :%d :%m[^:\n]:%m[^\n]", &flags, &channelbuffer, &daybuffer, &start, &stop, &priority, &lifetime, &filebuffer, &aux)) {
|
||||
ClrFlags(tfRecording);
|
||||
if (aux && !*skipspace(aux)) {
|
||||
free(aux);
|
||||
aux = NULL;
|
||||
@@ -322,10 +332,11 @@ bool cTimer::Parse(const char *s)
|
||||
result = ParseDay(daybuffer, day, weekdays);
|
||||
Utf8Strn0Cpy(file, filebuffer, sizeof(file));
|
||||
strreplace(file, '|', ':');
|
||||
LOCK_CHANNELS_READ;
|
||||
if (isnumber(channelbuffer))
|
||||
channel = Channels.GetByNumber(atoi(channelbuffer));
|
||||
channel = Channels->GetByNumber(atoi(channelbuffer));
|
||||
else
|
||||
channel = Channels.GetByChannelID(tChannelID::FromString(channelbuffer), true, true);
|
||||
channel = Channels->GetByChannelID(tChannelID::FromString(channelbuffer), true, true);
|
||||
if (!channel) {
|
||||
esyslog("ERROR: channel %s not defined", channelbuffer);
|
||||
result = false;
|
||||
@@ -340,7 +351,9 @@ bool cTimer::Parse(const char *s)
|
||||
|
||||
bool cTimer::Save(FILE *f)
|
||||
{
|
||||
return fprintf(f, "%s", *ToText(true)) > 0;
|
||||
if (!Remote())
|
||||
return fprintf(f, "%s", *ToText(true)) > 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cTimer::IsSingleEvent(void) const
|
||||
@@ -441,10 +454,8 @@ bool cTimer::Matches(time_t t, bool Directly, int Margin) const
|
||||
startTime = event->StartTime();
|
||||
stopTime = event->EndTime();
|
||||
if (!Margin) { // this is an actual check
|
||||
if (event->Schedule()->PresentSeenWithin(EITPRESENTFOLLOWINGRATE)) { // VPS control can only work with up-to-date events...
|
||||
if (event->StartTime() > 0) // checks for "phased out" events
|
||||
return event->IsRunning(true);
|
||||
}
|
||||
if (event->Schedule()->PresentSeenWithin(EITPRESENTFOLLOWINGRATE)) // VPS control can only work with up-to-date events...
|
||||
return event->IsRunning(true);
|
||||
return startTime <= t && t < stopTime; // ...otherwise we fall back to normal timer handling
|
||||
}
|
||||
}
|
||||
@@ -511,27 +522,13 @@ time_t cTimer::StopTime(void) const
|
||||
#define EPGLIMITBEFORE (1 * 3600) // Time in seconds before a timer's start time and
|
||||
#define EPGLIMITAFTER (1 * 3600) // after its stop time within which EPG events will be taken into consideration.
|
||||
|
||||
void cTimer::SetEventFromSchedule(const cSchedules *Schedules)
|
||||
bool cTimer::SetEventFromSchedule(const cSchedules *Schedules)
|
||||
{
|
||||
cSchedulesLock SchedulesLock;
|
||||
if (!Schedules) {
|
||||
lastSetEvent = 0; // forces setting the event, even if the schedule hasn't been modified
|
||||
if (!(Schedules = cSchedules::Schedules(SchedulesLock)))
|
||||
return;
|
||||
}
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(Channel());
|
||||
if (Schedule && Schedule->Events()->First()) {
|
||||
time_t now = time(NULL);
|
||||
if (!lastSetEvent || Schedule->Modified() >= lastSetEvent) {
|
||||
lastSetEvent = now;
|
||||
if (Schedule->Modified(scheduleState)) {
|
||||
const cEvent *Event = NULL;
|
||||
if (HasFlags(tfVps) && Schedule->Events()->First()->Vps()) {
|
||||
if (event && event->StartTime() > 0) { // checks for "phased out" events
|
||||
if (Recording())
|
||||
return; // let the recording end first
|
||||
if (now <= event->EndTime() || Matches(0, true))
|
||||
return; // stay with the old event until the timer has completely expired
|
||||
}
|
||||
// VPS timers only match if their start time exactly matches the event's VPS time:
|
||||
for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) {
|
||||
if (e->StartTime() && e->RunningStatus() != SI::RunningStatusNotRunning) { // skip outdated events
|
||||
@@ -566,30 +563,39 @@ void cTimer::SetEventFromSchedule(const cSchedules *Schedules)
|
||||
}
|
||||
}
|
||||
}
|
||||
SetEvent(Event);
|
||||
return SetEvent(Event);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cTimer::SetEvent(const cEvent *Event)
|
||||
bool cTimer::SetEvent(const cEvent *Event)
|
||||
{
|
||||
if (event != Event) { //XXX TODO check event data, too???
|
||||
if (Event)
|
||||
if (event != Event) {
|
||||
if (event)
|
||||
event->DecNumTimers();
|
||||
if (Event) {
|
||||
isyslog("timer %s set to event %s", *ToDescr(), *Event->ToDescr());
|
||||
else
|
||||
Event->IncNumTimers();
|
||||
Event->Schedule()->Modified(scheduleState); // to get the current state
|
||||
}
|
||||
else {
|
||||
isyslog("timer %s set to no event", *ToDescr());
|
||||
scheduleState = -1;
|
||||
}
|
||||
event = Event;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cTimer::SetRecording(bool Recording)
|
||||
{
|
||||
recording = Recording;
|
||||
if (recording)
|
||||
if (Recording)
|
||||
SetFlags(tfRecording);
|
||||
else
|
||||
ClrFlags(tfRecording);
|
||||
isyslog("timer %s %s", *ToDescr(), recording ? "start" : "stop");
|
||||
isyslog("timer %s %s", *ToDescr(), Recording ? "start" : "stop");
|
||||
}
|
||||
|
||||
void cTimer::SetPending(bool Pending)
|
||||
@@ -637,7 +643,13 @@ void cTimer::SetLifetime(int Lifetime)
|
||||
void cTimer::SetAux(const char *Aux)
|
||||
{
|
||||
free(aux);
|
||||
aux = strdup(Aux);
|
||||
aux = Aux ? strdup(Aux) : NULL;
|
||||
}
|
||||
|
||||
void cTimer::SetRemote(const char *Remote)
|
||||
{
|
||||
free(remote);
|
||||
remote = Remote ? strdup(Remote) : NULL;
|
||||
}
|
||||
|
||||
void cTimer::SetDeferred(int Seconds)
|
||||
@@ -691,20 +703,33 @@ void cTimer::OnOff(void)
|
||||
|
||||
// --- cTimers ---------------------------------------------------------------
|
||||
|
||||
cTimers Timers;
|
||||
cTimers cTimers::timers;
|
||||
|
||||
cTimers::cTimers(void)
|
||||
:cConfig<cTimer>("Timers")
|
||||
{
|
||||
state = 0;
|
||||
beingEdited = 0;;
|
||||
lastSetEvents = 0;
|
||||
lastDeleteExpired = 0;
|
||||
}
|
||||
|
||||
bool cTimers::Load(const char *FileName)
|
||||
{
|
||||
LOCK_TIMERS_WRITE;
|
||||
Timers->SetExplicitModify();
|
||||
if (timers.cConfig<cTimer>::Load(FileName)) {
|
||||
for (cTimer *ti = timers.First(); ti; ti = timers.Next(ti)) {
|
||||
ti->ClrFlags(tfRecording);
|
||||
Timers->SetModified();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
cTimer *cTimers::GetTimer(cTimer *Timer)
|
||||
{
|
||||
for (cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
if (ti->Channel() == Timer->Channel() &&
|
||||
if (!ti->Remote() &&
|
||||
ti->Channel() == Timer->Channel() &&
|
||||
(ti->WeekDays() && ti->WeekDays() == Timer->WeekDays() || !ti->WeekDays() && ti->Day() == Timer->Day()) &&
|
||||
ti->Start() == Timer->Start() &&
|
||||
ti->Stop() == Timer->Stop())
|
||||
@@ -713,12 +738,12 @@ cTimer *cTimers::GetTimer(cTimer *Timer)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cTimer *cTimers::GetMatch(time_t t)
|
||||
const cTimer *cTimers::GetMatch(time_t t) const
|
||||
{
|
||||
static int LastPending = -1;
|
||||
cTimer *t0 = NULL;
|
||||
for (cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
if (!ti->Recording() && ti->Matches(t)) {
|
||||
const cTimer *t0 = NULL;
|
||||
for (const cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
if (!ti->Remote() && !ti->Recording() && ti->Matches(t)) {
|
||||
if (ti->Pending()) {
|
||||
if (ti->Index() > LastPending) {
|
||||
LastPending = ti->Index();
|
||||
@@ -736,11 +761,11 @@ cTimer *cTimers::GetMatch(time_t t)
|
||||
return t0;
|
||||
}
|
||||
|
||||
cTimer *cTimers::GetMatch(const cEvent *Event, eTimerMatch *Match)
|
||||
const cTimer *cTimers::GetMatch(const cEvent *Event, eTimerMatch *Match) const
|
||||
{
|
||||
cTimer *t = NULL;
|
||||
const cTimer *t = NULL;
|
||||
eTimerMatch m = tmNone;
|
||||
for (cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
for (const cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
eTimerMatch tm = ti->Matches(Event);
|
||||
if (tm > m) {
|
||||
t = ti;
|
||||
@@ -754,21 +779,27 @@ cTimer *cTimers::GetMatch(const cEvent *Event, eTimerMatch *Match)
|
||||
return t;
|
||||
}
|
||||
|
||||
cTimer *cTimers::GetNextActiveTimer(void)
|
||||
const cTimer *cTimers::GetNextActiveTimer(void) const
|
||||
{
|
||||
cTimer *t0 = NULL;
|
||||
for (cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
ti->Matches();
|
||||
if ((ti->HasFlags(tfActive)) && (!t0 || ti->StopTime() > time(NULL) && ti->Compare(*t0) < 0))
|
||||
t0 = ti;
|
||||
const cTimer *t0 = NULL;
|
||||
for (const cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
if (!ti->Remote()) {
|
||||
ti->Matches();
|
||||
if ((ti->HasFlags(tfActive)) && (!t0 || ti->StopTime() > time(NULL) && ti->Compare(*t0) < 0))
|
||||
t0 = ti;
|
||||
}
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
void cTimers::SetModified(void)
|
||||
const cTimers *cTimers::GetTimersRead(cStateKey &StateKey, int TimeoutMs)
|
||||
{
|
||||
cStatus::MsgTimerChange(NULL, tcMod);
|
||||
state++;
|
||||
return timers.Lock(StateKey, false, TimeoutMs) ? &timers : NULL;
|
||||
}
|
||||
|
||||
cTimers *cTimers::GetTimersWrite(cStateKey &StateKey, int TimeoutMs)
|
||||
{
|
||||
return timers.Lock(StateKey, true, TimeoutMs) ? &timers : NULL;
|
||||
}
|
||||
|
||||
void cTimers::Add(cTimer *Timer, cTimer *After)
|
||||
@@ -789,46 +820,113 @@ void cTimers::Del(cTimer *Timer, bool DeleteObject)
|
||||
cConfig<cTimer>::Del(Timer, DeleteObject);
|
||||
}
|
||||
|
||||
bool cTimers::Modified(int &State)
|
||||
const cTimer *cTimers::UsesChannel(const cChannel *Channel) const
|
||||
{
|
||||
bool Result = state != State;
|
||||
State = state;
|
||||
return Result;
|
||||
for (const cTimer *Timer = First(); Timer; Timer = Next(Timer)) {
|
||||
if (Timer->Channel() == Channel)
|
||||
return Timer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cTimers::SetEvents(void)
|
||||
bool cTimers::SetEvents(const cSchedules *Schedules)
|
||||
{
|
||||
if (time(NULL) - lastSetEvents < 5)
|
||||
return;
|
||||
cSchedulesLock SchedulesLock(false, 100);
|
||||
const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
|
||||
if (Schedules) {
|
||||
if (!lastSetEvents || Schedules->Modified() >= lastSetEvents) {
|
||||
for (cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
if (cRemote::HasKeys())
|
||||
return; // react immediately on user input
|
||||
ti->SetEventFromSchedule(Schedules);
|
||||
}
|
||||
}
|
||||
}
|
||||
lastSetEvents = time(NULL);
|
||||
bool TimersModified = false;
|
||||
for (cTimer *ti = First(); ti; ti = Next(ti))
|
||||
TimersModified |= ti->SetEventFromSchedule(Schedules);
|
||||
return TimersModified;
|
||||
}
|
||||
|
||||
void cTimers::DeleteExpired(void)
|
||||
bool cTimers::DeleteExpired(void)
|
||||
{
|
||||
if (time(NULL) - lastDeleteExpired < 30)
|
||||
return;
|
||||
return false;
|
||||
bool TimersModified = false;
|
||||
cTimer *ti = First();
|
||||
while (ti) {
|
||||
cTimer *next = Next(ti);
|
||||
if (ti->Expired()) {
|
||||
if (!ti->Remote() && ti->Expired()) {
|
||||
isyslog("deleting timer %s", *ti->ToDescr());
|
||||
Del(ti);
|
||||
SetModified();
|
||||
TimersModified = true;
|
||||
}
|
||||
ti = next;
|
||||
}
|
||||
lastDeleteExpired = time(NULL);
|
||||
return TimersModified;
|
||||
}
|
||||
|
||||
bool cTimers::GetRemoteTimers(const char *ServerName)
|
||||
{
|
||||
bool Result = false;
|
||||
if (ServerName) {
|
||||
Result = DelRemoteTimers(ServerName);
|
||||
cSVDRPCommand Cmd(ServerName, "LSTT ID");
|
||||
if (Cmd.Execute()) {
|
||||
const char *s;
|
||||
for (int i = 0; s = Cmd.Response(i); i++) {
|
||||
int Code = Cmd.Code(s);
|
||||
if (Code == 250) {
|
||||
if (const char *v = Cmd.Value(s)) {
|
||||
while (*v && *v != ' ')
|
||||
v++; // skip number
|
||||
cTimer *Timer = new cTimer;
|
||||
if (Timer->Parse(v)) {
|
||||
Timer->SetRemote(ServerName);
|
||||
Add(Timer);
|
||||
Result = true;
|
||||
}
|
||||
else {
|
||||
esyslog("ERROR: %s: error in timer settings: %s", ServerName, v);
|
||||
delete Timer;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Code != 550)
|
||||
esyslog("ERROR: %s: %s", ServerName, s);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
cStringList ServerNames;
|
||||
if (GetSVDRPServerNames(&ServerNames, sffTimers)) {
|
||||
for (int i = 0; i < ServerNames.Size(); i++)
|
||||
Result |= GetRemoteTimers(ServerNames[i]);
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool cTimers::DelRemoteTimers(const char *ServerName)
|
||||
{
|
||||
bool Deleted = false;
|
||||
cTimer *Timer = First();
|
||||
while (Timer) {
|
||||
cTimer *t = Next(Timer);
|
||||
if (Timer->Remote() && (!ServerName || strcmp(Timer->Remote(), ServerName) == 0)) {
|
||||
Del(Timer);
|
||||
Deleted = true;
|
||||
}
|
||||
Timer = t;
|
||||
}
|
||||
return Deleted;
|
||||
}
|
||||
|
||||
void cTimers::TriggerRemoteTimerPoll(const char *ServerName)
|
||||
{
|
||||
if (ServerName) {
|
||||
cSVDRPCommand Cmd(ServerName, cString::sprintf("POLL %s TIMERS", SVDRPHostName()));
|
||||
if (!Cmd.Execute())
|
||||
esyslog("ERROR: can't send 'POLL %s TIMERS' to '%s'", SVDRPHostName(), ServerName);
|
||||
}
|
||||
else {
|
||||
cStringList ServerNames;
|
||||
if (GetSVDRPServerNames(&ServerNames)) {
|
||||
for (int i = 0; i < ServerNames.Size(); i++)
|
||||
TriggerRemoteTimerPoll(ServerNames[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- cSortedTimers ---------------------------------------------------------
|
||||
@@ -838,10 +936,10 @@ static int CompareTimers(const void *a, const void *b)
|
||||
return (*(const cTimer **)a)->Compare(**(const cTimer **)b);
|
||||
}
|
||||
|
||||
cSortedTimers::cSortedTimers(void)
|
||||
:cVector<const cTimer *>(Timers.Count())
|
||||
cSortedTimers::cSortedTimers(const cTimers *Timers)
|
||||
:cVector<const cTimer *>(Timers->Count())
|
||||
{
|
||||
for (const cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer))
|
||||
for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer))
|
||||
Append(Timer);
|
||||
Sort(CompareTimers);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user