*/
#include "backupgui.hpp"
-
+ReVerbose_t BackupEngine::m_verboseLevel = VerboseStandard;
bool BackupEngine::m_shouldStop = false;
QStringList BackupEngine::m_files;
qint64 BackupEngine::m_hotBytes = 0;
return true;
}
-/**
- * Inserts a remove command into queue for too old files in the shadow.
- *
- * Note: this method is recursive.
- *
- * @param directory directory to inspect, e.g. "/media/trg/x"
- * @param maxAge all files older than this time point will be deleted
- */
-void BackupEngine::removeOlder(const QString& directory, const QDateTime& time){
- QDirIterator it(directory);
- QString info, node;
- m_mutex.lock();
- m_totalDirs++;
- m_mutex.unlock();
- bool isEmpty = true;
- while (it.hasNext()){
- if (m_shouldStop){
- break;
- }
- it.next();
- node = it.fileName();
- if (it.fileInfo().isDir()){
- if (node != "." && node != ".."){
- removeOlder(it.filePath(), time);
- isEmpty = false;
- }
- } else if (it.fileInfo().lastModified() < time){
- isEmpty = false;
- info = QChar(MAX_INDEX) + it.filePath() + m_separatorString
- + QChar(CmdRemove);
- m_mutex.lock();
- m_files.append(info);
- m_hotFiles++;
- m_hotBytes += it.fileInfo().size();
- m_totalFiles++;
- m_mutex.unlock();
- }
- }
- if (isEmpty){
- info = QChar(MAX_INDEX) + it.filePath() + m_separatorString
- + QChar(CmdRemoveDir);
- m_mutex.lock();
- m_files.append(info);
- m_matchedFiles++;
- m_mutex.unlock();
- }
-
-}
-
/**
* Constructor.
*
error(tr("cannot make directory (%1): %2").arg(errno).arg(targetDir));
}
QFileInfo info(source);
- m_mainWindow->addToFileList(source + " " + ReQStringUtils::readableSize(info.size()));
+ if (m_verboseLevel >= VerboseStandard)
+ m_mainWindow->addToFileList(source + " " + ReQStringUtils::readableSize(info.size()));
m_processedFiles++;
m_processedBytes += info.size();
QString errorMsg = ReFileUtils::copy(source, target, &info, m_buffer);
if (! errorMsg.isEmpty()){
error(errorMsg);
- m_mainWindow->expandFileList(errorMsg);
- } else {
+ if (m_verboseLevel >= VerboseStandard)
+ m_mainWindow->expandFileList(errorMsg);
+ } else if (m_verboseLevel >= VerboseStandard) {
m_mainWindow->expandFileList(ReQStringUtils::readableDuration(
QDateTime::currentMSecsSinceEpoch() - start));
}
relPath = info.mid(1, pos - 1);
node = info.mid(pos + 1);
copyFile(index, relPath, node);
- qint64 duration = QDateTime::currentMSecsSinceEpoch() - start.currentMSecsSinceEpoch();
- double factor = double(m_hotBytes) / max(1LL, m_processedBytes);
- m_mainWindow->externalAppend(ReGuiQueueItem::StatusLine, NULL,
- tr("%1 of %2 (%3 of %4) %5 MB/sec runtime: %6")
- .arg(m_processedFiles).arg(m_hotFiles)
- .arg(ReQStringUtils::readableSize(m_processedBytes))
- .arg(ReQStringUtils::readableSize(m_hotBytes))
- .arg(m_processedBytes / 1024.0 / 1024 * 1000 / max(1LL, duration), 0, 'f', 3)
- .arg(ReQStringUtils::runtimeEstimation(start, factor)));
+ if (m_verboseLevel > VerboseQuiet){
+ qint64 duration = QDateTime::currentMSecsSinceEpoch() - start.currentMSecsSinceEpoch();
+ double factor = double(m_hotBytes) / max(1LL, m_processedBytes);
+ m_mainWindow->externalAppend(ReGuiQueueItem::StatusLine, NULL,
+ tr("%1 of %2 (%3 of %4) %5 MB/sec runtime: %6")
+ .arg(m_processedFiles).arg(m_hotFiles)
+ .arg(ReQStringUtils::readableSize(m_processedBytes))
+ .arg(ReQStringUtils::readableSize(m_hotBytes))
+ .arg(m_processedBytes / 1024.0 / 1024 * 1000 / max(1LL, duration), 0, 'f', 3)
+ .arg(ReQStringUtils::runtimeEstimation(start, factor)));
+ }
}
}
m_mainWindow->externalTaskFinished(tr("backup complete after %1. Errors: %2")
m_mutex.unlock();
if (rc.isEmpty()){
error(QObject::tr("cannot build checksum: %1").arg(filename) );
- } else {
+ } if (m_verboseLevel >= VerboseStandard){
m_mainWindow->addToFileList(QString(rc) + " " + filename);
}
return rc;
processedBytes = m_processedBytes;
processedFiles = m_processedFiles;
m_mutex.unlock();
- now = QDateTime::currentMSecsSinceEpoch();
- qint64 duration = (now - start.currentMSecsSinceEpoch());
- double factor = double(m_hotBytes) * 2 / max(1LL, m_processedBytes);
- m_mainWindow->externalAppend(ReGuiQueueItem::StatusLine, NULL,
- tr("%1 of %2 (%3 of %4) %5 MB/sec runtime: %6")
+ if (m_verboseLevel > VerboseQuiet){
+ now = QDateTime::currentMSecsSinceEpoch();
+ qint64 duration = (now - start.currentMSecsSinceEpoch());
+ double factor = double(m_hotBytes) * 2 / max(1LL, m_processedBytes);
+ m_mainWindow->externalAppend(ReGuiQueueItem::StatusLine, NULL,
+ tr("%1 of %2 (%3 of %4) %5 MB/sec runtime: %6")
.arg(processedFiles).arg(hotFiles * 2)
.arg(ReQStringUtils::readableSize(processedBytes))
.arg(ReQStringUtils::readableSize(hotBytes * 2))
.arg(processedBytes / 1024.0 / 1024 / max(1LL, duration) * 1000.0, 0, 'f', 3)
.arg(ReQStringUtils::runtimeEstimation(start, factor)));
+ }
}
}
} else {
int index = int(info.at(0).unicode()) - 1;
int pos = info.indexOf(m_separator, 1);
+ struct stat info2;
if (pos == 1)
relPath.clear();
else
node = info.mid(pos + 2);
switch(command){
case CmdRemove:
- if (unlink(I18N::s2b(relPath)) != 0)
- error(QObject::tr("cannot delete target (%1): %2").arg(errno)
+ if (unlink(I18N::s2b(relPath)) != 0){
+ int errNo = errno;
+ if (stat(I18N::s2b(relPath), &info2) == 0)
+ error(QObject::tr("cannot delete (%1): %2").arg(errNo)
.arg(relPath));
- else
+ } else if (m_verboseLevel >= VerboseStandard)
m_mainWindow->addToFileList("- " + relPath);
break;
case CmdRemoveDir:
- m_mainWindow->addToFileList("/ " + relPath);
+ if (_rmdir(I18N::s2b(relPath)) != 0){
+ int errNo = errno;
+ if (stat(I18N::s2b(relPath), &info2) == 0)
+ error(QObject::tr("cannot remove directory (%1): %2").arg(errNo)
+ .arg(relPath));
+ } else if (m_verboseLevel >= VerboseStandard)
+ m_mainWindow->addToFileList("/ " + relPath);
break;
case CmdMove:
{
if (rename(I18N::s2b(target).constData(), shadow2.constData()) != 0)
error(QObject::tr("cannot rename target file (%1): %2 -> %3")
.arg(errno).arg(target).arg(shadow));
- m_mainWindow->addToFileList(">" + target);
+ if (m_verboseLevel >= VerboseStandard)
+ m_mainWindow->addToFileList(">" + target);
break;
}
default:
error("unknown command: " + QString::number(command));
break;
}
- double factor = double(m_hotFiles) / max(1, m_processedFiles);
- qint64 duration = QDateTime::currentMSecsSinceEpoch() - start.currentMSecsSinceEpoch();
- m_mainWindow->externalAppend(ReGuiQueueItem::StatusLine, NULL,
- tr("%1 of %2 (%3 of %4) %5 MB/sec runtime: %6")
- .arg(m_processedFiles)
- .arg(m_hotFiles)
- .arg(ReQStringUtils::readableSize(m_processedBytes))
- .arg(ReQStringUtils::readableSize(m_hotBytes))
- .arg(m_processedBytes / 1024.0 / 1024 * 1000
- / max(1.0, (double) duration), 0, 'f', 3)
- .arg(ReQStringUtils::runtimeEstimation(start, factor)));
+ if (m_verboseLevel > VerboseQuiet){
+ double factor = double(m_hotFiles) / max(1, m_processedFiles);
+ qint64 duration = QDateTime::currentMSecsSinceEpoch() - start.currentMSecsSinceEpoch();
+ m_mainWindow->externalAppend(ReGuiQueueItem::StatusLine, NULL,
+ tr("%1 of %2 (%3 of %4) %5 MB/sec runtime: %6")
+ .arg(m_processedFiles)
+ .arg(m_hotFiles)
+ .arg(ReQStringUtils::readableSize(m_processedBytes))
+ .arg(ReQStringUtils::readableSize(m_hotBytes))
+ .arg(m_processedBytes / 1024.0 / 1024 * 1000
+ / max(1.0, (double) duration), 0, 'f', 3)
+ .arg(ReQStringUtils::runtimeEstimation(start, factor)));
+ }
}
}
m_mainWindow->externalTaskFinished(tr("backup complete after %1. Errors: %2")
initializeShadowDir();
}
+/**
+ * Inserts a remove command into queue for too old files in the shadow.
+ *
+ * Note: this method is recursive.
+ *
+ * @param directory directory to inspect, e.g. "/media/trg/x"
+ * @param maxAge all files older than this time point will be deleted
+ * @return <code>true</code>: the directory was deleted if empty
+ */
+bool SearchTargetTask::removeOlder(const QString& directory, const QDateTime& time){
+ QDirIterator it(directory);
+ QString info, node;
+ m_mutex.lock();
+ m_totalDirs++;
+ m_mutex.unlock();
+ bool isEmpty = true;
+ while (it.hasNext()){
+ if (m_shouldStop){
+ break;
+ }
+ it.next();
+ node = it.fileName();
+ if (it.fileInfo().isDir()){
+ if (node != "." && node != ".."){
+ if (! removeOlder(it.filePath(), time))
+ isEmpty = false;
+ }
+ } else if (it.fileInfo().lastModified() < time){
+ if (m_verboseLevel >= VerboseChatty)
+ m_mainWindow->addToFileList("% " + it.filePath() + " "
+ + it.fileInfo().lastModified().toString("yyyy.MM.dd/hh:mm:ss"));
+ isEmpty = false;
+ info = QChar(MAX_INDEX) + it.filePath() + m_separatorString
+ + QChar(CmdRemove);
+ m_mutex.lock();
+ m_files.append(info);
+ m_hotFiles++;
+ m_hotBytes += it.fileInfo().size();
+ m_totalFiles++;
+ m_mutex.unlock();
+ }
+ }
+ if (isEmpty){
+ if (m_verboseLevel >= VerboseChatty)
+ m_mainWindow->addToFileList("x " + directory);
+ info = QChar(MAX_INDEX) + directory + m_separatorString
+ + QChar(CmdRemoveDir);
+ m_mutex.lock();
+ m_files.append(info);
+ m_matchedFiles++;
+ m_mutex.unlock();
+ }
+ return isEmpty;
+}
+
/**
* Search the files to clean.
*
QString fullSrc = source + it.fileName();
QFileInfo src(fullSrc);
if (! src.exists()){
+ if (m_verboseLevel >= VerboseChatty)
+ m_mainWindow->addToFileList("? " + fullSrc);
const QFileInfo trg = it.fileInfo();
QDateTime trgTime = trg.lastModified();
if (trgTime < m_maxAge){
if (rename(I18N::s2b(target).constData(), I18N::s2b(shadow).constData()) != 0){
error(QObject::tr("cannot move to shadow directory (%1): %2 -> %3")
.arg(errno).arg(target).arg(shadow));
- } else {
- removeOlder(shadow, m_maxAge);
}
}
}
externalAppend(ReGuiQueueItem::ListEnd, ui->listWidgetFile, info);
}
+/**
+ * Returns the error count.
+ * @return the error count
+ */
+int MainWindow::errors() const
+{
+ return m_errors;
+}
+
/**
* Appends a string to the current line in the filelist.
*
externalAppend(ReGuiQueueItem::ListAppendToCurrent, ui->listWidgetFile, info);
}
-/**
- * Issues an error message.
- *
- * @param message the message to issue
- * @return <code>false</code>
- */
-bool MainWindow::error(const QString& message){
- ui->listWidgetError->addItem(message);
- ui->listWidgetError->setCurrentRow(ui->listWidgetError->count() - 1);
- m_errors++;
- return false;
-}
-
-/**
- * Returns the count of errors since the last start of the backup.
- *
- * @return the current count of errors
- */
-int MainWindow::errors() const
-{
- return m_errors;
-}
-
/**
* Find the target identification.
*
ui->listWidgetLog->addItem(item.m_value);
break;
case ReGuiQueueItem::ReadyMessage:
- log(item.m_value);
+ say(LOG_INFO, item.m_value);
startStop(false);
break;
case ReGuiQueueItem::LogMessage:
- log(item.m_value);
+ say(LOG_INFO, item.m_value);
break;
case ReGuiQueueItem::LogError:
- error(item.m_value);
+ say(LOG_ERROR, item.m_value);
break;
case ReGuiQueueItem::StatusLine:
setStatusMessage(LOG_INFO, item.m_value);
break;
default:
- error("unknown item type: " + QString::number(item.m_type)
+ say(LOG_ERROR, "unknown item type: " + QString::number(item.m_type)
+ " " + item.m_value);
break;
}
return rc;
}
-/**
- * @brief Logs a message
- *
- * @param message the message to log
- * @return <code>true</code>
- */
-bool MainWindow::log(const QString& message){
- ui->listWidgetLog->addItem(message);
- ui->listWidgetLog->setCurrentRow(ui->listWidgetLog->count() - 1);
- return true;
-}
-
/**
* Shows the "about" window.
*/
* @return <code>false</code>level is error or warning
*/
bool MainWindow::say(ReLoggerLevel level, const QString& message){
- if (level == LOG_ERROR || level == LOG_WARNING)
- error(message);
- else
- log(message);
+ switch(level){
+ case LOG_ERROR:
+ case LOG_WARNING:
+ ui->listWidgetError->addItem(message);
+ ui->listWidgetError->setCurrentRow(ui->listWidgetError->count() - 1);
+ setStatusMessage(LOG_ERROR, message);
+ m_errors++;
+ break;
+ default:
+ case LOG_INFO:
+ ui->listWidgetLog->addItem(message);
+ ui->listWidgetLog->setCurrentRow(ui->listWidgetLog->count() - 1);
+ break;
+ }
return level >= LOG_INFO;
}
ui->pushButtonStop->setEnabled(isStart);
ui->pushButtonChecksum->setEnabled(! isStart);
ui->actionChecksums->setEnabled(! isStart);
+ if (isStart)
+ BackupEngine::m_verboseLevel = (ReVerbose_t) ui->comboBoxVerbose->currentIndex();
}