|
MythTV
0.26-pre
|
00001 #include <vector> 00002 using namespace std; 00003 00004 #include <QReadWriteLock> 00005 #include <QTextStream> 00006 #include <QSqlError> 00007 #include <QMutex> 00008 #include <QFile> 00009 #include <QHash> 00010 #include <QDir> 00011 00012 #include "mythdb.h" 00013 #include "mythdbcon.h" 00014 #include "mythlogging.h" 00015 #include "mythdirs.h" 00016 #include "mythcorecontext.h" 00017 00018 static MythDB *mythdb = NULL; 00019 static QMutex dbLock; 00020 00021 // For thread safety reasons this is not a QString 00022 const char *kSentinelValue = "<settings_sentinel_value>"; 00023 const char *kClearSettingValue = "<clear_setting_value>"; 00024 00025 MythDB *MythDB::getMythDB(void) 00026 { 00027 if (mythdb) 00028 return mythdb; 00029 00030 dbLock.lock(); 00031 if (!mythdb) 00032 mythdb = new MythDB(); 00033 dbLock.unlock(); 00034 00035 return mythdb; 00036 } 00037 00038 void MythDB::destroyMythDB(void) 00039 { 00040 dbLock.lock(); 00041 delete mythdb; 00042 mythdb = NULL; 00043 dbLock.unlock(); 00044 } 00045 00046 MythDB *GetMythDB(void) 00047 { 00048 return MythDB::getMythDB(); 00049 } 00050 00051 void DestroyMythDB(void) 00052 { 00053 MythDB::destroyMythDB(); 00054 } 00055 00056 struct SingleSetting 00057 { 00058 QString key; 00059 QString value; 00060 QString host; 00061 }; 00062 00063 typedef QHash<QString,QString> SettingsMap; 00064 00065 class MythDBPrivate 00066 { 00067 public: 00068 MythDBPrivate(); 00069 ~MythDBPrivate(); 00070 00071 DatabaseParams m_DBparams; 00072 QString m_localhostname; 00073 MDBManager m_dbmanager; 00074 00075 bool ignoreDatabase; 00076 bool suppressDBMessages; 00077 00078 QReadWriteLock settingsCacheLock; 00079 volatile bool useSettingsCache; 00081 SettingsMap settingsCache; 00083 SettingsMap overriddenSettings; 00086 QList<SingleSetting> delayedSettings; 00087 00088 bool haveDBConnection; 00089 bool haveSchema; 00090 }; 00091 00092 static const int settings_reserve = 61; 00093 00094 MythDBPrivate::MythDBPrivate() : 00095 ignoreDatabase(false), suppressDBMessages(true), useSettingsCache(false), 00096 haveDBConnection(false), haveSchema(false) 00097 { 00098 m_localhostname.clear(); 00099 settingsCache.reserve(settings_reserve); 00100 } 00101 00102 MythDBPrivate::~MythDBPrivate() 00103 { 00104 LOG(VB_DATABASE, LOG_INFO, "Destroying MythDBPrivate"); 00105 } 00106 00107 MythDB::MythDB() 00108 { 00109 d = new MythDBPrivate(); 00110 } 00111 00112 MythDB::~MythDB() 00113 { 00114 delete d; 00115 } 00116 00117 MDBManager *MythDB::GetDBManager(void) 00118 { 00119 return &(d->m_dbmanager); 00120 } 00121 00122 QString MythDB::toCommaList(const QMap<QString, QVariant> &bindings, 00123 uint indent, uint maxColumn) 00124 { 00125 QMap<QString, QVariant>::const_iterator it = bindings.begin(); 00126 if (it == bindings.end()) 00127 return ""; 00128 00129 uint curColumn = indent; 00130 QString str = QString("%1").arg("", indent); 00131 for (; it != bindings.end(); ++it) 00132 { 00133 QString val = (*it).toString(); 00134 if ((*it).isNull()) 00135 { 00136 val = "NULL"; 00137 } 00138 else if (it->type() == QVariant::String) 00139 { 00140 val = (it->toString().isNull()) ? 00141 "NULL" : QString("\"%1\"").arg(val); 00142 } 00143 const QString curBinding = it.key() + '=' + val + ','; 00144 if ((curColumn > indent) && 00145 ((curBinding.length() + curColumn) > maxColumn)) 00146 { 00147 str += '\n'; 00148 str += QString("%1").arg("", indent); 00149 curColumn = indent; 00150 } 00151 if (curColumn > indent) 00152 { 00153 str += ' '; 00154 curColumn++; 00155 } 00156 str += curBinding; 00157 curColumn += curBinding.length(); 00158 } 00159 str = str.left(str.length() - 1); // remove trailing comma. 00160 str += '\n'; 00161 00162 return str; 00163 } 00164 00165 QString MythDB::GetError(const QString &where, const MSqlQuery &query) 00166 { 00167 QString str = QString("DB Error (%1):\n").arg(where); 00168 00169 str += "Query was:\n"; 00170 str += query.executedQuery() + '\n'; 00171 QString tmp = toCommaList(query.boundValues()); 00172 if (!tmp.isEmpty()) 00173 { 00174 str += "Bindings were:\n"; 00175 str += tmp; 00176 } 00177 str += DBErrorMessage(query.lastError()); 00178 return str; 00179 } 00180 00181 void MythDB::DBError(const QString &where, const MSqlQuery &query) 00182 { 00183 LOG(VB_GENERAL, LOG_ERR, GetError(where, query)); 00184 } 00185 00186 QString MythDB::DBErrorMessage(const QSqlError& err) 00187 { 00188 if (!err.type()) 00189 return "No error type from QSqlError? Strange..."; 00190 00191 return QString("Driver error was [%1/%2]:\n" 00192 "%3\n" 00193 "Database error was:\n" 00194 "%4\n") 00195 .arg(err.type()) 00196 .arg(err.number()) 00197 .arg(err.driverText()) 00198 .arg(err.databaseText()); 00199 } 00200 00201 DatabaseParams MythDB::GetDatabaseParams(void) const 00202 { 00203 return d->m_DBparams; 00204 } 00205 00206 void MythDB::SetDatabaseParams(const DatabaseParams ¶ms) 00207 { 00208 d->m_DBparams = params; 00209 } 00210 00211 void MythDB::SetLocalHostname(const QString &name) 00212 { 00213 if (d->m_localhostname != name.toLower()) 00214 { 00215 d->m_localhostname = name.toLower(); 00216 ClearSettingsCache(); 00217 } 00218 } 00219 00220 QString MythDB::GetHostName(void) const 00221 { 00222 return d->m_localhostname; 00223 } 00224 00225 void MythDB::IgnoreDatabase(bool bIgnore) 00226 { 00227 d->ignoreDatabase = bIgnore; 00228 } 00229 00230 bool MythDB::IsDatabaseIgnored(void) const 00231 { 00232 return d->ignoreDatabase; 00233 } 00234 00235 void MythDB::SetSuppressDBMessages(bool bUpgraded) 00236 { 00237 d->suppressDBMessages = bUpgraded; 00238 } 00239 00240 bool MythDB::SuppressDBMessages(void) const 00241 { 00242 return d->suppressDBMessages; 00243 } 00244 00245 void MythDB::SaveSetting(const QString &key, int newValue) 00246 { 00247 (void) SaveSettingOnHost(key, 00248 QString::number(newValue), d->m_localhostname); 00249 } 00250 00251 void MythDB::SaveSetting(const QString &key, const QString &newValue) 00252 { 00253 (void) SaveSettingOnHost(key, newValue, d->m_localhostname); 00254 } 00255 00256 bool MythDB::SaveSettingOnHost(const QString &key, 00257 const QString &newValueRaw, 00258 const QString &host) 00259 { 00260 QString loc = QString("SaveSettingOnHost('%1') ").arg(key); 00261 if (key.isEmpty()) 00262 { 00263 LOG(VB_GENERAL, LOG_ERR, loc + "- Illegal null key"); 00264 return false; 00265 } 00266 00267 QString newValue = (newValueRaw.isNull()) ? "" : newValueRaw; 00268 00269 if (d->ignoreDatabase) 00270 { 00271 if (host.toLower() == d->m_localhostname) 00272 { 00273 if (newValue != kClearSettingValue) 00274 OverrideSettingForSession(key, newValue); 00275 else 00276 ClearOverrideSettingForSession(key); 00277 } 00278 return true; 00279 } 00280 00281 if (!HaveValidDatabase()) // Bootstrapping without database? 00282 { 00283 if (host.toLower() == d->m_localhostname) 00284 OverrideSettingForSession(key, newValue); 00285 if (!d->suppressDBMessages) 00286 LOG(VB_GENERAL, LOG_ERR, loc + "- No database yet"); 00287 SingleSetting setting; 00288 setting.host = host; 00289 setting.key = key; 00290 setting.value = newValue; 00291 d->delayedSettings.append(setting); 00292 return false; 00293 } 00294 00295 bool success = false; 00296 00297 MSqlQuery query(MSqlQuery::InitCon()); 00298 if (query.isConnected()) 00299 { 00300 00301 if (!host.isEmpty()) 00302 query.prepare("DELETE FROM settings WHERE value = :KEY " 00303 "AND hostname = :HOSTNAME ;"); 00304 else 00305 query.prepare("DELETE FROM settings WHERE value = :KEY " 00306 "AND hostname is NULL;"); 00307 00308 query.bindValue(":KEY", key); 00309 if (!host.isEmpty()) 00310 query.bindValue(":HOSTNAME", host); 00311 00312 if (!query.exec()) 00313 { 00314 if (!GetMythDB()->SuppressDBMessages()) 00315 MythDB::DBError("Clear setting", query); 00316 } 00317 else 00318 { 00319 success = true; 00320 } 00321 } 00322 00323 if (success && (newValue != kClearSettingValue)) 00324 { 00325 if (!host.isEmpty()) 00326 query.prepare("INSERT INTO settings (value,data,hostname) " 00327 "VALUES ( :VALUE, :DATA, :HOSTNAME );"); 00328 else 00329 query.prepare("INSERT INTO settings (value,data ) " 00330 "VALUES ( :VALUE, :DATA );"); 00331 00332 query.bindValue(":VALUE", key); 00333 query.bindValue(":DATA", newValue); 00334 if (!host.isEmpty()) 00335 query.bindValue(":HOSTNAME", host); 00336 00337 if (!query.exec()) 00338 { 00339 success = false; 00340 if (!(GetMythDB()->SuppressDBMessages())) 00341 MythDB::DBError(loc + "- query failure: ", query); 00342 } 00343 } 00344 else if (!success) 00345 { 00346 LOG(VB_GENERAL, LOG_ERR, loc + "- database not open"); 00347 } 00348 00349 ClearSettingsCache(host + ' ' + key); 00350 00351 return success; 00352 } 00353 00354 bool MythDB::ClearSetting(const QString &key) 00355 { 00356 return ClearSettingOnHost(key, d->m_localhostname); 00357 } 00358 00359 bool MythDB::ClearSettingOnHost(const QString &key, const QString &host) 00360 { 00361 return SaveSettingOnHost(key, kClearSettingValue, host); 00362 } 00363 00364 QString MythDB::GetSetting(const QString &_key, const QString &defaultval) 00365 { 00366 QString key = _key.toLower(); 00367 QString value = defaultval; 00368 00369 d->settingsCacheLock.lockForRead(); 00370 if (d->useSettingsCache) 00371 { 00372 SettingsMap::const_iterator it = d->settingsCache.find(key); 00373 if (it != d->settingsCache.end()) 00374 { 00375 value = *it; 00376 d->settingsCacheLock.unlock(); 00377 return value; 00378 } 00379 } 00380 SettingsMap::const_iterator it = d->overriddenSettings.find(key); 00381 if (it != d->overriddenSettings.end()) 00382 { 00383 value = *it; 00384 d->settingsCacheLock.unlock(); 00385 return value; 00386 } 00387 d->settingsCacheLock.unlock(); 00388 00389 if (d->ignoreDatabase || !HaveValidDatabase()) 00390 return value; 00391 00392 MSqlQuery query(MSqlQuery::InitCon()); 00393 if (!query.isConnected()) 00394 return value; 00395 00396 query.prepare( 00397 "SELECT data " 00398 "FROM settings " 00399 "WHERE value = :KEY AND hostname = :HOSTNAME"); 00400 query.bindValue(":KEY", key); 00401 query.bindValue(":HOSTNAME", d->m_localhostname); 00402 00403 if (query.exec() && query.next()) 00404 { 00405 value = query.value(0).toString(); 00406 } 00407 else 00408 { 00409 query.prepare( 00410 "SELECT data " 00411 "FROM settings " 00412 "WHERE value = :KEY AND hostname IS NULL"); 00413 query.bindValue(":KEY", key); 00414 00415 if (query.exec() && query.next()) 00416 { 00417 value = query.value(0).toString(); 00418 } 00419 } 00420 00421 if (d->useSettingsCache && value != kSentinelValue) 00422 { 00423 key.squeeze(); 00424 value.squeeze(); 00425 d->settingsCacheLock.lockForWrite(); 00426 // another thread may have inserted a value into the cache 00427 // while we did not have the lock, check first then save 00428 if (d->settingsCache.find(key) == d->settingsCache.end()) 00429 d->settingsCache[key] = value; 00430 d->settingsCacheLock.unlock(); 00431 } 00432 00433 return value; 00434 } 00435 00436 bool MythDB::GetSettings(QMap<QString,QString> &_key_value_pairs) 00437 { 00438 QMap<QString,bool> done; 00439 typedef QMap<QString,QString>::iterator KVIt; 00440 KVIt kvit = _key_value_pairs.begin(); 00441 for (; kvit != _key_value_pairs.end(); ++kvit) 00442 done[kvit.key().toLower()] = false; 00443 00444 QMap<QString,bool>::iterator dit = done.begin(); 00445 kvit = _key_value_pairs.begin(); 00446 00447 { 00448 uint done_cnt = 0; 00449 d->settingsCacheLock.lockForRead(); 00450 if (d->useSettingsCache) 00451 { 00452 for (; kvit != _key_value_pairs.end(); ++dit, ++kvit) 00453 { 00454 SettingsMap::const_iterator it = d->settingsCache.find(dit.key()); 00455 if (it != d->settingsCache.end()) 00456 { 00457 *kvit = *it; 00458 *dit = true; 00459 done_cnt++; 00460 } 00461 } 00462 } 00463 for (; kvit != _key_value_pairs.end(); ++dit, ++kvit) 00464 { 00465 SettingsMap::const_iterator it = 00466 d->overriddenSettings.find(dit.key()); 00467 if (it != d->overriddenSettings.end()) 00468 { 00469 *kvit = *it; 00470 *dit = true; 00471 done_cnt++; 00472 } 00473 } 00474 d->settingsCacheLock.unlock(); 00475 00476 // Avoid extra work if everything was in the caches and 00477 // also don't try to access the DB if ignoreDatabase is set 00478 if (((uint)done.size()) == done_cnt || d->ignoreDatabase) 00479 return true; 00480 } 00481 00482 dit = done.begin(); 00483 kvit = _key_value_pairs.begin(); 00484 00485 QString keylist(""); 00486 QMap<QString,KVIt> keymap; 00487 for (; kvit != _key_value_pairs.end(); ++dit, ++kvit) 00488 { 00489 if (*dit) 00490 continue; 00491 00492 QString key = dit.key(); 00493 if (!key.contains("'")) 00494 { 00495 keylist += QString("'%1',").arg(key); 00496 keymap[key] = kvit; 00497 } 00498 else 00499 { // hopefully no one actually uses quotes for in a settings key. 00500 // but in case they do, just get that value inefficiently.. 00501 *kvit = GetSetting(key, *kvit); 00502 } 00503 } 00504 00505 if (keylist.isEmpty()) 00506 return true; 00507 00508 keylist = keylist.left(keylist.length() - 1); 00509 00510 MSqlQuery query(MSqlQuery::InitCon()); 00511 if (!query.exec( 00512 QString( 00513 "SELECT value, data, hostname " 00514 "FROM settings " 00515 "WHERE (hostname = '%1' OR hostname IS NULL) AND " 00516 " value IN (%2) " 00517 "ORDER BY hostname DESC") 00518 .arg(d->m_localhostname).arg(keylist))) 00519 { 00520 if (!d->suppressDBMessages) 00521 DBError("GetSettings", query); 00522 return false; 00523 } 00524 00525 while (query.next()) 00526 { 00527 QString key = query.value(0).toString().toLower(); 00528 QMap<QString,KVIt>::const_iterator it = keymap.find(key); 00529 if (it != keymap.end()) 00530 **it = query.value(1).toString(); 00531 } 00532 00533 if (d->useSettingsCache) 00534 { 00535 d->settingsCacheLock.lockForWrite(); 00536 QMap<QString,KVIt>::const_iterator it = keymap.begin(); 00537 for (; it != keymap.end(); ++it) 00538 { 00539 QString key = it.key(), value = **it; 00540 00541 // another thread may have inserted a value into the cache 00542 // while we did not have the lock, check first then save 00543 if (d->settingsCache.find(key) == d->settingsCache.end()) 00544 { 00545 key.squeeze(); 00546 value.squeeze(); 00547 d->settingsCache[key] = value; 00548 } 00549 } 00550 d->settingsCacheLock.unlock(); 00551 } 00552 00553 return true; 00554 } 00555 00556 00557 int MythDB::GetNumSetting(const QString &key, int defaultval) 00558 { 00559 QString val = QString::number(defaultval); 00560 QString retval = GetSetting(key, val); 00561 00562 return retval.toInt(); 00563 } 00564 00565 double MythDB::GetFloatSetting(const QString &key, double defaultval) 00566 { 00567 QString val = QString::number(defaultval); 00568 QString retval = GetSetting(key, val); 00569 00570 return retval.toDouble(); 00571 } 00572 00573 QString MythDB::GetSetting(const QString &key) 00574 { 00575 QString sentinel = QString(kSentinelValue); 00576 QString retval = GetSetting(key, sentinel); 00577 return (retval == sentinel) ? "" : retval; 00578 } 00579 00580 int MythDB::GetNumSetting(const QString &key) 00581 { 00582 QString sentinel = QString(kSentinelValue); 00583 QString retval = GetSetting(key, sentinel); 00584 return (retval == sentinel) ? 0 : retval.toInt(); 00585 } 00586 00587 double MythDB::GetFloatSetting(const QString &key) 00588 { 00589 QString sentinel = QString(kSentinelValue); 00590 QString retval = GetSetting(key, sentinel); 00591 return (retval == sentinel) ? 0.0 : retval.toDouble(); 00592 } 00593 00594 QString MythDB::GetSettingOnHost(const QString &_key, const QString &_host, 00595 const QString &defaultval) 00596 { 00597 QString key = _key.toLower(); 00598 QString host = _host.toLower(); 00599 QString value = defaultval; 00600 QString myKey = host + ' ' + key; 00601 00602 d->settingsCacheLock.lockForRead(); 00603 if (d->useSettingsCache) 00604 { 00605 SettingsMap::const_iterator it = d->settingsCache.find(myKey); 00606 if (it != d->settingsCache.end()) 00607 { 00608 value = *it; 00609 d->settingsCacheLock.unlock(); 00610 return value; 00611 } 00612 } 00613 SettingsMap::const_iterator it = d->overriddenSettings.find(myKey); 00614 if (it != d->overriddenSettings.end()) 00615 { 00616 value = *it; 00617 d->settingsCacheLock.unlock(); 00618 return value; 00619 } 00620 d->settingsCacheLock.unlock(); 00621 00622 if (d->ignoreDatabase) 00623 return value; 00624 00625 MSqlQuery query(MSqlQuery::InitCon()); 00626 if (!query.isConnected()) 00627 { 00628 if (!d->suppressDBMessages) 00629 LOG(VB_GENERAL, LOG_ERR, 00630 QString("Database not open while trying to " 00631 "load setting: %1").arg(key)); 00632 return value; 00633 } 00634 00635 query.prepare( 00636 "SELECT data " 00637 "FROM settings " 00638 "WHERE value = :VALUE AND hostname = :HOSTNAME"); 00639 query.bindValue(":VALUE", key); 00640 query.bindValue(":HOSTNAME", host); 00641 00642 if (query.exec() && query.next()) 00643 { 00644 value = query.value(0).toString(); 00645 } 00646 00647 if (d->useSettingsCache && value != kSentinelValue) 00648 { 00649 myKey.squeeze(); 00650 value.squeeze(); 00651 d->settingsCacheLock.lockForWrite(); 00652 if (d->settingsCache.find(myKey) == d->settingsCache.end()) 00653 d->settingsCache[myKey] = value; 00654 d->settingsCacheLock.unlock(); 00655 } 00656 00657 return value; 00658 } 00659 00660 int MythDB::GetNumSettingOnHost(const QString &key, const QString &host, 00661 int defaultval) 00662 { 00663 QString val = QString::number(defaultval); 00664 QString retval = GetSettingOnHost(key, host, val); 00665 00666 return retval.toInt(); 00667 } 00668 00669 double MythDB::GetFloatSettingOnHost( 00670 const QString &key, const QString &host, double defaultval) 00671 { 00672 QString val = QString::number(defaultval); 00673 QString retval = GetSettingOnHost(key, host, val); 00674 00675 return retval.toDouble(); 00676 } 00677 00678 QString MythDB::GetSettingOnHost(const QString &key, const QString &host) 00679 { 00680 QString sentinel = QString(kSentinelValue); 00681 QString retval = GetSettingOnHost(key, host, sentinel); 00682 return (retval == sentinel) ? "" : retval; 00683 } 00684 00685 int MythDB::GetNumSettingOnHost(const QString &key, const QString &host) 00686 { 00687 QString sentinel = QString(kSentinelValue); 00688 QString retval = GetSettingOnHost(key, host, sentinel); 00689 return (retval == sentinel) ? 0 : retval.toInt(); 00690 } 00691 00692 double MythDB::GetFloatSettingOnHost(const QString &key, const QString &host) 00693 { 00694 QString sentinel = QString(kSentinelValue); 00695 QString retval = GetSettingOnHost(key, host, sentinel); 00696 return (retval == sentinel) ? 0.0 : retval.toDouble(); 00697 } 00698 00699 void MythDB::GetResolutionSetting(const QString &type, 00700 int &width, int &height, 00701 double &forced_aspect, 00702 double &refresh_rate, 00703 int index) 00704 { 00705 bool ok = false, ok0 = false, ok1 = false; 00706 QString sRes = QString("%1Resolution").arg(type); 00707 QString sRR = QString("%1RefreshRate").arg(type); 00708 QString sAspect = QString("%1ForceAspect").arg(type); 00709 QString sWidth = QString("%1Width").arg(type); 00710 QString sHeight = QString("%1Height").arg(type); 00711 if (index >= 0) 00712 { 00713 sRes = QString("%1Resolution%2").arg(type).arg(index); 00714 sRR = QString("%1RefreshRate%2").arg(type).arg(index); 00715 sAspect = QString("%1ForceAspect%2").arg(type).arg(index); 00716 sWidth = QString("%1Width%2").arg(type).arg(index); 00717 sHeight = QString("%1Height%2").arg(type).arg(index); 00718 } 00719 00720 QString res = GetSetting(sRes); 00721 00722 if (!res.isEmpty()) 00723 { 00724 QStringList slist = res.split(QString("x")); 00725 int w = width, h = height; 00726 if (2 == slist.size()) 00727 { 00728 w = slist[0].toInt(&ok0); 00729 h = slist[1].toInt(&ok1); 00730 } 00731 bool ok = ok0 && ok1; 00732 if (ok) 00733 { 00734 width = w; 00735 height = h; 00736 refresh_rate = GetFloatSetting(sRR); 00737 forced_aspect = GetFloatSetting(sAspect); 00738 } 00739 } 00740 else 00741 00742 if (!ok) 00743 { 00744 int tmpWidth = GetNumSetting(sWidth, width); 00745 if (tmpWidth) 00746 width = tmpWidth; 00747 00748 int tmpHeight = GetNumSetting(sHeight, height); 00749 if (tmpHeight) 00750 height = tmpHeight; 00751 00752 refresh_rate = 0.0; 00753 forced_aspect = 0.0; 00754 //SetSetting(sRes, QString("%1x%2").arg(width).arg(height)); 00755 } 00756 } 00757 00758 void MythDB::GetResolutionSetting(const QString &t, int &w, int &h, int i) 00759 { 00760 double forced_aspect = 0; 00761 double refresh_rate = 0.0; 00762 GetResolutionSetting(t, w, h, forced_aspect, refresh_rate, i); 00763 } 00764 00765 00772 void MythDB::OverrideSettingForSession( 00773 const QString &key, const QString &value) 00774 { 00775 QString mk = key.toLower(), mk2 = d->m_localhostname + ' ' + mk, mv = value; 00776 if ("dbschemaver" == mk) 00777 { 00778 LOG(VB_GENERAL, LOG_ERR, 00779 QString("ERROR: Refusing to allow override for '%1'.").arg(key)); 00780 return; 00781 } 00782 mk.squeeze(); 00783 mk2.squeeze(); 00784 mv.squeeze(); 00785 00786 d->settingsCacheLock.lockForWrite(); 00787 d->overriddenSettings[mk] = mv; 00788 d->settingsCache[mk] = mv; 00789 d->settingsCache[mk2] = mv; 00790 d->settingsCacheLock.unlock(); 00791 } 00792 00794 void MythDB::ClearOverrideSettingForSession(const QString &key) 00795 { 00796 QString mk = key.toLower(); 00797 QString mk2 = d->m_localhostname + ' ' + mk; 00798 00799 d->settingsCacheLock.lockForWrite(); 00800 00801 SettingsMap::iterator oit = d->overriddenSettings.find(mk); 00802 if (oit != d->overriddenSettings.end()) 00803 d->overriddenSettings.erase(oit); 00804 00805 SettingsMap::iterator sit = d->settingsCache.find(mk); 00806 if (sit != d->settingsCache.end()) 00807 d->settingsCache.erase(sit); 00808 00809 sit = d->settingsCache.find(mk2); 00810 if (sit != d->settingsCache.end()) 00811 d->settingsCache.erase(sit); 00812 00813 d->settingsCacheLock.unlock(); 00814 } 00815 00816 static void clear( 00817 SettingsMap &cache, SettingsMap &overrides, const QString &myKey) 00818 { 00819 // Do the actual clearing.. 00820 SettingsMap::iterator it = cache.find(myKey); 00821 if (it != cache.end()) 00822 { 00823 SettingsMap::const_iterator oit = overrides.find(myKey); 00824 if (oit == overrides.end()) 00825 { 00826 LOG(VB_DATABASE, LOG_INFO, 00827 QString("Clearing Settings Cache for '%1'.").arg(myKey)); 00828 cache.erase(it); 00829 } 00830 else 00831 { 00832 LOG(VB_DATABASE, LOG_INFO, 00833 QString("Clearing Cache of overridden '%1' ignored.") 00834 .arg(myKey)); 00835 } 00836 } 00837 } 00838 00839 void MythDB::ClearSettingsCache(const QString &_key) 00840 { 00841 d->settingsCacheLock.lockForWrite(); 00842 00843 if (_key.isEmpty()) 00844 { 00845 LOG(VB_DATABASE, LOG_INFO, "Clearing Settings Cache."); 00846 d->settingsCache.clear(); 00847 d->settingsCache.reserve(settings_reserve); 00848 00849 SettingsMap::const_iterator it = d->overriddenSettings.begin(); 00850 for (; it != d->overriddenSettings.end(); ++it) 00851 { 00852 QString mk2 = d->m_localhostname + ' ' + it.key(); 00853 mk2.squeeze(); 00854 00855 d->settingsCache[it.key()] = *it; 00856 d->settingsCache[mk2] = *it; 00857 } 00858 } 00859 else 00860 { 00861 QString myKey = _key.toLower(); 00862 clear(d->settingsCache, d->overriddenSettings, myKey); 00863 00864 // To be safe always clear any local[ized] version too 00865 QString mkl = myKey.section(QChar(' '), 1); 00866 if (!mkl.isEmpty()) 00867 clear(d->settingsCache, d->overriddenSettings, mkl); 00868 } 00869 00870 d->settingsCacheLock.unlock(); 00871 } 00872 00873 void MythDB::ActivateSettingsCache(bool activate) 00874 { 00875 if (activate) 00876 LOG(VB_DATABASE, LOG_INFO, "Enabling Settings Cache."); 00877 else 00878 LOG(VB_DATABASE, LOG_INFO, "Disabling Settings Cache."); 00879 00880 d->useSettingsCache = activate; 00881 ClearSettingsCache(); 00882 } 00883 00884 void MythDB::WriteDelayedSettings(void) 00885 { 00886 if (!HaveValidDatabase()) 00887 return; 00888 00889 if (!gCoreContext->IsUIThread()) 00890 return; 00891 00892 while (!d->delayedSettings.isEmpty()) 00893 { 00894 SingleSetting setting = d->delayedSettings.takeFirst(); 00895 SaveSettingOnHost(setting.key, setting.value, setting.host); 00896 } 00897 } 00898 00902 void MythDB::SetHaveDBConnection(bool connected) 00903 { 00904 d->haveDBConnection = connected; 00905 } 00906 00911 void MythDB::SetHaveSchema(bool schema) 00912 { 00913 d->haveSchema = schema; 00914 } 00915 00923 bool MythDB::HaveSchema(void) const 00924 { 00925 return d->haveSchema; 00926 } 00927 00935 bool MythDB::HaveValidDatabase(void) const 00936 { 00937 return (d->haveDBConnection && d->haveSchema); 00938 }
1.7.6.1