Fixed bug when deallocating EContact from GList.
authorJamie Thompson <jamie@.(none)>
Wed, 24 Aug 2011 22:17:06 +0000 (23:17 +0100)
committerJamie Thompson <jamie@.(none)>
Wed, 24 Aug 2011 22:17:06 +0000 (23:17 +0100)
Fixed bug in attachment iterator use in RtcomEventLogger

DBBackends/RtcomEventLogger.cpp
DBBackends/RtcomEventLoggerComponents/TriggerDisabler.cpp [new file with mode: 0644]
DBBackends/RtcomEventLoggerComponents/TriggerDisabler.h [new file with mode: 0644]
NumberToNameLookup.cpp

index 7957baf..8e54f38 100644 (file)
@@ -171,7 +171,7 @@ void RtcomEventLogger::ProcessService(EventProcessors::iEventProcessor &processo
 
                                                                                QList<RTComElAttachment *> 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 (file)
index 0000000..e7edc8e
--- /dev/null
@@ -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
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "TriggerDisabler.h"
+
+#include "Settings.h"
+
+#include <QtSql>
+
+#include <sqlite3.h>
+
+#include <stdexcept>
+
+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>());
+                               QString sqlTrigger(dbqGetTriggers.value(1).value<QString>());
+
+                               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<int>());
+                       QString group_uid(dbqRecalculateGroupCache.value(1).value<QString>());
+                       int total(dbqRecalculateGroupCache.value(2).value<int>());
+                       int readcount(dbqRecalculateGroupCache.value(3).value<int>());
+                       int flags(dbqRecalculateGroupCache.value(4).value<int>());
+
+                       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<sqlite3**>(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 (file)
index 0000000..fe26af9
--- /dev/null
@@ -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
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DBBACKENDS_RTCOMEVENTLOGGERCOMPONENTS_TRIGGERDISABLER_H
+#define DBBACKENDS_RTCOMEVENTLOGGERCOMPONENTS_TRIGGERDISABLER_H
+
+class Settings;
+
+#include <QHash>
+class QSqlDatabase;
+#include <QString>
+
+namespace DBBackends
+{
+       namespace RtcomEventLoggerComponents
+       {
+               class TriggerDisabler
+               {
+               public:
+                       TriggerDisabler(const Settings &settings);
+                       ~TriggerDisabler();
+
+                       void Reenable();
+
+               protected:
+                       const Settings &CurrentSettings() const { return m_Settings; }
+
+                       const QHash<QString, QString> &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<QString, QString> &Triggers() { return m_Triggers; }
+                       QHash<QString, QString> m_Triggers;
+
+                       void Reenabled(bool reenabled) { m_Reenabled = reenabled; }
+                       bool m_Reenabled;
+               };
+       }
+}
+
+#endif // DBBACKENDS_RTCOMEVENTLOGGERCOMPONENTS_TRIGGERDISABLER_H
index 96eb7f9..6fa3b12 100644 (file)
@@ -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<uint, QString>(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.