Commit ac57e0d1 authored by Lisa's avatar Lisa
Browse files

Added storage/detection of important error messages

parent 22a2fab6
......@@ -35,21 +35,11 @@ void regExp(sqlite3_context* context,int,sqlite3_value** value)
class SQLiteConnection::Private
{
public:
Private(const QString &dbName, bool readonly)
: statement(0)
{
int flags(readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE);
std::string tmp = dbName.toStdString();
const char* name( tmp.c_str() );
int retvalue(sqlite3_open_v2(name, &dbHandle, flags, NULL));
checkForErrors(retvalue);
sqlite3_create_function_v2(dbHandle, "REGEXP_REPLACE", 2, SQLITE_ANY, NULL, regExpReplace, NULL, NULL, NULL);
sqlite3_create_function_v2(dbHandle, "REGEXP", 2, SQLITE_ANY, NULL, regExp, NULL, NULL, NULL);
}
public:
Private()
: isConnected(false)
, statement(0)
{}
~Private()
{
......@@ -63,8 +53,11 @@ public:
void checkForErrors(int);
Row getRowFromStatement(sqlite3_stmt*);
bool isConnected;
sqlite3 *dbHandle;
sqlite3_stmt *statement;
QList<Row> rows;
QMap<QString, int> intBindings;
QMap<QString, QString> stringBindings;
......@@ -76,7 +69,13 @@ public:
* Establish a connection with dbName
*/
SQLiteConnection::SQLiteConnection(QString const& dbName, bool readonly)
: d(new Private(dbName, readonly))
: d(new Private())
{
connectToDB(dbName, readonly);
}
SQLiteConnection::SQLiteConnection()
: d(new Private())
{}
/*
......@@ -88,6 +87,25 @@ SQLiteConnection::~SQLiteConnection()
delete d;
}
void SQLiteConnection::connectToDB(QString const& dbName, bool readonly)
{
if (d->isConnected) {
throw SQLiteException("Object already connected to database");
}
int flags(readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE);
std::string tmp = dbName.toStdString();
const char* name( tmp.c_str() );
int retvalue(sqlite3_open_v2(name, &(d->dbHandle), flags, NULL));
d->checkForErrors(retvalue);
sqlite3_create_function_v2(d->dbHandle, "REGEXP_REPLACE", 2, SQLITE_ANY, NULL, regExpReplace, NULL, NULL, NULL);
sqlite3_create_function_v2(d->dbHandle, "REGEXP", 2, SQLITE_ANY, NULL, regExp, NULL, NULL, NULL);
d->isConnected = true;
}
/*
* Executes a query
*/
......@@ -95,6 +113,10 @@ SQLiteResource SQLiteConnection::query(const QString &q)
{
QMutexLocker locker(&d->mutex);
d->rows.clear();
if (!d->isConnected) {
throw SQLiteException("Object is not connected to database");
}
/*
* Prepares the statement. _v2 assures us a better error checking
......@@ -191,6 +213,11 @@ SQLiteConnection::Row SQLiteConnection::Private::getRowFromStatement(sqlite3_stm
qint64 SQLiteConnection::getLastRowId()
{
QMutexLocker locker(&d->mutex);
if (!d->isConnected) {
throw SQLiteException("Object is not connected to database");
}
sqlite3_int64 id = sqlite3_last_insert_rowid(d->dbHandle);
return static_cast<qint64>(id);
}
......@@ -201,6 +228,11 @@ qint64 SQLiteConnection::getLastRowId()
void SQLiteConnection::bind(const QString& name, int value)
{
QMutexLocker locker(&d->mutex);
if (!d->isConnected) {
throw SQLiteException("Object is not connected to database");
}
if (d->intBindings.contains(name) || d->stringBindings.contains(name)) {
return;
}
......@@ -211,6 +243,11 @@ void SQLiteConnection::bind(const QString& name, int value)
void SQLiteConnection::bind(const QString& name, QString value)
{
QMutexLocker locker(&d->mutex);
if (!d->isConnected) {
throw SQLiteException("Object is not connected to database");
}
if (d->intBindings.contains(name) || d->stringBindings.contains(name)) {
return;
}
......@@ -221,6 +258,11 @@ void SQLiteConnection::bind(const QString& name, QString value)
void SQLiteConnection::bind(const QString& name, QByteArray value)
{
QMutexLocker locker(&d->mutex);
if (!d->isConnected) {
throw SQLiteException("Object is not connected to database");
}
if (d->intBindings.contains(name) || d->stringBindings.contains(name)) {
return;
}
......
......@@ -86,7 +86,21 @@ public:
* @param readonly true if read-only access, false for read-write
*/
SQLiteConnection(QString const&, bool);
/**
* Constructs an object without establishing any connection
*/
SQLiteConnection();
~SQLiteConnection();
/**
* Establishes a new connection with a database
*
* @param name the database filename
* @param readonly true if read-only access, false for read-write
*/
void connectToDB(QString const&, bool);
/**
* Executes a query on the database
......
......@@ -29,6 +29,7 @@
#include <libarchive++/archivehandler.h>
#include <akabeihook.h>
#include <fcntl.h>
#include <klocalizedstring.h>
Q_DECLARE_METATYPE(QUuid)
Q_DECLARE_METATYPE(QList< Akabei::Package* >)
......@@ -81,7 +82,7 @@ QHash<QString, Database*> BackendPrivate::performInitialization()
QDir dbDir(Config::instance()->databasePath());
if (!dbDir.exists()) {
initError.setType(Error::BackendInitializationError);
initError.setDescription("Database dir " + Config::instance()->databasePath() + " does not exist");
initError.setDescription(QObject::tr("Database dir %1 does not exist").arg(Config::instance()->databasePath()));
// Fail
return QHash<QString, Database*>();
}
......@@ -89,7 +90,7 @@ QHash<QString, Database*> BackendPrivate::performInitialization()
QDir cacheDir(Config::instance()->cachePath());
if (!cacheDir.exists()) {
initError.setType(Error::BackendInitializationError);
initError.setDescription("Cache dir " + Config::instance()->cachePath() + " does not exist");
initError.setDescription(QObject::tr("Cache dir %1 does not exist").arg(Config::instance()->cachePath()));
// Fail
return QHash<QString, Database*>();
}
......@@ -97,17 +98,15 @@ QHash<QString, Database*> BackendPrivate::performInitialization()
QDir rootDir(Config::instance()->root());
if (!rootDir.exists()) {
initError.setType(Error::BackendInitializationError);
initError.setDescription("Root dir " + Config::instance()->root() + " does not exist");
initError.setDescription(QObject::tr("Root dir %1 does not exist").arg(Config::instance()->root()));
// Fail
return QHash<QString, Database*>();
}
Database* localDb = q->loadDatabaseFromFile(dbDir.absoluteFilePath("local.db"));
if (!localDb) {
// Fail
Database* localDb = new Database( dbDir.absoluteFilePath("local.db") );
if (!localDb->isValid()) {
initError.setType(Error::BackendInitializationError);
initError.setDescription("Error while loading the local database from " + dbDir.absolutePath() + ". Please check if you have the local"
" database in place.");
initError.setDescription(QObject::tr("Error while loading the local database from %1: %2").arg(dbDir.path(), localDb->error().description()));
return QHash<QString, Database*>();
}
......@@ -116,11 +115,12 @@ QHash<QString, Database*> BackendPrivate::performInitialization()
// Now process all the various databases
foreach (QString const& db, Config::instance()->databases()) {
Database* database = q->loadDatabaseFromFile(dbDir.absoluteFilePath(db + ".db"));
// Ok, add it to our rethash
if (database)
Database* database = new Database(dbDir.absoluteFilePath(db + ".db"));
if (database->isValid()) {
// Ok, add it to our rethash
rethash.insert(db, database);
}
}
// Return it straight
......@@ -129,15 +129,15 @@ QHash<QString, Database*> BackendPrivate::performInitialization()
void BackendPrivate::addDatabase(const QString &name)
{
Q_Q(Backend);
if (name == "local") {
return;
}
Database * database = q->loadDatabaseFromFile(Akabei::Config::instance()->databaseDir().absoluteFilePath(name + ".db"));
if (database)
Database* database = new Database(Akabei::Config::instance()->databaseDir().absoluteFilePath(name + ".db"));
if (database->isValid()) {
databases.append(database);
}
}
void BackendPrivate::setStatus(Backend::Status s)
......@@ -515,7 +515,7 @@ OperationRunner* Backend::operationRunner()
Package* Backend::loadPackageFromFile(const QString& path)
{
Q_D(Backend);
if (!QFile::exists(path)) {
return 0;
}
......@@ -588,7 +588,15 @@ Package* Backend::loadPackageFromFile(const QString& path)
} else if (key == "hook") {
retpackage->d_func()->hooks << value;
} else if (key == "backup") {
retpackage->d_func()->backup.insert(value, pkg.md5(value));
/*
* TODO: make the application know why the md5 function failed
*/
QString md5 = pkg.md5(value);
if (!md5.isEmpty()) {
retpackage->d_func()->backup.insert(value, md5);
}
} else if (key == "makepkgopt") {
// retpackage->d_func()->arch = value;
} else if (key == "screenshot") {
......@@ -777,23 +785,6 @@ Hook* Backend::loadHookFromFile(const QString& path, QList<Package*> pkgs)
return new Hook(name, in.readAll(), pkgs);
}
Database* Backend::loadDatabaseFromFile(const QString& path)
{
if (!QFile::exists(path)) {
qWarning() << "The databases file does not exist:" << path;
return 0;
}
Database* database = new Database(path);
if (!database->isValid()) {
qWarning() << "Invalid database:" << path;
delete database;
return 0;
}
return database;
}
}
#include "akabeibackend.moc"
......@@ -175,11 +175,6 @@ class AKABEICORESHARED_EXPORT Backend : public QObject
* @param path the path of the file containing the hook information
*/
Hook *loadHookFromFile(const QString &path, QList<Package*> pkgs);
/**
* Loads a database from a ".db"-file.
* @param path the path of the database-file
*/
Database *loadDatabaseFromFile(const QString &path);
/**
* @returns what went wrong during initialization
......
......@@ -21,15 +21,18 @@
namespace Akabei {
//TODO: Only open local database readwrite
DatabasePrivate::DatabasePrivate(Database* db, QString const& pathToDatabase)
try : q_ptr(db)
: q_ptr(db)
, pathToDb(pathToDatabase)
, dbConnection(pathToDb, false)
, valid(true)
, mutex(new QMutex())
{
} catch (SQLiteException const& e) {
akabeiDebug() << e.what();
valid = false;
try {
dbConnection.connectToDB(pathToDb, false);
} catch (SQLiteException &ex) {
valid = false;
error.setType( Error::DatabaseError );
error.setDescription( ex.what() );
}
}
DatabasePrivate::~DatabasePrivate()
......@@ -296,7 +299,14 @@ Database::Database(QString const& pathToDatabase)
: d_ptr(new DatabasePrivate(this, pathToDatabase))
{
Q_D(Database);
d->init();
/*
* If the connection to the database wasn't established correctly, there's no point
* in going on with the initialization (althought it's a safe NOP if you do it)
*/
if (isValid()) {
d->init();
}
}
Database::~Database()
......@@ -320,6 +330,12 @@ bool Database::isValid() const
return d->valid;
}
Error Database::error() const
{
Q_D(const Database);
return d->error;
}
Package::List Database::packages()
{
return queryPackages("SELECT * FROM packages");
......
......@@ -13,6 +13,7 @@
#include <akabeicore_global.h>
#include <akabeipackage.h>
#include <akabeierror.h>
#include <QObject>
......@@ -38,6 +39,7 @@ class AKABEICORESHARED_EXPORT Database
Q_DISABLE_COPY(Database)
Q_DECLARE_PRIVATE(Database)
public:
Database(QString const& pathToDatabase);
virtual ~Database();
/**
......@@ -49,6 +51,8 @@ public:
* @returns if the database is ready to read from disk
*/
bool isValid() const;
Error error() const;
/**
* @returns the path to the database on disk
......@@ -107,16 +111,11 @@ public:
QList<Hook*> queryHooks(QString const& sql);
private:
Database(QString const& pathToDatabase);
DatabasePrivate* const d_ptr;
friend class BackendPrivate;
friend class QueryHelper;
friend class Package;
friend class Backend;
};
}
#endif // AKABEIDATABASE_H
......@@ -42,8 +42,10 @@ public:
QString pathToDb;
SQLiteConnection dbConnection;
bool valid;
Error error;
QHash<int, Package*> packageCache;
QHash<QString, Group*> groupCache;
QHash<QString, Delta*> deltaCache;
......
......@@ -48,6 +48,7 @@ class Error
ArchiveError = 10,
SignatureError = 11,
BackendInitializationError = 12,
Md5Error = 13,
//
GenericError = 128,
AkabeiInternalError = 129
......
......@@ -425,10 +425,9 @@ QByteArray ArchiveHandler::md5(const QString& file)
QList<QByteArray> hashes = md5(list);
if (hashes.isEmpty()) {
QString error = "MD5: requested file \"" + file + "\" isn't present in archive \"" + archiveName + "\"";
qWarning() << error;
QString errorString = QObject::tr("MD5: requested file %1 isn't present in archive %2").arg(file, archiveName);
errs << Akabei::Error(Akabei::Error::Md5Error, errorString);
return QByteArray();
//throw ArchiveException(error.toUtf8().data());
}
return hashes.first();
......@@ -441,9 +440,25 @@ QList< QByteArray > ArchiveHandler::md5(const QStringList& files)
{
Akabei::Md5Functor hasher(files, 0, (*this));
handleEntries(hasher);
if (!hasher.skipped().isEmpty()) {
QString description;
foreach (const QString& target, hasher.skipped()) {
description += QObject::tr("MD5: requested file %1 isn't present in archive %2\n").arg(target, archiveName);
}
errs << Akabei::Error(Akabei::Error::Md5Error, description);
}
return hasher.result();
}
Akabei::Error::List ArchiveHandler::errors()
{
return errs;
}
struct archive *ArchiveHandler::getArchive()
{
return archive;
......@@ -648,6 +663,7 @@ bool Md5Functor::operator()(const ArchiveEntry& currentEntry)
md5_finish(&context, md5output); /* Write md5 hash to our array and ends processing */
m_result.append(Akabei::Helpers::processMd5(md5output));
m_toCompute.removeOne(currentEntry.getFileName());
return true;
}
......@@ -655,4 +671,9 @@ QList< QByteArray > Md5Functor::result()
{
return m_result;
}
QStringList Md5Functor::skipped()
{
return m_toCompute;
}
}
\ No newline at end of file
......@@ -130,6 +130,11 @@ public:
*/
bool checkPackageValidity();
/**
* @returns a list of errors occurred during execution
*/
Akabei::Error::List errors();
/**
* @returns the archive structure.
*/
......@@ -153,6 +158,7 @@ private:
struct archive *archive;
QString archiveName;
Akabei::Error::List errs;
};
/**
......
......@@ -96,6 +96,7 @@ public:
bool operator() (const ArchiveEntry &);
QList<QByteArray> result();
QStringList skipped();
private:
QStringList m_toCompute;
......
......@@ -219,8 +219,13 @@ void CreateDb::add()
out << "Checking if targets may already be in database...";
out.flush();
Akabei::Database *db = Akabei::Backend::instance()->loadDatabaseFromFile(unc);
Akabei::Database *db = new Akabei::Database( unc );
if (!db->isValid()) {
out << "Could not access the database: " << db->error().description();
exit(1);
}
Akabei::Package::List packages;
QString query = "SELECT * FROM packages WHERE";
foreach (const QString &pkgPath, m_targets) {
......@@ -319,7 +324,11 @@ void CreateDb::remove()
unc = m_db;
}
Akabei::Database *db = Akabei::Backend::instance()->loadDatabaseFromFile(unc);
Akabei::Database *db = new Akabei::Database( unc );
if (!db->isValid()) {
out << "Could not access the database: " << db->error().description();
exit(1);
}
QString query = "SELECT * FROM packages WHERE";
foreach (const QString &pkg, m_targets) {
......
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