[PVR][Estuary] Timer settings dialog: Show client name in timer type selection dialog...
[xbmc.git] / xbmc / DatabaseManager.cpp
blob33f38e876699aef4dc2970917211b89e6f66275e
1 /*
2 * Copyright (C) 2012-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "DatabaseManager.h"
11 #include "ServiceBroker.h"
12 #include "TextureDatabase.h"
13 #include "addons/AddonDatabase.h"
14 #include "music/MusicDatabase.h"
15 #include "pvr/PVRDatabase.h"
16 #include "pvr/epg/EpgDatabase.h"
17 #include "settings/AdvancedSettings.h"
18 #include "settings/SettingsComponent.h"
19 #include "utils/log.h"
20 #include "video/VideoDatabase.h"
21 #include "view/ViewDatabase.h"
23 #include <mutex>
25 using namespace PVR;
27 CDatabaseManager::CDatabaseManager() :
28 m_bIsUpgrading(false)
30 // Initialize the addon database (must be before the addon manager is init'd)
31 ADDON::CAddonDatabase db;
32 UpdateDatabase(db);
35 CDatabaseManager::~CDatabaseManager() = default;
37 void CDatabaseManager::Initialize()
39 std::unique_lock<CCriticalSection> lock(m_section);
41 m_dbStatus.clear();
43 CLog::Log(LOGDEBUG, "{}, updating databases...", __FUNCTION__);
45 const std::shared_ptr<CAdvancedSettings> advancedSettings = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings();
47 // NOTE: Order here is important. In particular, CTextureDatabase has to be updated
48 // before CVideoDatabase.
50 ADDON::CAddonDatabase db;
51 UpdateDatabase(db);
53 { CViewDatabase db; UpdateDatabase(db); }
54 { CTextureDatabase db; UpdateDatabase(db); }
55 { CMusicDatabase db; UpdateDatabase(db, &advancedSettings->m_databaseMusic); }
56 { CVideoDatabase db; UpdateDatabase(db, &advancedSettings->m_databaseVideo); }
57 { CPVRDatabase db; UpdateDatabase(db, &advancedSettings->m_databaseTV); }
58 { CPVREpgDatabase db; UpdateDatabase(db, &advancedSettings->m_databaseEpg); }
60 CLog::Log(LOGDEBUG, "{}, updating databases... DONE", __FUNCTION__);
62 m_bIsUpgrading = false;
65 bool CDatabaseManager::CanOpen(const std::string &name)
67 std::unique_lock<CCriticalSection> lock(m_section);
68 std::map<std::string, DB_STATUS>::const_iterator i = m_dbStatus.find(name);
69 if (i != m_dbStatus.end())
70 return i->second == DB_READY;
71 return false; // db isn't even attempted to update yet
74 void CDatabaseManager::UpdateDatabase(CDatabase &db, DatabaseSettings *settings)
76 std::string name = db.GetBaseDBName();
77 UpdateStatus(name, DB_UPDATING);
78 if (Update(db, settings ? *settings : DatabaseSettings()))
79 UpdateStatus(name, DB_READY);
80 else
81 UpdateStatus(name, DB_FAILED);
84 bool CDatabaseManager::Update(CDatabase &db, const DatabaseSettings &settings)
86 DatabaseSettings dbSettings = settings;
87 db.InitSettings(dbSettings);
89 int version = db.GetSchemaVersion();
90 std::string latestDb = dbSettings.name;
91 latestDb += std::to_string(version);
93 while (version >= db.GetMinSchemaVersion())
95 std::string dbName = dbSettings.name;
96 if (version)
97 dbName += std::to_string(version);
99 if (db.Connect(dbName, dbSettings, false))
101 // Database exists, take a copy for our current version (if needed) and reopen that one
102 if (version < db.GetSchemaVersion())
104 CLog::Log(LOGINFO, "Old database found - updating from version {} to {}", version,
105 db.GetSchemaVersion());
106 m_bIsUpgrading = true;
108 bool copy_fail = false;
112 db.CopyDB(latestDb);
114 catch (...)
116 CLog::Log(LOGERROR, "Unable to copy old database {} to new version {}", dbName, latestDb);
117 copy_fail = true;
120 db.Close();
122 if (copy_fail)
123 return false;
125 if (!db.Connect(latestDb, dbSettings, false))
127 CLog::Log(LOGERROR, "Unable to open freshly copied database {}", latestDb);
128 return false;
132 // yay - we have a copy of our db, now do our worst with it
133 if (UpdateVersion(db, latestDb))
134 return true;
136 // update failed - loop around and see if we have another one available
137 db.Close();
140 // drop back to the previous version and try that
141 version--;
143 // try creating a new one
144 if (db.Connect(latestDb, dbSettings, true))
145 return true;
147 // failed to update or open the database
148 db.Close();
149 CLog::Log(LOGERROR, "Unable to create new database");
150 return false;
153 bool CDatabaseManager::UpdateVersion(CDatabase &db, const std::string &dbName)
155 int version = db.GetDBVersion();
156 bool bReturn = false;
158 if (version < db.GetMinSchemaVersion())
160 CLog::Log(LOGERROR, "Can't update database {} from version {} - it's too old", dbName, version);
161 return false;
163 else if (version < db.GetSchemaVersion())
165 CLog::Log(LOGINFO, "Attempting to update the database {} from version {} to {}", dbName,
166 version, db.GetSchemaVersion());
167 bool success = true;
168 db.BeginTransaction();
172 // drop old analytics
173 db.DropAnalytics();
175 catch (...)
177 success = false;
179 if (!success)
181 CLog::Log(LOGERROR, "Exception droping old analytics from {}", dbName);
182 db.RollbackTransaction();
183 return false;
186 db.CommitTransaction();
187 db.BeginTransaction();
191 // update table(s), recreate analytics, update version
192 db.UpdateTables(version);
193 db.CreateAnalytics();
194 db.UpdateVersionNumber();
196 catch (...)
198 CLog::Log(LOGERROR, "Exception updating database {} from version {} to {}", dbName, version,
199 db.GetSchemaVersion());
200 success = false;
202 if (!success)
204 CLog::Log(LOGERROR, "Error updating database {} from version {} to {}", dbName, version,
205 db.GetSchemaVersion());
206 db.RollbackTransaction();
207 return false;
209 bReturn = db.CommitTransaction();
210 CLog::Log(LOGINFO, "Update to version {} successful", db.GetSchemaVersion());
212 else if (version > db.GetSchemaVersion())
214 bReturn = false;
215 CLog::Log(LOGERROR,
216 "Can't open the database {} as it is a NEWER version than what we were expecting?",
217 dbName);
219 else
221 bReturn = true;
222 CLog::Log(LOGINFO, "Running database version {}", dbName);
225 return bReturn;
228 void CDatabaseManager::UpdateStatus(const std::string &name, DB_STATUS status)
230 std::unique_lock<CCriticalSection> lock(m_section);
231 m_dbStatus[name] = status;