aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Sommerfeld <kai.sommerfeld@gmx.com>2017-09-30 13:54:31 +0200
committerGitHub <noreply@github.com>2017-09-30 13:54:31 +0200
commit1bca5092c50a5da20599a2edb7831a41e1066827 (patch)
tree3db91e99ebcca6f638d04e22269b673d7cadaf04
parentec46f30fd04140b00a38ccc79f6e97422b5bf51f (diff)
parent82abc43122ead0d8cba4d5444026335515a3fabc (diff)
Merge pull request #12844 from ksooo/pvr-database-concurrency
[PVR] Make PVR database threadsafe.
-rw-r--r--xbmc/dbwrappers/Database.h2
-rw-r--r--xbmc/pvr/PVRDatabase.cpp148
-rw-r--r--xbmc/pvr/PVRDatabase.h22
-rw-r--r--xbmc/pvr/PVRManager.cpp2
-rw-r--r--xbmc/pvr/channels/PVRChannel.cpp3
-rw-r--r--xbmc/pvr/channels/PVRChannelGroup.cpp28
-rw-r--r--xbmc/pvr/channels/PVRChannelGroup.h1
-rw-r--r--xbmc/pvr/channels/PVRChannelGroupInternal.cpp10
-rw-r--r--xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp2
9 files changed, 129 insertions, 89 deletions
diff --git a/xbmc/dbwrappers/Database.h b/xbmc/dbwrappers/Database.h
index 435f5d8686..9aabf5f8cb 100644
--- a/xbmc/dbwrappers/Database.h
+++ b/xbmc/dbwrappers/Database.h
@@ -76,7 +76,7 @@ public:
CDatabase(void);
virtual ~CDatabase(void);
bool IsOpen();
- void Close();
+ virtual void Close();
bool Compress(bool bForce=true);
void Interrupt();
diff --git a/xbmc/pvr/PVRDatabase.cpp b/xbmc/pvr/PVRDatabase.cpp
index 5958cdc0b8..df8db76c32 100644
--- a/xbmc/pvr/PVRDatabase.cpp
+++ b/xbmc/pvr/PVRDatabase.cpp
@@ -24,28 +24,32 @@
#include "ServiceBroker.h"
#include "dbwrappers/dataset.h"
-#include "addons/PVRClient.h"
#include "settings/AdvancedSettings.h"
#include "settings/Settings.h"
#include "utils/StringUtils.h"
#include "utils/log.h"
-#include "pvr/channels/PVRChannelGroupInternal.h"
-#include "pvr/channels/PVRChannelGroupsContainer.h"
+#include "pvr/channels/PVRChannelGroups.h"
using namespace dbiplus;
using namespace PVR;
-using namespace ADDON;
-
-#define PVRDB_DEBUGGING 0
bool CPVRDatabase::Open()
{
+ CSingleLock lock(m_critSection);
return CDatabase::Open(g_advancedSettings.m_databaseTV);
}
+void CPVRDatabase::Close()
+{
+ CSingleLock lock(m_critSection);
+ CDatabase::Close();
+}
+
void CPVRDatabase::CreateTables()
{
+ CSingleLock lock(m_critSection);
+
CLog::Log(LOGINFO, "PVR - %s - creating tables", __FUNCTION__);
CLog::Log(LOGDEBUG, "PVR - %s - creating table 'channels'", __FUNCTION__);
@@ -95,6 +99,8 @@ void CPVRDatabase::CreateTables()
void CPVRDatabase::CreateAnalytics()
{
+ CSingleLock lock(m_critSection);
+
CLog::Log(LOGINFO, "%s - creating indices", __FUNCTION__);
m_pDS->exec("CREATE UNIQUE INDEX idx_channels_iClientId_iUniqueId on channels(iClientId, iUniqueId);");
m_pDS->exec("CREATE INDEX idx_channelgroups_bIsRadio on channelgroups(bIsRadio);");
@@ -103,6 +109,8 @@ void CPVRDatabase::CreateAnalytics()
void CPVRDatabase::UpdateTables(int iVersion)
{
+ CSingleLock lock(m_critSection);
+
if (iVersion < 13)
m_pDS->exec("ALTER TABLE channels ADD idEpg integer;");
@@ -147,6 +155,8 @@ void CPVRDatabase::UpdateTables(int iVersion)
bool CPVRDatabase::DeleteChannels(void)
{
CLog::Log(LOGDEBUG, "PVR - %s - deleting all channels from the database", __FUNCTION__);
+
+ CSingleLock lock(m_critSection);
return DeleteValues("channels");
}
@@ -161,12 +171,14 @@ bool CPVRDatabase::Delete(const CPVRChannel &channel)
Filter filter;
filter.AppendWhere(PrepareSQL("idChannel = %u", channel.ChannelID()));
+ CSingleLock lock(m_critSection);
return DeleteValues("channels", filter);
}
-int CPVRDatabase::Get(CPVRChannelGroupInternal &results)
+int CPVRDatabase::Get(CPVRChannelGroup &results, bool bCompressDB)
{
int iReturn(0);
+ bool bIgnoreEpgDB = CServiceBroker::GetSettings().GetBool(CSettings::SETTING_EPG_IGNOREDBFORCLIENT);
std::string strQuery = PrepareSQL("SELECT channels.idChannel, channels.iUniqueId, channels.bIsRadio, channels.bIsHidden, channels.bIsUserSetIcon, channels.bIsUserSetName, "
"channels.sIconPath, channels.sChannelName, channels.bIsVirtual, channels.bEPGEnabled, channels.sEPGScraper, channels.iLastWatched, channels.iClientId, channels.bIsLocked, "
@@ -174,11 +186,12 @@ int CPVRDatabase::Get(CPVRChannelGroupInternal &results)
"FROM map_channelgroups_channels "
"LEFT JOIN channels ON channels.idChannel = map_channelgroups_channels.idChannel "
"WHERE map_channelgroups_channels.idGroup = %u", results.GroupID());
+
+ CSingleLock lock(m_critSection);
if (ResultQuery(strQuery))
{
try
{
- bool bIgnoreEpgDB = CServiceBroker::GetSettings().GetBool(CSettings::SETTING_EPG_IGNOREDBFORCLIENT);
while (!m_pDS->eof())
{
CPVRChannelPtr channel = CPVRChannelPtr(new CPVRChannel());
@@ -194,19 +207,13 @@ int CPVRDatabase::Get(CPVRChannelGroupInternal &results)
channel->m_strChannelName = m_pDS->fv("sChannelName").get_asString();
channel->m_bEPGEnabled = m_pDS->fv("bEPGEnabled").get_asBool();
channel->m_strEPGScraper = m_pDS->fv("sEPGScraper").get_asString();
- channel->m_iLastWatched = (time_t) m_pDS->fv("iLastWatched").get_asInt();
+ channel->m_iLastWatched = static_cast<time_t>(m_pDS->fv("iLastWatched").get_asInt());
channel->m_iClientId = m_pDS->fv("iClientId").get_asInt();
- if (bIgnoreEpgDB)
- channel->m_iEpgId = -1;
- else
- channel->m_iEpgId = m_pDS->fv("idEpg").get_asInt();
+ channel->m_iEpgId = bIgnoreEpgDB ? -1 : m_pDS->fv("idEpg").get_asInt();
channel->UpdateEncryptionName();
-#if PVRDB_DEBUGGING
- CLog::Log(LOGDEBUG, "PVR - %s - channel '%s' loaded from the database", __FUNCTION__, channel->m_strChannelName.c_str());
-#endif
- PVRChannelGroupMember newMember = { channel, (unsigned int)m_pDS->fv("iChannelNumber").get_asInt() };
- results.m_sortedMembers.push_back(newMember);
+ PVRChannelGroupMember newMember = { channel, static_cast<unsigned int>(m_pDS->fv("iChannelNumber").get_asInt()) };
+ results.m_sortedMembers.emplace_back(newMember);
results.m_members.insert(std::make_pair(channel->StorageId(), newMember));
m_pDS->next();
@@ -225,6 +232,10 @@ int CPVRDatabase::Get(CPVRChannelGroupInternal &results)
}
m_pDS->close();
+
+ if (iReturn > 0 && bCompressDB)
+ Compress(true);
+
return iReturn;
}
@@ -235,6 +246,7 @@ bool CPVRDatabase::RemoveChannelsFromGroup(const CPVRChannelGroup &group)
Filter filter;
filter.AppendWhere(PrepareSQL("idGroup = %u", group.GroupID()));
+ CSingleLock lock(m_critSection);
return DeleteValues("map_channelgroups_channels", filter);
}
@@ -248,14 +260,16 @@ bool CPVRDatabase::GetCurrentGroupMembers(const CPVRChannelGroup &group, std::ve
return false;
}
- std::string strCurrentMembersQuery = PrepareSQL("SELECT idChannel FROM map_channelgroups_channels WHERE idGroup = %u", group.GroupID());
+ CSingleLock lock(m_critSection);
+
+ const std::string strCurrentMembersQuery = PrepareSQL("SELECT idChannel FROM map_channelgroups_channels WHERE idGroup = %u", group.GroupID());
if (ResultQuery(strCurrentMembersQuery))
{
try
{
while (!m_pDS->eof())
{
- members.push_back(m_pDS->fv("idChannel").get_asInt());
+ members.emplace_back(m_pDS->fv("idChannel").get_asInt());
m_pDS->next();
}
m_pDS->close();
@@ -285,6 +299,8 @@ bool CPVRDatabase::DeleteChannelsFromGroup(const CPVRChannelGroup &group, const
return false;
}
+ CSingleLock lock(m_critSection);
+
while (iDeletedChannels < channelsToDelete.size())
{
std::string strChannelsToDelete;
@@ -319,6 +335,8 @@ bool CPVRDatabase::RemoveStaleChannelsFromGroup(const CPVRChannelGroup &group)
return false;
}
+ CSingleLock lock(m_critSection);
+
if (!group.IsInternalGroup())
{
/* First remove channels that don't exist in the main channels table */
@@ -327,7 +345,7 @@ bool CPVRDatabase::RemoveStaleChannelsFromGroup(const CPVRChannelGroup &group)
// mysql doesn't support subqueries when deleting and sqlite doesn't support joins when deleting
if (StringUtils::EqualsNoCase(g_advancedSettings.m_databaseTV.type, "mysql"))
{
- std::string strQuery = PrepareSQL("DELETE m FROM map_channelgroups_channels m LEFT JOIN channels c ON (c.idChannel = m.idChannel) WHERE c.idChannel IS NULL");
+ const std::string strQuery = PrepareSQL("DELETE m FROM map_channelgroups_channels m LEFT JOIN channels c ON (c.idChannel = m.idChannel) WHERE c.idChannel IS NULL");
bDelete = ExecuteQuery(strQuery);
}
else
@@ -348,7 +366,7 @@ bool CPVRDatabase::RemoveStaleChannelsFromGroup(const CPVRChannelGroup &group)
for (unsigned int iChannelPtr = 0; iChannelPtr < currentMembers.size(); iChannelPtr++)
{
if (!group.IsGroupMember(currentMembers.at(iChannelPtr)))
- channelsToDelete.push_back(currentMembers.at(iChannelPtr));
+ channelsToDelete.emplace_back(currentMembers.at(iChannelPtr));
}
bDelete = DeleteChannelsFromGroup(group, channelsToDelete) && bDelete;
@@ -369,8 +387,8 @@ bool CPVRDatabase::DeleteChannelGroups(void)
{
CLog::Log(LOGDEBUG, "PVR - %s - deleting all channel groups from the database", __FUNCTION__);
- return DeleteValues("channelgroups") &&
- DeleteValues("map_channelgroups_channels");
+ CSingleLock lock(m_critSection);
+ return DeleteValues("channelgroups") && DeleteValues("map_channelgroups_channels");
}
bool CPVRDatabase::Delete(const CPVRChannelGroup &group)
@@ -386,15 +404,16 @@ bool CPVRDatabase::Delete(const CPVRChannelGroup &group)
filter.AppendWhere(PrepareSQL("idGroup = %u", group.GroupID()));
filter.AppendWhere(PrepareSQL("bIsRadio = %u", group.IsRadio()));
- return RemoveChannelsFromGroup(group) &&
- DeleteValues("channelgroups", filter);
+ CSingleLock lock(m_critSection);
+ return RemoveChannelsFromGroup(group) && DeleteValues("channelgroups", filter);
}
bool CPVRDatabase::Get(CPVRChannelGroups &results)
{
bool bReturn = false;
- std::string strQuery = PrepareSQL("SELECT * from channelgroups WHERE bIsRadio = %u", results.IsRadio());
+ CSingleLock lock(m_critSection);
+ const std::string strQuery = PrepareSQL("SELECT * from channelgroups WHERE bIsRadio = %u", results.IsRadio());
if (ResultQuery(strQuery))
{
try
@@ -403,7 +422,7 @@ bool CPVRDatabase::Get(CPVRChannelGroups &results)
{
CPVRChannelGroup data(m_pDS->fv("bIsRadio").get_asBool(), m_pDS->fv("idGroup").get_asInt(), m_pDS->fv("sName").get_asString());
data.SetGroupType(m_pDS->fv("iGroupType").get_asInt());
- data.SetLastWatched((time_t) m_pDS->fv("iLastWatched").get_asInt());
+ data.SetLastWatched(static_cast<time_t>(m_pDS->fv("iLastWatched").get_asInt()));
data.SetHidden(m_pDS->fv("bIsHidden").get_asBool());
data.SetPosition(m_pDS->fv("iPosition").get_asInt());
results.Update(data);
@@ -423,7 +442,7 @@ bool CPVRDatabase::Get(CPVRChannelGroups &results)
return bReturn;
}
-int CPVRDatabase::Get(CPVRChannelGroup &group)
+int CPVRDatabase::Get(CPVRChannelGroup &group, const std::map<int, CPVRChannelPtr> &allChannels)
{
int iReturn = -1;
@@ -434,7 +453,9 @@ int CPVRDatabase::Get(CPVRChannelGroup &group)
return -1;
}
- std::string strQuery = PrepareSQL("SELECT idChannel, iChannelNumber FROM map_channelgroups_channels WHERE idGroup = %u ORDER BY iChannelNumber", group.GroupID());
+ CSingleLock lock(m_critSection);
+
+ const std::string strQuery = PrepareSQL("SELECT idChannel, iChannelNumber FROM map_channelgroups_channels WHERE idGroup = %u ORDER BY iChannelNumber", group.GroupID());
if (ResultQuery(strQuery))
{
iReturn = 0;
@@ -445,16 +466,13 @@ int CPVRDatabase::Get(CPVRChannelGroup &group)
{
int iChannelId = m_pDS->fv("idChannel").get_asInt();
int iChannelNumber = m_pDS->fv("iChannelNumber").get_asInt();
- CPVRChannelPtr channel = CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAll(group.IsRadio())->GetByChannelID(iChannelId);
+ const auto& channel = allChannels.find(iChannelId);
- if (channel)
+ if (channel != allChannels.end())
{
-#if PVRDB_DEBUGGING
- CLog::Log(LOGDEBUG, "PVR - %s - channel '%s' loaded from the database", __FUNCTION__, channel->m_strChannelName.c_str());
-#endif
- PVRChannelGroupMember newMember = { channel, (unsigned int)iChannelNumber };
- group.m_sortedMembers.push_back(newMember);
- group.m_members.insert(std::make_pair(channel->StorageId(), newMember));
+ PVRChannelGroupMember newMember = { channel->second, static_cast<unsigned int>(iChannelNumber) };
+ group.m_sortedMembers.emplace_back(newMember);
+ group.m_members.insert(std::make_pair(channel->second->StorageId(), newMember));
++iReturn;
}
else
@@ -487,13 +505,15 @@ bool CPVRDatabase::PersistChannels(CPVRChannelGroup &group)
{
bool bReturn(true);
- for (PVR_CHANNEL_GROUP_MEMBERS::iterator it = group.m_members.begin(); it != group.m_members.end(); ++it)
+ CPVRChannelPtr channel;
+ for (const auto& groupMember : group.m_members)
{
- if (it->second.channel->IsChanged() || it->second.channel->IsNew())
+ channel = groupMember.second.channel;
+ if (channel->IsChanged() || channel->IsNew())
{
- if (Persist(*it->second.channel))
+ if (Persist(*channel, false))
{
- it->second.channel->Persisted();
+ groupMember.second.channel->Persisted();
bReturn = true;
}
}
@@ -505,12 +525,13 @@ bool CPVRDatabase::PersistChannels(CPVRChannelGroup &group)
{
std::string strQuery;
std::string strValue;
- for (PVR_CHANNEL_GROUP_MEMBERS::iterator it = group.m_members.begin(); it != group.m_members.end(); ++it)
+ for (const auto& groupMember : group.m_members)
{
- strQuery = PrepareSQL("iUniqueId = %u AND iClientId = %u", it->second.channel->UniqueID(), it->second.channel->ClientID());
+ channel = groupMember.second.channel;
+ strQuery = PrepareSQL("iUniqueId = %u AND iClientId = %u", channel->UniqueID(), channel->ClientID());
strValue = GetSingleValue("channels", "idChannel", strQuery);
if (!strValue.empty() && StringUtils::IsInteger(strValue))
- it->second.channel->SetChannelID(atoi(strValue.c_str()));
+ channel->SetChannelID(atoi(strValue.c_str()));
}
}
@@ -526,22 +547,21 @@ bool CPVRDatabase::PersistGroupMembers(const CPVRChannelGroup &group)
if (group.HasChannels())
{
- for (PVR_CHANNEL_GROUP_SORTED_MEMBERS::const_iterator it = group.m_sortedMembers.begin(); it != group.m_sortedMembers.end(); ++it)
+ for (const auto& groupMember : group.m_sortedMembers)
{
- std::string strWhereClause = PrepareSQL("idChannel = %u AND idGroup = %u AND iChannelNumber = %u AND iSubChannelNumber = %u",
- (*it).channel->ChannelID(), group.GroupID(), (*it).iChannelNumber, (*it).iSubChannelNumber);
+ const std::string strWhereClause = PrepareSQL("idChannel = %u AND idGroup = %u AND iChannelNumber = %u AND iSubChannelNumber = %u",
+ groupMember.channel->ChannelID(), group.GroupID(), groupMember.iChannelNumber, groupMember.iSubChannelNumber);
- std::string strValue = GetSingleValue("map_channelgroups_channels", "idChannel", strWhereClause);
+ const std::string strValue = GetSingleValue("map_channelgroups_channels", "idChannel", strWhereClause);
if (strValue.empty())
{
strQuery = PrepareSQL("REPLACE INTO map_channelgroups_channels ("
"idGroup, idChannel, iChannelNumber, iSubChannelNumber) "
"VALUES (%i, %i, %i, %i);",
- group.GroupID(), (*it).channel->ChannelID(), (*it).iChannelNumber, (*it).iSubChannelNumber);
+ group.GroupID(), groupMember.channel->ChannelID(), groupMember.iChannelNumber, groupMember.iSubChannelNumber);
QueueInsertQuery(strQuery);
}
}
- lock.Leave();
bReturn = CommitInsertQueries();
bRemoveChannels = RemoveStaleChannelsFromGroup(group);
@@ -554,7 +574,8 @@ bool CPVRDatabase::PersistGroupMembers(const CPVRChannelGroup &group)
bool CPVRDatabase::ResetEPG(void)
{
- std::string strQuery = PrepareSQL("UPDATE channels SET idEpg = 0");
+ CSingleLock lock(m_critSection);
+ const std::string strQuery = PrepareSQL("UPDATE channels SET idEpg = 0");
return ExecuteQuery(strQuery);
}
@@ -569,9 +590,8 @@ bool CPVRDatabase::Persist(CPVRChannelGroup &group)
std::string strQuery;
bReturn = true;
+ CSingleLock lock(m_critSection);
{
- CSingleLock lock(group.m_critSection);
-
/* insert a new entry when this is a new group, or replace the existing one otherwise */
if (group.GroupID() <= 0)
strQuery = PrepareSQL("INSERT INTO channelgroups (bIsRadio, iGroupType, sName, iLastWatched, bIsHidden, iPosition) VALUES (%i, %i, '%s', %u, %i, %i)",
@@ -584,7 +604,10 @@ bool CPVRDatabase::Persist(CPVRChannelGroup &group)
/* set the group id if it was <= 0 */
if (bReturn && group.GroupID() <= 0)
+ {
+ CSingleLock lock(group.m_critSection);
group.m_iGroupId = (int) m_pDS->lastinsertid();
+ }
}
/* only persist the channel data for the internal groups */
@@ -598,7 +621,7 @@ bool CPVRDatabase::Persist(CPVRChannelGroup &group)
return bReturn;
}
-bool CPVRDatabase::Persist(CPVRChannel &channel)
+bool CPVRDatabase::Persist(CPVRChannel &channel, bool bCommit)
{
bool bReturn(false);
@@ -610,6 +633,8 @@ bool CPVRDatabase::Persist(CPVRChannel &channel)
}
std::string strQuery;
+ CSingleLock lock(m_critSection);
+
if (channel.ChannelID() <= 0)
{
/* new channel */
@@ -640,9 +665,12 @@ bool CPVRDatabase::Persist(CPVRChannel &channel)
{
/* update the channel ID for new channels */
if (channel.ChannelID() <= 0)
- channel.SetChannelID((int)m_pDS->lastinsertid());
+ channel.SetChannelID(static_cast<int>(m_pDS->lastinsertid()));
bReturn = true;
+
+ if (bCommit)
+ bReturn = CommitInsertQueries();
}
return bReturn;
@@ -650,16 +678,16 @@ bool CPVRDatabase::Persist(CPVRChannel &channel)
bool CPVRDatabase::UpdateLastWatched(const CPVRChannel &channel)
{
- std::string strQuery = PrepareSQL("UPDATE channels SET iLastWatched = %u WHERE idChannel = %d",
+ CSingleLock lock(m_critSection);
+ const std::string strQuery = PrepareSQL("UPDATE channels SET iLastWatched = %u WHERE idChannel = %d",
static_cast<unsigned int>(channel.LastWatched()), channel.ChannelID());
-
return ExecuteQuery(strQuery);
}
bool CPVRDatabase::UpdateLastWatched(const CPVRChannelGroup &group)
{
- std::string strQuery = PrepareSQL("UPDATE channelgroups SET iLastWatched = %u WHERE idGroup = %d",
+ CSingleLock lock(m_critSection);
+ const std::string strQuery = PrepareSQL("UPDATE channelgroups SET iLastWatched = %u WHERE idGroup = %d",
static_cast<unsigned int>(group.LastWatched()), group.GroupID());
-
return ExecuteQuery(strQuery);
}
diff --git a/xbmc/pvr/PVRDatabase.h b/xbmc/pvr/PVRDatabase.h
index a8267b7edb..128d4221f0 100644
--- a/xbmc/pvr/PVRDatabase.h
+++ b/xbmc/pvr/PVRDatabase.h
@@ -19,17 +19,17 @@
*
*/
+#include <map>
#include <vector>
#include "dbwrappers/Database.h"
-#include "utils/log.h"
+#include "threads/CriticalSection.h"
-#include "pvr/PVRManager.h"
+#include "pvr/PVRTypes.h"
namespace PVR
{
class CPVRChannelGroup;
- class CPVRChannelGroupInternal;
class CPVRChannel;
class CPVRChannelGroups;
@@ -51,6 +51,11 @@ namespace PVR
bool Open() override;
/*!
+ * @brief Close the database.
+ */
+ void Close() override;
+
+ /*!
* @brief Get the minimal database version that is required to operate correctly.
* @return The minimal database version.
*/
@@ -74,9 +79,10 @@ namespace PVR
/*!
* @brief Add or update a channel entry in the database
* @param channel The channel to persist.
+ * @param bCommit queue only or queue and commit
* @return True when persisted or queued, false otherwise.
*/
- bool Persist(CPVRChannel &channel);
+ bool Persist(CPVRChannel &channel, bool bCommit);
/*!
* @brief Remove a channel entry from the database
@@ -88,9 +94,10 @@ namespace PVR
/*!
* @brief Get the list of channels from the database
* @param results The channel group to store the results in.
+ * @param bCompressDB Compress the DB after getting the list
* @return The amount of channels that were added.
*/
- int Get(CPVRChannelGroupInternal &results);
+ int Get(CPVRChannelGroup &results, bool bCompressDB);
//@}
@@ -120,9 +127,10 @@ namespace PVR
/*!
* @brief Add the group members to a group.
* @param group The group to get the channels for.
+ * @param allChannels All channels contained in the "all channels group" matching param group's 'IsRadio' property.
* @return The amount of channels that were added.
*/
- int Get(CPVRChannelGroup &group);
+ int Get(CPVRChannelGroup &group, const std::map<int, CPVRChannelPtr> &allChannels);
/*!
* @brief Add or update a channel group entry in the database.
@@ -180,5 +188,7 @@ namespace PVR
bool PersistChannels(CPVRChannelGroup &group);
bool RemoveChannelsFromGroup(const CPVRChannelGroup &group);
+
+ CCriticalSection m_critSection;
};
}
diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp
index 9d103b4261..c516734d43 100644
--- a/xbmc/pvr/PVRManager.cpp
+++ b/xbmc/pvr/PVRManager.cpp
@@ -343,7 +343,7 @@ void CPVRManager::Stop(void)
/* close database */
const CPVRDatabasePtr database(GetTVDatabase());
- if (database && database->IsOpen())
+ if (database)
database->Close();
SetState(ManagerStateStopped);
diff --git a/xbmc/pvr/channels/PVRChannel.cpp b/xbmc/pvr/channels/PVRChannel.cpp
index dee2d9a4c5..e2146806ba 100644
--- a/xbmc/pvr/channels/PVRChannel.cpp
+++ b/xbmc/pvr/channels/PVRChannel.cpp
@@ -29,6 +29,7 @@
#include "utils/log.h"
#include "pvr/PVRDatabase.h"
+#include "pvr/PVRManager.h"
#include "pvr/addons/PVRClients.h"
#include "pvr/channels/PVRChannelGroupInternal.h"
#include "pvr/epg/EpgContainer.h"
@@ -235,7 +236,7 @@ bool CPVRChannel::Persist()
const CPVRDatabasePtr database(CServiceBroker::GetPVRManager().GetTVDatabase());
if (database)
{
- bool bReturn = database->Persist(*this) && database->CommitInsertQueries();
+ bool bReturn = database->Persist(*this, true);
CSingleLock lock(m_critSection);
m_bChanged = !bReturn;
return bReturn;
diff --git a/xbmc/pvr/channels/PVRChannelGroup.cpp b/xbmc/pvr/channels/PVRChannelGroup.cpp
index f46efc7b1d..c48a4b5c00 100644
--- a/xbmc/pvr/channels/PVRChannelGroup.cpp
+++ b/xbmc/pvr/channels/PVRChannelGroup.cpp
@@ -589,7 +589,20 @@ int CPVRChannelGroup::LoadFromDb(bool bCompress /* = false */)
int iChannelCount = Size();
- database->Get(*this);
+ const CPVRChannelGroupPtr allGroup = CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAll(IsRadio());
+ if (!allGroup)
+ return -1;
+
+ std::map<int, CPVRChannelPtr> allChannels;
+ {
+ CSingleLock lock(allGroup->m_critSection);
+ for (const auto& groupMember : allGroup->m_members)
+ {
+ allChannels.insert(std::make_pair(groupMember.second.channel->ChannelID(), groupMember.second.channel));
+ }
+ }
+
+ database->Get(*this, allChannels);
return Size() - iChannelCount;
}
@@ -700,10 +713,6 @@ bool CPVRChannelGroup::UpdateGroupEntries(const CPVRChannelGroup &channels)
bool bChanged(false);
bool bRemoved(false);
- const CPVRDatabasePtr database(CServiceBroker::GetPVRManager().GetTVDatabase());
- if (!database)
- return bReturn;
-
CSingleLock lock(m_critSection);
/* sort by client channel number if this is the first time or if pvrmanager.backendchannelorder is true */
bool bUseBackendChannelNumbers(m_members.empty() || m_bUsingBackendChannelOrder);
@@ -717,12 +726,12 @@ bool CPVRChannelGroup::UpdateGroupEntries(const CPVRChannelGroup &channels)
new channels were added at the back, so they'll get the highest numbers */
bool bRenumbered = SortAndRenumber();
+ bReturn = Persist();
+
SetChanged();
- lock.Leave();
+ lock.Leave();
NotifyObservers(HasNewChannels() || bRemoved || bRenumbered ? ObservableMessageChannelGroupReset : ObservableMessageChannelGroup);
-
- bReturn = Persist();
}
else
{
@@ -855,7 +864,6 @@ bool CPVRChannelGroup::Persist(void)
CLog::Log(LOGDEBUG, "CPVRChannelGroup - %s - persisting channel group '%s' with %d channels",
__FUNCTION__, GroupName().c_str(), (int) m_members.size());
m_bChanged = false;
- lock.Leave();
bReturn = database->Persist(*this);
}
@@ -981,7 +989,6 @@ void CPVRChannelGroup::OnSettingChanged(std::shared_ptr<const CSetting> setting)
m_bUsingBackendChannelOrder = bUsingBackendChannelOrder;
m_bUsingBackendChannelNumbers = bUsingBackendChannelNumbers;
- lock.Leave();
/* check whether this channel group has to be renumbered */
if (bChannelOrderChanged || bChannelNumbersChanged)
@@ -1143,7 +1150,6 @@ bool CPVRChannelGroup::SetLastWatched(time_t iLastWatched)
if (m_iLastWatched != iLastWatched)
{
m_iLastWatched = iLastWatched;
- lock.Leave();
/* update the database immediately */
if (database)
diff --git a/xbmc/pvr/channels/PVRChannelGroup.h b/xbmc/pvr/channels/PVRChannelGroup.h
index 26ceec8923..e14ea5ef9a 100644
--- a/xbmc/pvr/channels/PVRChannelGroup.h
+++ b/xbmc/pvr/channels/PVRChannelGroup.h
@@ -19,6 +19,7 @@
*
*/
+#include <map>
#include <memory>
#include <utility>
#include <vector>
diff --git a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp
index 7aa286f0a5..2a852c1797 100644
--- a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp
+++ b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp
@@ -224,15 +224,9 @@ int CPVRChannelGroupInternal::LoadFromDb(bool bCompress /* = false */)
int iChannelCount = Size();
- if (database->Get(*this) > 0)
+ if (database->Get(*this, bCompress) == 0)
{
- if (bCompress)
- database->Compress(true);
- }
- else
- {
- CLog::Log(LOGINFO, "PVRChannelGroupInternal - %s - no channels in the database",
- __FUNCTION__);
+ CLog::Log(LOGINFO, "PVRChannelGroupInternal - %s - no channels in the database", __FUNCTION__);
}
SortByChannelNumber();
diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp
index 597c7b6a76..cedb81ea0c 100644
--- a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp
+++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp
@@ -125,7 +125,7 @@ void CGUIDialogPVRChannelsOSD::OnDeinitWindow(int nextWindowID)
{
CGUIWindowPVRBase::SetSelectedItemPath(m_group->IsRadio(), m_viewControl.GetSelectedItemPath());
- // next OnInitWindow will set the group which is then selceted
+ // next OnInitWindow will set the group which is then selected
m_group.reset();
}