00001 #include <cstdlib>
00002 #include <iostream>
00003 #include <fcntl.h>
00004
00005 using namespace std;
00006
00007 #include <QList>
00008 #include <QTimer>
00009 #include <QString>
00010 #include <QFileInfo>
00011 #include <QDateTime>
00012 #include <QStringList>
00013 #include <QMutexLocker>
00014
00015 #include "requesthandler/deletethread.h"
00016 #include "mythmiscutil.h"
00017 #include "mythdb.h"
00018 #include "mythcorecontext.h"
00019 #include "mythlogging.h"
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 DeleteThread::DeleteThread(void) :
00030 MThread("Delete"), m_increment(9961472), m_run(true)
00031 {
00032 m_slow = (bool) gCoreContext->GetNumSetting("TruncateDeletesSlowly", 0);
00033 m_link = (bool) gCoreContext->GetNumSetting("DeletesFollowLinks", 0);
00034 }
00035
00036 void DeleteThread::run(void)
00037 {
00038 RunProlog();
00039
00040 LOG(VB_FILE, LOG_DEBUG, "Spawning new delete thread.");
00041
00042 while (gCoreContext && m_run)
00043 {
00044
00045 ProcessNew();
00046 ProcessOld();
00047 usleep(500000);
00048 }
00049
00050 if (!m_files.empty())
00051 {
00052
00053
00054 QList<DeleteHandler*>::iterator i;
00055 (*i)->DownRef();
00056 }
00057 else
00058 LOG(VB_FILE, LOG_DEBUG, "Delete thread self-terminating due to idle.");
00059
00060 RunEpilog();
00061 }
00062
00063 bool DeleteThread::AddFile(QString path)
00064 {
00065
00066 QFileInfo finfo(path);
00067 if (!finfo.exists())
00068 return false;
00069
00070 QMutexLocker lock(&m_newlock);
00071 DeleteHandler *handler = new DeleteHandler(path);
00072 m_newfiles << handler;
00073 return true;
00074 }
00075
00076 bool DeleteThread::AddFile(DeleteHandler *handler)
00077 {
00078 handler->UpRef();
00079 QMutexLocker lock(&m_newlock);
00080 m_newfiles << handler;
00081 return true;
00082 }
00083
00084 void DeleteThread::ProcessNew(void)
00085 {
00086
00087
00088
00089 QDateTime ctime = QDateTime::currentDateTime();
00090
00091 while (true)
00092 {
00093
00094 DeleteHandler *handler;
00095 {
00096 QMutexLocker lock(&m_newlock);
00097 if (m_newfiles.isEmpty())
00098 break;
00099 else
00100 handler = m_newfiles.takeFirst();
00101 }
00102
00103
00104
00105
00106
00107 QString path = handler->m_path;
00108 QByteArray cpath_ba = handler->m_path.toLocal8Bit();
00109 const char *cpath = cpath_ba.constData();
00110
00111 QFileInfo finfo(handler->m_path);
00112 if (finfo.isSymLink())
00113 {
00114 if (m_link)
00115 {
00116
00117
00118
00119 QString tmppath = getSymlinkTarget(handler->m_path);
00120
00121 if (unlink(cpath))
00122 {
00123 LOG(VB_GENERAL, LOG_ERR,
00124 QString("Error deleting '%1' -> '%2': ")
00125 .arg(handler->m_path).arg(tmppath) + ENO);
00126 handler->DeleteFailed();
00127 handler->DownRef();
00128 continue;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 handler->DeleteSucceeded();
00140 handler->m_path = tmppath;
00141 cpath_ba = handler->m_path.toLocal8Bit();
00142 cpath = cpath_ba.constData();
00143 }
00144 else
00145 {
00146
00147
00148 if (unlink(cpath))
00149 {
00150 LOG(VB_GENERAL, LOG_ERR,
00151 QString("Error deleting '%1': count not unlink ")
00152 .arg(path) + ENO);
00153 handler->DeleteFailed();
00154 }
00155 else
00156 handler->DeleteFailed();
00157
00158 handler->DownRef();
00159 continue;
00160 }
00161 }
00162
00163
00164 LOG(VB_FILE, LOG_INFO, QString("About to unlink/delete file: '%1'")
00165 .arg(handler->m_path));
00166 int fd = open(cpath, O_WRONLY);
00167 if (fd == -1)
00168 {
00169 LOG(VB_GENERAL, LOG_ERR,
00170 QString("Error deleting '%1': could not open ")
00171 .arg(handler->m_path) + ENO);
00172 handler->DeleteFailed();
00173 handler->DownRef();
00174 continue;
00175 }
00176
00177
00178
00179 if (unlink(cpath))
00180 {
00181 LOG(VB_GENERAL, LOG_ERR,
00182 QString("Error deleting '%1': could not unlink ")
00183 .arg(path) + ENO);
00184 handler->DeleteFailed();
00185 close(fd);
00186 handler->DownRef();
00187 continue;
00188 }
00189
00190 handler->DeleteSucceeded();
00191
00192
00193 handler->m_fd = fd;
00194 handler->m_size = finfo.size();
00195 handler->m_wait = ctime.addSecs(3);
00196
00197
00198 m_files << handler;
00199 }
00200 }
00201
00202 void DeleteThread::ProcessOld(void)
00203 {
00204
00205 if (m_files.empty())
00206 return;
00207
00208 QDateTime ctime = QDateTime::currentDateTime();
00209
00210
00211
00212 while (true)
00213 {
00214 DeleteHandler *handler = m_files.first();
00215
00216
00217 if (handler->m_wait > ctime)
00218 break;
00219
00220 if (m_slow)
00221 {
00222 handler->m_size -= m_increment;
00223 int err = ftruncate(handler->m_fd, handler->m_size);
00224
00225 if (err)
00226 {
00227 LOG(VB_GENERAL, LOG_ERR, QString("Error truncating '%1'")
00228 .arg(handler->m_path) + ENO);
00229 handler->m_size = 0;
00230 }
00231 }
00232 else
00233 handler->m_size = 0;
00234
00235 if (handler->m_size == 0)
00236 {
00237 handler->Close();
00238 m_files.removeFirst();
00239 handler->DownRef();
00240 }
00241
00242
00243
00244 if (m_slow || m_files.empty())
00245 break;
00246 }
00247 }