Commit 5255dfff authored by Lisa's avatar Lisa Committed by Lukas Appelhans
Browse files

Implement error handling

parent a98c4893
......@@ -103,13 +103,11 @@ SQLiteResource PolKitSQLiteConnection::query(const QString &q)
void PolKitSQLiteConnection::query(const QString &q, const QVariantMap &bindings)
{
qDebug() << "Multiply query" << q;
if ((d->access.testFlag(Akabei::Helpers::ReadWritePermission)) || ((d->access.testFlag(Akabei::Helpers::ReadPermission)) && q.startsWith("SELECT"))) {
d->connection->query(q, bindings);
d->lastQueryDBus = false;
return;
}
if (Akabei::Helpers::checkAuthorizationSync("org.chakraproject.akabeicorehelper.sqlite.query")) {
QDBusInterface iface("org.chakraproject.akabeicorehelper", "/sqlite", "org.chakraproject.akabeicorehelper.sqlite", QDBusConnection::systemBus());
SETUP_DBUS_DATABASE
......@@ -137,14 +135,12 @@ qint64 PolKitSQLiteConnection::getLastRowId()
void PolKitSQLiteConnection::bind(QString const& key, int value)
{
qDebug() << "TRY BIND";
if (!d->access.testFlag(Akabei::Helpers::NoPermission))
d->connection->bind(key, value);
if (d->access.testFlag(Akabei::Helpers::ReadWritePermission))
return;
qDebug() << "call bind";
//We bind to both databases, as we have no information yet if we have a read or write query
QDBusInterface iface("org.chakraproject.akabeicorehelper", "/sqlite", "org.chakraproject.akabeicorehelper.sqlite", QDBusConnection::systemBus());
......
......@@ -179,11 +179,9 @@ SQLiteResource SQLiteConnection::query(const QString &q)
void SQLiteConnection::query(const QString &q, const QVariantMap &bindings)
{
if (bindings.isEmpty()) {
qDebug() << "Empty";
rowQuery(q);
return;
}
qDebug() << bindings.keys() << bindings.values().first().toList().count();
int count = bindings.constBegin().value().toList().count();
for (int i = 0; i != count; i++) {
QVariantMap::const_iterator it = bindings.constBegin();
......
......@@ -138,32 +138,43 @@ QHash<QString, Database*> BackendPrivate::performInitialization()
// Check for the existence of all the needed directories
QDir dbDir(Config::instance()->databasePath());
if (!dbDir.exists()) {
Error initError;
initError.setType(Error::BackendInitializationError);
initError.setDescription(QObject::tr("Database dir %1 does not exist").arg(Config::instance()->databasePath()));
ErrorQueue::instance()->appendError(initError);
// Fail
return QHash<QString, Database*>();
}
QDir cacheDir(Config::instance()->cachePath());
if (!cacheDir.exists()) {
Error initError;
initError.setType(Error::BackendInitializationError);
initError.setDescription(QObject::tr("Cache dir %1 does not exist").arg(Config::instance()->cachePath()));
ErrorQueue::instance()->appendError(initError);
// Fail
return QHash<QString, Database*>();
}
QDir rootDir(Config::instance()->root());
if (!rootDir.exists()) {
Error initError;
initError.setType(Error::BackendInitializationError);
initError.setDescription(QObject::tr("Root dir %1 does not exist").arg(Config::instance()->root()));
ErrorQueue::instance()->appendError(initError);
// Fail
return QHash<QString, Database*>();
}
Database* localDb = new Database( dbDir.absoluteFilePath("local.db") );
if (!localDb->isValid()) {
qDebug() << "Local db";
Error initError;
initError.setType(Error::BackendInitializationError);
initError.setDescription(QObject::tr("Error while loading the local database from %1: %2").arg(dbDir.path(), localDb->error().description()));
ErrorQueue::instance()->appendError(initError);
return QHash<QString, Database*>();
}
......@@ -225,8 +236,10 @@ void Backend::setStatus(Backend::Status s, QObject * cO, const char * cS)
QDBusMessage mes = iface.call("getLock", QCoreApplication::applicationPid());
} else {
qDebug() << "Authorization not granted" << PolkitQt1::Authority::instance()->errorDetails();
Akabei::ErrorQueue::instance()->appendError(Error(Error::PermissionError, tr("An authorization error occurred: %1").arg(PolkitQt1::Authority::instance()->errorDetails())));
setStatus(Backend::StatusBroken);
}
return;
} else {
qDebug() << "WE HERE";
......@@ -234,8 +247,7 @@ void Backend::setStatus(Backend::Status s, QObject * cO, const char * cS)
d->lockFileHandle = new QFile(Akabei::Config::instance()->rootDir().absoluteFilePath("var/local/akabei.lck"));
if (!d->lockFileHandle->open(QFile::ReadWrite)) {
d->initError.setType(Error::BackendInitializationError);
d->initError.setDescription("Could not open lock file for writing.");
ErrorQueue::instance()->appendError( Error(Error::PermissionError, "Could not open lock file for writing") );
setStatus(Backend::StatusBroken);
return;
}
......@@ -274,6 +286,7 @@ void Backend::setStatus(Backend::Status s, QObject * cO, const char * cS)
} else {
qDebug() << "Authorization not granted" << PolkitQt1::Authority::instance()->errorDetails();
setStatus(Backend::StatusBroken);
Akabei::ErrorQueue::instance()->appendError(Error(Error::PermissionError, PolkitQt1::Authority::instance()->errorDetails()));
}
return;
}
......@@ -286,6 +299,7 @@ void Backend::setStatus(Backend::Status s, QObject * cO, const char * cS)
lockinfo.l_len = 0;
if (fcntl(d->lockFileHandle->handle(), F_SETLK, &lockinfo) == -1) {
Akabei::ErrorQueue::instance()->appendError(Error(Error::FilesystemError, tr("Could not remove lock file properly!")));
akabeiDebug() << "lock could not get released?!";
}
}
......@@ -535,13 +549,6 @@ void Backend::deInit()
setStatus(Backend::StatusBare); /* remove the lock */
}
Error Backend::initError()
{
Q_D(Backend);
QReadLocker locker(d->mutex);
return d->initError;
}
QList< Database* > Backend::databases()
{
Q_D(Backend);
......
......@@ -201,11 +201,6 @@ class AKABEICORESHARED_EXPORT Backend : public QObject
*/
Hook *loadHookFromFile(const QString &path, QList<Package*> pkgs);
/**
* @returns what went wrong during initialization
*/
Error initError();
/**
* This function contains all the operations that must be performed before exiting, either normally or
* as a result of some error.
......
......@@ -87,8 +87,6 @@ class BackendPrivate : public QObject
OperationRunner *runner;
Error initError;
QObject * callbackObject;
const char * callbackSlot;
......
......@@ -27,9 +27,18 @@ DatabasePrivate::DatabasePrivate(Database* db, QString const& pathToDatabase)
, valid(true)
, mutex(new QMutex(QMutex::Recursive))
{
if (!QFile::exists(pathToDatabase)) {
qDebug() << "Caught this";
error.setType(Error::DatabaseError);
error.setDescription(QObject::tr("Cannot find database file on disk: %1").arg(pathToDatabase));
valid = false;
return;
}
try {
qDebug() << "Connect to db";
dbConnection.connectToDB(pathToDb, false);
} catch (SQLiteException &ex) {
qDebug() << "Caught an error?!";
valid = false;
error.setType( Error::DatabaseError );
error.setDescription( ex.what() );
......
......@@ -9,10 +9,146 @@
*/
#include <akabeierror.h>
#include <QQueue>
#include <QMap>
#include <QMetaType>
#include <QDebug>
#include <QReadWriteLock>
namespace Akabei
{
class ErrorHandler
{
public:
ErrorHandler(QObject* receiver, const char* handler)
: m_receiver(receiver)
, m_slot(handler)
{}
QObject* receiver() const
{
return m_receiver;
}
const char* slot() const
{
return m_slot;
}
private:
QObject* m_receiver;
const char* m_slot;
};
class ErrorQueue::Private
{
public:
Private() : mutex(new QReadWriteLock(QReadWriteLock::Recursive))
{}
~Private()
{
}
QQueue<Error> errorQueue;
QMultiMap< Error::Type, ErrorHandler* > errorSlots;
QReadWriteLock * mutex;
};
class ErrorQueueHelper
{
public:
ErrorQueueHelper()
: q( 0 )
{}
virtual ~ErrorQueueHelper()
{
delete q;
}
ErrorQueue* q;
};
Q_GLOBAL_STATIC(ErrorQueueHelper, s_globalErrorQueue)
ErrorQueue::ErrorQueue()
: d( new Private )
{
Q_ASSERT(!s_globalErrorQueue()->q);
qRegisterMetaType<Error::Type>("Error::Type");
s_globalErrorQueue()->q = this;
}
ErrorQueue::~ErrorQueue()
{
delete d;
}
ErrorQueue* ErrorQueue::instance()
{
if (!s_globalErrorQueue()->q) {
new ErrorQueue;
}
return s_globalErrorQueue()->q;
}
void ErrorQueue::registerForErrorType(Error::Type t, QObject* receiver, const char* slot)
{
QWriteLocker locker(d->mutex);
d->errorSlots.insertMulti(t, new ErrorHandler(receiver, slot));
}
void ErrorQueue::registerForAllErrors(QObject* receiver, const char* slot)
{
QWriteLocker locker(d->mutex);
ErrorHandler* h = new ErrorHandler(receiver, slot);
for (int t = Error::UnknownError; t <= Error::FilesystemError; t++) {
d->errorSlots.insertMulti((Error::Type)t, h);
}
d->errorSlots.insertMulti(Error::GenericError, h);
d->errorSlots.insertMulti(Error::AkabeiInternalError, h);
}
void ErrorQueue::appendError(const Error& error)
{
QWriteLocker locker(d->mutex);
d->errorQueue.enqueue(error);
foreach (ErrorHandler* registeredHandler, d->errorSlots.values( error.type() )) {
QMetaObject::invokeMethod(registeredHandler->receiver(), registeredHandler->slot(), Qt::QueuedConnection);
}
}
void ErrorQueue::appendErrors(const Error::List& errors)
{
QWriteLocker locker(d->mutex);
foreach (const Error& error, errors) {
appendError(error);
}
}
bool ErrorQueue::isEmpty() const
{
QReadLocker locker(d->mutex);
return d->errorQueue.isEmpty();
}
Error ErrorQueue::takeError()
{
QReadLocker locker(d->mutex);
return d->errorQueue.dequeue();
}
Error::Type ErrorQueue::headType() const
{
QReadLocker locker(d->mutex);
return d->errorQueue.first().type();
}
/**
* @class Error::Private
* @brief Class for operation errors.
......@@ -110,4 +246,3 @@ Error::Type Error::type() const
}
}
\ No newline at end of file
......@@ -52,6 +52,8 @@ class Error
ChecksumError = 13,
OpenFileError = 14,
FullDiskError = 15,
PermissionError = 16,
FilesystemError = 17,
//
GenericError = 128,
AkabeiInternalError = 129
......@@ -124,6 +126,32 @@ class Error
QSharedDataPointer<Private> d;
};
class ErrorQueue
{
Q_DISABLE_COPY(ErrorQueue)
public:
virtual ~ErrorQueue();
static ErrorQueue* instance();
Error takeError();
Error::Type headType() const;
bool isEmpty() const;
void appendError(const Error &);
void appendErrors(const Error::List &);
void registerForErrorType(Error::Type, QObject *, const char *);
void registerForAllErrors(QObject *, const char *);
private:
ErrorQueue();
class Private;
Private* d;
};
}
#endif // AKABEI_AKABEIERROR_H
......@@ -373,9 +373,12 @@ Permissions permissionsOfPath(const QString &path)
return perm;
}
AuthorityLoop::AuthorityLoop(QObject* parent)
: QEventLoop(parent)
{}
: QEventLoop(parent), m_result(PolkitQt1::Authority::No)
{
}
AuthorityLoop::~AuthorityLoop() {}
PolkitQt1::Authority::Result AuthorityLoop::result()
......@@ -400,7 +403,7 @@ bool checkAuthorizationSync(const QString &action)
e.exec();
return e.result();//(auth == PolkitQt1::Authority::Yes);
return e.result() == PolkitQt1::Authority::Yes;//(auth == PolkitQt1::Authority::Yes);
}
///////
......@@ -547,7 +550,6 @@ int QueryPerformer::insertPackage(PolKitSQLiteConnection &dbConnection, Package*
dbConnection.query(sqlQuery);
int id = dbConnection.getLastRowId();
qDebug() << "INSERTED ID WAS" << id;
QueryHelper::packagePrivateFromPackage(p)->setDatabaseId(id);
foreach (Akabei::Group *group, p->groups()) {
......@@ -961,8 +963,6 @@ int QueryPerformer::updateFiles(PolKitSQLiteConnection &dbConnection, Package* f
try {
QSet<QString> oldFiles = from->retrieveFiles(Package::FilepathNoPrefix).toSet();
QSet<QString> newFiles = to->retrieveFiles(Package::FilepathNoPrefix).toSet();
qDebug() << oldFiles;
qDebug() << newFiles;
QSet<QString> remove = oldFiles;
remove.subtract(newFiles);
......
......@@ -49,7 +49,6 @@ public:
void runFunctor();
public slots:
virtual void newMessage(const QString &archive, const QString &message) = 0;
virtual void updateProgress(const QString &archive, int progress) = 0;
......@@ -71,7 +70,6 @@ public:
void run();
public slots:
void newMessage(const QString &archive, const QString &message);
void updateProgress(const QString &archive, int progress);
......@@ -91,7 +89,6 @@ public:
void run();
public slots:
void newMessage(const QString &archive, const QString &message);
void updateProgress(const QString &archive, int progress);
......
......@@ -14,6 +14,7 @@
#include <QDBusMessage>
#include <QDBusInterface>
#include <QVariantMap>
#include <qmetaobject.h>
#include <akabeiconfig.h>
#include <akabeihelpers.h>
#include <PolkitQt1/Authority>
......@@ -22,26 +23,34 @@
#include <unistd.h>
#include <sys/types.h>
//FIXME: Check if we should transfer all the qDebug() to Akabei::Errors?
class PolKitArchiveHandler::Private
{
public:
Private(const QString &file) : filename(file), readLocally(true), handler(0) {
Private(const QString &file) : filename(file), readLocally(true), handler(0), functor(0) {
readLocally = Akabei::Helpers::permissionsOfPath(file).testFlag(Akabei::Helpers::ReadPermission);//We check whether we have at least read access to the archive
handler = new ArchiveHandler(file);
iface = new QDBusInterface("org.chakraproject.akabeicorehelper", "/archive", "org.chakraproject.akabeicorehelper.archive", QDBusConnection::systemBus());
}
~Private() {
delete handler;
delete iface;
}
void __k__newMessage(const QString&, const QString&);
void __k__updateProgress(const QString&, int);
QString filename;
bool readLocally;
ArchiveHandler * handler;
Akabei::Error::List errors;
Akabei::PolKitEntryHandlerFunctor * functor;
QDBusInterface * iface;
};
//TODO: Just connect once to the dbusinterface, and just keep the connection in tact for the whole time
PolKitArchiveHandler::PolKitArchiveHandler(const QString &f, QObject * parent)
: QObject(parent),
d(new Private(f))
......@@ -72,6 +81,7 @@ bool PolKitArchiveHandler::write(const QString& filename, const QHash<QString, Q
if (Akabei::Helpers::checkAuthorizationSync("org.chakraproject.akabeicorehelper.archive.write")) {
qDebug() << "Authorization granted";
QDBusInterface iface("org.chakraproject.akabeicorehelper", "/archive", "org.chakraproject.akabeicorehelper.archive", QDBusConnection::systemBus());
iface.setProperty("filename", filename);
QVariantMap map;
......@@ -81,6 +91,7 @@ bool PolKitArchiveHandler::write(const QString& filename, const QHash<QString, Q
return !mes.arguments().isEmpty() && mes.arguments().first().toBool();
} else {
qDebug() << "Authorization not granted" << PolkitQt1::Authority::instance()->errorDetails();//TODO:Error handling
Akabei::ErrorQueue::instance()->appendError(Akabei::Error(Akabei::Error::PermissionError, PolkitQt1::Authority::instance()->errorDetails()));
}
return false;
}
......@@ -93,14 +104,14 @@ QStringList PolKitArchiveHandler::getEntries() const
if (Akabei::Helpers::checkAuthorizationSync("org.chakraproject.akabeicorehelper.archive.read")) {
qDebug() << "Authorization granted";
QDBusInterface iface("org.chakraproject.akabeicorehelper", "/archive", "org.chakraproject.akabeicorehelper.archive", QDBusConnection::systemBus());
iface.setProperty("filename", d->filename);
d->iface->setProperty("filename", d->filename);
QDBusMessage mes = iface.call("entries");
QDBusMessage mes = d->iface->call("entries");
if (!mes.arguments().isEmpty())
return mes.arguments().first().toStringList();
} else {
qDebug() << "Authorization not granted" << PolkitQt1::Authority::instance()->errorDetails();
Akabei::ErrorQueue::instance()->appendError(Akabei::Error(Akabei::Error::PermissionError, PolkitQt1::Authority::instance()->errorDetails()));
}
return QStringList();
}
......@@ -112,14 +123,15 @@ size_t PolKitArchiveHandler::getEntrySize(QString const& fileName) const
if (Akabei::Helpers::checkAuthorizationSync("org.chakraproject.akabeicorehelper.archive.read")) {
qDebug() << "Authorization granted";
QDBusInterface iface("org.chakraproject.akabeicorehelper", "/archive", "org.chakraproject.akabeicorehelper.archive", QDBusConnection::systemBus());
iface.setProperty("filename", d->filename);
d->iface->setProperty("filename", d->filename);
QDBusMessage mes = iface.call("entrySize", fileName);
QDBusMessage mes = d->iface->call("entrySize", fileName);
if (!mes.arguments().isEmpty())
return mes.arguments().first().toInt();
} else {
qDebug() << "Authorization not granted" << PolkitQt1::Authority::instance()->errorDetails();
Akabei::ErrorQueue::instance()->appendError(Akabei::Error(Akabei::Error::PermissionError, PolkitQt1::Authority::instance()->errorDetails()));
}
return -1;
}
......@@ -131,14 +143,15 @@ size_t PolKitArchiveHandler::totalEntrySize() const
if (Akabei::Helpers::checkAuthorizationSync("org.chakraproject.akabeicorehelper.archive.read")) {
qDebug() << "Authorization granted";
QDBusInterface iface("org.chakraproject.akabeicorehelper", "/archive", "org.chakraproject.akabeicorehelper.archive", QDBusConnection::systemBus());
iface.setProperty("filename", d->filename);
d->iface->setProperty("filename", d->filename);
QDBusMessage mes = iface.call("totalEntrySize");
QDBusMessage mes = d->iface->call("totalEntrySize");
if (!mes.arguments().isEmpty())
return mes.arguments().first().toInt();
} else {
qDebug() << "Authorization not granted" << PolkitQt1::Authority::instance()->errorDetails();
Akabei::ErrorQueue::instance()->appendError(Akabei::Error(Akabei::Error::PermissionError, PolkitQt1::Authority::instance()->errorDetails()));
}
return -1;
}
......@@ -150,14 +163,15 @@ QString PolKitArchiveHandler::readTextFile(const QString &file)
if (Akabei::Helpers::checkAuthorizationSync("org.chakraproject.akabeicorehelper.archive.read")) {
qDebug() << "Authorization granted";
QDBusInterface iface("org.chakraproject.akabeicorehelper", "/archive", "org.chakraproject.akabeicorehelper.archive", QDBusConnection::systemBus());
iface.setProperty("filename", d->filename);
d->iface->setProperty("filename", d->filename);
QDBusMessage mes = iface.call("readTextFile", file);
QDBusMessage mes = d->iface->call("readTextFile", file);
if (!mes.arguments().isEmpty())
return mes.arguments().first().toString();
} else {
qDebug() << "Authorization not granted" << PolkitQt1::Authority::instance()->errorDetails();
Akabei::ErrorQueue::instance()->appendError(Akabei::Error(Akabei::Error::PermissionError, PolkitQt1::Authority::instance()->errorDetails()));
}
return QString();
}
......@@ -169,12 +183,12 @@ void PolKitArchiveHandler::extract(const QString& source, const QString& destNam
if (Akabei::Helpers::checkAuthorizationSync("org.chakraproject.akabeicorehelper.archive.extract")) {
qDebug() << "Authorization granted";
QDBusInterface iface("org.chakraproject.akabeicorehelper", "/archive", "org.chakraproject.akabeicorehelper.archive", QDBusConnection::systemBus());
iface.setProperty("filename", d->filename);
d->iface->setProperty("filename", d->filename);
QDBusMessage mes = iface.call("extract", source, destName, overwrite);
QDBusMessage mes = d->iface->call("extract", source, destName, overwrite);
} else {
qDebug() << "Authorization not granted" << PolkitQt1::Authority::instance()->errorDetails();
Akabei::ErrorQueue::instance()->appendError(Akabei::Error(Akabei::Error::PermissionError, PolkitQt1::Authority::instance()->errorDetails()));
}
}
......@@ -185,12 +199,12 @@ void PolKitArchiveHandler::extract(const ArchiveEntry &entry, const QString& des
if (Akabei::Helpers::checkAuthorizationSync("org.chakraproject.akabeicorehelper.archive.extract")) {
qDebug() << "Authorization granted";
QDBusInterface iface("org.chakraproject.akabeicorehelper", "/archive", "org.chakraproject.akabeicorehelper.archive", QDBusConnection::systemBus());
iface.setProperty("filename", d->filename);
d->iface->setProperty("filename", d->filename);
QDBusMessage mes = iface.call("extract", entry.getFileName(), destName, overwrite);
QDBusMessage mes = d->iface->call("extract", entry.getFileName(), destName, overwrite);
} else {
qDebug() << "Authorization not granted" << PolkitQt1::Authority::instance()->errorDetails();
Akabei::ErrorQueue::instance()->appendError(Akabei::Error(Akabei::Error::PermissionError, PolkitQt1::Authority::instance()->errorDetails()));
}
}