Ticket #7372: 7372-v1.patch

File 7372-v1.patch, 15.8 KB (added by danielk, 15 years ago)
  • libs/libmyth/mythcontext.h

     
    114114
    115115    QString GetHostName(void);
    116116
    117     void ClearSettingsCache(QString myKey = "", QString newVal = "");
     117    void ClearSettingsCache(const QString &myKey = QString(""));
    118118    void ActivateSettingsCache(bool activate = true);
    119119    void OverrideSettingForSession(const QString &key, const QString &newValue);
    120120
  • libs/libmyth/mythcontext.cpp

     
    18971897    return ret;
    18981898}
    18991899
    1900 void MythContext::ClearSettingsCache(QString myKey, QString newVal)
     1900void MythContext::ClearSettingsCache(const QString &myKey)
    19011901{
    1902     d->m_database->ClearSettingsCache(myKey, newVal);
     1902    d->m_database->ClearSettingsCache(myKey);
    19031903}
    19041904
    19051905void MythContext::ActivateSettingsCache(bool activate)
  • libs/libmythdb/mythdb.cpp

     
    11#include <QMutex>
     2#include <QReadWriteLock>
    23#include <QHash>
    34#include <QSqlError>
    45
     
    4445    MythDB::destroyMythDB();
    4546}
    4647
     48typedef QHash<QString,QString> SettingsMap;
    4749
    4850class MythDBPrivate
    4951{
     
    5860    Settings *m_settings;
    5961
    6062    bool ignoreDatabase;
    61     bool useSettingsCache;
    6263    bool suppressDBMessages;
    63     QMutex settingsCacheLock;
    64     QHash <QString, QString> settingsCache;      // permanent settings in the DB
    65     QHash <QString, QString> overriddenSettings; // overridden this session only
     64
     65    QReadWriteLock settingsCacheLock;
     66    volatile bool useSettingsCache;
     67    /// Permanent settings in the DB and overridden settings
     68    SettingsMap settingsCache;
     69    /// Overridden this session only
     70    SettingsMap overriddenSettings;
    6671};
    6772
    6873static const int settings_reserve = 61;
    6974
    7075MythDBPrivate::MythDBPrivate()
    7176    : m_settings(new Settings()),
    72       ignoreDatabase(false), useSettingsCache(false), suppressDBMessages(true)
     77      ignoreDatabase(false), suppressDBMessages(true), useSettingsCache(false)
    7378{
    7479    m_localhostname.clear();
    7580    settingsCache.reserve(settings_reserve);
     
    174179    d->m_DBparams = params;
    175180}
    176181
    177 void MythDB::SetLocalHostname(QString name)
     182void MythDB::SetLocalHostname(const QString &name)
    178183{
    179     d->m_localhostname = name;
     184    if (d->m_localhostname != name.toLower())
     185    {
     186        d->m_localhostname = name.toLower();
     187        ClearSettingsCache();
     188    }
    180189}
    181190
    182191QString MythDB::GetHostName(void)
    183192{
    184     QString tmp = d->m_localhostname;
    185     return tmp;
     193    return d->m_localhostname;
    186194}
    187195
    188196void MythDB::IgnoreDatabase(bool bIgnore)
     
    218226}
    219227
    220228bool MythDB::SaveSettingOnHost(const QString &key,
    221                                     const QString &newValue,
    222                                     const QString &host)
     229                               const QString &newValue,
     230                               const QString &host)
    223231{
    224232    QString LOC  = QString("SaveSettingOnHost('%1') ").arg(key);
    225233    bool success = false;
    226234
    227235    if (d->ignoreDatabase)
    228236    {
    229         ClearSettingsCache(key, newValue);
    230         ClearSettingsCache(host + ' ' + key, newValue);
     237        if (host.toLower() == d->m_localhostname)
     238            OverrideSettingForSession(key, newValue);
    231239        return true;
    232240    }
    233241
     
    284292        VERBOSE(VB_IMPORTANT, LOC + "- database not open");
    285293    }
    286294
    287     ClearSettingsCache(key, newValue);
    288     ClearSettingsCache(host + ' ' + key, newValue);
     295    ClearSettingsCache(host + ' ' + key);
    289296
    290297    return success;
    291298}
    292299
    293 QString MythDB::GetSetting(const QString &key, const QString &defaultval)
     300QString MythDB::GetSetting(const QString &_key, const QString &defaultval)
    294301{
     302    QString key = _key.toLower();
    295303    QString value;
    296    
    297     if (d->overriddenSettings.contains(key))
     304
     305    d->settingsCacheLock.lockForRead();
     306    if (d->useSettingsCache)
    298307    {
    299         value = d->overriddenSettings[key];
    300         return value;
     308        SettingsMap::const_iterator it = d->settingsCache.find(key);
     309        if (it != d->settingsCache.end())
     310        {
     311            value = *it;
     312            d->settingsCacheLock.unlock();
     313            return value;
     314        }
    301315    }
    302    
    303     d->settingsCacheLock.lock();
    304 
    305     value = d->settingsCache.value(key, "_cold_");
    306 
     316    else
     317    {
     318        SettingsMap::const_iterator it = d->overriddenSettings.find(key);
     319        if (it != d->overriddenSettings.end())
     320        {
     321            value = *it;
     322            d->settingsCacheLock.unlock();
     323            return value;
     324        }
     325    }
    307326    d->settingsCacheLock.unlock();
    308327
    309     if (value != "_cold_" && d->useSettingsCache)
     328    if (d->ignoreDatabase)
    310329        return value;
    311330
    312     bool found = false;
    313     if (!d->ignoreDatabase)
     331    MSqlQuery query(MSqlQuery::InitCon());
     332    if (!query.isConnected())
    314333    {
    315         MSqlQuery query(MSqlQuery::InitCon());
    316         if (query.isConnected())
    317         {
    318             query.prepare("SELECT data FROM settings WHERE value "
    319                           "= :KEY AND hostname = :HOSTNAME ;");
    320             query.bindValue(":KEY", key);
    321             query.bindValue(":HOSTNAME", d->m_localhostname);
     334        VERBOSE(VB_IMPORTANT,
     335                QString("Database not open while trying to load setting: %1")
     336                .arg(key));
     337        return d->m_settings->GetSetting(key, defaultval);
     338    }
    322339
    323             if (query.exec() && query.next())
    324             {
    325                 found = true;
    326                 value = query.value(0).toString();
    327             }
    328             else
    329             {
    330                 query.prepare("SELECT data FROM settings "
    331                               "WHERE value = :KEY AND "
    332                               "hostname IS NULL;");
    333                 query.bindValue(":KEY", key);
     340    query.prepare(
     341        "SELECT data "
     342        "FROM settings "
     343        "WHERE value = :KEY AND hostname = :HOSTNAME");
     344    query.bindValue(":KEY", key);
     345    query.bindValue(":HOSTNAME", d->m_localhostname);
     346   
     347    if (query.exec() && query.next())
     348    {
     349        value = query.value(0).toString();
     350    }
     351    else
     352    {
     353        query.prepare(
     354            "SELECT data "
     355            "FROM settings "
     356            "WHERE value = :KEY AND hostname IS NULL");
     357        query.bindValue(":KEY", key);
    334358
    335                 if (query.exec() && query.next())
    336                 {
    337                     found = true;
    338                     value = query.value(0).toString();
    339                 }
    340                 else
    341                 {
    342                     value = defaultval;
    343                 }
    344             }
     359        if (query.exec() && query.next())
     360        {
     361            value = query.value(0).toString();
    345362        }
    346363        else
    347364        {
    348             VERBOSE(VB_IMPORTANT,
    349                     QString("Database not open while trying to "
    350                             "load setting: %1")
    351                     .arg(key));
     365            return d->m_settings->GetSetting(key, defaultval);
    352366        }
    353367    }
    354368
    355     if (!found)
    356         return d->m_settings->GetSetting(key, defaultval);
    357 
    358     // Do not store default values since they may not have been specified.
    359     if (!value.isNull() && d->useSettingsCache)
     369    if (d->useSettingsCache)
    360370    {
    361         d->settingsCacheLock.lock();
    362         d->settingsCache[key] = value;
     371        key.squeeze();
     372        value.squeeze();
     373        d->settingsCacheLock.lockForWrite();
     374        // another thread may have inserted a value into the cache
     375        // while we did not have the lock, check first then save
     376        if (d->settingsCache.find(key) == d->settingsCache.end())
     377            d->settingsCache[key] = value;
    363378        d->settingsCacheLock.unlock();
    364379    }
    365380
     
    382397    return retval.toDouble();
    383398}
    384399
    385 QString MythDB::GetSettingOnHost(const QString &key, const QString &host,
    386                                       const QString &defaultval)
     400QString MythDB::GetSettingOnHost(const QString &_key, const QString &_host,
     401                                 const QString &defaultval)
    387402{
    388     bool found = false;
     403    QString key   = _key.toLower();
     404    QString host  = _host.toLower();
    389405    QString value = defaultval;
    390406    QString myKey = host + ' ' + key;
    391407
    392     if (d->overriddenSettings.contains(myKey))
     408    d->settingsCacheLock.lockForRead();
     409    if (d->useSettingsCache)
    393410    {
    394         value = d->overriddenSettings[myKey];
    395         return value;
     411        SettingsMap::const_iterator it = d->settingsCache.find(myKey);
     412        if (it != d->settingsCache.end())
     413        {
     414            value = *it;
     415            d->settingsCacheLock.unlock();
     416            return value;
     417        }
    396418    }
    397 
    398     if ((host == d->m_localhostname) &&
    399         (d->overriddenSettings.contains(key)))
     419    else
    400420    {
    401 
    402         value = d->overriddenSettings[key];
    403         return value;
    404     }
    405 
    406     if (d->useSettingsCache)
    407     {
    408         d->settingsCacheLock.lock();
    409         if (d->settingsCache.contains(myKey))
     421        SettingsMap::const_iterator it = d->overriddenSettings.find(myKey);
     422        if (it != d->overriddenSettings.end())
    410423        {
    411             value = d->settingsCache[myKey];
     424            value = *it;
    412425            d->settingsCacheLock.unlock();
    413426            return value;
    414427        }
    415         d->settingsCacheLock.unlock();
    416428    }
     429    d->settingsCacheLock.unlock();
    417430
    418     if (!d->ignoreDatabase)
     431    if (d->ignoreDatabase)
     432        return value;
     433
     434    MSqlQuery query(MSqlQuery::InitCon());
     435    if (!query.isConnected())
    419436    {
    420         MSqlQuery query(MSqlQuery::InitCon());
    421         if (query.isConnected())
    422         {
    423             query.prepare("SELECT data FROM settings WHERE value = :VALUE "
    424                           "AND hostname = :HOSTNAME ;");
    425             query.bindValue(":VALUE", key);
    426             query.bindValue(":HOSTNAME", host);
     437        VERBOSE(VB_IMPORTANT,
     438                QString("Database not open while trying to "
     439                        "load setting: %1").arg(key));
     440        return value;
     441    }
    427442
    428             if (query.exec() && query.isActive() && query.size() > 0)
    429             {
    430                 if (query.next())
    431                 {
    432                     value = query.value(0).toString();
    433                     found = true;
    434                 }
    435             }
    436         }
    437         else
     443    query.prepare(
     444        "SELECT data "
     445        "FROM settings "
     446        "WHERE value = :VALUE AND hostname = :HOSTNAME");
     447    query.bindValue(":VALUE", key);
     448    query.bindValue(":HOSTNAME", host);
     449
     450    if (query.exec() && query.next())
     451    {
     452        value = query.value(0).toString();
     453
     454        if (d->useSettingsCache)
    438455        {
    439             VERBOSE(VB_IMPORTANT,
    440                     QString("Database not open while trying to "
    441                             "load setting: %1")
    442                     .arg(key));
     456            myKey.squeeze();
     457            value.squeeze();
     458            d->settingsCacheLock.lockForWrite();
     459            if (d->settingsCache.find(myKey) == d->settingsCache.end())
     460                d->settingsCache[myKey] = value;
     461            d->settingsCacheLock.unlock();
    443462        }
    444463    }
    445464
    446     if (found && d->useSettingsCache)
    447     {
    448         d->settingsCacheLock.lock();
    449         d->settingsCache[host + ' ' + key] = value;
    450         d->settingsCacheLock.unlock();
    451     }
    452 
    453465    return value;
    454466}
    455467
     
    474486void MythDB::SetSetting(const QString &key, const QString &newValue)
    475487{
    476488    d->m_settings->SetSetting(key, newValue);
    477     ClearSettingsCache(key, newValue);
     489    ClearSettingsCache(key);
    478490}
    479491
    480492void MythDB::GetResolutionSetting(const QString &type,
     
    550562 * This allows defining settings for the session only, without touching the
    551563 * settings in the data base.
    552564 */
    553 void MythDB::OverrideSettingForSession(const QString &key,
    554                                             const QString &value)
     565void MythDB::OverrideSettingForSession(
     566    const QString &key, const QString &value)
    555567{
    556     d->overriddenSettings[key] = value;
     568    QString mk = key.toLower(), mk2 = d->m_localhostname + ' ' + mk, mv = value;
     569    mk.squeeze();
     570    mk2.squeeze();
     571    mv.squeeze();
     572
     573    d->settingsCacheLock.lockForWrite();
     574    d->overriddenSettings[mk] = mv;
     575    d->settingsCache[mk]      = mv;
     576    d->settingsCache[mk2]     = mv;
     577    d->settingsCacheLock.unlock();
    557578}
    558579
    559 void MythDB::ClearSettingsCache(QString myKey, QString newVal)
     580static void clear(
     581    SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
    560582{
    561     d->settingsCacheLock.lock();
    562     if (!myKey.isEmpty() && d->settingsCache.contains(myKey))
     583    // Do the actual clearing..
     584    SettingsMap::iterator it = cache.find(myKey);
     585    if (it != cache.end())
    563586    {
    564         VERBOSE(VB_DATABASE, QString("Clearing Settings Cache for '%1'.")
    565                                     .arg(myKey));
    566         d->settingsCache.remove(myKey);
    567         d->settingsCache[myKey] = newVal;
     587        SettingsMap::const_iterator oit = overrides.find(myKey);
     588        if (oit == overrides.end())
     589        {
     590            VERBOSE(VB_DATABASE,
     591                    QString("Clearing Settings Cache for '%1'.").arg(myKey));
     592            cache.erase(it);
     593        }
     594        else
     595        {
     596            VERBOSE(VB_DATABASE,
     597                    QString("Clearing Cache of overridden '%1' ignored.")
     598                    .arg(myKey));
     599        }
    568600    }
    569     else
     601}
     602
     603void MythDB::ClearSettingsCache(const QString &_key)
     604{
     605    d->settingsCacheLock.lockForWrite();
     606
     607    if (_key.isEmpty())
    570608    {
    571609        VERBOSE(VB_DATABASE, "Clearing Settings Cache.");
    572610        d->settingsCache.clear();
    573611        d->settingsCache.reserve(settings_reserve);
     612
     613        SettingsMap::const_iterator it = d->overriddenSettings.begin();
     614        for (; it != d->overriddenSettings.end(); ++it)
     615        {
     616            QString mk2 = d->m_localhostname + ' ' + it.key();
     617            mk2.squeeze();
     618
     619            d->settingsCache[it.key()] = *it;
     620            d->settingsCache[mk2] = *it;
     621        }
    574622    }
     623    else
     624    {
     625        QString myKey = _key.toLower();
     626        clear(d->settingsCache, d->overriddenSettings, myKey);
     627
     628        // To be safe always clear any local[ized] version too
     629        QStringList mkl = myKey.split(QChar(' '));
     630        if (mkl.size() == 2)
     631            clear(d->settingsCache, d->overriddenSettings, mkl[1]);       
     632    }
     633
    575634    d->settingsCacheLock.unlock();
    576635}
    577636
     
    585644    d->useSettingsCache = activate;
    586645    ClearSettingsCache();
    587646}
    588 
  • libs/libmythdb/mythversion.h

     
    88/// Update this whenever the plug-in API changes.
    99/// Including changes in the libmythdb, libmyth and libmythui class methods
    1010/// used by plug-ins.
    11 #define MYTH_BINARY_VERSION "0.22.20091016-1"
     11#define MYTH_BINARY_VERSION "0.22.20091021-1"
    1212
    1313/** \brief Increment this whenever the MythTV network protocol changes.
    1414 *
  • libs/libmythdb/mythdb.h

     
    2323    DatabaseParams GetDatabaseParams(void);
    2424    void SetDatabaseParams(const DatabaseParams &params);
    2525
    26     void SetLocalHostname(QString name);
     26    void SetLocalHostname(const QString &name);
    2727    QString GetHostName(void);
    2828
    2929    void IgnoreDatabase(bool bIgnore);
     
    3232    void SetSuppressDBMessages(bool bUpgraded);
    3333    bool SuppressDBMessages(void) const;
    3434
    35     void ClearSettingsCache(QString myKey = "", QString newVal = "");
     35    void ClearSettingsCache(const QString &key = QString());
    3636    void ActivateSettingsCache(bool activate = true);
    3737    void OverrideSettingForSession(const QString &key, const QString &newValue);
    3838