From d270693d12f8d9c45d08c4f6f4f4151e4edf0f87 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 24 Aug 2011 23:17:06 +0100 Subject: [PATCH] Fixed bug when deallocating EContact from GList. Fixed bug in attachment iterator use in RtcomEventLogger --- DBBackends/RtcomEventLogger.cpp | 2 +- .../RtcomEventLoggerComponents/TriggerDisabler.cpp | 231 ++++++++++++++++++++ .../RtcomEventLoggerComponents/TriggerDisabler.h | 62 ++++++ NumberToNameLookup.cpp | 6 +- 4 files changed, 297 insertions(+), 4 deletions(-) create mode 100644 DBBackends/RtcomEventLoggerComponents/TriggerDisabler.cpp create mode 100644 DBBackends/RtcomEventLoggerComponents/TriggerDisabler.h diff --git a/DBBackends/RtcomEventLogger.cpp b/DBBackends/RtcomEventLogger.cpp index 7957baf..8e54f38 100644 --- a/DBBackends/RtcomEventLogger.cpp +++ b/DBBackends/RtcomEventLogger.cpp @@ -171,7 +171,7 @@ void RtcomEventLogger::ProcessService(EventProcessors::iEventProcessor &processo QList rattachments; RTComElAttachIter *at_it = rtcom_el_iter_get_attachments(it); - if(it != NULL) + if(at_it != NULL) { qDebug() << "Attachments OK"; if(rtcom_el_attach_iter_first(at_it)) diff --git a/DBBackends/RtcomEventLoggerComponents/TriggerDisabler.cpp b/DBBackends/RtcomEventLoggerComponents/TriggerDisabler.cpp new file mode 100644 index 0000000..e7edc8e --- /dev/null +++ b/DBBackends/RtcomEventLoggerComponents/TriggerDisabler.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2011, Jamie Thompson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see + * . + */ + +#include "TriggerDisabler.h" + +#include "Settings.h" + +#include + +#include + +#include + +static void _sqlite3ORStep(sqlite3_context *context, int numArgs, sqlite3_value **value); +static void _sqlite3ORFinal(sqlite3_context *context); +bool createSQLiteFunctions(const QSqlDatabase &db); + +using namespace DBBackends::RtcomEventLoggerComponents; + +TriggerDisabler::TriggerDisabler(const Settings &settings) + : m_Settings(settings), m_Reenabled(false) +{ + // Preserve default cache triggers + // Set up the database connection... + QSqlDatabase db(QSqlDatabase::addDatabase( "QSQLITE" )); + + db.setDatabaseName(CurrentSettings().DBPath()); + if ( ! db.open() ) + throw std::runtime_error("Cannot open database: Unable to establish database connection"); + else + { + qDebug() << "DB Opened"; + + QSqlQuery dbqGetTriggers(db); + dbqGetTriggers.setForwardOnly( true ); + + const char * sqlGetTriggers("SELECT name, sql FROM sqlite_master WHERE type = \"trigger\" AND name LIKE \"gc_update_ev_%\""); + if(dbqGetTriggers.exec(sqlGetTriggers)) + { + qDebug() << "Query OK, " << dbqGetTriggers.numRowsAffected() << " rows affected."; + + while( dbqGetTriggers.next()) + { + QString name(dbqGetTriggers.value(0).value()); + QString sqlTrigger(dbqGetTriggers.value(1).value()); + + qDebug() << "( " << name << ", " << sqlTrigger << " )"; + + Triggers().insert(name, sqlTrigger); + } + + qDebug() << Triggers().count() << " triggers found."; + + QSqlQuery dbqRemoveTriggers(db); + dbqRemoveTriggers.setForwardOnly( true ); + + const QString sqlRemoveTriggers("DROP TRIGGER "); + foreach(QString triggerName, Triggers().keys()) + { + qDebug() << "Executing: " << sqlRemoveTriggers + triggerName; + if(dbqRemoveTriggers.exec(sqlRemoveTriggers + triggerName)) + qDebug() << "Query OK, " << dbqGetTriggers.numRowsAffected() << " rows affected."; + else + qDebug() << "Query failed, " << dbqGetTriggers.numRowsAffected() << " rows affected. Error: " << dbqRemoveTriggers.lastError().text(); + } + } + else + { + qDebug() << "SQL EXEC Error: " << "EXEC query failed"; + qDebug() << "Query: " << sqlGetTriggers; + } + + qDebug() << "Closing."; + db.close(); + } + + QSqlDatabase::removeDatabase("QSQLITE"); + + return; +} + +TriggerDisabler::~TriggerDisabler() +{ + // Restore default cache triggers + if(!Reenabled()) + Reenable(); +} + +void TriggerDisabler::Reenable() +{ + // Set up the database connection... + QSqlDatabase db(QSqlDatabase::addDatabase( "QSQLITE" )); + + db.setDatabaseName(CurrentSettings().DBPath()); + if (!db.open()) + throw std::runtime_error("Cannot open database: Unable to establish database connection"); + else + { + qDebug() << "DB Opened"; + + RestoreTriggers(db); + + UpdateGroupCache(db); + + qDebug() << "Closing DB."; + db.close(); + } + + QSqlDatabase::removeDatabase( "QSQLITE" ); + + Reenabled(true); +} + +void TriggerDisabler::RestoreTriggers(QSqlDatabase &db) +{ + QSqlQuery dbqRestoreTriggers(db); + dbqRestoreTriggers.setForwardOnly( true ); + + foreach(QString triggerName, Triggers().keys()) + { + qDebug() << "Restoring trigger " << triggerName; + qDebug() << "\tSQL: " << Triggers().value(triggerName); + if(dbqRestoreTriggers.exec(Triggers().value(triggerName))) + qDebug() << "Query OK, " << dbqRestoreTriggers.numRowsAffected() << " rows affected."; + else + qDebug() << "Query failed, " << dbqRestoreTriggers.numRowsAffected() << " rows affected. Error: " << dbqRestoreTriggers.lastError().text(); + } +} + +void TriggerDisabler::UpdateGroupCache(QSqlDatabase &db) +{ + const char * sqlUpdateGroupCache( + "INSERT OR REPLACE INTO groupcache " + "SELECT id, service_id, group_uid, total, readcount, mergedflags " + "FROM events e, " + "(SELECT max(start_time) as maxdate, group_uid as maxgid, count(group_uid) as total, total(is_read) as readcount, _OR(flags) as mergedflags " + "FROM events " + "GROUP BY maxgid) maxresults " + "WHERE group_uid = maxgid AND start_time=maxresults.maxdate " + "GROUP BY group_uid"); + + QSqlQuery dbqRecalculateGroupCache(db); + dbqRecalculateGroupCache.setForwardOnly(true); + + createSQLiteFunctions(db); + + qDebug() << "Updating group cache..."; + if(dbqRecalculateGroupCache.exec(sqlUpdateGroupCache)) + { + qDebug() << "Query OK, " << dbqRecalculateGroupCache.numRowsAffected() << " rows affected."; + + while(dbqRecalculateGroupCache.next()) + { + int id(dbqRecalculateGroupCache.value(0).value()); + QString group_uid(dbqRecalculateGroupCache.value(1).value()); + int total(dbqRecalculateGroupCache.value(2).value()); + int readcount(dbqRecalculateGroupCache.value(3).value()); + int flags(dbqRecalculateGroupCache.value(4).value()); + + qDebug() << "( " << id << ", " << group_uid << ", " << total << ", " << readcount << ", " << flags << " )"; + } + } + else + { + qDebug() << "SQL EXEC Error: " << "EXEC query failed. Error: " << dbqRecalculateGroupCache.lastError().text(); + qDebug() << "Query: " << sqlUpdateGroupCache; + } +} + +bool createSQLiteFunctions(const QSqlDatabase &db) +{ + // Get handle to the driver and check it is both valid and refers to SQLite3. + QVariant v(db.driver()->handle()); + if (!v.isValid() || qstrcmp(v.typeName(), "sqlite3*") != 0) + { + qDebug() << "Cannot get a sqlite3 handle to the driver."; + return false; + } + + // Create a handler and attach functions. + sqlite3 *handler(*static_cast(v.data())); + if (!handler) + { + qDebug() << "Cannot get a sqlite3 handler."; + return false; + } + + // Check validity of the state. + if (!db.isValid()) + { + qDebug() << "Cannot create SQLite custom functions: db object is not valid."; + return false; + } + + if (!db.isOpen()) + { + qDebug() << "Cannot create SQLite custom functions: db object is not open."; + return false; + } + + if (sqlite3_create_function(handler, "_OR", 1, SQLITE_ANY, NULL, NULL, _sqlite3ORStep, _sqlite3ORFinal)) + qDebug() << "Cannot create SQLite functions: sqlite3_create_function failed."; + + return true; +} + +static void _sqlite3ORStep(sqlite3_context *context, int, sqlite3_value **value) +{ + int *result((int *)sqlite3_aggregate_context(context, sizeof(int))); + *result |= sqlite3_value_int(*value); +} + +static void _sqlite3ORFinal(sqlite3_context *context) +{ + sqlite3_result_int(context, *(int *)sqlite3_aggregate_context(context, sizeof(int))); +} diff --git a/DBBackends/RtcomEventLoggerComponents/TriggerDisabler.h b/DBBackends/RtcomEventLoggerComponents/TriggerDisabler.h new file mode 100644 index 0000000..fe26af9 --- /dev/null +++ b/DBBackends/RtcomEventLoggerComponents/TriggerDisabler.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011, Jamie Thompson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see + * . + */ + +#ifndef DBBACKENDS_RTCOMEVENTLOGGERCOMPONENTS_TRIGGERDISABLER_H +#define DBBACKENDS_RTCOMEVENTLOGGERCOMPONENTS_TRIGGERDISABLER_H + +class Settings; + +#include +class QSqlDatabase; +#include + +namespace DBBackends +{ + namespace RtcomEventLoggerComponents + { + class TriggerDisabler + { + public: + TriggerDisabler(const Settings &settings); + ~TriggerDisabler(); + + void Reenable(); + + protected: + const Settings &CurrentSettings() const { return m_Settings; } + + const QHash &Triggers() const { return m_Triggers; } + + const bool Reenabled() const { return m_Reenabled; } + + void RestoreTriggers(QSqlDatabase &db); + void UpdateGroupCache(QSqlDatabase &db); + + private: + const Settings &m_Settings; + + QHash &Triggers() { return m_Triggers; } + QHash m_Triggers; + + void Reenabled(bool reenabled) { m_Reenabled = reenabled; } + bool m_Reenabled; + }; + } +} + +#endif // DBBACKENDS_RTCOMEVENTLOGGERCOMPONENTS_TRIGGERDISABLER_H diff --git a/NumberToNameLookup.cpp b/NumberToNameLookup.cpp index 96eb7f9..6fa3b12 100644 --- a/NumberToNameLookup.cpp +++ b/NumberToNameLookup.cpp @@ -82,7 +82,7 @@ NumberToNameLookup::NumberToNameLookup() // Now work out the current name for the contact and add it to the lookup EContactName *contactName = (EContactName*)e_contact_get((EContact*)currentContact->data, E_CONTACT_NAME); char *completeName(e_contact_name_to_string(contactName)); - qDebug() << completeName; + //qDebug() << completeName; // Looking at each number they have... GList * attrs(e_contact_get_attributes(E_CONTACT(currentContact->data), E_CONTACT_FIRST_PHONE_ID)); @@ -102,7 +102,7 @@ NumberToNameLookup::NumberToNameLookup() m_ContactDetails.insert(QString(number), QPair(remote_ebook_uid, QString(completeName))); - qDebug() << "Number: " << number << ", ID: " << remote_ebook_uid << ", completeName: " << completeName; + //qDebug() << "Number: " << number << ", ID: " << remote_ebook_uid << ", completeName: " << completeName; } } } @@ -112,7 +112,7 @@ NumberToNameLookup::NumberToNameLookup() e_contact_name_free(contactName); // I hate C-style APIs. - g_object_unref(currentContact); + g_object_unref(currentContact->data); } // I *really* hate C-style APIs. -- 1.7.9.5