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.
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"
27 CDatabaseManager::CDatabaseManager() :
30 // Initialize the addon database (must be before the addon manager is init'd)
31 ADDON::CAddonDatabase db
;
35 CDatabaseManager::~CDatabaseManager() = default;
37 void CDatabaseManager::Initialize()
39 std::unique_lock
<CCriticalSection
> lock(m_section
);
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
;
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
);
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
;
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;
116 CLog::Log(LOGERROR
, "Unable to copy old database {} to new version {}", dbName
, latestDb
);
125 if (!db
.Connect(latestDb
, dbSettings
, false))
127 CLog::Log(LOGERROR
, "Unable to open freshly copied database {}", latestDb
);
132 // yay - we have a copy of our db, now do our worst with it
133 if (UpdateVersion(db
, latestDb
))
136 // update failed - loop around and see if we have another one available
140 // drop back to the previous version and try that
143 // try creating a new one
144 if (db
.Connect(latestDb
, dbSettings
, true))
147 // failed to update or open the database
149 CLog::Log(LOGERROR
, "Unable to create new database");
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
);
163 else if (version
< db
.GetSchemaVersion())
165 CLog::Log(LOGINFO
, "Attempting to update the database {} from version {} to {}", dbName
,
166 version
, db
.GetSchemaVersion());
168 db
.BeginTransaction();
172 // drop old analytics
181 CLog::Log(LOGERROR
, "Exception droping old analytics from {}", dbName
);
182 db
.RollbackTransaction();
186 db
.CommitTransaction();
187 db
.BeginTransaction();
191 // update table(s), recreate analytics, update version
192 db
.UpdateTables(version
);
193 db
.CreateAnalytics();
194 db
.UpdateVersionNumber();
198 CLog::Log(LOGERROR
, "Exception updating database {} from version {} to {}", dbName
, version
,
199 db
.GetSchemaVersion());
204 CLog::Log(LOGERROR
, "Error updating database {} from version {} to {}", dbName
, version
,
205 db
.GetSchemaVersion());
206 db
.RollbackTransaction();
209 bReturn
= db
.CommitTransaction();
210 CLog::Log(LOGINFO
, "Update to version {} successful", db
.GetSchemaVersion());
212 else if (version
> db
.GetSchemaVersion())
216 "Can't open the database {} as it is a NEWER version than what we were expecting?",
222 CLog::Log(LOGINFO
, "Running database version {}", dbName
);
228 void CDatabaseManager::UpdateStatus(const std::string
&name
, DB_STATUS status
)
230 std::unique_lock
<CCriticalSection
> lock(m_section
);
231 m_dbStatus
[name
] = status
;