Skip to content
Browse files

Remove use of signals and slots from protocol server.

The rewritten delete thread in libmythprotoserver was intended to be
ignorant of any metadata pertaining to the file it was deleting, and
simply implement the slow delete and follow symlinks features.  Signals
would be fired off to indicate success or failure of deletion, so other
code could handle removal of the metadata from the database.

This reworks that behavior, replacing the deletestruct with a
DeleteHandler class, and replacing the signals with DeleteSucceeded()
and DeleteFailed() virtual methods.  In order to handle metadata,
subclass this and overwrite those two methods.  FileServerHandler
accepts it using the HandleDeleteFile() method.
  • Loading branch information...
1 parent 63746de commit 86d35376119b4794eb054225a31b1cd04b02ab84 @wagnerrp wagnerrp committed Sep 8, 2011
View
2 mythtv/libs/libmythbase/mythversion.h
@@ -12,7 +12,7 @@
/// Update this whenever the plug-in API changes.
/// Including changes in the libmythbase, libmyth, libmythtv, libmythav* and
/// libmythui class methods used by plug-ins.
-#define MYTH_BINARY_VERSION "0.25.20110907-2"
+#define MYTH_BINARY_VERSION "0.25.20110908-1"
/** \brief Increment this whenever the MythTV network protocol changes.
*
View
117 mythtv/libs/libmythprotoserver/requesthandler/deletethread.cpp
@@ -12,9 +12,9 @@ using namespace std;
#include <QStringList>
#include <QMutexLocker>
+#include "requesthandler/deletethread.h"
#include "util.h"
#include "mythdb.h"
-#include "requesthandler/deletethread.h"
#include "mythcorecontext.h"
#include "mythlogging.h"
@@ -23,17 +23,14 @@ using namespace std;
that may be completely irrelevent to a machine that does not record, just
choose a reasonable value.
- 38 Mbps (full QAM-256 multiplex) * 8 tuners = 9961472B/0.5s
+ 38 Mbps (full QAM-256 multiplex) * 4 tuners = 9961472B/0.5s
*/
DeleteThread::DeleteThread(void) :
- MThread("Delete"), m_increment(9961472), m_run(true), m_timeout(20000)
+ MThread("Delete"), m_increment(9961472), m_run(true)
{
m_slow = (bool) gCoreContext->GetNumSetting("TruncateDeletesSlowly", 0);
m_link = (bool) gCoreContext->GetNumSetting("DeletesFollowLinks", 0);
-
- connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
- m_timer.start(m_timeout);
}
void DeleteThread::run(void)
@@ -54,12 +51,8 @@ void DeleteThread::run(void)
{
// this will only happen if the program is closing, so fast
// deletion is not a problem
- QList<deletestruct *>::iterator i;
- for (i = m_files.begin(); i != m_files.end(); ++i)
- {
- close((*i)->fd);
- delete (*i);
- }
+ QList<DeleteHandler*>::iterator i;
+ (*i)->DownRef();
}
else
LOG(VB_FILE, LOG_DEBUG, "Delete thread self-terminating due to idle.");
@@ -75,52 +68,62 @@ bool DeleteThread::AddFile(QString path)
return false;
QMutexLocker lock(&m_newlock);
- m_newfiles << path;
+ DeleteHandler *handler = new DeleteHandler(path);
+ m_newfiles << handler;
+ return true;
+}
+
+bool DeleteThread::AddFile(DeleteHandler *handler)
+{
+ handler->UpRef();
+ QMutexLocker lock(&m_newlock);
+ m_newfiles << handler;
return true;
}
void DeleteThread::ProcessNew(void)
{
// loop through new files, unlinking and adding for deletion
// until none are left
- // TODO: add support for symlinks
QDateTime ctime = QDateTime::currentDateTime();
while (true)
{
// pull a new path from the stack
- QString path;
+ DeleteHandler *handler;
{
QMutexLocker lock(&m_newlock);
- if (!m_newfiles.isEmpty())
- path = m_newfiles.takeFirst();
+ if (m_newfiles.isEmpty())
+ break;
+ else
+ handler = m_newfiles.takeFirst();
}
// empty path given to delete thread, this should not happen
- if (path.isEmpty())
- continue;
-
- m_timer.start(m_timeout);
+ //if (path.isEmpty())
+ // continue;
- const char *cpath = path.toLocal8Bit().constData();
+ QString path = handler->m_path;
+ const char *cpath = handler->m_path.toLocal8Bit().constData();
- QFileInfo finfo(path);
+ QFileInfo finfo(handler->m_path);
if (finfo.isSymLink())
{
if (m_link)
{
// if file is a symlink and symlinks are processed,
// grab the target of the link, and attempt to unlink
// the link itself
- QString tmppath = getSymlinkTarget(path);
+ QString tmppath = getSymlinkTarget(handler->m_path);
if (unlink(cpath))
{
LOG(VB_GENERAL, LOG_ERR,
QString("Error deleting '%1' -> '%2': ")
- .arg(path).arg(tmppath) + ENO);
- emit unlinkFailed(path);
+ .arg(handler->m_path).arg(tmppath) + ENO);
+ handler->DeleteFailed();
+ handler->DownRef();
continue;
}
@@ -132,9 +135,9 @@ void DeleteThread::ProcessNew(void)
// signalling the matching metadata for removal, but the
// target itself fails, resulting in a spurious file in
// an external directory with no link into mythtv
- emit fileUnlinked(path);
- path = tmppath;
- cpath = path.toLocal8Bit().constData();
+ handler->DeleteSucceeded();
+ handler->m_path = tmppath;
+ cpath = handler->m_path.toLocal8Bit().constData();
}
else
{
@@ -145,25 +148,27 @@ void DeleteThread::ProcessNew(void)
LOG(VB_GENERAL, LOG_ERR,
QString("Error deleting '%1': count not unlink ")
.arg(path) + ENO);
- emit unlinkFailed(path);
+ handler->DeleteFailed();
}
else
- emit fileUnlinked(path);
+ handler->DeleteFailed();
+ handler->DownRef();
continue;
}
}
// open the file so it can be unlinked without immediate deletion
LOG(VB_FILE, LOG_INFO, QString("About to unlink/delete file: '%1'")
- .arg(path));
+ .arg(handler->m_path));
int fd = open(cpath, O_WRONLY);
if (fd == -1)
{
LOG(VB_GENERAL, LOG_ERR,
QString("Error deleting '%1': could not open ")
- .arg(path) + ENO);
- emit unlinkFailed(path);
+ .arg(handler->m_path) + ENO);
+ handler->DeleteFailed();
+ handler->DownRef();
continue;
}
@@ -174,22 +179,21 @@ void DeleteThread::ProcessNew(void)
LOG(VB_GENERAL, LOG_ERR,
QString("Error deleting '%1': could not unlink ")
.arg(path) + ENO);
- emit unlinkFailed(path);
+ handler->DeleteFailed();
close(fd);
+ handler->DownRef();
continue;
}
- emit fileUnlinked(path);
+ handler->DeleteSucceeded();
// insert the file into a queue of opened references to be deleted
- deletestruct *ds = new deletestruct;
- ds->path = path;
- ds->fd = fd;
- ds->size = finfo.size();
- ds->wait = ctime.addSecs(3); // delay deletion a bit to allow
- // UI to get any needed IO time
-
- m_files << ds;
+ handler->m_fd = fd;
+ handler->m_size = finfo.size();
+ handler->m_wait = ctime.addSecs(3); // delay deletion a bit to allow
+ // UI to get any needed IO time
+
+ m_files << handler;
}
}
@@ -199,41 +203,38 @@ void DeleteThread::ProcessOld(void)
if (m_files.empty())
return;
- // files exist for deletion, reset the timer
- m_timer.start(m_timeout);
-
QDateTime ctime = QDateTime::currentDateTime();
// only operate on one file at a time
// delete that file completely before moving onto the next
while (true)
{
- deletestruct *ds = m_files.first();
+ DeleteHandler *handler = m_files.first();
// first file in the list has been delayed for deletion
- if (ds->wait > ctime)
+ if (handler->m_wait > ctime)
break;
-
+
if (m_slow)
{
- ds->size -= m_increment;
- int err = ftruncate(ds->fd, ds->size);
+ handler->m_size -= m_increment;
+ int err = ftruncate(handler->m_fd, handler->m_size);
if (err)
{
LOG(VB_GENERAL, LOG_ERR, QString("Error truncating '%1'")
- .arg(ds->path) + ENO);
- ds->size = 0;
+ .arg(handler->m_path) + ENO);
+ handler->m_size = 0;
}
}
else
- ds->size = 0;
+ handler->m_size = 0;
- if (ds->size == 0)
+ if (handler->m_size == 0)
{
- close(ds->fd);
+ handler->Close();
m_files.removeFirst();
- delete ds;
+ handler->DownRef();
}
// fast delete can close out all, but slow delete needs
View
26 mythtv/libs/libmythprotoserver/requesthandler/deletethread.h
@@ -17,14 +17,7 @@ using namespace std;
// MythTV headers
#include "mthread.h"
-
-typedef struct deletestruct
-{
- QString path;
- int fd;
- off_t size;
- QDateTime wait;
-} DeleteStruct;
+#include "requesthandler/fileserverutil.h"
class DeleteThread : public QObject, public MThread
{
@@ -33,13 +26,8 @@ class DeleteThread : public QObject, public MThread
DeleteThread(void);
void run(void);
bool AddFile(QString path);
-
- signals:
- void fileUnlinked(QString path);
- void unlinkFailed(QString path);
-
- private slots:
- void timeout(void) { m_run = false; }
+ bool AddFile(DeleteHandler *handler);
+ void Stop(void) { m_run = false; }
private:
void ProcessNew(void);
@@ -49,13 +37,11 @@ class DeleteThread : public QObject, public MThread
bool m_slow;
bool m_link;
bool m_run;
- QTimer m_timer;
- int m_timeout;
- QStringList m_newfiles;
- QMutex m_newlock;
+ QList<DeleteHandler*> m_newfiles;
+ QMutex m_newlock;
- QList<deletestruct*> m_files;
+ QList<DeleteHandler*> m_files;
};
#endif
View
30 mythtv/libs/libmythprotoserver/requesthandler/fileserverhandler.cpp
@@ -156,23 +156,17 @@ QString FileServerHandler::LocalFilePath(const QUrl &url,
void FileServerHandler::RunDeleteThread(void)
{
- if (deletethread == NULL)
+ if (deletethread != NULL)
{
- deletethread = new DeleteThread();
- connect(deletethread, SIGNAL(unlinkFailed(QString)),
- this, SIGNAL(unlinkFailed(QString)));
- connect(deletethread, SIGNAL(fileUnlinked(QString)),
- this, SIGNAL(fileUnlinked(QString)));
- connect(deletethread->qthread(), SIGNAL(finished()),
- this, SLOT(deleteThreadTerminated()));
- deletethread->start();
+ if (deletethread->isRunning())
+ return
+
+ delete deletethread;
+ deletethread = NULL;
}
-}
-void FileServerHandler::deleteThreadTerminated(void)
-{
- delete deletethread;
- deletethread = NULL;
+ deletethread = new DeleteThread();
+ deletethread->start();
}
bool FileServerHandler::HandleAnnounce(MythSocket *socket,
@@ -730,7 +724,7 @@ bool FileServerHandler::HandleDeleteFile(SocketHandler *socket,
bool FileServerHandler::DeleteFile(QString filename, QString storagegroup)
{
- return HandleDeleteFile(NULL, filename, storagegroup);
+ return HandleDeleteFile( (SocketHandler *)NULL, filename, storagegroup);
}
bool FileServerHandler::HandleDeleteFile(SocketHandler *socket,
@@ -795,6 +789,12 @@ bool FileServerHandler::HandleDeleteFile(SocketHandler *socket,
return true;
}
+bool FileServerHandler::HandleDeleteFile(DeleteHandler *handler)
+{
+ RunDeleteThread();
+ deletethread->AddFile(handler);
+}
+
bool FileServerHandler::HandleGetFileList(SocketHandler *socket,
QStringList &slist)
{
View
14 mythtv/libs/libmythprotoserver/requesthandler/fileserverhandler.h
@@ -10,6 +10,7 @@ using namespace std;
#include "mythprotoserverexp.h"
#include "sockethandler/filetransfer.h"
+#include "requesthandler/fileserverutil.h"
class PROTOSERVER_PUBLIC FileServerHandler : public SocketRequestHandler
{
@@ -30,14 +31,6 @@ class PROTOSERVER_PUBLIC FileServerHandler : public SocketRequestHandler
QList<FileSystemInfo> QueryFileSystems(void);
QList<FileSystemInfo> QueryAllFileSystems(void);
- signals:
- void unlinkFailed(QString path);
- void fileUnlinked(QString path);
-
- protected slots:
- void deleteThreadTerminated(void);
-// void deferredDeleteSlot(void);
-
private:
bool HandleQueryFreeSpace(SocketHandler *socket);
bool HandleQueryFreeSpaceList(SocketHandler *socket);
@@ -49,9 +42,8 @@ class PROTOSERVER_PUBLIC FileServerHandler : public SocketRequestHandler
bool HandleDeleteFile(SocketHandler *socket, QStringList &slist);
bool HandleDeleteFile(SocketHandler *socket, QString filename,
QString storagegroup);
- bool HandleDeleteFile(QString filename, QString storagegroup)
- { return HandleDeleteFile((SocketHandler*)NULL,
- filename, storagegroup); }
+ bool HandleDeleteFile(QString filename, QString storagegroup);
+ bool HandleDeleteFile(DeleteHandler *handler);
bool HandleGetFileList(SocketHandler *socket, QStringList &slist);
bool HandleFileQuery(SocketHandler *socket, QStringList &slist);
View
22 mythtv/libs/libmythprotoserver/requesthandler/fileserverutil.cpp
@@ -15,6 +15,28 @@
#include "requesthandler/fileserverutil.h"
#include "programinfo.h"
+DeleteHandler::DeleteHandler(void) :
+ ReferenceCounter(), m_fd(-1), m_size(0)
+{
+}
+
+DeleteHandler::DeleteHandler(QString filename) :
+ ReferenceCounter(), m_path(filename), m_fd(-1), m_size(0)
+{
+}
+
+DeleteHandler::~DeleteHandler()
+{
+ Close();
+}
+
+void DeleteHandler::Close(void)
+{
+ if (m_fd >= 0)
+ close(m_fd);
+ m_fd = -1;
+}
+
QMap <QString, QString> recordingPathCache;
QString GetPlaybackURL(ProgramInfo *pginfo, bool storePath)
View
35 mythtv/libs/libmythprotoserver/requesthandler/fileserverutil.h
@@ -4,8 +4,43 @@
using namespace std;
#include <QString>
+#include <QDateTime>
+#include "mythprotoserverexp.h"
#include "programinfo.h"
+#include "referencecounter.h"
+
+class DeleteThread;
+
+class PROTOSERVER_PUBLIC DeleteHandler : public ReferenceCounter
+{
+ Q_OBJECT
+ public:
+ DeleteHandler(void);
+ DeleteHandler(QString filename);
+ ~DeleteHandler(void);
+
+ void Close(void);
+
+ QString GetPath(void) { return m_path; }
+ int GetFD(void) { return m_fd; }
+ off_t GetSize(void) { return m_size; }
+ QDateTime GetWait(void) { return m_wait; }
+
+ void SetPath(QString path) { m_path= path; }
+
+ virtual void DeleteSucceeded(void) {};
+ virtual void DeleteFailed(void) {};
+
+ friend class DeleteThread;
+
+ private:
+ QString m_path;
+ int m_fd;
+ off_t m_size;
+ QDateTime m_wait;
+
+};
QString GetPlaybackURL(ProgramInfo *pginfo, bool storePath = true);

0 comments on commit 86d3537

Please sign in to comment.
Something went wrong with that request. Please try again.