Fixed canceling moving a folder with several recordings between volumes

This commit is contained in:
Klaus Schmidinger 2017-12-11 13:55:38 +01:00
parent ea217de338
commit 7455fbd2ad
3 changed files with 47 additions and 34 deletions

View File

@ -9162,7 +9162,7 @@ Video Disk Recorder Revision History
a subdirectory.
- SVDRP peering can now be limited to the default SVDRP host (see MANUAL for details).
2017-12-10: Version 2.3.9
2017-12-11: Version 2.3.9
- Updated the Italian OSD texts (thanks to Diego Pierotto).
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
@ -9229,3 +9229,4 @@ Video Disk Recorder Revision History
- When moving recordings between volumes, the "Recordings" menu now displays those items
that have not yet been moved completely as non-selectable. This avoids situations
where trying to play such a recording might fail.
- Fixed canceling moving a folder with several recordings between volumes.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.c 4.13 2017/12/09 14:24:35 kls Exp $
* $Id: recording.c 4.14 2017/12/11 13:35:14 kls Exp $
*/
#include "recording.h"
@ -1682,7 +1682,6 @@ private:
public:
cDirCopier(const char *DirNameSrc, const char *DirNameDst);
virtual ~cDirCopier();
void Stop(void);
bool Error(void) { return error; }
};
@ -1697,7 +1696,7 @@ cDirCopier::cDirCopier(const char *DirNameSrc, const char *DirNameDst)
cDirCopier::~cDirCopier()
{
Stop();
Cancel(3);
}
bool cDirCopier::Throttled(void)
@ -1833,17 +1832,6 @@ void cDirCopier::Action(void)
esyslog("ERROR: can't access '%s'", *dirNameDst);
}
void cDirCopier::Stop(void)
{
Cancel(3);
if (error) {
cVideoDirectory::RemoveVideoFile(dirNameDst);
LOCK_RECORDINGS_WRITE;
Recordings->AddByName(dirNameSrc);
Recordings->DelByName(dirNameDst);
}
}
// --- cRecordingsHandlerEntry -----------------------------------------------
class cRecordingsHandlerEntry : public cListObject {
@ -1853,14 +1841,18 @@ private:
cString fileNameDst;
cCutter *cutter;
cDirCopier *copier;
bool error;
void ClearPending(void) { usage &= ~ruPending; }
public:
cRecordingsHandlerEntry(int Usage, const char *FileNameSrc, const char *FileNameDst);
~cRecordingsHandlerEntry();
int Usage(const char *FileName = NULL) const;
bool Error(void) const { return error; }
void SetCanceled(void) { usage |= ruCanceled; }
const char *FileNameSrc(void) const { return fileNameSrc; }
const char *FileNameDst(void) const { return fileNameDst; }
bool Active(cRecordings *Recordings, bool &Error);
bool Active(cRecordings *Recordings);
void Cleanup(cRecordings *Recordings);
};
cRecordingsHandlerEntry::cRecordingsHandlerEntry(int Usage, const char *FileNameSrc, const char *FileNameDst)
@ -1870,6 +1862,7 @@ cRecordingsHandlerEntry::cRecordingsHandlerEntry(int Usage, const char *FileName
fileNameDst = FileNameDst;
cutter = NULL;
copier = NULL;
error = false;
}
cRecordingsHandlerEntry::~cRecordingsHandlerEntry()
@ -1890,22 +1883,22 @@ int cRecordingsHandlerEntry::Usage(const char *FileName) const
return u;
}
bool cRecordingsHandlerEntry::Active(cRecordings *Recordings, bool &Error)
bool cRecordingsHandlerEntry::Active(cRecordings *Recordings)
{
bool CopierFinishedOk = false;
if ((usage & ruCanceled) != 0)
return false;
// First test whether there is an ongoing operation:
if (cutter) {
if (cutter->Active())
return true;
Error |= cutter->Error();
error = cutter->Error();
delete cutter;
cutter = NULL;
}
else if (copier) {
if (copier->Active())
return true;
Error |= copier->Error();
CopierFinishedOk = !copier->Error();
error = copier->Error();
delete copier;
copier = NULL;
}
@ -1923,19 +1916,34 @@ bool cRecordingsHandlerEntry::Active(cRecordings *Recordings, bool &Error)
Recordings->SetModified(); // to trigger a state change
return true;
}
// Clean up:
if (CopierFinishedOk && (Usage() & ruMove) != 0) {
// We're done:
if (!error && (usage & ruMove) != 0) {
cRecording Recording(FileNameSrc());
if (Recording.Delete()) {
if (Recording.Delete())
Recordings->DelByName(Recording.FileName());
Recordings->SetModified(); // to trigger a state change
}
}
Recordings->SetModified(); // to trigger a state change
Recordings->TouchUpdate();
return false;
}
void cRecordingsHandlerEntry::Cleanup(cRecordings *Recordings)
{
if ((usage & (ruMove | ruCopy)) // this was a move/copy operation...
&& ((usage & ruPending) // ...which had not yet started...
|| copier // ...or not yet finished...
|| error)) { // ...or finished with error
if (copier) {
delete copier;
copier = NULL;
}
cVideoDirectory::RemoveVideoFile(fileNameDst);
if ((usage & ruMove) != 0)
Recordings->AddByName(fileNameSrc);
Recordings->DelByName(fileNameDst);
}
}
// --- cRecordingsHandler ----------------------------------------------------
cRecordingsHandler RecordingsHandler;
@ -1961,8 +1969,11 @@ void cRecordingsHandler::Action(void)
Recordings->SetExplicitModify();
cMutexLock MutexLock(&mutex);
if (cRecordingsHandlerEntry *r = operations.First()) {
if (!r->Active(Recordings, error))
if (!r->Active(Recordings)) {
error |= r->Error();
r->Cleanup(Recordings);
operations.Del(r);
}
else
Sleep = true;
}
@ -1978,6 +1989,8 @@ cRecordingsHandlerEntry *cRecordingsHandler::Get(const char *FileName)
{
if (FileName && *FileName) {
for (cRecordingsHandlerEntry *r = operations.First(); r; r = operations.Next(r)) {
if ((r->Usage() & ruCanceled) != 0)
continue;
if (strcmp(FileName, r->FileNameSrc()) == 0 || strcmp(FileName, r->FileNameDst()) == 0)
return r;
}
@ -2020,16 +2033,14 @@ void cRecordingsHandler::Del(const char *FileName)
{
cMutexLock MutexLock(&mutex);
if (cRecordingsHandlerEntry *r = Get(FileName))
operations.Del(r);
r->SetCanceled();
}
void cRecordingsHandler::DelAll(void)
{
{
cMutexLock MutexLock(&mutex);
operations.Clear();
}
Cancel(3);
cMutexLock MutexLock(&mutex);
for (cRecordingsHandlerEntry *r = operations.First(); r; r = operations.Next(r))
r->SetCanceled();
}
int cRecordingsHandler::GetUsage(const char *FileName)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.h 4.6 2017/12/09 14:11:16 kls Exp $
* $Id: recording.h 4.7 2017/12/11 12:56:57 kls Exp $
*/
#ifndef __RECORDING_H
@ -38,6 +38,7 @@ enum eRecordingUsage {
ruDst = 0x0040, // the recording is the destination of a cut, move or copy process
//
ruPending = 0x0080, // the recording is pending a cut, move or copy process
ruCanceled = 0x8000, // the operation has been canceled, waiting for cleanup
};
void RemoveDeletedRecordings(void);