summaryrefslogtreecommitdiff
path: root/conflictcheck.c
diff options
context:
space:
mode:
authorJohann Friedrichs <johann.friedrichs@web.de>2017-07-11 08:35:04 +0200
committerFrank Neumann <fnu@yavdr.org>2017-07-11 08:35:04 +0200
commit04124ba1ebae36f15eafe95cd23bbb8e220a8e8a (patch)
tree2cfe1873c29382ed79feaf49eb81a3897ae12860 /conflictcheck.c
parentceb158e1bd9df3cc0c6f9243856faac6f735ffb8 (diff)
downloadvdr-plugin-epgsearch-04124ba1ebae36f15eafe95cd23bbb8e220a8e8a.tar.gz
vdr-plugin-epgsearch-04124ba1ebae36f15eafe95cd23bbb8e220a8e8a.tar.bz2
Add conflict check for remote timers.
Diffstat (limited to 'conflictcheck.c')
-rw-r--r--conflictcheck.c168
1 files changed, 158 insertions, 10 deletions
diff --git a/conflictcheck.c b/conflictcheck.c
index 7b30ccd..8e6bd53 100644
--- a/conflictcheck.c
+++ b/conflictcheck.c
@@ -30,6 +30,7 @@ The project's page is at http://winni.vdr-developer.org/epgsearch
#include "recstatus.h"
#include "timerstatus.h"
#include "uservars.h"
+#include <vdr/svdrp.h>
#define FULLMATCH 1000
#define EPGLIMITBEFORE (1 * 3600) // Time in seconds before a timer's start time and
@@ -166,6 +167,7 @@ cConflictCheck::cConflictCheck()
relevantConflicts = 0;
numConflicts = 0;
devices = NULL;
+ localConflicts = !(EPGSearchConfig.RemoteConflictCheck && Setup.SVDRPPeering);
InitDevicesInfo();
}
@@ -232,18 +234,23 @@ void cConflictCheck::Check()
if (timerList)
DELETENULL(timerList);
+ LogFile.Log(3, "check only local conflicts = %s",GetLocal()?"yes":"no");
timerList = CreateCurrentTimerList();
if (timerList) evaltimeList = CreateEvaluationTimeList(timerList);
if (evaltimeList) failedList = CreateConflictList(evaltimeList, timerList);
+ if ((!localConflicts) && timerList) CreateRemoteConflictList(timerList,failedList);
if (failedList)
- {
for(cConflictCheckTime* checkTime = failedList->First(); checkTime; checkTime = failedList->Next(checkTime))
{
LogFile.Log(2,"result of conflict check for %s:", DAYDATETIME(checkTime->evaltime));
std::set<cConflictCheckTimerObj*,TimerObjSort>::iterator it;
for (it = checkTime->failedTimers.begin(); it != checkTime->failedTimers.end(); ++it)
- LogFile.Log(2,"timer '%s' (%s, channel %s) failed", (*it)->timer->File(), DAYDATETIME((*it)->timer->StartTime()), CHANNELNAME((*it)->timer->Channel()));
- }
+ {
+ if (!localConflicts)
+ LogFile.Log(2,"timer '%s' (%s, channel %s) %s%s failed", (*it)->timer->File(), DAYDATETIME((*it)->timer->StartTime()), CHANNELNAME((*it)->timer->Channel()), (*it)->timer->Remote()?"@":"",(*it)->timer->Remote()?(*it)->timer->Remote():"");
+ else
+ LogFile.Log(2,"timer '%s' (%s, channel %s) failed", (*it)->timer->File(), DAYDATETIME((*it)->timer->StartTime()), CHANNELNAME((*it)->timer->Channel()));
+ }
}
if (numConflicts > 0 && gl_timerStatusMonitor)
gl_timerStatusMonitor->SetConflictCheckAdvised();
@@ -261,14 +268,16 @@ cList<cConflictCheckTimerObj>* cConflictCheck::CreateCurrentTimerList()
for (ti = Timers->First(); ti; ti = Timers->Next(ti))
{
tMax = std::max(tMax, ti->StartTime());
- if (ti->Remote()) continue; // TO BE DONE: remote service request CC
+ if (localConflicts && ti->Remote()) continue;
if (!ti->IsSingleEvent()) continue;
// already recording?
- int deviceNr = gl_recStatusMonitor->TimerRecDevice(ti)-1;
+ int deviceNr = -1;
+ if (ti->Local()) // we check devices only for local timers
+ deviceNr = gl_recStatusMonitor->TimerRecDevice(ti)-1;
- // create a copy of this timer
- cTimer* clone = new cTimer(*ti);
- clone->SetEvent(ti->Event());
+ // create a copy of this timer
+ cTimer* clone = new cTimer(*ti);
+ clone->SetEvent(ti->Event());
cConflictCheckTimerObj* timerObj = new cConflictCheckTimerObj(clone, ti->StartTime(), ti->StopTime(), deviceNr, ti->Id());
if (deviceNr >= 0)
@@ -290,6 +299,7 @@ cList<cConflictCheckTimerObj>* cConflictCheck::CreateCurrentTimerList()
for (ti = Timers->First(); ti; ti = Timers->Next(ti))
{
if (ti->IsSingleEvent()) continue;
+ if (localConflicts && ti->Remote()) continue; //JF???
time_t day = time(NULL);
while(day < tMax)
{
@@ -300,7 +310,7 @@ cList<cConflictCheckTimerObj>* cConflictCheck::CreateCurrentTimerList()
if (Start < time(NULL))
{
#ifndef DEBUG_CONFL
- if (ti->Recording())
+ if (ti->Local() && ti->Recording())
deviceNr = gl_recStatusMonitor->TimerRecDevice(ti)-1;
#else
if (Start + ti->StopTime() - ti->StartTime() > time(NULL))
@@ -335,7 +345,7 @@ cList<cConflictCheckTimerObj>* cConflictCheck::CreateCurrentTimerList()
}
day += SECSINDAY;
}
- }
+ }
if (CurrentTimerList) CurrentTimerList->Sort();
LogFile.Log(3,"current timer list created");
@@ -351,6 +361,8 @@ cList<cConflictCheckTime>* cConflictCheck::CreateEvaluationTimeList(cList<cConfl
{
if (!TimerObj->timer->HasFlags(tfActive)) continue;
+ if (TimerObj->timer->Remote()) continue; // here we check local timers only
+
if (!EvalTimeList) EvalTimeList = new cList<cConflictCheckTime>;
cConflictCheckTime* checkTime = NULL;
@@ -462,6 +474,140 @@ cList<cConflictCheckTime>* cConflictCheck::CreateConflictList(cList<cConflictChe
return EvalTimeList;
}
+void cConflictCheck::CreateRemoteConflictList(cList<cConflictCheckTimerObj>* TimerList, cList<cConflictCheckTime>* failedList)
+{
+ LogFile.Log(3,"add remote conflicts to list");
+ bool foundRemote = false;
+ cStringList RemoteHosts;
+ // check if we have any Remote timers
+ RemoteHosts.Clear();
+ for(cConflictCheckTimerObj* TimerObj= TimerList->First(); TimerObj; TimerObj = TimerList->Next(TimerObj))
+ {
+ if (!TimerObj->timer->HasFlags(tfActive)) continue;
+
+ if (TimerObj->timer->Remote())
+ {
+ if (RemoteHosts.Find(TimerObj->timer->Remote()) < 0)
+ {
+ foundRemote = true;
+ RemoteHosts.Append(strdup(TimerObj->timer->Remote()));
+ }
+ }
+ }
+
+ if (!foundRemote)
+ {
+ LogFile.Log(3,"no remote timers to add");
+ return;
+ }
+
+ RemoteHosts.Sort();
+
+ cStringList Response;
+ // for all RemoteHosts
+ for (int i=0; i< RemoteHosts.Size(); i++)
+ {
+ Response.Clear();
+ if (ExecSVDRPCommand(RemoteHosts[i], "PLUG epgsearch LSCC REL", &Response))
+ {
+ for (int j = 0; j < Response.Size(); j++)
+ {
+ const char *s = Response[j];
+ int Code = SVDRPCode(s);
+ if (Code == 901)
+ {
+ LogFile.Log(3,"conflictcheck %s no remote conflicts found",RemoteHosts[i]);
+ continue;
+ } else if (Code != 900)
+ {
+ LogFile.Log(2,"Invalid remote response %d %s", Code,
+ SVDRPValue(s));
+ break;
+ } else if (const char* line = SVDRPValue(s))
+ {
+ LogFile.Log(2,"remote conflictcheck line %s",line);
+ int Id,recPart;
+ char rest[256];
+ time_t evaltime;
+ sscanf(line,"%ld:%d|%s",&evaltime,&Id,rest);
+ cConflictCheckTime* checkTime = new cConflictCheckTime(evaltime);
+ if (!failedList)
+ failedList = new cList<cConflictCheckTime>;
+ LogFile.Log(2,"added remote checkTime %s to failedList",DAYDATETIME(evaltime));
+ failedList->Add(checkTime);
+ numConflicts++;
+ // find TimerObj with id Id in timerList
+ cConflictCheckTimerObj* failedTimer = NULL;
+ bool foundfT = false;
+ for(failedTimer = TimerList->First(); failedTimer; failedTimer = TimerList->Next(failedTimer))
+ {
+ if (failedTimer->timer->Id() == Id)
+ {
+ foundfT = true;
+ break;
+ }
+ }
+ if (!foundfT)
+ {
+ LogFile.Log(2,"remote failed Timer disappeared");
+ continue;
+ }
+ LogFile.Log(2,"create remote failedTimer with Id %d",Id);
+ failedTimer->conflCheckTime = checkTime;
+ failedTimer->origIndex = Id;
+ sscanf(rest,"%d|%s",&recPart,rest);
+ failedTimer->recDuration=((failedTimer->stop-failedTimer->start)* recPart / 100);
+ cConflictCheckTimerObj* concurrentTimer = NULL;
+ while (strlen(rest) > 0)
+ {
+ int n = sscanf(rest,"%d#%s",&Id,rest);
+ if (n < 2)
+ {
+ if (sscanf(rest,"%d",&Id) <= 0)
+ {
+ LogFile.Log(2,"error scanning rest of line %s",rest);
+ break;
+ }
+ *rest = 0; // TODO :<more timers> possible ??
+ }
+ // find TimerObj itcc for with Id in timerList
+ bool foundcT = false;
+ for(concurrentTimer = TimerList->First(); concurrentTimer; concurrentTimer = TimerList->Next(concurrentTimer))
+ {
+ if (concurrentTimer->timer->Id() == Id)
+ {
+ foundcT = true;
+ break;
+ }
+ }
+ if (!foundcT)
+ {
+ LogFile.Log(2,"remote concurrent Timer disappeared");
+ continue;
+ }
+ if (!failedTimer->concurrentTimers)
+ failedTimer->concurrentTimers = new std::set<cConflictCheckTimerObj*,TimerObjSort>;
+ LogFile.Log(2,"insert remote Id %d into concurrentTimers",concurrentTimer->timer->Id());
+ failedTimer->concurrentTimers->insert(concurrentTimer);
+ } // while concurrent Timers
+ LogFile.Log(2,"insert Id %d into checkTime->failedTimers",failedTimer->timer->Id());
+ checkTime->failedTimers.insert(failedTimer);
+ relevantConflicts++;
+ }
+ else
+ LogFile.Log(2,"got Code %d, but no Value from %s",Code,RemoteHosts[i]);
+ } // received response
+ }
+ else
+ {
+ LogFile.Log(2,"ExecSVDRPCommand failed for %s",RemoteHosts[i]);
+ }
+ } // for all RemoteHosts
+ cConflictCheckThread::m_cacheTotalConflicts = numConflicts;
+ cConflictCheckThread::m_cacheRelevantConflicts = relevantConflicts;
+ LogFile.Log(3,"add remote conflicts done");
+}
+
// checks for conflicts at one special time
int cConflictCheck::ProcessCheckTime(cConflictCheckTime* checkTime)
{
@@ -667,6 +813,8 @@ void cConflictCheck::AddConflict(cConflictCheckTimerObj* TimerObj, cConflictChec
bool cConflictCheck::TimerInConflict(const cTimer* timer)
{
+ if (!failedList)
+ return false;
for(cConflictCheckTime* checkTime = failedList->First(); checkTime; checkTime = failedList->Next(checkTime))
{
std::set<cConflictCheckTimerObj*,TimerObjSort>::iterator it;