1 #include <QApplication>
2 #include <QDateTime>
3 #include <QSqlDriver>
4 #include <QSqlQuery>
5 #include <QSqlError>
6 #include <QDateTime>
7 #include <QDir>
8 #include <QUuid>
9 #include <QRegExp>
10 
11 #include "macros.h"
12 #include "settings.h"
13 #include "options.h"
14 #include "checksumdbmgr.h"
15 
16 // external global variables
17 extern Settings *qmc2Config;
18 
CheckSumDatabaseManager(QObject * parent,QString settingsKey)19 CheckSumDatabaseManager::CheckSumDatabaseManager(QObject *parent, QString settingsKey) :
20 	QObject(parent),
21 	m_settingsKey(settingsKey)
22 {
23 	m_fileTypes << "ZIP" << "7Z" << "CHD" << "FILE";
24 	m_connectionName = QString("checksum-db-connection-%1").arg(QUuid::createUuid().toString());
25 	m_db = QSqlDatabase::addDatabase("QSQLITE", m_connectionName);
26 	QString variantName(QMC2_VARIANT_NAME.toLower().replace(QRegExp("\\..*$"), ""));
27 	if ( m_settingsKey == "ROMAlyzer" )
28 		m_db.setDatabaseName(qmc2Config->value(QMC2_FRONTEND_PREFIX + m_settingsKey + "/CheckSumDbDatabasePath", QString(Options::configPath() + "/%1-checksum.db").arg(variantName)).toString());
29 	else
30 		m_db.setDatabaseName(qmc2Config->value(QMC2_FRONTEND_PREFIX + m_settingsKey + "/CheckSumDbDatabasePath", QString(Options::configPath() + "/%1-software-checksum.db").arg(variantName)).toString());
31 	m_tableBasename = QString("%1_checksum").arg(variantName.replace("-", "_"));
32 	if ( m_db.open() ) {
33 		QStringList tables(m_db.driver()->tables(QSql::Tables));
34 		if ( tables.count() != 2 || !tables.contains(m_tableBasename) || !tables.contains(QString("%1_metadata").arg(m_tableBasename)) || checkSumDbVersion() != QMC2_CHECKSUM_DB_VERSION )
35 			recreateDatabase();
36 	} else
37 		emitlog(tr("WARNING: failed to open check-sum database '%1': error = '%2'").arg(m_db.databaseName()).arg(m_db.lastError().text()));
38 	m_lastRowId = -1;
39 }
40 
~CheckSumDatabaseManager()41 CheckSumDatabaseManager::~CheckSumDatabaseManager()
42 {
43 	if ( m_db.isOpen() )
44 		m_db.close();
45 }
46 
qmc2Version()47 QString CheckSumDatabaseManager::qmc2Version()
48 {
49 	QString qmc2_version;
50 	QSqlQuery query(m_db);
51 	query.prepare(QString("SELECT qmc2_version FROM %1_metadata WHERE row=0").arg(m_tableBasename));
52 	if ( query.exec() ) {
53 		if ( query.first() )
54 			qmc2_version = query.value(0).toString();
55 		query.finish();
56 	} else
57 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("qmc2_version").arg(query.lastQuery()).arg(query.lastError().text()));
58 	return qmc2_version;
59 }
60 
setQmc2Version(QString qmc2_version)61 void CheckSumDatabaseManager::setQmc2Version(QString qmc2_version)
62 {
63 	QSqlQuery query(m_db);
64 	query.prepare(QString("SELECT qmc2_version FROM %1_metadata WHERE row=0").arg(m_tableBasename));
65 	if ( query.exec() ) {
66 		if ( !query.next() ) {
67 			query.finish();
68 			query.prepare(QString("INSERT INTO %1_metadata (qmc2_version, row) VALUES (:qmc2_version, 0)").arg(m_tableBasename));
69 			query.bindValue(":qmc2_version", qmc2_version);
70 			if ( !query.exec() )
71 				emitlog(tr("WARNING: failed to add '%1' to check-sum database: query = '%2', error = '%3'").arg("qmc2_version").arg(query.lastQuery()).arg(query.lastError().text()));
72 		} else {
73 			query.finish();
74 			query.prepare(QString("UPDATE %1_metadata SET qmc2_version=:qmc2_version WHERE row=0").arg(m_tableBasename));
75 			query.bindValue(":qmc2_version", qmc2_version);
76 			if ( !query.exec() )
77 				emitlog(tr("WARNING: failed to update '%1' in check-sum database: query = '%2', error = '%3'").arg("qmc2_version").arg(query.lastQuery()).arg(query.lastError().text()));
78 		}
79 		query.finish();
80 	} else
81 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("qmc2_version").arg(query.lastQuery()).arg(query.lastError().text()));
82 }
83 
checkSumDbVersion()84 int CheckSumDatabaseManager::checkSumDbVersion()
85 {
86 	int checksum_db_version = -1;
87 	QSqlQuery query(m_db);
88 	query.prepare(QString("SELECT checksum_db_version FROM %1_metadata WHERE row=0").arg(m_tableBasename));
89 	if ( query.exec() ) {
90 		if ( query.first() )
91 			checksum_db_version = query.value(0).toInt();
92 		query.finish();
93 	} else
94 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("checksum_db_version").arg(query.lastQuery()).arg(query.lastError().text()));
95 	return checksum_db_version;
96 }
97 
setCheckSumDbVersion(int checksum_db_version)98 void CheckSumDatabaseManager::setCheckSumDbVersion(int checksum_db_version)
99 {
100 	QSqlQuery query(m_db);
101 	query.prepare(QString("SELECT checksum_db_version FROM %1_metadata WHERE row=0").arg(m_tableBasename));
102 	if ( query.exec() ) {
103 		if ( !query.next() ) {
104 			query.finish();
105 			query.prepare(QString("INSERT INTO %1_metadata (checksum_db_version, row) VALUES (:checksum_db_version, 0)").arg(m_tableBasename));
106 			query.bindValue(":checksum_db_version", checksum_db_version);
107 			if ( !query.exec() )
108 				emitlog(tr("WARNING: failed to add '%1' to check-sum database: query = '%2', error = '%3'").arg("checksum_db_version").arg(query.lastQuery()).arg(query.lastError().text()));
109 		} else {
110 			query.finish();
111 			query.prepare(QString("UPDATE %1_metadata SET checksum_db_version=:checksum_db_version WHERE row=0").arg(m_tableBasename));
112 			query.bindValue(":checksum_db_version", checksum_db_version);
113 			if ( !query.exec() )
114 				emitlog(tr("WARNING: failed to update '%1' in check-sum database: query = '%2', error = '%3'").arg("checksum_db_version").arg(query.lastQuery()).arg(query.lastError().text()));
115 		}
116 		query.finish();
117 	} else
118 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("checksum_db_version").arg(query.lastQuery()).arg(query.lastError().text()));
119 }
120 
scanTime()121 uint CheckSumDatabaseManager::scanTime()
122 {
123 	uint scan_time = 0;
124 	QSqlQuery query(m_db);
125 	query.prepare(QString("SELECT scan_time FROM %1_metadata WHERE row=0").arg(m_tableBasename));
126 	if ( query.exec() ) {
127 		if ( query.first() )
128 			scan_time = query.value(0).toUInt();
129 		query.finish();
130 	} else
131 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("scan_time").arg(query.lastQuery()).arg(query.lastError().text()));
132 	return scan_time;
133 }
134 
setScanTime(uint scan_time)135 void CheckSumDatabaseManager::setScanTime(uint scan_time)
136 {
137 	QSqlQuery query(m_db);
138 	query.prepare(QString("SELECT scan_time FROM %1_metadata WHERE row=0").arg(m_tableBasename));
139 	if ( query.exec() ) {
140 		if ( !query.next() ) {
141 			query.finish();
142 			query.prepare(QString("INSERT INTO %1_metadata (scan_time, row) VALUES (:scan_time, 0)").arg(m_tableBasename));
143 			query.bindValue(":scan_time", scan_time);
144 			if ( !query.exec() )
145 				emitlog(tr("WARNING: failed to add '%1' to check-sum database: query = '%2', error = '%3'").arg("scan_time").arg(query.lastQuery()).arg(query.lastError().text()));
146 		} else {
147 			query.finish();
148 			query.prepare(QString("UPDATE %1_metadata SET scan_time=:scan_time WHERE row=0").arg(m_tableBasename));
149 			query.bindValue(":scan_time", scan_time);
150 			if ( !query.exec() )
151 				emitlog(tr("WARNING: failed to update '%1' in check-sum database: query = '%2', error = '%3'").arg("scan_time").arg(query.lastQuery()).arg(query.lastError().text()));
152 		}
153 		query.finish();
154 	} else
155 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("scan_time").arg(query.lastQuery()).arg(query.lastError().text()));
156 }
157 
checkSumRowCount()158 qint64 CheckSumDatabaseManager::checkSumRowCount()
159 {
160 	QSqlQuery query(m_db);
161 	if ( query.exec(QString("SELECT COUNT(*) FROM %1").arg(m_tableBasename)) ) {
162 		if ( query.first() )
163 			return query.value(0).toLongLong();
164 		else
165 			return -1;
166 	} else {
167 		emitlog(tr("WARNING: failed to fetch row count from check-sum database: query = '%1', error = '%2'").arg(query.lastQuery()).arg(query.lastError().text()));
168 		return -1;
169 	}
170 }
171 
nextRowId(bool refreshRowIds)172 qint64 CheckSumDatabaseManager::nextRowId(bool refreshRowIds)
173 {
174 	if ( refreshRowIds ) {
175 		m_rowIdList.clear();
176 		m_lastRowId = -1;
177 		QSqlQuery query(m_db);
178 		if ( query.exec(QString("SELECT rowid FROM %1").arg(m_tableBasename)) ) {
179 			if ( query.first() ) {
180 				do {
181 					m_rowIdList << query.value(0).toLongLong();
182 				} while ( query.next() );
183 				m_lastRowId = 0;
184 				return m_rowIdList[0];
185 			}
186 		} else {
187 			emitlog(tr("WARNING: failed to fetch row IDs from check-sum database: query = '%1', error = '%2'").arg(query.lastQuery()).arg(query.lastError().text()));
188 			return -1;
189 		}
190 	} else if ( m_lastRowId > -1 ) {
191 		m_lastRowId++;
192 		if ( m_lastRowId < m_rowIdList.count() )
193 			return m_rowIdList[m_lastRowId];
194 		else
195 			return -1;
196 	}
197 	return -1;
198 }
199 
databaseSize()200 quint64 CheckSumDatabaseManager::databaseSize()
201 {
202 	QSqlQuery query(m_db);
203 	if ( query.exec("PRAGMA page_count") ) {
204 		if ( query.first() ) {
205 			quint64 page_count = query.value(0).toULongLong();
206 			query.finish();
207 			if ( query.exec("PRAGMA page_size") ) {
208 				if ( query.first() ) {
209 					quint64 page_size = query.value(0).toULongLong();
210 					return page_count * page_size;
211 				} else
212 					return 0;
213 			} else
214 				return 0;
215 		} else
216 			return 0;
217 	} else
218 		return 0;
219 }
220 
setCacheSize(quint64 kiloBytes)221 void CheckSumDatabaseManager::setCacheSize(quint64 kiloBytes)
222 {
223 	QSqlQuery query(m_db);
224 	if ( !query.exec(QString("PRAGMA cache_size = -%1").arg(kiloBytes)) )
225 		emitlog(tr("WARNING: failed to change the '%1' setting for the check-sum database: query = '%2', error = '%3'").arg("cache_size").arg(query.lastQuery()).arg(query.lastError().text()));
226 }
227 
setSyncMode(uint syncMode)228 void CheckSumDatabaseManager::setSyncMode(uint syncMode)
229 {
230 	static QStringList dbSyncModes = QStringList() << "OFF" << "NORMAL" << "FULL";
231 	if ( (int)syncMode > dbSyncModes.count() - 1 )
232 		return;
233 	QSqlQuery query(m_db);
234 	if ( !query.exec(QString("PRAGMA synchronous = %1").arg(dbSyncModes[syncMode])) )
235 		emitlog(tr("WARNING: failed to change the '%1' setting for the check-sum database: query = '%2', error = '%3'").arg("synchronous").arg(query.lastQuery()).arg(query.lastError().text()));
236 }
237 
setJournalMode(uint journalMode)238 void CheckSumDatabaseManager::setJournalMode(uint journalMode)
239 {
240 	static QStringList dbJournalModes = QStringList() << "DELETE" << "TRUNCATE" << "PERSIST" << "MEMORY" << "WAL" << "OFF";
241 	if ( (int)journalMode > dbJournalModes.count() - 1 )
242 		return;
243 	QSqlQuery query(m_db);
244 	if ( !query.exec(QString("PRAGMA journal_mode = %1").arg(dbJournalModes[journalMode])) )
245 		emitlog(tr("WARNING: failed to change the '%1' setting for the check-sum database: query = '%2', error = '%3'").arg("journal_mode").arg(query.lastQuery()).arg(query.lastError().text()));
246 }
247 
exists(QString sha1,QString crc,quint64 size)248 bool CheckSumDatabaseManager::exists(QString sha1, QString crc, quint64 size)
249 {
250 	QSqlQuery query(m_db);
251 	if ( size > 0 ) {
252 		if ( sha1.isEmpty() ) {
253 			query.prepare(QString("SELECT sha1, crc, size FROM %1 WHERE crc=:crc AND size=:size LIMIT 1").arg(m_tableBasename));
254 			query.bindValue(":crc", crc);
255 			query.bindValue(":size", size);
256 		} else if ( crc.isEmpty() ) {
257 			query.prepare(QString("SELECT sha1, crc, size FROM %1 WHERE sha1=:sha1 AND size=:size LIMIT 1").arg(m_tableBasename));
258 			query.bindValue(":sha1", sha1);
259 			query.bindValue(":size", size);
260 		} else {
261 			query.prepare(QString("SELECT sha1, crc, size FROM %1 WHERE sha1=:sha1 AND crc=:crc AND size=:size LIMIT 1").arg(m_tableBasename));
262 			query.bindValue(":sha1", sha1);
263 			query.bindValue(":crc", crc);
264 			query.bindValue(":size", size);
265 		}
266 	} else {
267 		if ( sha1.isEmpty() ) {
268 			query.prepare(QString("SELECT sha1, crc FROM %1 WHERE crc=:crc LIMIT 1").arg(m_tableBasename));
269 			query.bindValue(":crc", crc);
270 		} else if ( crc.isEmpty() ) {
271 			query.prepare(QString("SELECT sha1, crc FROM %1 WHERE sha1=:sha1 LIMIT 1").arg(m_tableBasename));
272 			query.bindValue(":sha1", sha1);
273 		} else {
274 			query.prepare(QString("SELECT sha1, crc FROM %1 WHERE sha1=:sha1 AND crc=:crc LIMIT 1").arg(m_tableBasename));
275 			query.bindValue(":sha1", sha1);
276 			query.bindValue(":crc", crc);
277 		}
278 	}
279 	if ( query.exec() )
280 		return query.first();
281 	else {
282 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("sha1, crc").arg(query.lastQuery()).arg(query.lastError().text()));
283 		return false;
284 	}
285 }
286 
setData(QString sha1,QString crc,quint64 size,QString path,QString member,QString type)287 void CheckSumDatabaseManager::setData(QString sha1, QString crc, quint64 size, QString path, QString member, QString type)
288 {
289 	QSqlQuery query(m_db);
290 	query.prepare(QString("INSERT INTO %1 (sha1, crc, size, path, member, type) VALUES (:sha1, :crc, :size, :path, :member, :type)").arg(m_tableBasename));
291 	query.bindValue(":sha1", sha1);
292 	query.bindValue(":crc", crc);
293 	query.bindValue(":size", size);
294 	query.bindValue(":path", path);
295 	query.bindValue(":member", member);
296 	query.bindValue(":type", type);
297 	if ( !query.exec() )
298 		emitlog(tr("WARNING: failed to add '%1' to check-sum database: query = '%2', error = '%3'").arg("sha1, crc, size, path, member, type").arg(query.lastQuery()).arg(query.lastError().text()));
299 }
300 
getData(QString sha1,QString crc,quint64 * size,QString * path,QString * member,QString * type)301 bool CheckSumDatabaseManager::getData(QString sha1, QString crc, quint64 *size, QString *path, QString *member, QString *type)
302 {
303 	QSqlQuery query(m_db);
304 	if ( *size > 0 ) {
305 		if ( sha1.isEmpty() ) {
306 			query.prepare(QString("SELECT size, path, member, type FROM %1 WHERE crc=:crc AND size=:size").arg(m_tableBasename));
307 			query.bindValue(":crc", crc);
308 			query.bindValue(":size", *size);
309 		} else if ( crc.isEmpty() ) {
310 			query.prepare(QString("SELECT size, path, member, type FROM %1 WHERE sha1=:sha1 AND size=:size").arg(m_tableBasename));
311 			query.bindValue(":sha1", sha1);
312 			query.bindValue(":size", *size);
313 		} else {
314 			query.prepare(QString("SELECT size, path, member, type FROM %1 WHERE sha1=:sha1 AND crc=:crc AND size=:size").arg(m_tableBasename));
315 			query.bindValue(":sha1", sha1);
316 			query.bindValue(":crc", crc);
317 			query.bindValue(":size", *size);
318 		}
319 	} else {
320 		if ( sha1.isEmpty() ) {
321 			query.prepare(QString("SELECT size, path, member, type FROM %1 WHERE crc=:crc").arg(m_tableBasename));
322 			query.bindValue(":crc", crc);
323 		} else if ( crc.isEmpty() ) {
324 			query.prepare(QString("SELECT size, path, member, type FROM %1 WHERE sha1=:sha1").arg(m_tableBasename));
325 			query.bindValue(":sha1", sha1);
326 		} else {
327 			query.prepare(QString("SELECT size, path, member, type FROM %1 WHERE sha1=:sha1 AND crc=:crc").arg(m_tableBasename));
328 			query.bindValue(":sha1", sha1);
329 			query.bindValue(":crc", crc);
330 		}
331 	}
332 	if ( query.exec() ) {
333 		if ( query.first() ) {
334 			*size = query.value(0).toULongLong();
335 			*path = query.value(1).toString();
336 			*member = query.value(2).toString();
337 			*type = query.value(3).toString();
338 			return true;
339 		} else
340 			return false;
341 	} else {
342 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("path, member, type").arg(query.lastQuery()).arg(query.lastError().text()));
343 		return false;
344 	}
345 }
346 
getCrc(QString sha1)347 QString CheckSumDatabaseManager::getCrc(QString sha1)
348 {
349 	QSqlQuery query(m_db);
350 	query.prepare(QString("SELECT crc FROM %1 WHERE sha1=:sha1").arg(m_tableBasename));
351 	query.bindValue(":sha1", sha1);
352 	if ( query.exec() ) {
353 		if ( query.first() )
354 			return query.value(0).toString();
355 		else
356 			return QString();
357 	} else {
358 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("crc").arg(query.lastQuery()).arg(query.lastError().text()));
359 		return QString();
360 	}
361 }
362 
getSha1(QString crc)363 QString CheckSumDatabaseManager::getSha1(QString crc)
364 {
365 	QSqlQuery query(m_db);
366 	query.prepare(QString("SELECT sha1 FROM %1 WHERE crc=:crc").arg(m_tableBasename));
367 	query.bindValue(":crc", crc);
368 	if ( query.exec() ) {
369 		if ( query.first() )
370 			return query.value(0).toString();
371 		else
372 			return QString();
373 	} else {
374 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("sha1").arg(query.lastQuery()).arg(query.lastError().text()));
375 		return QString();
376 	}
377 }
378 
pathRemove(QString path)379 void CheckSumDatabaseManager::pathRemove(QString path)
380 {
381 	QSqlQuery query(m_db);
382 	query.prepare(QString("DELETE FROM %1 WHERE path=:path").arg(m_tableBasename));
383 	query.bindValue(":path", path);
384 	if ( !query.exec() )
385 		emitlog(tr("WARNING: failed to remove path '%1' from check-sum database: query = '%2', error = '%3'").arg(path).arg(query.lastQuery()).arg(query.lastError().text()));
386 }
387 
pathOfRow(qint64 row,QString * key,bool simpleKey)388 QString CheckSumDatabaseManager::pathOfRow(qint64 row, QString *key, bool simpleKey)
389 {
390 	QSqlQuery query(m_db);
391 	if ( key ) {
392 		query.prepare(QString("SELECT path, sha1, crc, size, type FROM %1 WHERE rowid=:row").arg(m_tableBasename));
393 		query.bindValue(":row", row);
394 		if ( query.exec() ) {
395 			if ( query.first() ) {
396 				if ( !simpleKey )
397 					*key = QString("%1-%2-%3").arg(query.value(1).toString()).arg(query.value(2).toString()).arg(query.value(3).toString());
398 				else if ( query.value(4).toString() == "CHD" )
399 					*key = QString("%1-0-0").arg(query.value(1).toString());
400 				else
401 					*key = QString("%1-%2-%3").arg(query.value(1).toString()).arg(query.value(2).toString()).arg(query.value(3).toString());
402 				return query.value(0).toString();
403 			} else
404 				return QString();
405 		} else {
406 			emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("path, sha1, crc, size").arg(query.lastQuery()).arg(query.lastError().text()));
407 			return QString();
408 		}
409 	} else {
410 		query.prepare(QString("SELECT path FROM %1 WHERE rowid=:row").arg(m_tableBasename));
411 		query.bindValue(":row", row);
412 		if ( query.exec() ) {
413 			if ( query.first() )
414 				return query.value(0).toString();
415 			else
416 				return QString();
417 		} else {
418 			emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("path").arg(query.lastQuery()).arg(query.lastError().text()));
419 			return QString();
420 		}
421 	}
422 }
423 
keyOfRow(qint64 row)424 QString CheckSumDatabaseManager::keyOfRow(qint64 row)
425 {
426 	QSqlQuery query(m_db);
427 	query.prepare(QString("SELECT sha1, crc, size FROM %1 WHERE rowid=:row").arg(m_tableBasename));
428 	query.bindValue(":row", row);
429 	if ( query.exec() ) {
430 		if ( query.first() )
431 			return QString("%1-%2-%3").arg(query.value(0).toString()).arg(query.value(1).toString()).arg(query.value(2).toString());
432 		else
433 			return QString();
434 	} else {
435 		emitlog(tr("WARNING: failed to fetch '%1' from check-sum database: query = '%2', error = '%3'").arg("sha1, crc, size").arg(query.lastQuery()).arg(query.lastError().text()));
436 		return QString();
437 	}
438 }
439 
invalidateRow(qint64 row)440 void CheckSumDatabaseManager::invalidateRow(qint64 row)
441 {
442 	QSqlQuery query(m_db);
443 	query.prepare(QString("UPDATE %1 SET sha1='I' WHERE rowid=:row").arg(m_tableBasename));
444 	query.bindValue(":row", row);
445 	if ( !query.exec() )
446 		emitlog(tr("WARNING: failed to update '%1' in check-sum database: query = '%2', error = '%3'").arg("sha1").arg(query.lastQuery()).arg(query.lastError().text()));
447 
448 }
449 
removeInvalidatedRows()450 void CheckSumDatabaseManager::removeInvalidatedRows()
451 {
452 	QSqlQuery query(m_db);
453 	if ( !query.exec(QString("DELETE FROM %1 WHERE sha1='I'").arg(m_tableBasename)) )
454 		emitlog(tr("WARNING: failed to remove invalidated rows from check-sum database: query = '%1', error = '%2'").arg(query.lastQuery()).arg(query.lastError().text()));
455 }
456 
nameToType(QString name)457 int CheckSumDatabaseManager::nameToType(QString name)
458 {
459 	return m_fileTypes.indexOf(name);
460 }
461 
typeToName(int type)462 QString CheckSumDatabaseManager::typeToName(int type)
463 {
464 	if ( type < m_fileTypes.count() )
465 		return m_fileTypes[type];
466 	else
467 		return QString("UNKNOWN");
468 }
469 
vacuum()470 void CheckSumDatabaseManager::vacuum()
471 {
472 	QSqlQuery query(m_db);
473 	query.exec("VACUUM");
474 	query.finish();
475 }
476 
recreateDatabase()477 void CheckSumDatabaseManager::recreateDatabase()
478 {
479 	QSqlQuery query(m_db);
480 	if ( !query.exec(QString("DROP INDEX IF EXISTS %1_index").arg(m_tableBasename)) ) {
481 		emitlog(tr("WARNING: failed to remove check-sum database: query = '%1', error = '%2'").arg(query.lastQuery()).arg(query.lastError().text()));
482 		return;
483 	}
484 	query.finish();
485 	if ( !query.exec(QString("DROP TABLE IF EXISTS %1").arg(m_tableBasename)) ) {
486 		emitlog(tr("WARNING: failed to remove check-sum database: query = '%1', error = '%2'").arg(query.lastQuery()).arg(query.lastError().text()));
487 		return;
488 	}
489 	query.finish();
490 	if ( !query.exec(QString("DROP TABLE IF EXISTS %1_metadata").arg(m_tableBasename)) ) {
491 		emitlog(tr("WARNING: failed to remove check-sum database: query = '%1', error = '%2'").arg(query.lastQuery()).arg(query.lastError().text()));
492 		return;
493 	}
494 	query.finish();
495 	// vaccum'ing the database frees all disk-space previously used
496 	query.exec("VACUUM");
497 	query.finish();
498 	if ( !query.exec(QString("CREATE TABLE %1 (sha1 TEXT, crc TEXT, size UNSIGNED BIG INT, path TEXT, member TEXT, type TEXT, PRIMARY KEY (sha1, crc), CONSTRAINT %1_unique_checksums UNIQUE (sha1, crc))").arg(m_tableBasename)) ) {
499 		emitlog(tr("WARNING: failed to create check-sum database: query = '%1', error = '%2'").arg(query.lastQuery()).arg(query.lastError().text()));
500 		return;
501 	}
502 	query.finish();
503 	if ( !query.exec(QString("CREATE INDEX %1_index ON %1 (sha1, crc)").arg(m_tableBasename)) ) {
504 		emitlog(tr("WARNING: failed to create check-sum database: query = '%1', error = '%2'").arg(query.lastQuery()).arg(query.lastError().text()));
505 		return;
506 	}
507 	query.finish();
508 	if ( !query.exec(QString("CREATE TABLE %1_metadata (row INTEGER PRIMARY KEY, scan_time UNSIGNED BIG INT, qmc2_version TEXT, checksum_db_version INTEGER)").arg(m_tableBasename)) ) {
509 		emitlog(tr("WARNING: failed to create check-sum database: query = '%1', error = '%2'").arg(query.lastQuery()).arg(query.lastError().text()));
510 		return;
511 	}
512 	setScanTime(QDateTime::currentDateTime().toTime_t());
513 	setQmc2Version(XSTR(QMC2_VERSION));
514 	setCheckSumDbVersion(QMC2_CHECKSUM_DB_VERSION);
515 	emitlog(tr("check-sum database '%1' initialized").arg(databasePath()));
516 }
517 
emitlog(QString message)518 void CheckSumDatabaseManager::emitlog(QString message)
519 {
520 	emit log(QDateTime::currentDateTime().toString("hh:mm:ss.zzz") + ": " + message);
521 }
522