MythTV  master
mythdb.cpp
Go to the documentation of this file.
1 #include <vector>
2 using namespace std;
3 
4 #include <QReadWriteLock>
5 #include <QTextStream>
6 #include <QSqlError>
7 #include <QMutex>
8 #include <QFile>
9 #include <QHash>
10 #include <QDir>
11 
12 #include "mythdb.h"
13 #include "mythdbcon.h"
14 #include "mythlogging.h"
15 #include "mythdirs.h"
16 #include "mythcorecontext.h"
17 
18 static MythDB *mythdb = nullptr;
19 static QMutex dbLock;
20 
21 // For thread safety reasons this is not a QString
22 const char *kSentinelValue = "<settings_sentinel_value>";
23 const char *kClearSettingValue = "<clear_setting_value>";
24 
25 MythDB *MythDB::getMythDB(void)
26 {
27  if (mythdb)
28  return mythdb;
29 
30  dbLock.lock();
31  if (!mythdb)
32  mythdb = new MythDB();
33  dbLock.unlock();
34 
35  return mythdb;
36 }
37 
39 {
40  dbLock.lock();
41  delete mythdb;
42  mythdb = nullptr;
43  dbLock.unlock();
44 }
45 
46 MythDB *GetMythDB(void)
47 {
48  return MythDB::getMythDB();
49 }
50 
51 void DestroyMythDB(void)
52 {
54 }
55 
57 {
58  QString m_key;
59  QString m_value;
60  QString m_host;
61 };
62 
63 using SettingsMap = QHash<QString,QString>;
64 
66 {
67  public:
68  MythDBPrivate();
69  ~MythDBPrivate();
70 
72  QString m_localhostname;
74 
75  bool m_ignoreDatabase {false};
76  bool m_suppressDBMessages {true};
77 
78  QReadWriteLock m_settingsCacheLock;
79  volatile bool m_useSettingsCache {false};
86  QList<SingleSetting> m_delayedSettings;
87 
88  bool m_haveDBConnection {false};
89  bool m_haveSchema {false};
90 };
91 
92 static const int settings_reserve = 61;
93 
95 {
96  m_localhostname.clear();
97  m_settingsCache.reserve(settings_reserve);
98 }
99 
101 {
102  LOG(VB_DATABASE, LOG_INFO, "Destroying MythDBPrivate");
103 }
104 
106 {
107  d = new MythDBPrivate();
108 }
109 
111 {
112  delete d;
113 }
114 
116 {
117  return &(d->m_dbmanager);
118 }
119 
120 QString MythDB::toCommaList(const QMap<QString, QVariant> &bindings,
121  uint indent, uint maxColumn)
122 {
123  QMap<QString, QVariant>::const_iterator it = bindings.begin();
124  if (it == bindings.end())
125  return "";
126 
127  uint curColumn = indent;
128  QString str = QString("%1").arg("", indent);
129  for (; it != bindings.end(); ++it)
130  {
131  QString val = (*it).toString();
132  if ((*it).isNull())
133  {
134  val = "NULL";
135  }
136  else if (it->type() == QVariant::String)
137  {
138  val = (it->toString().isNull()) ?
139  "NULL" : QString("\"%1\"").arg(val);
140  }
141  const QString curBinding = it.key() + '=' + val + ',';
142  if ((curColumn > indent) &&
143  ((curBinding.length() + curColumn) > maxColumn))
144  {
145  str += '\n';
146  str += QString("%1").arg("", indent);
147  curColumn = indent;
148  }
149  if (curColumn > indent)
150  {
151  str += ' ';
152  curColumn++;
153  }
154  str += curBinding;
155  curColumn += curBinding.length();
156  }
157  str = str.left(str.length() - 1); // remove trailing comma.
158  str += '\n';
159 
160  return str;
161 }
162 
163 QString MythDB::GetError(const QString &where, const MSqlQuery &query)
164 {
165  QString str = QString("DB Error (%1):\n").arg(where);
166 
167  str += "Query was:\n";
168  str += query.executedQuery() + '\n';
169  QString tmp = toCommaList(query.boundValues());
170  if (!tmp.isEmpty())
171  {
172  str += "Bindings were:\n";
173  str += tmp;
174  }
175  str += DBErrorMessage(query.lastError());
176  return str;
177 }
178 
179 void MythDB::DBError(const QString &where, const MSqlQuery &query)
180 {
181  LOG(VB_GENERAL, LOG_ERR, GetError(where, query));
182 }
183 
184 QString MythDB::DBErrorMessage(const QSqlError& err)
185 {
186  if (!err.type())
187  return "No error type from QSqlError? Strange...";
188 
189  return QString("Driver error was [%1/%2]:\n"
190  "%3\n"
191  "Database error was:\n"
192  "%4\n")
193  .arg(err.type())
194  .arg(err.nativeErrorCode())
195  .arg(err.driverText())
196  .arg(err.databaseText());
197 }
198 
200 {
201  return d->m_dbParams;
202 }
203 
205 {
206  d->m_dbParams = params;
207 }
208 
209 void MythDB::SetLocalHostname(const QString &name)
210 {
211  if (d->m_localhostname != name.toLower())
212  {
213  d->m_localhostname = name.toLower();
215  }
216 }
217 
218 QString MythDB::GetHostName(void) const
219 {
220  return d->m_localhostname;
221 }
222 
223 void MythDB::IgnoreDatabase(bool bIgnore)
224 {
225  d->m_ignoreDatabase = bIgnore;
226 }
227 
229 {
230  return d->m_ignoreDatabase;
231 }
232 
233 void MythDB::SetSuppressDBMessages(bool bUpgraded)
234 {
235  d->m_suppressDBMessages = bUpgraded;
236 }
237 
239 {
240  return d->m_suppressDBMessages;
241 }
242 
243 void MythDB::SaveSetting(const QString &key, int newValue)
244 {
245  (void) SaveSettingOnHost(key,
246  QString::number(newValue), d->m_localhostname);
247 }
248 
249 void MythDB::SaveSetting(const QString &key, const QString &newValue)
250 {
251  (void) SaveSettingOnHost(key, newValue, d->m_localhostname);
252 }
253 
254 bool MythDB::SaveSettingOnHost(const QString &key,
255  const QString &newValueRaw,
256  const QString &host)
257 {
258  QString loc = QString("SaveSettingOnHost('%1') ").arg(key);
259  if (key.isEmpty())
260  {
261  LOG(VB_GENERAL, LOG_ERR, loc + "- Illegal null key");
262  return false;
263  }
264 
265  QString newValue = (newValueRaw.isNull()) ? "" : newValueRaw;
266 
267  if (d->m_ignoreDatabase)
268  {
269  if (host.toLower() == d->m_localhostname)
270  {
271  if (newValue != kClearSettingValue)
272  OverrideSettingForSession(key, newValue);
273  else
274  ClearOverrideSettingForSession(key);
275  }
276  return true;
277  }
278 
279  if (!HaveValidDatabase()) // Bootstrapping without database?
280  {
281  if (host.toLower() == d->m_localhostname)
282  OverrideSettingForSession(key, newValue);
283  if (!d->m_suppressDBMessages)
284  LOG(VB_GENERAL, LOG_ERR, loc + "- No database yet");
285  SingleSetting setting;
286  setting.m_host = host;
287  setting.m_key = key;
288  setting.m_value = newValue;
289  d->m_delayedSettings.append(setting);
290  return false;
291  }
292 
293  bool success = false;
294 
296  if (query.isConnected())
297  {
298 
299  if (!host.isEmpty())
300  {
301  query.prepare("DELETE FROM settings WHERE value = :KEY "
302  "AND hostname = :HOSTNAME ;");
303  }
304  else
305  {
306  query.prepare("DELETE FROM settings WHERE value = :KEY "
307  "AND hostname is NULL;");
308  }
309 
310  query.bindValue(":KEY", key);
311  if (!host.isEmpty())
312  query.bindValue(":HOSTNAME", host);
313 
314  if (!query.exec())
315  {
316  if (!GetMythDB()->SuppressDBMessages())
317  MythDB::DBError("Clear setting", query);
318  }
319  else
320  {
321  success = true;
322  }
323  }
324 
325  if (success && (newValue != kClearSettingValue))
326  {
327  if (!host.isEmpty())
328  {
329  query.prepare("INSERT INTO settings (value,data,hostname) "
330  "VALUES ( :VALUE, :DATA, :HOSTNAME );");
331  }
332  else
333  {
334  query.prepare("INSERT INTO settings (value,data ) "
335  "VALUES ( :VALUE, :DATA );");
336  }
337 
338  query.bindValue(":VALUE", key);
339  query.bindValue(":DATA", newValue);
340  if (!host.isEmpty())
341  query.bindValue(":HOSTNAME", host);
342 
343  if (!query.exec())
344  {
345  success = false;
346  if (!(GetMythDB()->SuppressDBMessages()))
347  MythDB::DBError(loc + "- query failure: ", query);
348  }
349  }
350  else if (!success)
351  {
352  LOG(VB_GENERAL, LOG_ERR, loc + "- database not open");
353  }
354 
355  ClearSettingsCache(host + ' ' + key);
356 
357  return success;
358 }
359 
360 bool MythDB::ClearSetting(const QString &key)
361 {
362  return ClearSettingOnHost(key, d->m_localhostname);
363 }
364 
365 bool MythDB::ClearSettingOnHost(const QString &key, const QString &host)
366 {
367  return SaveSettingOnHost(key, kClearSettingValue, host);
368 }
369 
370 QString MythDB::GetSetting(const QString &_key, const QString &defaultval)
371 {
372  QString key = _key.toLower();
373  QString value = defaultval;
374 
375  d->m_settingsCacheLock.lockForRead();
376  if (d->m_useSettingsCache)
377  {
378  SettingsMap::const_iterator it = d->m_settingsCache.find(key);
379  if (it != d->m_settingsCache.end())
380  {
381  value = *it;
382  d->m_settingsCacheLock.unlock();
383  return value;
384  }
385  }
386  SettingsMap::const_iterator it = d->m_overriddenSettings.find(key);
387  if (it != d->m_overriddenSettings.end())
388  {
389  value = *it;
390  d->m_settingsCacheLock.unlock();
391  return value;
392  }
393  d->m_settingsCacheLock.unlock();
394 
395  if (d->m_ignoreDatabase || !HaveValidDatabase())
396  return value;
397 
399  if (!query.isConnected())
400  return value;
401 
402  query.prepare(
403  "SELECT data "
404  "FROM settings "
405  "WHERE value = :KEY AND hostname = :HOSTNAME");
406  query.bindValue(":KEY", key);
407  query.bindValue(":HOSTNAME", d->m_localhostname);
408 
409  if (query.exec() && query.next())
410  {
411  value = query.value(0).toString();
412  }
413  else
414  {
415  query.prepare(
416  "SELECT data "
417  "FROM settings "
418  "WHERE value = :KEY AND hostname IS NULL");
419  query.bindValue(":KEY", key);
420 
421  if (query.exec() && query.next())
422  {
423  value = query.value(0).toString();
424  }
425  }
426 
427  if (d->m_useSettingsCache && value != kSentinelValue)
428  {
429  key.squeeze();
430  value.squeeze();
431  d->m_settingsCacheLock.lockForWrite();
432  // another thread may have inserted a value into the cache
433  // while we did not have the lock, check first then save
434  if (d->m_settingsCache.find(key) == d->m_settingsCache.end())
435  d->m_settingsCache[key] = value;
436  d->m_settingsCacheLock.unlock();
437  }
438 
439  return value;
440 }
441 
442 bool MythDB::GetSettings(QMap<QString,QString> &_key_value_pairs)
443 {
444  QMap<QString,bool> done;
445  using KVIt = QMap<QString,QString>::iterator;
446  KVIt kvit = _key_value_pairs.begin();
447  for (; kvit != _key_value_pairs.end(); ++kvit)
448  done[kvit.key().toLower()] = false;
449 
450  QMap<QString,bool>::iterator dit = done.begin();
451  kvit = _key_value_pairs.begin();
452 
453  {
454  uint done_cnt = 0;
455  d->m_settingsCacheLock.lockForRead();
456  if (d->m_useSettingsCache)
457  {
458  for (; kvit != _key_value_pairs.end(); ++dit, ++kvit)
459  {
460  SettingsMap::const_iterator it = d->m_settingsCache.find(dit.key());
461  if (it != d->m_settingsCache.end())
462  {
463  *kvit = *it;
464  *dit = true;
465  done_cnt++;
466  }
467  }
468  }
469  for (; kvit != _key_value_pairs.end(); ++dit, ++kvit)
470  {
471  SettingsMap::const_iterator it =
472  d->m_overriddenSettings.find(dit.key());
473  if (it != d->m_overriddenSettings.end())
474  {
475  *kvit = *it;
476  *dit = true;
477  done_cnt++;
478  }
479  }
480  d->m_settingsCacheLock.unlock();
481 
482  // Avoid extra work if everything was in the caches and
483  // also don't try to access the DB if m_ignoreDatabase is set
484  if (((uint)done.size()) == done_cnt || d->m_ignoreDatabase)
485  return true;
486  }
487 
488  dit = done.begin();
489  kvit = _key_value_pairs.begin();
490 
491  QString keylist("");
492  QMap<QString,KVIt> keymap;
493  for (; kvit != _key_value_pairs.end(); ++dit, ++kvit)
494  {
495  if (*dit)
496  continue;
497 
498  const QString& key = dit.key();
499  if (!key.contains("'"))
500  {
501  keylist += QString("'%1',").arg(key);
502  keymap[key] = kvit;
503  }
504  else
505  { // hopefully no one actually uses quotes for in a settings key.
506  // but in case they do, just get that value inefficiently..
507  *kvit = GetSetting(key, *kvit);
508  }
509  }
510 
511  if (keylist.isEmpty())
512  return true;
513 
514  keylist = keylist.left(keylist.length() - 1);
515 
517  if (!query.exec(
518  QString(
519  "SELECT value, data, hostname "
520  "FROM settings "
521  "WHERE (hostname = '%1' OR hostname IS NULL) AND "
522  " value IN (%2) "
523  "ORDER BY hostname DESC")
524  .arg(d->m_localhostname).arg(keylist)))
525  {
526  if (!d->m_suppressDBMessages)
527  DBError("GetSettings", query);
528  return false;
529  }
530 
531  while (query.next())
532  {
533  QString key = query.value(0).toString().toLower();
534  QMap<QString,KVIt>::const_iterator it = keymap.find(key);
535  if (it != keymap.end())
536  **it = query.value(1).toString();
537  }
538 
539  if (d->m_useSettingsCache)
540  {
541  d->m_settingsCacheLock.lockForWrite();
542  QMap<QString,KVIt>::const_iterator it = keymap.begin();
543  for (; it != keymap.end(); ++it)
544  {
545  QString key = it.key();
546  QString value = **it;
547 
548  // another thread may have inserted a value into the cache
549  // while we did not have the lock, check first then save
550  if (d->m_settingsCache.find(key) == d->m_settingsCache.end())
551  {
552  key.squeeze();
553  value.squeeze();
554  d->m_settingsCache[key] = value;
555  }
556  }
557  d->m_settingsCacheLock.unlock();
558  }
559 
560  return true;
561 }
562 
563 
564 bool MythDB::GetBoolSetting(const QString &key, bool defaultval)
565 {
566  QString val = QString::number(static_cast<int>(defaultval));
567  QString retval = GetSetting(key, val);
568 
569  return retval.toInt() > 0;
570 }
571 
572 int MythDB::GetNumSetting(const QString &key, int defaultval)
573 {
574  QString val = QString::number(defaultval);
575  QString retval = GetSetting(key, val);
576 
577  return retval.toInt();
578 }
579 
580 double MythDB::GetFloatSetting(const QString &key, double defaultval)
581 {
582  QString val = QString::number(defaultval);
583  QString retval = GetSetting(key, val);
584 
585  return retval.toDouble();
586 }
587 
588 QString MythDB::GetSetting(const QString &key)
589 {
590  QString sentinel = QString(kSentinelValue);
591  QString retval = GetSetting(key, sentinel);
592  return (retval == sentinel) ? "" : retval;
593 }
594 
595 bool MythDB::GetBoolSetting(const QString &key)
596 {
597  QString sentinel = QString(kSentinelValue);
598  QString retval = GetSetting(key, sentinel);
599  if (retval == sentinel)
600  return false;
601  return retval.toInt() > 0;
602 }
603 
604 int MythDB::GetNumSetting(const QString &key)
605 {
606  QString sentinel = QString(kSentinelValue);
607  QString retval = GetSetting(key, sentinel);
608  return (retval == sentinel) ? 0 : retval.toInt();
609 }
610 
611 double MythDB::GetFloatSetting(const QString &key)
612 {
613  QString sentinel = QString(kSentinelValue);
614  QString retval = GetSetting(key, sentinel);
615  return (retval == sentinel) ? 0.0 : retval.toDouble();
616 }
617 
618 QString MythDB::GetSettingOnHost(const QString &_key, const QString &_host,
619  const QString &defaultval)
620 {
621  QString key = _key.toLower();
622  QString host = _host.toLower();
623  QString value = defaultval;
624  QString myKey = host + ' ' + key;
625 
626  d->m_settingsCacheLock.lockForRead();
627  if (d->m_useSettingsCache)
628  {
629  SettingsMap::const_iterator it = d->m_settingsCache.find(myKey);
630  if (it != d->m_settingsCache.end())
631  {
632  value = *it;
633  d->m_settingsCacheLock.unlock();
634  return value;
635  }
636  }
637  SettingsMap::const_iterator it = d->m_overriddenSettings.find(myKey);
638  if (it != d->m_overriddenSettings.end())
639  {
640  value = *it;
641  d->m_settingsCacheLock.unlock();
642  return value;
643  }
644  d->m_settingsCacheLock.unlock();
645 
646  if (d->m_ignoreDatabase)
647  return value;
648 
650  if (!query.isConnected())
651  {
652  if (!d->m_suppressDBMessages)
653  {
654  LOG(VB_GENERAL, LOG_ERR,
655  QString("Database not open while trying to "
656  "load setting: %1").arg(key));
657  }
658  return value;
659  }
660 
661  query.prepare(
662  "SELECT data "
663  "FROM settings "
664  "WHERE value = :VALUE AND hostname = :HOSTNAME");
665  query.bindValue(":VALUE", key);
666  query.bindValue(":HOSTNAME", host);
667 
668  if (query.exec() && query.next())
669  {
670  value = query.value(0).toString();
671  }
672 
673  if (d->m_useSettingsCache && value != kSentinelValue)
674  {
675  myKey.squeeze();
676  value.squeeze();
677  d->m_settingsCacheLock.lockForWrite();
678  if (d->m_settingsCache.find(myKey) == d->m_settingsCache.end())
679  d->m_settingsCache[myKey] = value;
680  d->m_settingsCacheLock.unlock();
681  }
682 
683  return value;
684 }
685 
686 int MythDB::GetNumSettingOnHost(const QString &key, const QString &host,
687  int defaultval)
688 {
689  QString val = QString::number(defaultval);
690  QString retval = GetSettingOnHost(key, host, val);
691 
692  return retval.toInt();
693 }
694 
696  const QString &key, const QString &host, double defaultval)
697 {
698  QString val = QString::number(defaultval);
699  QString retval = GetSettingOnHost(key, host, val);
700 
701  return retval.toDouble();
702 }
703 
704 QString MythDB::GetSettingOnHost(const QString &key, const QString &host)
705 {
706  QString sentinel = QString(kSentinelValue);
707  QString retval = GetSettingOnHost(key, host, sentinel);
708  return (retval == sentinel) ? "" : retval;
709 }
710 
711 int MythDB::GetNumSettingOnHost(const QString &key, const QString &host)
712 {
713  QString sentinel = QString(kSentinelValue);
714  QString retval = GetSettingOnHost(key, host, sentinel);
715  return (retval == sentinel) ? 0 : retval.toInt();
716 }
717 
718 double MythDB::GetFloatSettingOnHost(const QString &key, const QString &host)
719 {
720  QString sentinel = QString(kSentinelValue);
721  QString retval = GetSettingOnHost(key, host, sentinel);
722  return (retval == sentinel) ? 0.0 : retval.toDouble();
723 }
724 
725 void MythDB::GetResolutionSetting(const QString &type,
726  int &width, int &height,
727  double &forced_aspect,
728  double &refresh_rate,
729  int index)
730 {
731  bool ok = false;
732  bool ok0 = false;
733  bool ok1 = false;
734  QString sRes = QString("%1Resolution").arg(type);
735  QString sRR = QString("%1RefreshRate").arg(type);
736  QString sAspect = QString("%1ForceAspect").arg(type);
737  QString sWidth = QString("%1Width").arg(type);
738  QString sHeight = QString("%1Height").arg(type);
739  if (index >= 0)
740  {
741  sRes = QString("%1Resolution%2").arg(type).arg(index);
742  sRR = QString("%1RefreshRate%2").arg(type).arg(index);
743  sAspect = QString("%1ForceAspect%2").arg(type).arg(index);
744  sWidth = QString("%1Width%2").arg(type).arg(index);
745  sHeight = QString("%1Height%2").arg(type).arg(index);
746  }
747 
748  QString res = GetSetting(sRes);
749 
750  if (!res.isEmpty())
751  {
752  QStringList slist = res.split(QString("x"));
753  int w = width;
754  int h = height;
755  if (2 == slist.size())
756  {
757  w = slist[0].toInt(&ok0);
758  h = slist[1].toInt(&ok1);
759  }
760  ok = ok0 && ok1;
761  if (ok)
762  {
763  width = w;
764  height = h;
765  refresh_rate = GetFloatSetting(sRR);
766  forced_aspect = GetFloatSetting(sAspect);
767  }
768  }
769 
770  if (!ok)
771  {
772  int tmpWidth = GetNumSetting(sWidth, width);
773  if (tmpWidth)
774  width = tmpWidth;
775 
776  int tmpHeight = GetNumSetting(sHeight, height);
777  if (tmpHeight)
778  height = tmpHeight;
779 
780  refresh_rate = 0.0;
781  forced_aspect = 0.0;
782  //SetSetting(sRes, QString("%1x%2").arg(width).arg(height));
783  }
784 }
785 
786 void MythDB::GetResolutionSetting(const QString &t, int &w, int &h, int i)
787 {
788  double forced_aspect = 0;
789  double refresh_rate = 0.0;
790  GetResolutionSetting(t, w, h, forced_aspect, refresh_rate, i);
791 }
792 
793 
801  const QString &key, const QString &value)
802 {
803  QString mk = key.toLower();
804  QString mk2 = d->m_localhostname + ' ' + mk;
805  QString mv = value;
806  if ("dbschemaver" == mk)
807  {
808  LOG(VB_GENERAL, LOG_ERR,
809  QString("ERROR: Refusing to allow override for '%1'.").arg(key));
810  return;
811  }
812  mk.squeeze();
813  mk2.squeeze();
814  mv.squeeze();
815 
816  d->m_settingsCacheLock.lockForWrite();
817  d->m_overriddenSettings[mk] = mv;
818  d->m_settingsCache[mk] = mv;
819  d->m_settingsCache[mk2] = mv;
820  d->m_settingsCacheLock.unlock();
821 }
822 
825 {
826  QString mk = key.toLower();
827  QString mk2 = d->m_localhostname + ' ' + mk;
828 
829  d->m_settingsCacheLock.lockForWrite();
830 
831  SettingsMap::iterator oit = d->m_overriddenSettings.find(mk);
832  if (oit != d->m_overriddenSettings.end())
833  d->m_overriddenSettings.erase(oit);
834 
835  SettingsMap::iterator sit = d->m_settingsCache.find(mk);
836  if (sit != d->m_settingsCache.end())
837  d->m_settingsCache.erase(sit);
838 
839  sit = d->m_settingsCache.find(mk2);
840  if (sit != d->m_settingsCache.end())
841  d->m_settingsCache.erase(sit);
842 
843  d->m_settingsCacheLock.unlock();
844 }
845 
846 static void clear(
847  SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
848 {
849  // Do the actual clearing..
850  SettingsMap::iterator it = cache.find(myKey);
851  if (it != cache.end())
852  {
853  SettingsMap::const_iterator oit = overrides.find(myKey);
854  if (oit == overrides.end())
855  {
856  LOG(VB_DATABASE, LOG_INFO,
857  QString("Clearing Settings Cache for '%1'.").arg(myKey));
858  cache.erase(it);
859  }
860  else
861  {
862  LOG(VB_DATABASE, LOG_INFO,
863  QString("Clearing Cache of overridden '%1' ignored.")
864  .arg(myKey));
865  }
866  }
867 }
868 
869 void MythDB::ClearSettingsCache(const QString &_key)
870 {
871  d->m_settingsCacheLock.lockForWrite();
872 
873  if (_key.isEmpty())
874  {
875  LOG(VB_DATABASE, LOG_INFO, "Clearing Settings Cache.");
876  d->m_settingsCache.clear();
877  d->m_settingsCache.reserve(settings_reserve);
878 
879  SettingsMap::const_iterator it = d->m_overriddenSettings.begin();
880  for (; it != d->m_overriddenSettings.end(); ++it)
881  {
882  QString mk2 = d->m_localhostname + ' ' + it.key();
883  mk2.squeeze();
884 
885  d->m_settingsCache[it.key()] = *it;
886  d->m_settingsCache[mk2] = *it;
887  }
888  }
889  else
890  {
891  QString myKey = _key.toLower();
892  clear(d->m_settingsCache, d->m_overriddenSettings, myKey);
893 
894  // To be safe always clear any local[ized] version too
895  QString mkl = myKey.section(QChar(' '), 1);
896  if (!mkl.isEmpty())
897  clear(d->m_settingsCache, d->m_overriddenSettings, mkl);
898  }
899 
900  d->m_settingsCacheLock.unlock();
901 }
902 
903 void MythDB::ActivateSettingsCache(bool activate)
904 {
905  if (activate)
906  LOG(VB_DATABASE, LOG_INFO, "Enabling Settings Cache.");
907  else
908  LOG(VB_DATABASE, LOG_INFO, "Disabling Settings Cache.");
909 
910  d->m_useSettingsCache = activate;
912 }
913 
915 {
916  if (!HaveValidDatabase())
917  return;
918 
919  if (!gCoreContext->IsUIThread())
920  return;
921 
922  while (!d->m_delayedSettings.isEmpty())
923  {
924  SingleSetting setting = d->m_delayedSettings.takeFirst();
925  SaveSettingOnHost(setting.m_key, setting.m_value, setting.m_host);
926  }
927 }
928 
932 void MythDB::SetHaveDBConnection(bool connected)
933 {
934  d->m_haveDBConnection = connected;
935 }
936 
941 void MythDB::SetHaveSchema(bool schema)
942 {
943  d->m_haveSchema = schema;
944 }
945 
953 bool MythDB::HaveSchema(void) const
954 {
955  return d->m_haveSchema;
956 }
957 
966 {
967  return (d->m_haveDBConnection && d->m_haveSchema);
968 }
MythDB::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval)
Definition: mythdb.cpp:564
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:126
DestroyMythDB
void DestroyMythDB(void)
Definition: mythdb.cpp:51
MythDB::WriteDelayedSettings
void WriteDelayedSettings(void)
Definition: mythdb.cpp:914
dbLock
static QMutex dbLock
Definition: mythdb.cpp:19
MythDB::HaveSchema
bool HaveSchema(void) const
Get a flag indicating that we have discovered tables and that this therefore not a new empty database...
Definition: mythdb.cpp:953
MythDB::IsDatabaseIgnored
bool IsDatabaseIgnored(void) const
Definition: mythdb.cpp:228
MythDB::IgnoreDatabase
void IgnoreDatabase(bool bIgnore)
Definition: mythdb.cpp:223
MythDB::~MythDB
~MythDB()
Definition: mythdb.cpp:110
MythDB::GetSettingOnHost
QString GetSettingOnHost(const QString &_key, const QString &_host, const QString &defaultval)
Definition: mythdb.cpp:618
mythdb.h
MythDB::DBErrorMessage
static QString DBErrorMessage(const QSqlError &err)
Definition: mythdb.cpp:184
MythDB::ClearSettingOnHost
bool ClearSettingOnHost(const QString &key, const QString &host)
Definition: mythdb.cpp:365
DatabaseParams
Structure containing the basic Database parameters.
Definition: mythdbparams.h:10
MythDB::ActivateSettingsCache
void ActivateSettingsCache(bool activate=true)
Definition: mythdb.cpp:903
d
static const uint16_t * d
Definition: iso6937tables.cpp:1025
MDBManager
DB connection pool, used by MSqlQuery. Do not use directly.
Definition: mythdbcon.h:54
MythDBPrivate::m_settingsCache
SettingsMap m_settingsCache
Permanent settings in the DB and overridden settings.
Definition: mythdb.cpp:81
SingleSetting
Definition: mythdb.cpp:57
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
arg
arg(title).arg(filename).arg(doDelete))
mythdbcon.h
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
MSqlQuery::boundValues
QMap< QString, QVariant > boundValues(void) const
Definition: mythdbcon.h:200
MythCoreContext::IsUIThread
bool IsUIThread(void)
Definition: mythcorecontext.cpp:1356
MythDBPrivate::m_localhostname
QString m_localhostname
Definition: mythdb.cpp:72
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythDBPrivate::m_dbParams
DatabaseParams m_dbParams
Current database host & WOL details.
Definition: mythdb.cpp:71
kSentinelValue
const char * kSentinelValue
Definition: mythdb.cpp:22
GetMythDB
MythDB * GetMythDB(void)
Definition: mythdb.cpp:46
mythdirs.h
MythDB::GetFloatSettingOnHost
double GetFloatSettingOnHost(const QString &key, const QString &host, double defaultval)
Definition: mythdb.cpp:695
MythDBPrivate::m_dbmanager
MDBManager m_dbmanager
Definition: mythdb.cpp:73
MythDBPrivate
Definition: mythdb.cpp:66
tmp
static guint32 * tmp
Definition: goom_core.cpp:30
MythDB::GetFloatSetting
double GetFloatSetting(const QString &key, double defaultval)
Definition: mythdb.cpp:580
MythDB::ClearSettingsCache
void ClearSettingsCache(const QString &key=QString())
Definition: mythdb.cpp:869
MythDB::destroyMythDB
static void destroyMythDB()
Definition: mythdb.cpp:38
MythDBPrivate::m_settingsCacheLock
QReadWriteLock m_settingsCacheLock
Definition: mythdb.cpp:78
MythDB::SaveSettingOnHost
bool SaveSettingOnHost(const QString &key, const QString &newValue, const QString &host)
Definition: mythdb.cpp:254
SingleSetting::m_host
QString m_host
Definition: mythdb.cpp:60
MythDB::GetDatabaseParams
DatabaseParams GetDatabaseParams(void) const
Definition: mythdb.cpp:199
MythDB::ClearSetting
bool ClearSetting(const QString &key)
Definition: mythdb.cpp:360
mythlogging.h
MythDBPrivate::m_overriddenSettings
SettingsMap m_overriddenSettings
Overridden this session only.
Definition: mythdb.cpp:83
MythDBPrivate::MythDBPrivate
MythDBPrivate()
Definition: mythdb.cpp:94
mythdb
static MythDB * mythdb
Definition: mythdb.cpp:18
MythDB::GetNumSetting
int GetNumSetting(const QString &key, int defaultval)
Definition: mythdb.cpp:572
MythDB::GetError
static QString GetError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:163
hardwareprofile.i18n.t
t
Definition: i18n.py:36
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
kClearSettingValue
const char * kClearSettingValue
Definition: mythdb.cpp:23
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
MythDB::SuppressDBMessages
bool SuppressDBMessages(void) const
Definition: mythdb.cpp:238
MythDB::GetNumSettingOnHost
int GetNumSettingOnHost(const QString &key, const QString &host, int defaultval)
Definition: mythdb.cpp:686
SingleSetting::m_value
QString m_value
Definition: mythdb.cpp:59
clear
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:846
GetSetting
t<< doc.toString(4);f.close();LOG(VB_JOBQUEUE, LOG_INFO, "Copying video file");bool res=copyFile(filename, saveDirectory+title+"/"+baseName);if(!res) return 0;if(QFile::exists(filename+".png")) { LOG(VB_JOBQUEUE, LOG_INFO, "Copying preview image");res=copyFile(filename+".png", saveDirectory+title+"/"+baseName+".png");if(!res) return 0;} LOG(VB_JOBQUEUE, LOG_INFO, "Item Archived OK");return 1;}int NativeArchive::exportVideo(QDomElement &itemNode, const QString &saveDirectory){ QString dbVersion=gCoreContext-> GetSetting("DBSchemaVer", "")
SingleSetting::m_key
QString m_key
Definition: mythdb.cpp:58
MythDBPrivate::~MythDBPrivate
~MythDBPrivate()
Definition: mythdb.cpp:100
MSqlQuery::isConnected
bool isConnected(void) const
Only updated once during object creation.
Definition: mythdbcon.h:135
uint
unsigned int uint
Definition: compat.h:140
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
SettingsMap
QHash< QString, QString > SettingsMap
Definition: mythdb.cpp:63
MythDB::getMythDB
static MythDB * getMythDB()
Definition: mythdb.cpp:25
MythDB::SetHaveSchema
void SetHaveSchema(bool schema)
Set a flag indicating that we have discovered tables and that this therefore not a new empty database...
Definition: mythdb.cpp:941
MSqlQuery::lastError
QSqlError lastError(void) const
Definition: mythdbcon.h:202
MythDB::SetLocalHostname
void SetLocalHostname(const QString &name)
Definition: mythdb.cpp:209
MythDB::GetResolutionSetting
void GetResolutionSetting(const QString &type, int &width, int &height, double &forced_aspect, double &refresh_rate, int index=-1)
MythDB::GetHostName
QString GetHostName(void) const
Definition: mythdb.cpp:218
MythDB::MythDB
MythDB()
Definition: mythdb.cpp:105
MythDBPrivate::m_delayedSettings
QList< SingleSetting > m_delayedSettings
Settings which should be written to the database as soon as it becomes available.
Definition: mythdb.cpp:86
mythcorecontext.h
MSqlQuery::executedQuery
QString executedQuery(void) const
Definition: mythdbcon.h:199
toCommaList
static QString toCommaList(const QSet< uint > &list)
Definition: tv_play.cpp:8393
MythDB::GetSetting
QString GetSetting(const QString &_key, const QString &defaultval)
Definition: mythdb.cpp:370
MythDB::SetDatabaseParams
void SetDatabaseParams(const DatabaseParams &params)
Definition: mythdb.cpp:204
MythDB::SetSuppressDBMessages
void SetSuppressDBMessages(bool bUpgraded)
Definition: mythdb.cpp:233
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
MythDB::GetSettings
bool GetSettings(QMap< QString, QString > &_key_value_pairs)
Definition: mythdb.cpp:442
ClearSettingsCache
static int ClearSettingsCache(const MythUtilCommandLineParser &)
Definition: backendutils.cpp:39
MythDB::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythdb.cpp:243
MythDB::SetHaveDBConnection
void SetHaveDBConnection(bool connected)
Set a flag indicating we have successfully connected to the database.
Definition: mythdb.cpp:932
MythDB::HaveValidDatabase
bool HaveValidDatabase(void) const
Returns true if we have successfully connected to the database and that database has tables.
Definition: mythdb.cpp:965
settings_reserve
static const int settings_reserve
Definition: mythdb.cpp:92
MythDB::OverrideSettingForSession
void OverrideSettingForSession(const QString &key, const QString &newValue)
Overrides the given setting for the execution time of the process.
Definition: mythdb.cpp:800
indent
static QString indent(uint level)
Definition: mythsettings.cpp:17
MythDB::GetDBManager
MDBManager * GetDBManager(void)
Definition: mythdb.cpp:115
MythDB::ClearOverrideSettingForSession
void ClearOverrideSettingForSession(const QString &key)
Clears session Overrides for the given setting.
Definition: mythdb.cpp:824
query
MSqlQuery query(MSqlQuery::InitCon())
MythDB::toCommaList
static QString toCommaList(const QMap< QString, QVariant > &bindings, uint indent=0, uint softMaxColumn=80)
Definition: mythdb.cpp:120
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808