Merge pull request #1064 from croneter/optimize
Fix to correctly wipe Kodi databases
This commit is contained in:
commit
b9aaf92aed
5 changed files with 35 additions and 32 deletions
|
@ -52,21 +52,25 @@ def catch_operationalerrors(method):
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def _initial_db_connection_setup(conn):
|
def _initial_db_connection_setup(conn, wal_mode):
|
||||||
"""
|
"""
|
||||||
Set-up DB e.g. for WAL journal mode, if that hasn't already been done
|
Set-up DB e.g. for WAL journal mode, if that hasn't already been done
|
||||||
before. Also start a transaction
|
before. Also start a transaction
|
||||||
"""
|
"""
|
||||||
|
if wal_mode:
|
||||||
conn.execute('PRAGMA journal_mode=WAL;')
|
conn.execute('PRAGMA journal_mode=WAL;')
|
||||||
conn.execute('PRAGMA cache_size = -8000;')
|
conn.execute('PRAGMA cache_size = -8000;')
|
||||||
conn.execute('PRAGMA synchronous=NORMAL;')
|
conn.execute('PRAGMA synchronous=NORMAL;')
|
||||||
conn.execute('BEGIN')
|
conn.execute('BEGIN')
|
||||||
|
|
||||||
|
|
||||||
def connect(media_type=None):
|
def connect(media_type=None, wal_mode=True):
|
||||||
"""
|
"""
|
||||||
Open a connection to the Kodi database.
|
Open a connection to the Kodi database.
|
||||||
media_type: 'video' (standard if not passed), 'plex', 'music', 'texture'
|
media_type: 'video' (standard if not passed), 'plex', 'music', 'texture'
|
||||||
|
Pass wal_mode=False if you want the standard (and slower) sqlite
|
||||||
|
journal_mode, e.g. when wiping entire tables. Useful if you do NOT want
|
||||||
|
concurrent access to DB for both PKC and Kodi
|
||||||
"""
|
"""
|
||||||
if media_type == "plex":
|
if media_type == "plex":
|
||||||
db_path = v.DB_PLEX_PATH
|
db_path = v.DB_PLEX_PATH
|
||||||
|
@ -80,7 +84,7 @@ def connect(media_type=None):
|
||||||
attempts = DB_WRITE_ATTEMPTS
|
attempts = DB_WRITE_ATTEMPTS
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
_initial_db_connection_setup(conn)
|
_initial_db_connection_setup(conn, wal_mode)
|
||||||
except sqlite3.OperationalError as err:
|
except sqlite3.OperationalError as err:
|
||||||
if 'database is locked' not in err:
|
if 'database is locked' not in err:
|
||||||
# Not an error we want to catch, so reraise it
|
# Not an error we want to catch, so reraise it
|
||||||
|
|
|
@ -61,7 +61,10 @@ def setup_kodi_default_entries():
|
||||||
|
|
||||||
def reset_cached_images():
|
def reset_cached_images():
|
||||||
LOG.info('Resetting cached artwork')
|
LOG.info('Resetting cached artwork')
|
||||||
# Remove all existing textures first
|
LOG.debug('Resetting the Kodi texture DB')
|
||||||
|
with KodiTextureDB(wal_mode=False) as kodidb:
|
||||||
|
kodidb.wipe()
|
||||||
|
LOG.debug('Deleting all cached image files')
|
||||||
path = path_ops.translate_path('special://thumbnails/')
|
path = path_ops.translate_path('special://thumbnails/')
|
||||||
if path_ops.exists(path):
|
if path_ops.exists(path):
|
||||||
path_ops.rmtree(path, ignore_errors=True)
|
path_ops.rmtree(path, ignore_errors=True)
|
||||||
|
@ -72,10 +75,10 @@ def reset_cached_images():
|
||||||
new_path = path_ops.translate_path('special://thumbnails/%s' % path)
|
new_path = path_ops.translate_path('special://thumbnails/%s' % path)
|
||||||
try:
|
try:
|
||||||
path_ops.makedirs(path_ops.encode_path(new_path))
|
path_ops.makedirs(path_ops.encode_path(new_path))
|
||||||
except OSError:
|
except OSError as err:
|
||||||
pass
|
LOG.warn('Could not create thumbnail directory %s: %s',
|
||||||
with KodiTextureDB() as kodidb:
|
new_path, err)
|
||||||
kodidb.reset_cached_images()
|
LOG.info('Done resetting cached artwork')
|
||||||
|
|
||||||
|
|
||||||
def wipe_dbs(music=True):
|
def wipe_dbs(music=True):
|
||||||
|
@ -83,16 +86,18 @@ def wipe_dbs(music=True):
|
||||||
Completely resets the Kodi databases 'video', 'texture' and 'music' (if
|
Completely resets the Kodi databases 'video', 'texture' and 'music' (if
|
||||||
music sync is enabled)
|
music sync is enabled)
|
||||||
|
|
||||||
DO NOT use context menu as we need to connect without WAL mode - if Kodi
|
We need to connect without sqlite WAL mode as Kodi might still be accessing
|
||||||
is still accessing the DB
|
the dbs and we need to prevent that
|
||||||
"""
|
"""
|
||||||
LOG.warn('Wiping Kodi databases!')
|
LOG.warn('Wiping Kodi databases!')
|
||||||
kinds = [KodiVideoDB, KodiTextureDB]
|
LOG.info('Wiping Kodi video database')
|
||||||
if music:
|
with KodiVideoDB(wal_mode=False) as kodidb:
|
||||||
kinds.insert(1, KodiMusicDB)
|
|
||||||
for kind in kinds:
|
|
||||||
with kind() as kodidb:
|
|
||||||
kodidb.wipe()
|
kodidb.wipe()
|
||||||
|
if music:
|
||||||
|
LOG.info('Wiping Kodi music database')
|
||||||
|
with KodiMusicDB(wal_mode=False) as kodidb:
|
||||||
|
kodidb.wipe()
|
||||||
|
reset_cached_images()
|
||||||
setup_kodi_default_entries()
|
setup_kodi_default_entries()
|
||||||
# Delete SQLITE wal files
|
# Delete SQLITE wal files
|
||||||
import xbmc
|
import xbmc
|
||||||
|
|
|
@ -14,9 +14,12 @@ class KodiDBBase(object):
|
||||||
"""
|
"""
|
||||||
Kodi database methods used for all types of items
|
Kodi database methods used for all types of items
|
||||||
"""
|
"""
|
||||||
def __init__(self, texture_db=False, kodiconn=None, artconn=None, lock=True):
|
def __init__(self, texture_db=False, kodiconn=None, artconn=None,
|
||||||
|
lock=True, wal_mode=True):
|
||||||
"""
|
"""
|
||||||
Allows direct use with a cursor instead of context mgr
|
Allows direct use with a cursor instead of context mgr
|
||||||
|
Pass wal_mode=False if you want the standard sqlite journal_mode, e.g.
|
||||||
|
when wiping entire tables
|
||||||
"""
|
"""
|
||||||
self._texture_db = texture_db
|
self._texture_db = texture_db
|
||||||
self.lock = lock
|
self.lock = lock
|
||||||
|
@ -24,13 +27,15 @@ class KodiDBBase(object):
|
||||||
self.cursor = self.kodiconn.cursor() if self.kodiconn else None
|
self.cursor = self.kodiconn.cursor() if self.kodiconn else None
|
||||||
self.artconn = artconn
|
self.artconn = artconn
|
||||||
self.artcursor = self.artconn.cursor() if self.artconn else None
|
self.artcursor = self.artconn.cursor() if self.artconn else None
|
||||||
|
self.wal_mode = wal_mode
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
if self.lock:
|
if self.lock:
|
||||||
KODIDB_LOCK.acquire()
|
KODIDB_LOCK.acquire()
|
||||||
self.kodiconn = db.connect(self.db_kind)
|
self.kodiconn = db.connect(self.db_kind, self.wal_mode)
|
||||||
self.cursor = self.kodiconn.cursor()
|
self.cursor = self.kodiconn.cursor()
|
||||||
self.artconn = db.connect('texture') if self._texture_db else None
|
self.artconn = db.connect('texture', self.wal_mode) if self._texture_db \
|
||||||
|
else None
|
||||||
self.artcursor = self.artconn.cursor() if self._texture_db else None
|
self.artcursor = self.artconn.cursor() if self._texture_db else None
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
|
||||||
from . import common
|
from . import common
|
||||||
from .. import db
|
|
||||||
|
|
||||||
|
|
||||||
class KodiTextureDB(common.KodiDBBase):
|
class KodiTextureDB(common.KodiDBBase):
|
||||||
|
@ -16,11 +15,3 @@ class KodiTextureDB(common.KodiDBBase):
|
||||||
self.artcursor.execute('SELECT url FROM texture WHERE url = ? LIMIT 1',
|
self.artcursor.execute('SELECT url FROM texture WHERE url = ? LIMIT 1',
|
||||||
(url, ))
|
(url, ))
|
||||||
return self.artcursor.fetchone() is None
|
return self.artcursor.fetchone() is None
|
||||||
|
|
||||||
@db.catch_operationalerrors
|
|
||||||
def reset_cached_images(self):
|
|
||||||
for row in self.cursor.execute('SELECT tbl_name '
|
|
||||||
'FROM sqlite_master WHERE type=?',
|
|
||||||
('table', )):
|
|
||||||
if row[0] != 'version':
|
|
||||||
self.cursor.execute("DELETE FROM %s" % row[0])
|
|
||||||
|
|
|
@ -573,12 +573,10 @@ def wipe_database(reboot=True):
|
||||||
# Plex DB completely empty yet. Wipe existing Kodi music only if we
|
# Plex DB completely empty yet. Wipe existing Kodi music only if we
|
||||||
# expect to sync Plex music
|
# expect to sync Plex music
|
||||||
music = settings('enableMusic') == 'true'
|
music = settings('enableMusic') == 'true'
|
||||||
|
LOG.info("Resetting all cached artwork.")
|
||||||
kodi_db.wipe_dbs(music)
|
kodi_db.wipe_dbs(music)
|
||||||
plex_db.wipe()
|
plex_db.wipe()
|
||||||
|
|
||||||
LOG.info("Resetting all cached artwork.")
|
|
||||||
# Remove all cached artwork
|
|
||||||
kodi_db.reset_cached_images()
|
|
||||||
# reset the install run flag
|
# reset the install run flag
|
||||||
settings('SyncInstallRunDone', value="false")
|
settings('SyncInstallRunDone', value="false")
|
||||||
settings('sections_asked_for_machine_identifier', value='')
|
settings('sections_asked_for_machine_identifier', value='')
|
||||||
|
|
Loading…
Reference in a new issue