Commit ebc9040a authored by Karel Slaný's avatar Karel Slaný
Browse files

Attempting to revert to original files when database relocation fails.

parent ec8f737d
......@@ -268,8 +268,7 @@ Component {
var newLocation = settings.changeDbPath(dbPathText.text.toString(), false)
if (newLocation != "") {
if (newLocation != dbPathText.text) {
var allDbsSizeInBytes = messages.getAllDbsSizeInBytes();
if (messages.moveOrCreateNewDbsToNewLocation(newLocation, allDbsSizeInBytes)) {
if (messages.moveOrCreateNewDbsToNewLocation(newLocation)) {
dbPathText.text = newLocation;
dbResetPathButton.visible = true
}
......@@ -284,8 +283,7 @@ Component {
var newLocation = settings.changeDbPath(dbPathText.text.toString(), true)
if (newLocation != "") {
if (newLocation != dbPathText.text) {
var allDbsSizeInBytes = messages.getAllDbsSizeInBytes();
if (messages.moveOrCreateNewDbsToNewLocation(newLocation, allDbsSizeInBytes)) {
if (messages.moveOrCreateNewDbsToNewLocation(newLocation)) {
dbPathText.text = newLocation;
dbResetPathButton.visible = false
}
......
......@@ -22,7 +22,9 @@
*/
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <QPair>
#include <QPushButton>
#include <QStorageInfo>
......@@ -193,188 +195,55 @@ void Messages::deleteMessageFromDbs(const QString &userName, qint64 msgId)
}
}
/* ========================================================================= */
/*
* Slot: Move or create new databases to new location.
*/
bool Messages::moveOrCreateNewDbsToNewLocation(const QString &newLocation,
int currentDbsSizeInBytes)
/* ========================================================================= */
bool Messages::moveOrCreateNewDbsToNewLocation(const QString &newLocation)
{
qDebug("%s()", __func__);
QString action = "";
bool success = true;
int currentDbSize = currentDbsSizeInBytes;
int allDbSize = 0;
/*
* select action what do you want to do
* with the currently used databases
*/
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Change database location"));
msgBox.setIcon(QMessageBox::Question);
msgBox.setText(tr(
"What do you want to do with the currently used databases?"));
msgBox.setInformativeText(tr(
"You can move current databases to a new location or you can "
"delete it and create new empty databases."));
QAbstractButton *moveButton = msgBox.addButton(tr("Move"),
QMessageBox::ActionRole);
QAbstractButton *newButton = msgBox.addButton(tr("Create new"),
QMessageBox::ActionRole);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
msgBox.exec();
if (msgBox.clickedButton() == moveButton) {
action = "move";
} else if (msgBox.clickedButton() == newButton) {
action = "new";
currentDbSize = INITIAL_DB_SIZE_BYTES;
} else {
/* Select action what to do with the currently used databases. */
enum ReloactionAction action = askAction();
switch (action) {
case RA_NONE:
/* Do nothing and exit. */
return false;
break;
case RA_RELOCATE:
allDbSize = getAllDbSize();
break;
case RA_CREATE_NEW:
allDbSize = estimateAllDbSize();
break;
default:
/* Unsupported action. */
Q_ASSERT(0);
return false;
break;
}
/* check if new location has required size for database storing */
QStorageInfo si(newLocation);
if (si.bytesAvailable() < currentDbSize) {
QMessageBox msgBox;
msgBox.setWindowTitle(tr("New location error"));
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setText(tr("It is not possible to store databases in "
"the new location because there is enough disk space."));
msgBox.setInformativeText(tr("Databases size is %1 "
"MB.").arg(currentDbsSizeInBytes/1000000));
msgBox.exec();
if (allDbSize <= 0) {
/* Expecting a positive value. */
return false;
}
QStringList userNameMsgDone; /* username where message db location change was success */
QStringList userNameFileDone; /* username where files db location change was success */
userNameMsgDone.clear();
userNameFileDone.clear();
/* For all accounts do */
QStringList userNameList = AccountListModel::globAccounts.keys();
foreach (const QString &userName, userNameList) {
/* if account has data in memmory do nothing */
AcntData &acntData(AccountListModel::globAccounts[userName]);
if (!acntData.storeToDisk()) {
continue;
}
MessageDb *msgDb = NULL;
FileDb *fDb = NULL;
if (action == "new") {
msgDb = globMessageDbsPtr->accessMessageDb(
globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (msgDb == NULL) {
qDebug() << "ERROR: Message database "
"cannot open!" << userName;
success = false;
break;
}
fDb = globFileDbsPtr->accessFileDb(
globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (fDb == NULL) {
qDebug() << "ERROR: File database "
"cannot open!" << userName;
success = false;
break;
}
if (msgDb->createDb(newLocation)) {
success = false;
break;
}
userNameMsgDone.append(userName);
if (fDb->createDb(newLocation)) {
success = false;
break;
}
userNameFileDone.append(userName);
} else if (action == "move") {
msgDb = globMessageDbsPtr->accessMessageDb(
globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (msgDb == NULL) {
qDebug() << "ERROR: Message database "
"cannot open!" << userName;
success = false;
break;
}
fDb = globFileDbsPtr->accessFileDb(
globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (fDb == NULL) {
qDebug() << "ERROR: File database "
"cannot open!" << userName;
success = false;
break;
}
if (msgDb->moveDb(newLocation)) {
success = false;
break;
}
userNameMsgDone.append(userName);
if (fDb->moveDb(newLocation)) {
success = false;
break;
}
userNameFileDone.append(userName);
} else {
/* Check whether new location has required size for database storing. */
{
QStorageInfo si(newLocation);
if (si.bytesAvailable() < allDbSize) {
QMessageBox msgBox;
msgBox.setWindowTitle(tr("New location error"));
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setText(tr("It is not possible to store databases in the new location because there is enough space."));
msgBox.setInformativeText(tr("Databases size is %1 MB.")
.arg(allDbSize / (1024 * 1024)));
msgBox.exec();
return false;
}
}
/* all databases have creaated/moved successly */
if (success) {
if (action == "new") {
/*
* TODO - here delete all databases from old location
* Use userNameMsgDone.list and userNameFileDone.list
*/
}
/* save new location to settings */
globSet.dbsLocation = newLocation;
saveAllSettings();
} else {
/* an problem has occurred */
if (action == "new") {
/*
* TODO - open back old databases in the old locationo
* and delete new databases.
* Use userNameMsgDone.list and userNameFileDone.list
*/
}
if (action == "move") {
/*
* TODO - move back databases form new loaction
* to old location
* Use userNameMsgDone.list and userNameFileDone.list
*/
}
}
return success;
return relocateDatabases(newLocation, action);
}
......@@ -426,34 +295,193 @@ void Messages::deleteExpiredMessagesFromDbs(int days)
}
/* ========================================================================= */
/*
* Slot: Return size of all databases in bytes.
*/
int Messages::getAllDbsSizeInBytes(void)
/* ========================================================================= */
enum Messages::ReloactionAction Messages::askAction(void)
{
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Change database location"));
msgBox.setIcon(QMessageBox::Question);
msgBox.setText(tr(
"What do you want to do with the currently used database files?"));
msgBox.setInformativeText(tr(
"You can move current database to a new location or you can delete them and create new empty databases."));
QAbstractButton *moveButton = msgBox.addButton(tr("Move"),
QMessageBox::ActionRole);
QAbstractButton *newButton = msgBox.addButton(tr("Create new"),
QMessageBox::ActionRole);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
msgBox.exec();
if (msgBox.clickedButton() == moveButton) {
return RA_RELOCATE;
} else if (msgBox.clickedButton() == newButton) {
return RA_CREATE_NEW;
} else {
return RA_NONE;
}
}
int Messages::getAllDbSize(void)
{
int size = 0;
QStringList userNameList = AccountListModel::globAccounts.keys();
QStringList userNameList(AccountListModel::globAccounts.keys());
foreach (const QString &userName, userNameList) {
MessageDb *msgDb = NULL;
msgDb = globMessageDbsPtr->accessMessageDb(globSet.dbsLocation, userName);
MessageDb *msgDb = globMessageDbsPtr->accessMessageDb(
globSet.dbsLocation, userName);
if (msgDb == NULL) {
qDebug() << "ERROR: Message database cannot open!" << userName;
return size;
qDebug("ERROR: Cannot open message database for user name '%s'.", userName.toUtf8().constData());
return -1;
}
size += msgDb->getDbSizeInBytes();
FileDb *fDb = NULL;
fDb = globFileDbsPtr->accessFileDb(globSet.dbsLocation, userName);
FileDb *fDb = globFileDbsPtr->accessFileDb(globSet.dbsLocation,
userName);
if (fDb == NULL) {
qDebug() << "ERROR: File database cannot open!" << userName;
return size;
qDebug("ERROR: Cannot open file database for user name '%s'.", userName.toUtf8().constData());
return -1;
}
size += fDb->getDbSizeInBytes();
}
return size;
}
int Messages::estimateAllDbSize(void)
{
return
2 * AccountListModel::globAccounts.size() * INITIAL_DB_SIZE_BYTES;
}
bool Messages::relocateDatabases(const QString &newLocation,
enum ReloactionAction action)
{
if ((action != RA_RELOCATE) && (action != RA_CREATE_NEW)) {
return false;
}
/* List of message databases and old locations. */
typedef QPair<MessageDb *, QString> MsgDbListEntry;
QList< MsgDbListEntry > relocatedMsgDbs;
typedef QPair<FileDb *, QString> FileDbListEntry;
QList< FileDbListEntry > relocatedFileDbs;
bool relocationSucceeded = true;
QStringList userNameList(AccountListModel::globAccounts.keys());
foreach (const QString &userName, userNameList) {
/* Ignore accounts with data stored in memory. */
if (!AccountListModel::globAccounts[userName].storeToDisk()) {
continue;
}
MessageDb *mDb = globMessageDbsPtr->accessMessageDb(
globSet.dbsLocation, userName);
relocationSucceeded = (mDb != NULL);
if (!relocationSucceeded) {
qWarning("Cannot access message database for user name '%s'.",
userName.toUtf8().constData());
break; /* Break the for cycle. */
}
FileDb *fDb = globFileDbsPtr->accessFileDb(
globSet.dbsLocation, userName);
relocationSucceeded = (fDb != NULL);
if (!relocationSucceeded) {
qWarning("Cannot access file database for user name '%s'.",
userName.toUtf8().constData());
break; /* Break the for cycle. */
}
QString oldLocation;
/* Message database file. */
oldLocation = mDb->fileName();
switch (action) {
case RA_RELOCATE:
relocationSucceeded = mDb->copyDb(newLocation);
break;
case RA_CREATE_NEW:
relocationSucceeded = mDb->createDb(newLocation);
break;
default:
Q_ASSERT(0);
relocationSucceeded = false;
break;
}
if (relocationSucceeded) {
/*
* Remember original file name as the file still
* exists.
*/
relocatedMsgDbs.append(
MsgDbListEntry(mDb, oldLocation));
} else {
break; /* Break the for cycle. */
}
/* File database file. */
oldLocation = fDb->fileName();
switch (action) {
case RA_RELOCATE:
relocationSucceeded = fDb->copyDb(newLocation);
break;
case RA_CREATE_NEW:
relocationSucceeded = fDb->createDb(newLocation);
break;
default:
Q_ASSERT(0);
relocationSucceeded = false;
break;
}
if (relocationSucceeded) {
/*
* Remember original file name as the file still
* exists.
*/
relocatedFileDbs.append(
FileDbListEntry(fDb, oldLocation));
} else {
break; /* Break the for cycle. */
}
}
if (relocationSucceeded) {
/* Delete all original files. */
foreach (const MsgDbListEntry &entry, relocatedMsgDbs) {
QFile::remove(entry.second);
}
foreach (const FileDbListEntry &entry, relocatedFileDbs) {
QFile::remove(entry.second);
}
} else {
/*
* Revert all databases to original locations and delete the
* new locations.
*/
QString newLocation;
foreach (const MsgDbListEntry &entry, relocatedMsgDbs) {
newLocation = entry.first->fileName();
if (entry.first->openDb(entry.second, true)) {
QFile::remove(newLocation);
} else {
qCritical(
"Cannot revert to original message database file '%s'.",
entry.second.toUtf8().constData());
/* TODO -- Critical. Cannot revert. */
}
}
foreach (const FileDbListEntry &entry, relocatedFileDbs) {
newLocation = entry.first->fileName();
if (entry.first->openDb(entry.second, true)) {
QFile::remove(newLocation);
} else {
qCritical(
"Cannot revert to original file database file '%s'.",
entry.second.toUtf8().constData());
/* TODO -- Critical. Cannot revert. */
}
}
}
return relocationSucceeded;
}
......@@ -76,12 +76,11 @@ public:
/*!
* @brief Move or create new databases to new location.
*
* @param[in] newLocation - New databases location.
* @param[in] currentDbsSizeInBytes - Total size of all databases.
* @param[in] newLocation New databases location (folder).
* @return True on success, false of failure.
*/
Q_INVOKABLE
bool moveOrCreateNewDbsToNewLocation(const QString &newLocation,
int currentDbsSizeInBytes);
bool moveOrCreateNewDbsToNewLocation(const QString &newLocation);
/*!
* @brief Delete messages from all message databases together with files
......@@ -91,12 +90,6 @@ public:
*/
void deleteExpiredMessagesFromDbs(int days);
/*!
* @brief Return size of all databases in bytes.
*
*/
Q_INVOKABLE int getAllDbsSizeInBytes(void);
class Message {
public:
Message(void)
......@@ -168,6 +161,52 @@ signals:
* @brief Send message detait html string to QML.
*/
void messageDetailChanged(QString txt);
private:
/*!
* @brief Specifies whether the files should be moved or created from
* scratch.
*/
enum ReloactionAction {
RA_NONE, /*!< Don't do anything. */
RA_RELOCATE, /*!< relocate existing ones. */
RA_CREATE_NEW /*!< Create new empty databases. .*/
};
/*!
* @brief Generates a dialogue and asks the user what he wants to do.
*
* @return The chosen action.
*/
static
enum ReloactionAction askAction(void);
/*!
* @brief Return size of all databases in bytes.
*
* @return Total size of all database files or -1 on error.
*/
static
int getAllDbSize(void);
/*!
* @brief Estimate new database size in new location.
*
* @return Estimated required size.
*/
static
int estimateAllDbSize(void);
/*!
* @brief Relocates account database files.
*
* @param[in] newLocation New location (folder).
* @param[in] action Desired action to preform.
* @return True on success, false of failure.
*/
static
bool relocateDatabases(const QString &newLocation,
enum ReloactionAction action);
};
#endif // MESSAGES_H
......@@ -188,7 +188,7 @@ bool FileDb::copyDb(const QString &newLocDir)
QFile::remove(newFileName);
/* Copy database file. */
//copy_ret = QFile::copy(oldFileName, newFileName);
copy_ret = QFile::copy(oldFileName, newFileName);
/* Open database. */
open_ret = openDb(newFileName, true);
......@@ -243,7 +243,6 @@ bool FileDb::moveDb(const QString &newLocDir)
}
QList<class SQLiteTbl *> FileDb::listOfTables(void)
{
static QList<class SQLiteTbl *> tables;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment