defuze.me
Client
|
00001 /************************************************************************** 00002 ** defuze.me Epitech Innovative Project 00003 ** 00004 ** Copyright 2010 00005 ** Athena Calmettes - Jocelyn De La Rosa - Francois Gaillard 00006 ** Adrien Jarthon - Alexandre Moore - Luc Peres - Arnaud Sellier 00007 ** 00008 ** All rights reserved. 00009 **************************************************************************/ 00010 00011 #include <iostream> 00012 #include <QDir> 00013 #include "dbcore.hpp" 00014 #include "exception.hpp" 00015 #include "parser.hpp" 00016 #include "status.hpp" 00017 00018 using namespace DB; 00019 00020 DBCore::DBCore(QStringList &) 00021 { 00022 } 00023 00024 DBCore::~DBCore() 00025 { 00026 while (!locations.empty()) 00027 { 00028 delete locations.back(); 00029 locations.pop_back(); 00030 } 00031 } 00032 00033 void DBCore::defineParams() 00034 { 00035 // Default locations 00036 QVariantList list; 00037 list.push_back(QDesktopServices::storageLocation(QDesktopServices::DataLocation) + "/database.db"); 00038 list.push_back(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation) + "/defuze.me/backup/database.db"); 00039 setParameter("locations", list); 00040 } 00041 00042 void DBCore::loadLocations() 00043 { 00044 QVariantList list = getParameter("locations").toList(); 00045 for (int i = 0; i < list.size(); i++) 00046 locations.push_back(new Location(list.at(i).toString())); 00047 currentLocation = NULL; 00048 } 00049 00050 void DBCore::saveLocations() 00051 { 00052 QVariantList list; 00053 for (int i = 0; i < locations.size(); i++) 00054 list.push_back(locations[i]->filePath()); 00055 setParameter("locations", list); 00056 commitParameters(); 00057 } 00058 00059 void DBCore::init(Cores *c) 00060 { 00061 cores = c; 00062 00063 setParamsName("db"); 00064 setParamsBackEnd(Params::Parameterizable::SETTINGS); 00065 registerToParamsCore(cores->params()); 00066 loadLocations(); 00067 // Find the better location 00068 Location* original = locations.first(); 00069 00070 if (!original->exists() || !openLocation(original)) 00071 { 00072 // WARNING: can't open original database !!!!! 00073 00074 // try to load backups 00075 bool backupOk = false; 00076 for(int i = 1; i < locations.size(); ++i) 00077 { 00078 if (openLocation(locations.at(i))) 00079 { 00080 backupOk = true; 00081 break; 00082 } 00083 } 00084 if (!backupOk && !openLocation(original)) 00085 throw_exception(0x01, "No database found, no backup available, can't create a new one, please check your persmissions!"); 00086 } 00087 00088 MigrationEngine mEngine(*this); 00089 mEngine.migrate(); 00090 00091 if (getParameter("reset", false) == true) 00092 { 00093 qDebug() << "DB reset requested"; 00094 // Undo all migrations 00095 mEngine.undo(); 00096 // Migrate database to new schema 00097 mEngine.migrate(); 00098 } 00099 // self-test 00100 //test(); 00101 00102 backupAll(); 00103 } 00104 00105 void DBCore::aboutToQuit() 00106 { 00107 connection.close(); 00108 currentLocation = NULL; 00109 } 00110 00111 bool DBCore::openLocation(Location* loc) 00112 { 00113 qDebug() << "DB::Core opening database:" << loc->filePath(); 00114 loc->mkPath(); 00115 connection = QSqlDatabase::addDatabase("QSQLITE"); 00116 connection.setDatabaseName(loc->filePath()); 00117 connection.setUserName("defuze.me"); 00118 if (!connection.open()) 00119 { 00120 std::cerr << connection.lastError().text().toStdString() << std::endl; 00121 return false; 00122 } 00123 loc->open() = true; 00124 currentLocation = loc; 00125 return true; 00126 } 00127 00128 QVariant DBCore::setting(const QString& key) const 00129 { 00130 QSqlQuery query; 00131 QVariant value; 00132 query.prepare("SELECT * FROM settings WHERE key = :key LIMIT 1"); 00133 query.bindValue(":key", key); 00134 query.exec(); 00135 int fieldNo = query.record().indexOf("value"); 00136 if (query.next()) 00137 value = query.value(fieldNo); 00138 return (Network::JsonParser().parse(value.toByteArray())); 00139 } 00140 00141 QHash<QString, QVariant> DBCore::settingsStartingWith(const QString &key) const 00142 { 00143 QHash<QString, QVariant> result; 00144 QSqlQuery query; 00145 QVariant value; 00146 QString fullKey; 00147 query.prepare("SELECT * FROM settings WHERE key LIKE :key"); 00148 query.bindValue(":key", key + "%"); 00149 query.exec(); 00150 int keyFieldNo = query.record().indexOf("key"); 00151 int valueFieldNo = query.record().indexOf("value"); 00152 while (query.next()) 00153 { 00154 fullKey = query.value(keyFieldNo).toString(); 00155 value = query.value(valueFieldNo); 00156 result[fullKey] = Network::JsonParser().parse(value.toByteArray()); 00157 } 00158 return (result); 00159 } 00160 00161 bool DBCore::setSetting(const QString& key, const QVariant value) const 00162 { 00163 QSqlQuery query; 00164 query.prepare("INSERT OR REPLACE INTO settings (key, value) VALUES (:key, :value)"); 00165 query.bindValue(":key", key); 00166 query.bindValue(":value", Network::JsonParser().serialize(value)); 00167 if (!query.exec()) 00168 throw_exception(0x02, QString("Can't store setting value: " + query.lastError().text())); 00169 return true; 00170 } 00171 00172 int DBCore::currentMigration() const 00173 { 00174 QVariant value = setting("migration"); 00175 if (value.isNull()) 00176 return 0; 00177 else 00178 return value.toInt(); 00179 } 00180 00181 void DBCore::backupAll() 00182 { 00183 for(int i = 0; i < locations.size(); ++i) 00184 { 00185 Location* loc = locations.at(i); 00186 if (!loc->open()) 00187 { 00188 qDebug() << "DB::Core backuping database to" << loc->filePath() << "(age=" << loc->age() << ")"; 00189 loc->mkPath(); 00190 QFile::remove(loc->filePath()); 00191 QFile database(currentLocation->filePath()); 00192 if (!database.copy(loc->filePath())) 00193 { 00194 Notification::Status::gMessage(tr("Can't backup to %1 (%2)").arg(loc->filePath()).arg(database.errorString()), Notification::WARN); 00195 } 00196 loc->reload(); 00197 } 00198 } 00199 } 00200 00201 void DBCore::test() 00202 { 00203 // migration tests 00204 MigrationEngine mEngine(*this); 00205 mEngine.undo(); 00206 mEngine.migrate(); 00207 mEngine.undo(); 00208 mEngine.migrate(); 00209 00210 // settings tests 00211 setSetting("test-foo", 42); 00212 Q_ASSERT_X(setting("test-foo") == 42, "DBCore::test", "Integer setting error"); 00213 setSetting("test-foo", 40.42); 00214 Q_ASSERT_X(setting("test-foo") == 40.42, "DBCore::test", "Double setting error"); 00215 setSetting("test-foo", "Hello"); 00216 Q_ASSERT_X(setting("test-foo") == "Hello", "DBCore::test", "String setting error"); 00217 QVariantList list; 00218 list.append(42); 00219 list.append(40.42); 00220 list.append("Hello"); 00221 setSetting("test-foo", list); 00222 Q_ASSERT_X(setting("test-foo") == list, "DBCore::test", "Array setting error"); 00223 QVariantMap map; 00224 map["int"] = 42; 00225 map["double"] = 40.42; 00226 map["string"] = "Hello"; 00227 setSetting("test-foo", map); 00228 Q_ASSERT_X(setting("test-foo") == map, "DBCore::test", "Map setting error"); 00229 Q_ASSERT_X(setting("test-empty") == QVariant(), "DBCore::test", "Empty setting error"); 00230 }