//----------------------------------------------------------------------------- void QGCCacheWorker::_updateSetTotals(QGCCachedTileSet* set) { if(set->defaultSet()) { _updateTotals(); set->setSavedTiles(_totalCount); set->setSavedSize(_totalSize); set->setNumTiles(_defaultCount); set->setTilesSize(_defaultSize); return; } QSqlQuery subquery(*_db); QString sq = QString("SELECT COUNT(size), SUM(size) FROM Tiles A INNER JOIN SetTiles B on A.tileID = B.tileID WHERE B.setID = %1").arg(set->id()); if(subquery.exec(sq)) { if(subquery.next()) { set->setSavedTiles(subquery.value(0).toUInt()); set->setSavedSize(subquery.value(1).toULongLong()); //-- Update estimated size if(set->savedTiles() > 10 && set->savedSize()) { quint32 avg = set->savedSize() / set->savedTiles(); set->setTilesSize(avg * set->numTiles()); } } } }
//----------------------------------------------------------------------------- void QGCCacheWorker::_updateSetTotals(QGCCachedTileSet* set) { if(set->defaultSet()) { _updateTotals(); set->setSavedTileCount(_totalCount); set->setSavedTileSize(_totalSize); set->setTotalTileCount(_defaultCount); set->setTotalTileSize(_defaultSize); return; } QSqlQuery subquery(*_db); QString sq = QString("SELECT COUNT(size), SUM(size) FROM Tiles A INNER JOIN SetTiles B on A.tileID = B.tileID WHERE B.setID = %1").arg(set->id()); qCDebug(QGCTileCacheLog) << "_updateSetTotals(): " << sq; if(subquery.exec(sq)) { if(subquery.next()) { set->setSavedTileCount(subquery.value(0).toUInt()); set->setSavedTileSize(subquery.value(1).toULongLong()); qCDebug(QGCTileCacheLog) << "Set" << set->id() << "Totals:" << set->savedTileCount() << " " << set->savedTileSize() << "Expected: " << set->totalTileCount() << " " << set->totalTilesSize(); //-- Update (estimated) size quint64 avg = UrlFactory::averageSizeForType(set->type()); if(set->totalTileCount() <= set->savedTileCount()) { //-- We're done so the saved size is the total size set->setTotalTileSize(set->savedTileSize()); } else { //-- Otherwise we need to estimate it. if(set->savedTileCount() > 10 && set->savedTileSize()) { avg = set->savedTileSize() / set->savedTileCount(); } set->setTotalTileSize(avg * set->totalTileCount()); } //-- Now figure out the count for tiles unique to this set quint32 ucount = 0; quint64 usize = 0; sq = QString("SELECT COUNT(size), SUM(size) FROM Tiles WHERE tileID IN (SELECT A.tileID FROM SetTiles A join SetTiles B on A.tileID = B.tileID WHERE B.setID = %1 GROUP by A.tileID HAVING COUNT(A.tileID) = 1)").arg(set->id()); if(subquery.exec(sq)) { if(subquery.next()) { //-- This is only accurate when all tiles are downloaded ucount = subquery.value(0).toUInt(); usize = subquery.value(1).toULongLong(); } } //-- If we haven't downloaded it all, estimate size of unique tiles quint32 expectedUcount = set->totalTileCount() - set->savedTileCount(); if(!ucount) { usize = expectedUcount * avg; } else { expectedUcount = ucount; } set->setUniqueTileCount(expectedUcount); set->setUniqueTileSize(usize); } } }
//----------------------------------------------------------------------------- void QGCCacheWorker::_deleteTileSet(qulonglong id) { QSqlQuery query(*_db); QString s; //-- Only delete tiles unique to this set s = QString("DELETE FROM Tiles WHERE tileID IN (SELECT A.tileID FROM SetTiles A JOIN SetTiles B ON A.tileID = B.tileID WHERE B.setID = %1 GROUP BY A.tileID HAVING COUNT(A.tileID) = 1)").arg(id); query.exec(s); s = QString("DELETE FROM TilesDownload WHERE setID = %1").arg(id); query.exec(s); s = QString("DELETE FROM TileSets WHERE setID = %1").arg(id); query.exec(s); s = QString("DELETE FROM SetTiles WHERE setID = %1").arg(id); query.exec(s); _updateTotals(); }
//----------------------------------------------------------------------------- void QGCCacheWorker::_deleteTileSet(QGCMapTask* mtask) { if(!_valid) { mtask->setError("No Cache Database"); return; } QGCDeleteTileSetTask* task = static_cast<QGCDeleteTileSetTask*>(mtask); QSqlQuery query(*_db); QString s; s = QString("DELETE FROM Tiles WHERE tileID IN (SELECT tileID FROM SetTiles WHERE setID = %1)").arg(task->setID()); query.exec(s); s = QString("DELETE FROM TilesDownload WHERE setID = %1").arg(task->setID()); query.exec(s); s = QString("DELETE FROM TileSets WHERE setID = %1").arg(task->setID()); query.exec(s); s = QString("DELETE FROM SetTiles WHERE setID = %1").arg(task->setID()); query.exec(s); _updateTotals(); task->setTileSetDeleted(); }
//----------------------------------------------------------------------------- void QGCCacheWorker::run() { if(!_valid && !_failed) { _init(); } if(_valid) { _db = new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE", kSession)); _db->setDatabaseName(_databasePath); _db->setConnectOptions("QSQLITE_ENABLE_SHARED_CACHE"); _valid = _db->open(); } while(true) { QGCMapTask* task; if(_taskQueue.count()) { _mutex.lock(); task = _taskQueue.dequeue(); _mutex.unlock(); switch(task->type()) { case QGCMapTask::taskInit: break; case QGCMapTask::taskCacheTile: _saveTile(task); break; case QGCMapTask::taskFetchTile: _getTile(task); break; case QGCMapTask::taskFetchTileSets: _getTileSets(task); break; case QGCMapTask::taskCreateTileSet: _createTileSet(task); break; case QGCMapTask::taskGetTileDownloadList: _getTileDownloadList(task); break; case QGCMapTask::taskUpdateTileDownloadState: _updateTileDownloadState(task); break; case QGCMapTask::taskDeleteTileSet: _deleteTileSet(task); break; case QGCMapTask::taskPruneCache: _pruneCache(task); break; case QGCMapTask::taskReset: _resetCacheDatabase(task); break; } task->deleteLater(); //-- Check for update timeout size_t count = _taskQueue.count(); if(count > 100) { _updateTimeout = LONG_TIMEOUT; } else if(count < 25) { _updateTimeout = SHORT_TIMEOUT; } if(!count || (time(0) - _lastUpdate > _updateTimeout)) { _updateTotals(); } } else { //-- Wait a bit before shutting things down _waitmutex.lock(); int timeout = 5000; if(!_waitc.wait(&_waitmutex, timeout)) { _waitmutex.unlock(); _mutex.lock(); //-- If nothing to do, close db and leave thread if(!_taskQueue.count()) { _mutex.unlock(); break; } _mutex.unlock(); } _waitmutex.unlock(); } } if(_db) { delete _db; _db = NULL; QSqlDatabase::removeDatabase(kSession); } }