diff options
author | Klaus Schmidinger <vdr@tvdr.de> | 2015-09-01 11:14:27 +0200 |
---|---|---|
committer | Klaus Schmidinger <vdr@tvdr.de> | 2015-09-01 11:14:27 +0200 |
commit | 3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d (patch) | |
tree | da57ce74189de9bfb27e1a747063c37cd62de501 /recording.c | |
parent | 8a7bc6a0bbf60cae8b6391a630880aad5cba3363 (diff) | |
download | vdr-3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d.tar.gz vdr-3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d.tar.bz2 |
Implemented strict locking of global lists
Diffstat (limited to 'recording.c')
-rw-r--r-- | recording.c | 457 |
1 files changed, 225 insertions, 232 deletions
diff --git a/recording.c b/recording.c index a28bb444..3f5cec7c 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 4.2 2015/04/18 13:14:55 kls Exp $ + * $Id: recording.c 4.3 2015/08/29 14:42:53 kls Exp $ */ #include "recording.h" @@ -76,9 +76,6 @@ int DirectoryNameMax = NAME_MAX; bool DirectoryEncoding = false; int InstanceId = 0; -cRecordings DeletedRecordings(true); -static cRecordings VanishedRecordings; - // --- cRemoveDeletedRecordingsThread ---------------------------------------- class cRemoveDeletedRecordingsThread : public cThread { @@ -100,8 +97,8 @@ void cRemoveDeletedRecordingsThread::Action(void) if (LockFile.Lock()) { time_t StartTime = time(NULL); bool deleted = false; - cThreadLock DeletedRecordingsLock(&DeletedRecordings); - for (cRecording *r = DeletedRecordings.First(); r; ) { + LOCK_DELETEDRECORDINGS_WRITE; + for (cRecording *r = DeletedRecordings->First(); r; ) { if (cIoThrottle::Engaged()) return; if (time(NULL) - StartTime > MAXREMOVETIME) @@ -109,14 +106,14 @@ void cRemoveDeletedRecordingsThread::Action(void) if (cRemote::HasKeys()) return; // react immediately on user input if (r->Deleted() && time(NULL) - r->Deleted() > DELETEDLIFETIME) { - cRecording *next = DeletedRecordings.Next(r); + cRecording *next = DeletedRecordings->Next(r); r->Remove(); - DeletedRecordings.Del(r); + DeletedRecordings->Del(r); r = next; deleted = true; continue; } - r = DeletedRecordings.Next(r); + r = DeletedRecordings->Next(r); } if (deleted) { const char *IgnoreFiles[] = { SORTMODEFILE, NULL }; @@ -134,8 +131,8 @@ void RemoveDeletedRecordings(void) static time_t LastRemoveCheck = 0; if (time(NULL) - LastRemoveCheck > REMOVECHECKDELTA) { if (!RemoveDeletedRecordingsThread.Active()) { - cThreadLock DeletedRecordingsLock(&DeletedRecordings); - for (cRecording *r = DeletedRecordings.First(); r; r = DeletedRecordings.Next(r)) { + LOCK_DELETEDRECORDINGS_READ; + for (const cRecording *r = DeletedRecordings->First(); r; r = DeletedRecordings->Next(r)) { if (r->Deleted() && time(NULL) - r->Deleted() > DELETEDLIFETIME) { RemoveDeletedRecordingsThread.Start(); break; @@ -163,37 +160,43 @@ void AssertFreeDiskSpace(int Priority, bool Force) return; // Remove the oldest file that has been "deleted": isyslog("low disk space while recording, trying to remove a deleted recording..."); - cThreadLock DeletedRecordingsLock(&DeletedRecordings); - if (DeletedRecordings.Count()) { - cRecording *r = DeletedRecordings.First(); - cRecording *r0 = NULL; - while (r) { - if (r->IsOnVideoDirectoryFileSystem()) { // only remove recordings that will actually increase the free video disk space - if (!r0 || r->Start() < r0->Start()) - r0 = r; - } - r = DeletedRecordings.Next(r); - } - if (r0) { - if (r0->Remove()) - LastFreeDiskCheck += REMOVELATENCY / Factor; - DeletedRecordings.Del(r0); - return; - } - } - else { + int NumDeletedRecordings = 0; + { + LOCK_DELETEDRECORDINGS_WRITE; + NumDeletedRecordings = DeletedRecordings->Count(); + if (NumDeletedRecordings) { + cRecording *r = DeletedRecordings->First(); + cRecording *r0 = NULL; + while (r) { + if (r->IsOnVideoDirectoryFileSystem()) { // only remove recordings that will actually increase the free video disk space + if (!r0 || r->Start() < r0->Start()) + r0 = r; + } + r = DeletedRecordings->Next(r); + } + if (r0) { + if (r0->Remove()) + LastFreeDiskCheck += REMOVELATENCY / Factor; + DeletedRecordings->Del(r0); + return; + } + } + } + if (NumDeletedRecordings == 0) { // DeletedRecordings was empty, so to be absolutely sure there are no // deleted recordings we need to double check: - DeletedRecordings.Update(true); - if (DeletedRecordings.Count()) + cRecordings::Update(true); + LOCK_DELETEDRECORDINGS_READ; + if (DeletedRecordings->Count()) return; // the next call will actually remove it } // No "deleted" files to remove, so let's see if we can delete a recording: if (Priority > 0) { isyslog("...no deleted recording found, trying to delete an old recording..."); - cThreadLock RecordingsLock(&Recordings); - if (Recordings.Count()) { - cRecording *r = Recordings.First(); + LOCK_RECORDINGS_WRITE; + Recordings->SetExplicitModify(); + if (Recordings->Count()) { + cRecording *r = Recordings->First(); cRecording *r0 = NULL; while (r) { if (r->IsOnVideoDirectoryFileSystem()) { // only delete recordings that will actually increase the free video disk space @@ -209,10 +212,11 @@ void AssertFreeDiskSpace(int Priority, bool Force) } } } - r = Recordings.Next(r); + r = Recordings->Next(r); } if (r0 && r0->Delete()) { - Recordings.Del(r0); + Recordings->Del(r0); + Recordings->SetModified(); return; } } @@ -227,14 +231,6 @@ void AssertFreeDiskSpace(int Priority, bool Force) } } -// --- Clear vanished recordings --------------------------------------------- - -void ClearVanishedRecordings(void) -{ - cThreadLock RecordingsLock(&Recordings); // yes, it *is* Recordings! - VanishedRecordings.Clear(); -} - // --- cResumeFile ----------------------------------------------------------- cResumeFile::cResumeFile(const char *FileName, bool IsPesRecording) @@ -309,7 +305,8 @@ bool cResumeFile::Save(int Index) if (safe_write(f, &Index, sizeof(Index)) < 0) LOG_ERROR_STR(fileName); close(f); - Recordings.ResetResume(fileName); + LOCK_RECORDINGS_WRITE; + Recordings->ResetResume(fileName); return true; } } @@ -318,7 +315,8 @@ bool cResumeFile::Save(int Index) if (f) { fprintf(f, "I %d\n", Index); fclose(f); - Recordings.ResetResume(fileName); + LOCK_RECORDINGS_WRITE; + Recordings->ResetResume(fileName); } else LOG_ERROR_STR(fileName); @@ -331,8 +329,10 @@ bool cResumeFile::Save(int Index) void cResumeFile::Delete(void) { if (fileName) { - if (remove(fileName) == 0) - Recordings.ResetResume(fileName); + if (remove(fileName) == 0) { + LOCK_RECORDINGS_WRITE; + Recordings->ResetResume(fileName); + } else if (errno != ENOENT) LOG_ERROR_STR(fileName); } @@ -787,10 +787,8 @@ cRecording::cRecording(cTimer *Timer, const cEvent *Event) else break; } - if (Timer->IsSingleEvent()) { + if (Timer->IsSingleEvent()) Timer->SetFile(name); // this was an instant recording, so let's set the actual data - Timers.SetModified(); - } } else if (Timer->IsSingleEvent() || !Setup.UseSubtitle) name = strdup(Timer->File()); @@ -1017,7 +1015,7 @@ int cRecording::Compare(const cListObject &ListObject) const return strcasecmp(SortName(), r->SortName()); } -bool cRecording::IsInPath(const char *Path) +bool cRecording::IsInPath(const char *Path) const { if (isempty(Path)) return true; @@ -1154,20 +1152,14 @@ bool cRecording::IsOnVideoDirectoryFileSystem(void) const return isOnVideoDirectoryFileSystem; } -bool cRecording::HasMarks(void) +bool cRecording::HasMarks(void) const { return access(cMarks::MarksFileName(this), F_OK) == 0; } bool cRecording::DeleteMarks(void) { - if (remove(cMarks::MarksFileName(this)) < 0) { - if (errno != ENOENT) { - LOG_ERROR_STR(fileName); - return false; - } - } - return true; + return cMarks::DeleteMarksFile(this); } void cRecording::ReadInfo(void) @@ -1219,8 +1211,6 @@ bool cRecording::ChangePriorityLifetime(int NewPriority, int NewLifetime) if (!WriteInfo()) return false; } - Recordings.ChangeState(); - Recordings.TouchUpdate(); } return true; } @@ -1245,8 +1235,6 @@ bool cRecording::ChangeName(const char *NewName) } isOnVideoDirectoryFileSystem = -1; // it might have been moved to a different file system ClearSortName(); - Recordings.ChangeState(); - Recordings.TouchUpdate(); } return true; } @@ -1360,59 +1348,53 @@ int cRecording::FileSizeMB(void) const return fileSizeMB; } -// --- cRecordings ----------------------------------------------------------- +// --- cVideoDirectoryScannerThread ------------------------------------------ -cRecordings Recordings; - -char *cRecordings::updateFileName = NULL; +class cVideoDirectoryScannerThread : public cThread { +private: + cRecordings *recordings; + cRecordings *deletedRecordings; + bool initial; + void ScanVideoDir(const char *DirName, int LinkLevel = 0, int DirLevel = 0); +protected: + virtual void Action(void); +public: + cVideoDirectoryScannerThread(cRecordings *Recordings, cRecordings *DeletedRecordings); + ~cVideoDirectoryScannerThread(); + }; -cRecordings::cRecordings(bool Deleted) +cVideoDirectoryScannerThread::cVideoDirectoryScannerThread(cRecordings *Recordings, cRecordings *DeletedRecordings) :cThread("video directory scanner", true) { - deleted = Deleted; + recordings = Recordings; + deletedRecordings = DeletedRecordings; initial = true; - lastUpdate = 0; - state = 0; } -cRecordings::~cRecordings() +cVideoDirectoryScannerThread::~cVideoDirectoryScannerThread() { Cancel(3); } -void cRecordings::Action(void) +void cVideoDirectoryScannerThread::Action(void) { - Refresh(); -} - -const char *cRecordings::UpdateFileName(void) -{ - if (!updateFileName) - updateFileName = strdup(AddDirectory(cVideoDirectory::Name(), ".update")); - return updateFileName; + cStateKey StateKey; + recordings->Lock(StateKey); + initial = recordings->Count() == 0; // no name checking if the list is initially empty + StateKey.Remove(); + deletedRecordings->Lock(StateKey, true); + deletedRecordings->Clear(); + StateKey.Remove(); + ScanVideoDir(cVideoDirectory::Name()); } -void cRecordings::Refresh(bool Foreground) +void cVideoDirectoryScannerThread::ScanVideoDir(const char *DirName, int LinkLevel, int DirLevel) { - lastUpdate = time(NULL); // doing this first to make sure we don't miss anything - initial = Count() == 0; // no name checking if the list is initially empty - if (deleted) { - Lock(); - Clear(); - ChangeState(); - Unlock(); - } - ScanVideoDir(cVideoDirectory::Name(), Foreground); -} - -bool cRecordings::ScanVideoDir(const char *DirName, bool Foreground, int LinkLevel, int DirLevel) -{ - bool DoChangeState = false; // Find any new recordings: cReadDir d(DirName); struct dirent *e; - while ((Foreground || Running()) && (e = d.Next()) != NULL) { - if (!Foreground && cIoThrottle::Engaged()) + while (Running() && (e = d.Next()) != NULL) { + if (cIoThrottle::Engaged()) cCondWait::SleepMs(100); cString buffer = AddDirectory(DirName, e->d_name); struct stat st; @@ -1428,57 +1410,73 @@ bool cRecordings::ScanVideoDir(const char *DirName, bool Foreground, int LinkLev continue; } if (S_ISDIR(st.st_mode)) { - if (endswith(buffer, deleted ? DELEXT : RECEXT)) { - if (deleted || initial || !GetByName(buffer)) { + cRecordings *Recordings = NULL; + if (endswith(buffer, RECEXT)) + Recordings = recordings; + else if (endswith(buffer, DELEXT)) + Recordings = deletedRecordings; + if (Recordings) { + cStateKey StateKey; + Recordings->Lock(StateKey, true); + if (Recordings == deletedRecordings || initial || !Recordings->GetByName(buffer)) { cRecording *r = new cRecording(buffer); if (r->Name()) { r->NumFrames(); // initializes the numFrames member r->FileSizeMB(); // initializes the fileSizeMB member r->IsOnVideoDirectoryFileSystem(); // initializes the isOnVideoDirectoryFileSystem member - if (deleted) - r->deleted = time(NULL); - Lock(); - Add(r); - if (initial) - ChangeState(); - else - DoChangeState = true; - Unlock(); + if (Recordings == deletedRecordings) + r->SetDeleted(); + Recordings->Add(r); } else delete r; } + StateKey.Remove(); } else - DoChangeState |= ScanVideoDir(buffer, Foreground, LinkLevel + Link, DirLevel + 1); + ScanVideoDir(buffer, LinkLevel + Link, DirLevel + 1); } } } // Handle any vanished recordings: - if (!deleted && !initial && DirLevel == 0) { - for (cRecording *recording = First(); recording; ) { - cRecording *r = recording; - recording = Next(recording); - if (access(r->FileName(), F_OK) != 0) { - Lock(); - Del(r, false); - VanishedRecordings.Add(r); - DoChangeState = true; - Unlock(); - } + if (!initial && DirLevel == 0) { + cStateKey StateKey; + recordings->Lock(StateKey, true); + for (cRecording *Recording = recordings->First(); Recording; ) { + cRecording *r = Recording; + Recording = recordings->Next(Recording); + if (access(r->FileName(), F_OK) != 0) + recordings->Del(r); } + StateKey.Remove(); } - if (DoChangeState && DirLevel == 0) - ChangeState(); - return DoChangeState; } -bool cRecordings::StateChanged(int &State) +// --- cRecordings ----------------------------------------------------------- + +cRecordings cRecordings::recordings; +cRecordings cRecordings::deletedRecordings(true); +char *cRecordings::updateFileName = NULL; +cVideoDirectoryScannerThread *cRecordings::videoDirectoryScannerThread = NULL; +time_t cRecordings::lastUpdate = 0; + +cRecordings::cRecordings(bool Deleted) +:cList<cRecording>(Deleted ? "DelRecs" : "Recordings") { - int NewState = state; - bool Result = State != NewState; - State = state; - return Result; +} + +cRecordings::~cRecordings() +{ + // The first one to be destructed deletes it: + delete videoDirectoryScannerThread; + videoDirectoryScannerThread = NULL; +} + +const char *cRecordings::UpdateFileName(void) +{ + if (!updateFileName) + updateFileName = strdup(AddDirectory(cVideoDirectory::Name(), ".update")); + return updateFileName; } void cRecordings::TouchUpdate(void) @@ -1497,24 +1495,24 @@ bool cRecordings::NeedsUpdate(void) return lastUpdate < lastModified; } -bool cRecordings::Update(bool Wait) +void cRecordings::Update(bool Wait) { + if (!videoDirectoryScannerThread) + videoDirectoryScannerThread = new cVideoDirectoryScannerThread(&recordings, &deletedRecordings); + lastUpdate = time(NULL); // doing this first to make sure we don't miss anything + videoDirectoryScannerThread->Start(); if (Wait) { - Refresh(true); - return Count() > 0; + while (videoDirectoryScannerThread->Active()) + cCondWait::SleepMs(100); } - else - Start(); - return false; } -cRecording *cRecordings::GetByName(const char *FileName) +const cRecording *cRecordings::GetByName(const char *FileName) const { if (FileName) { - LOCK_THREAD; - for (cRecording *recording = First(); recording; recording = Next(recording)) { - if (strcmp(recording->FileName(), FileName) == 0) - return recording; + for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) { + if (strcmp(Recording->FileName(), FileName) == 0) + return Recording; } } return NULL; @@ -1522,12 +1520,8 @@ cRecording *cRecordings::GetByName(const char *FileName) void cRecordings::AddByName(const char *FileName, bool TriggerUpdate) { - LOCK_THREAD; - cRecording *recording = GetByName(FileName); - if (!recording) { - recording = new cRecording(FileName); - Add(recording); - ChangeState(); + if (!GetByName(FileName)) { + Add(new cRecording(FileName)); if (TriggerUpdate) TouchUpdate(); } @@ -1535,58 +1529,52 @@ void cRecordings::AddByName(const char *FileName, bool TriggerUpdate) void cRecordings::DelByName(const char *FileName) { - LOCK_THREAD; - cRecording *recording = GetByName(FileName); + cRecording *Recording = GetByName(FileName); cRecording *dummy = NULL; - if (!recording) - recording = dummy = new cRecording(FileName); // allows us to use a FileName that is not in the Recordings list - cThreadLock DeletedRecordingsLock(&DeletedRecordings); + if (!Recording) + Recording = dummy = new cRecording(FileName); // allows us to use a FileName that is not in the Recordings list + LOCK_DELETEDRECORDINGS_WRITE; if (!dummy) - Del(recording, false); - char *ext = strrchr(recording->fileName, '.'); + Del(Recording, false); + char *ext = strrchr(Recording->fileName, '.'); if (ext) { strncpy(ext, DELEXT, strlen(ext)); - if (access(recording->FileName(), F_OK) == 0) { - recording->deleted = time(NULL); - DeletedRecordings.Add(recording); - recording = NULL; // to prevent it from being deleted below + if (access(Recording->FileName(), F_OK) == 0) { + Recording->SetDeleted(); + DeletedRecordings->Add(Recording); + Recording = NULL; // to prevent it from being deleted below } } - delete recording; - ChangeState(); + delete Recording; TouchUpdate(); } void cRecordings::UpdateByName(const char *FileName) { - LOCK_THREAD; - cRecording *recording = GetByName(FileName); - if (recording) - recording->ReadInfo(); + if (cRecording *Recording = GetByName(FileName)) + Recording->ReadInfo(); } -int cRecordings::TotalFileSizeMB(void) +int cRecordings::TotalFileSizeMB(void) const { int size = 0; - LOCK_THREAD; - for (cRecording *recording = First(); recording; recording = Next(recording)) { - int FileSizeMB = recording->FileSizeMB(); - if (FileSizeMB > 0 && recording->IsOnVideoDirectoryFileSystem()) + for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) { + int FileSizeMB = Recording->FileSizeMB(); + if (FileSizeMB > 0 && Recording->IsOnVideoDirectoryFileSystem()) size += FileSizeMB; } return size; } -double cRecordings::MBperMinute(void) +double cRecordings::MBperMinute(void) const { int size = 0; int length = 0; - LOCK_THREAD; - for (cRecording *recording = First(); recording; recording = Next(recording)) { - if (recording->IsOnVideoDirectoryFileSystem()) { - int FileSizeMB = recording->FileSizeMB(); + for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) { + if (Recording->IsOnVideoDirectoryFileSystem()) { + int FileSizeMB = Recording->FileSizeMB(); if (FileSizeMB > 0) { - int LengthInSeconds = recording->LengthInSeconds(); + int LengthInSeconds = Recording->LengthInSeconds(); if (LengthInSeconds > 0) { if (LengthInSeconds / FileSizeMB < LIMIT_SECS_PER_MB_RADIO) { // don't count radio recordings size += FileSizeMB; @@ -1599,23 +1587,21 @@ double cRecordings::MBperMinute(void) return (size && length) ? double(size) * 60 / length : -1; } -int cRecordings::PathIsInUse(const char *Path) +int cRecordings::PathIsInUse(const char *Path) const { - LOCK_THREAD; int Use = ruNone; - for (cRecording *recording = First(); recording; recording = Next(recording)) { - if (recording->IsInPath(Path)) - Use |= recording->IsInUse(); + for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) { + if (Recording->IsInPath(Path)) + Use |= Recording->IsInUse(); } return Use; } -int cRecordings::GetNumRecordingsInPath(const char *Path) +int cRecordings::GetNumRecordingsInPath(const char *Path) const { - LOCK_THREAD; int n = 0; - for (cRecording *recording = First(); recording; recording = Next(recording)) { - if (recording->IsInPath(Path)) + for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) { + if (Recording->IsInPath(Path)) n++; } return n; @@ -1624,36 +1610,35 @@ int cRecordings::GetNumRecordingsInPath(const char *Path) bool cRecordings::MoveRecordings(const char *OldPath, const char *NewPath) { if (OldPath && NewPath && strcmp(OldPath, NewPath)) { - LOCK_THREAD; dsyslog("moving '%s' to '%s'", OldPath, NewPath); - for (cRecording *recording = First(); recording; recording = Next(recording)) { - if (recording->IsInPath(OldPath)) { - const char *p = recording->Name() + strlen(OldPath); + bool Moved = false; + for (cRecording *Recording = First(); Recording; Recording = Next(Recording)) { + if (Recording->IsInPath(OldPath)) { + const char *p = Recording->Name() + strlen(OldPath); cString NewName = cString::sprintf("%s%s", NewPath, p); - if (!recording->ChangeName(NewName)) + if (!Recording->ChangeName(NewName)) return false; - ChangeState(); + Moved = true; } } + if (Moved) + TouchUpdate(); } return true; } void cRecordings::ResetResume(const char *ResumeFileName) { - LOCK_THREAD; - for (cRecording *recording = First(); recording; recording = Next(recording)) { - if (!ResumeFileName || strncmp(ResumeFileName, recording->FileName(), strlen(recording->FileName())) == 0) - recording->ResetResume(); + for (cRecording *Recording = First(); Recording; Recording = Next(Recording)) { + if (!ResumeFileName || strncmp(ResumeFileName, Recording->FileName(), strlen(Recording->FileName())) == 0) + Recording->ResetResume(); } - ChangeState(); } void cRecordings::ClearSortNames(void) { - LOCK_THREAD; - for (cRecording *recording = First(); recording; recording = Next(recording)) - recording->ClearSortName(); + for (cRecording *Recording = First(); Recording; Recording = Next(Recording)) + Recording->ClearSortName(); } // --- cDirCopier ------------------------------------------------------------ @@ -1812,8 +1797,9 @@ void cDirCopier::Stop(void) Cancel(3); if (error) { cVideoDirectory::RemoveVideoFile(dirNameDst); - Recordings.AddByName(dirNameSrc); - Recordings.DelByName(dirNameDst); + LOCK_RECORDINGS_WRITE; + Recordings->AddByName(dirNameSrc); + Recordings->DelByName(dirNameDst); } } @@ -1893,17 +1879,19 @@ bool cRecordingsHandlerEntry::Active(bool &Error) copier->Start(); } ClearPending(); - Recordings.ChangeState(); + LOCK_RECORDINGS_WRITE; // to trigger a state change return true; } // Clean up: if (CopierFinishedOk && (Usage() & ruMove) != 0) { cRecording Recording(FileNameSrc()); - if (Recording.Delete()) - Recordings.DelByName(Recording.FileName()); + if (Recording.Delete()) { + LOCK_RECORDINGS_WRITE; + Recordings->DelByName(Recording.FileName()); + } } - Recordings.ChangeState(); - Recordings.TouchUpdate(); + LOCK_RECORDINGS_WRITE; // to trigger a state change + Recordings->TouchUpdate(); return false; } @@ -1947,7 +1935,7 @@ bool cRecordingsHandler::Add(int Usage, const char *FileNameSrc, const char *Fil operations.Add(new cRecordingsHandlerEntry(Usage, FileNameSrc, FileNameDst)); finished = false; Active(); // start it right away if possible - Recordings.ChangeState(); + LOCK_RECORDINGS_WRITE; // to trigger a state change return true; } else @@ -1969,7 +1957,7 @@ void cRecordingsHandler::Del(const char *FileName) cMutexLock MutexLock(&mutex); if (cRecordingsHandlerEntry *r = Get(FileName)) { operations.Del(r); - Recordings.ChangeState(); + LOCK_RECORDINGS_WRITE; // to trigger a state change } } @@ -1977,7 +1965,7 @@ void cRecordingsHandler::DelAll(void) { cMutexLock MutexLock(&mutex); operations.Clear(); - Recordings.ChangeState(); + LOCK_RECORDINGS_WRITE; // to trigger a state change } int cRecordingsHandler::GetUsage(const char *FileName) @@ -2059,9 +2047,19 @@ cString cMarks::MarksFileName(const cRecording *Recording) return AddDirectory(Recording->FileName(), Recording->IsPesRecording() ? MARKSFILESUFFIX ".vdr" : MARKSFILESUFFIX); } +bool cMarks::DeleteMarksFile(const cRecording *Recording) +{ + if (remove(cMarks::MarksFileName(Recording)) < 0) { + if (errno != ENOENT) { + LOG_ERROR_STR(Recording->FileName()); + return false; + } + } + return true; +} + bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool IsPesRecording) { - cMutexLock MutexLock(this); recordingFileName = RecordingFileName; fileName = AddDirectory(RecordingFileName, IsPesRecording ? MARKSFILESUFFIX ".vdr" : MARKSFILESUFFIX); framesPerSecond = FramesPerSecond; @@ -2074,7 +2072,6 @@ bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool Is bool cMarks::Update(void) { - cMutexLock MutexLock(this); time_t t = time(NULL); if (t > nextUpdate && *fileName) { time_t LastModified = LastModifiedTime(fileName); @@ -2106,7 +2103,6 @@ bool cMarks::Update(void) bool cMarks::Save(void) { - cMutexLock MutexLock(this); if (cConfig<cMark>::Save()) { lastFileTime = LastModifiedTime(fileName); return true; @@ -2116,7 +2112,6 @@ bool cMarks::Save(void) void cMarks::Align(void) { - cMutexLock MutexLock(this); cIndexFile IndexFile(recordingFileName, false, isPesRecording); for (cMark *m = First(); m; m = Next(m)) { int p = IndexFile.GetClosestIFrame(m->Position()); @@ -2129,7 +2124,6 @@ void cMarks::Align(void) void cMarks::Sort(void) { - cMutexLock MutexLock(this); for (cMark *m1 = First(); m1; m1 = Next(m1)) { for (cMark *m2 = Next(m1); m2; m2 = Next(m2)) { if (m2->Position() < m1->Position()) { @@ -2142,43 +2136,42 @@ void cMarks::Sort(void) void cMarks::Add(int Position) { - cMutexLock MutexLock(this); cConfig<cMark>::Add(new cMark(Position, NULL, framesPerSecond)); Sort(); } -cMark *cMarks::Get(int Position) +const cMark *cMarks::Get(int Position) const { - for (cMark *mi = First(); mi; mi = Next(mi)) { + for (const cMark *mi = First(); mi; mi = Next(mi)) { if (mi->Position() == Position) return mi; } return NULL; } -cMark *cMarks::GetPrev(int Position) +const cMark *cMarks::GetPrev(int Position) const { - for (cMark *mi = Last(); mi; mi = Prev(mi)) { + for (const cMark *mi = Last(); mi; mi = Prev(mi)) { if (mi->Position() < Position) return mi; } return NULL; } -cMark *cMarks::GetNext(int Position) +const cMark *cMarks::GetNext(int Position) const { - for (cMark *mi = First(); mi; mi = Next(mi)) { + for (const cMark *mi = First(); mi; mi = Next(mi)) { if (mi->Position() > Position) return mi; } return NULL; } -cMark *cMarks::GetNextBegin(cMark *EndMark) +const cMark *cMarks::GetNextBegin(const cMark *EndMark) const { - cMark *BeginMark = EndMark ? Next(EndMark) : First(); + const cMark *BeginMark = EndMark ? Next(EndMark) : First(); if (BeginMark && EndMark && BeginMark->Position() == EndMark->Position()) { - while (cMark *NextMark = Next(BeginMark)) { + while (const cMark *NextMark = Next(BeginMark)) { if (BeginMark->Position() == NextMark->Position()) { // skip Begin/End at the same position if (!(BeginMark = Next(NextMark))) break; @@ -2190,13 +2183,13 @@ cMark *cMarks::GetNextBegin(cMark *EndMark) return BeginMark; } -cMark *cMarks::GetNextEnd(cMark *BeginMark) +const cMark *cMarks::GetNextEnd(const cMark *BeginMark) const { if (!BeginMark) return NULL; - cMark *EndMark = Next(BeginMark); + const cMark *EndMark = Next(BeginMark); if (EndMark && BeginMark && BeginMark->Position() == EndMark->Position()) { - while (cMark *NextMark = Next(EndMark)) { + while (const cMark *NextMark = Next(EndMark)) { if (EndMark->Position() == NextMark->Position()) { // skip End/Begin at the same position if (!(EndMark = Next(NextMark))) break; @@ -2208,12 +2201,11 @@ cMark *cMarks::GetNextEnd(cMark *BeginMark) return EndMark; } -int cMarks::GetNumSequences(void) +int cMarks::GetNumSequences(void) const { - cMutexLock MutexLock(this); int NumSequences = 0; - if (cMark *BeginMark = GetNextBegin()) { - while (cMark *EndMark = GetNextEnd(BeginMark)) { + if (const cMark *BeginMark = GetNextBegin()) { + while (const cMark *EndMark = GetNextEnd(BeginMark)) { NumSequences++; BeginMark = GetNextBegin(EndMark); } @@ -2403,7 +2395,8 @@ void cIndexFileGenerator::Action(void) if (FrameDetector.FramesPerSecond() > 0 && !DoubleEqual(RecordingInfo.FramesPerSecond(), FrameDetector.FramesPerSecond())) { RecordingInfo.SetFramesPerSecond(FrameDetector.FramesPerSecond()); RecordingInfo.Write(); - Recordings.UpdateByName(recordingName); + LOCK_RECORDINGS_WRITE; + Recordings->UpdateByName(recordingName); } } Skins.QueueMessage(mtInfo, tr("Index file regeneration complete")); |