aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphunkyfish <phunkyfish@gmail.com>2020-11-08 15:25:08 +0000
committerGitHub <noreply@github.com>2020-11-08 15:25:08 +0000
commitcce99b44d13314611f20bbfe80221c8463d5dc09 (patch)
tree6c672d9dc8443e7450bc0d448d65273bc86f23ab
parentd6a4bc3f030d5e57e8e706ff5c759fa3e812eca0 (diff)
parent4cf954f6695bf0cfece1a41e49f98e3aaa70d080 (diff)
Merge pull request #18700 from phunkyfish/bulk-commmit-pvr
[pvr] bulk commit epg queries when deleting a channel
-rw-r--r--xbmc/pvr/PVRDatabase.cpp20
-rw-r--r--xbmc/pvr/PVRDatabase.h12
-rw-r--r--xbmc/pvr/channels/PVRChannel.cpp4
-rw-r--r--xbmc/pvr/channels/PVRChannel.h2
-rw-r--r--xbmc/pvr/channels/PVRChannelGroupInternal.cpp24
-rw-r--r--xbmc/pvr/epg/Epg.cpp6
-rw-r--r--xbmc/pvr/epg/Epg.h6
-rw-r--r--xbmc/pvr/epg/EpgContainer.cpp12
-rw-r--r--xbmc/pvr/epg/EpgDatabase.cpp19
-rw-r--r--xbmc/pvr/epg/EpgDatabase.h15
-rw-r--r--xbmc/pvr/epg/EpgTagsContainer.cpp4
-rw-r--r--xbmc/pvr/epg/EpgTagsContainer.h4
12 files changed, 100 insertions, 28 deletions
diff --git a/xbmc/pvr/PVRDatabase.cpp b/xbmc/pvr/PVRDatabase.cpp
index afba3956b5..77895e4e4e 100644
--- a/xbmc/pvr/PVRDatabase.cpp
+++ b/xbmc/pvr/PVRDatabase.cpp
@@ -75,6 +75,16 @@ void CPVRDatabase::Close()
CDatabase::Close();
}
+void CPVRDatabase::Lock()
+{
+ m_critSection.lock();
+}
+
+void CPVRDatabase::Unlock()
+{
+ m_critSection.unlock();
+}
+
void CPVRDatabase::CreateTables()
{
CSingleLock lock(m_critSection);
@@ -289,19 +299,21 @@ bool CPVRDatabase::DeleteChannels()
return DeleteValues("channels");
}
-bool CPVRDatabase::Delete(const CPVRChannel& channel)
+bool CPVRDatabase::QueueDeleteQuery(const CPVRChannel& channel)
{
/* invalid channel */
if (channel.ChannelID() <= 0)
return false;
- CLog::LogFC(LOGDEBUG, LOGPVR, "Deleting channel '{}' from the database", channel.ChannelName());
+ CLog::LogFC(LOGDEBUG, LOGPVR, "Queueing delete for channel '{}' from the database",
+ channel.ChannelName());
Filter filter;
filter.AppendWhere(PrepareSQL("idChannel = %u", channel.ChannelID()));
- CSingleLock lock(m_critSection);
- return DeleteValues("channels", filter);
+ std::string strQuery;
+ BuildSQL(PrepareSQL("DELETE FROM %s ", "channels"), filter, strQuery);
+ return CDatabase::QueueDeleteQuery(strQuery);
}
int CPVRDatabase::Get(CPVRChannelGroup& results, bool bCompressDB)
diff --git a/xbmc/pvr/PVRDatabase.h b/xbmc/pvr/PVRDatabase.h
index d0cb5cc879..b2b73db319 100644
--- a/xbmc/pvr/PVRDatabase.h
+++ b/xbmc/pvr/PVRDatabase.h
@@ -46,6 +46,16 @@ namespace PVR
void Close() override;
/*!
+ * @brief Lock the database.
+ */
+ void Lock();
+
+ /*!
+ * @brief Unlock the database.
+ */
+ void Unlock();
+
+ /*!
* @brief Get the minimal database version that is required to operate correctly.
* @return The minimal database version.
*/
@@ -109,7 +119,7 @@ namespace PVR
* @param channel The channel to remove.
* @return True if the channel was removed, false otherwise.
*/
- bool Delete(const CPVRChannel& channel);
+ bool QueueDeleteQuery(const CPVRChannel& channel);
/*!
* @brief Get the list of channels from the database
diff --git a/xbmc/pvr/channels/PVRChannel.cpp b/xbmc/pvr/channels/PVRChannel.cpp
index 5187b1647d..271d1b336e 100644
--- a/xbmc/pvr/channels/PVRChannel.cpp
+++ b/xbmc/pvr/channels/PVRChannel.cpp
@@ -101,7 +101,7 @@ void CPVRChannel::Serialize(CVariant& value) const
/********** XBMC related channel methods **********/
-bool CPVRChannel::Delete()
+bool CPVRChannel::QueueDelete()
{
bool bReturn = false;
const std::shared_ptr<CPVRDatabase> database = CServiceBroker::GetPVRManager().GetTVDatabase();
@@ -117,7 +117,7 @@ bool CPVRChannel::Delete()
m_epg.reset();
}
- bReturn = database->Delete(*this);
+ bReturn = database->QueueDeleteQuery(*this);
return bReturn;
}
diff --git a/xbmc/pvr/channels/PVRChannel.h b/xbmc/pvr/channels/PVRChannel.h
index f678ed4661..ff489197f6 100644
--- a/xbmc/pvr/channels/PVRChannel.h
+++ b/xbmc/pvr/channels/PVRChannel.h
@@ -50,7 +50,7 @@ namespace PVR
* @brief Delete this channel from the database and delete the corresponding EPG table if it exists.
* @return True if it was deleted successfully, false otherwise.
*/
- bool Delete();
+ bool QueueDelete();
/*!
* @brief Update this channel tag with the data of the given channel tag.
diff --git a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp
index 96e065d9dd..5b51c4ca2d 100644
--- a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp
+++ b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp
@@ -282,10 +282,28 @@ std::vector<std::shared_ptr<CPVRChannel>> CPVRChannelGroupInternal::RemoveDelete
{
std::vector<std::shared_ptr<CPVRChannel>> removedChannels = CPVRChannelGroup::RemoveDeletedChannels(channels);
- for (const auto& channel : removedChannels)
+ bool channelsDeleted = false;
+
+ const std::shared_ptr<CPVRDatabase> database = CServiceBroker::GetPVRManager().GetTVDatabase();
+ if (!database)
+ {
+ CLog::LogF(LOGERROR, "No TV database");
+ }
+ else
{
- // since channel was not found in the internal group, it was deleted from the backend
- channel->Delete();
+ // Note: We must lock the db the whole time, otherwise races may occur.
+ database->Lock();
+
+ for (const auto& channel : removedChannels)
+ {
+ // since channel was not found in the internal group, it was deleted from the backend
+ channelsDeleted |= channel->QueueDelete();
+ }
+
+ if (channelsDeleted)
+ database->CommitDeleteQueries();
+
+ database->Unlock();
}
return removedChannels;
diff --git a/xbmc/pvr/epg/Epg.cpp b/xbmc/pvr/epg/Epg.cpp
index 8fce752b2c..1c8972994c 100644
--- a/xbmc/pvr/epg/Epg.cpp
+++ b/xbmc/pvr/epg/Epg.cpp
@@ -330,7 +330,7 @@ bool CPVREpg::QueuePersistQuery(const std::shared_ptr<CPVREpgDatabase>& database
return true;
}
-bool CPVREpg::Delete(const std::shared_ptr<CPVREpgDatabase>& database)
+bool CPVREpg::QueueDeleteQueries(const std::shared_ptr<CPVREpgDatabase>& database)
{
if (!database)
{
@@ -339,10 +339,10 @@ bool CPVREpg::Delete(const std::shared_ptr<CPVREpgDatabase>& database)
}
// delete own epg db entry
- database->Delete(*this);
+ database->QueueDeleteEpgQuery(*this);
// delete all tags for this epg from db
- m_tags.Delete();
+ m_tags.QueueDelete();
Clear();
diff --git a/xbmc/pvr/epg/Epg.h b/xbmc/pvr/epg/Epg.h
index 09577c378f..6b3f18da64 100644
--- a/xbmc/pvr/epg/Epg.h
+++ b/xbmc/pvr/epg/Epg.h
@@ -217,11 +217,11 @@ namespace PVR
bool QueuePersistQuery(const std::shared_ptr<CPVREpgDatabase>& database);
/*!
- * @brief Delete this table from the given database
+ * @brief Write the delete queries into the given database's queue
* @param database The database.
- * @return True if the table was deleted, false otherwise.
+ * @return True on success, false otherwise.
*/
- bool Delete(const std::shared_ptr<CPVREpgDatabase>& database);
+ bool QueueDeleteQueries(const std::shared_ptr<CPVREpgDatabase>& database);
/*!
* @brief Get the start time of the first entry in this table.
diff --git a/xbmc/pvr/epg/EpgContainer.cpp b/xbmc/pvr/epg/EpgContainer.cpp
index 5aff3f3df3..00ca07e522 100644
--- a/xbmc/pvr/epg/EpgContainer.cpp
+++ b/xbmc/pvr/epg/EpgContainer.cpp
@@ -631,6 +631,13 @@ bool CPVREpgContainer::DeleteEpg(const std::shared_ptr<CPVREpg>& epg)
if (!epg || epg->EpgID() < 0)
return false;
+ const std::shared_ptr<CPVREpgDatabase> database = GetEpgDatabase();
+ if (!database)
+ {
+ CLog::LogF(LOGERROR, "No EPG database");
+ return false;
+ }
+
std::shared_ptr<CPVREpg> epgToDelete;
{
CSingleLock lock(m_critSection);
@@ -646,7 +653,10 @@ bool CPVREpgContainer::DeleteEpg(const std::shared_ptr<CPVREpg>& epg)
CLog::LogFC(LOGDEBUG, LOGEPG, "Deleting EPG table {} ({})", epg->Name(), epg->EpgID());
- epgEntry->second->Delete(GetEpgDatabase());
+ database->Lock();
+ epgEntry->second->QueueDeleteQueries(database);
+ database->CommitDeleteQueries();
+ database->Unlock();
epgToDelete = epgEntry->second;
m_epgIdToEpgMap.erase(epgEntry);
diff --git a/xbmc/pvr/epg/EpgDatabase.cpp b/xbmc/pvr/epg/EpgDatabase.cpp
index 383872d6a1..9fb62c5020 100644
--- a/xbmc/pvr/epg/EpgDatabase.cpp
+++ b/xbmc/pvr/epg/EpgDatabase.cpp
@@ -274,7 +274,7 @@ bool CPVREpgDatabase::DeleteEpg()
return bReturn;
}
-bool CPVREpgDatabase::Delete(const CPVREpg& table)
+bool CPVREpgDatabase::QueueDeleteEpgQuery(const CPVREpg& table)
{
/* invalid channel */
if (table.EpgID() <= 0)
@@ -287,7 +287,10 @@ bool CPVREpgDatabase::Delete(const CPVREpg& table)
CSingleLock lock(m_critSection);
filter.AppendWhere(PrepareSQL("idEpg = %u", table.EpgID()));
- return DeleteValues("epg", filter);
+
+ std::string strQuery;
+ BuildSQL(PrepareSQL("DELETE FROM %s ", "epg"), filter, strQuery);
+ return QueueDeleteQuery(strQuery);
}
bool CPVREpgDatabase::QueueDeleteTagQuery(const CPVREpgInfoTag& tag)
@@ -1052,6 +1055,18 @@ bool CPVREpgDatabase::DeleteEpgTags(int iEpgId)
return DeleteValues("epgtags", filter);
}
+bool CPVREpgDatabase::QueueDeleteEpgTags(int iEpgId)
+{
+ Filter filter;
+
+ CSingleLock lock(m_critSection);
+ filter.AppendWhere(PrepareSQL("idEpg = %u", iEpgId));
+
+ std::string strQuery;
+ BuildSQL(PrepareSQL("DELETE FROM %s ", "epg"), filter, strQuery);
+ return QueueDeleteQuery(strQuery);
+}
+
bool CPVREpgDatabase::QueuePersistQuery(const CPVREpgInfoTag& tag)
{
if (tag.EpgID() <= 0)
diff --git a/xbmc/pvr/epg/EpgDatabase.h b/xbmc/pvr/epg/EpgDatabase.h
index 1e02e6f90b..c9b28842fd 100644
--- a/xbmc/pvr/epg/EpgDatabase.h
+++ b/xbmc/pvr/epg/EpgDatabase.h
@@ -81,11 +81,11 @@ namespace PVR
bool DeleteEpg();
/*!
- * @brief Delete an EPG table.
- * @param table The table to remove.
- * @return True if the table was removed successfully, false otherwise.
+ * @brief Queue deletionof an EPG table.
+ * @param tag The table to queue for deletion.
+ * @return True on success, false otherwise.
*/
- bool Delete(const CPVREpg& table);
+ bool QueueDeleteEpgQuery(const CPVREpg& table);
/*!
* @brief Write the query to delete the given EPG tag to db query queue.
@@ -258,6 +258,13 @@ namespace PVR
bool DeleteEpgTags(int iEpgId);
/*!
+ * @brief Queue the erase all EPG tags with the given epg ID.
+ * @param iEpgId The ID of the EPG.
+ * @return True if the entries were queued successfully, false otherwise.
+ */
+ bool QueueDeleteEpgTags(int iEpgId);
+
+ /*!
* @brief Write the query to persist the given EPG tag to db query queue.
* @param tag The tag to persist.
* @return True on success, false otherwise.
diff --git a/xbmc/pvr/epg/EpgTagsContainer.cpp b/xbmc/pvr/epg/EpgTagsContainer.cpp
index 797f0c10c7..c1a8123959 100644
--- a/xbmc/pvr/epg/EpgTagsContainer.cpp
+++ b/xbmc/pvr/epg/EpgTagsContainer.cpp
@@ -643,10 +643,10 @@ void CPVREpgTagsContainer::QueuePersistQuery()
}
}
-void CPVREpgTagsContainer::Delete()
+void CPVREpgTagsContainer::QueueDelete()
{
if (m_database)
- m_database->DeleteEpgTags(m_iEpgID);
+ m_database->QueueDeleteEpgTags(m_iEpgID);
Clear();
}
diff --git a/xbmc/pvr/epg/EpgTagsContainer.h b/xbmc/pvr/epg/EpgTagsContainer.h
index 75ed5029b9..99b06b946f 100644
--- a/xbmc/pvr/epg/EpgTagsContainer.h
+++ b/xbmc/pvr/epg/EpgTagsContainer.h
@@ -171,9 +171,9 @@ public:
void QueuePersistQuery();
/*!
- * @brief Delete this container from its database.
+ * @brief Queue the deletion of this container from its database.
*/
- void Delete();
+ void QueueDelete();
private:
/*!