mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Kobo driver: Handle WAL journal when copying db
This commit is contained in:
parent
4915282ba1
commit
7aa9d1d7fc
@ -11,13 +11,15 @@ from calibre.prints import debug_print
|
|||||||
from calibre.ptempfile import PersistentTemporaryFile, TemporaryDirectory
|
from calibre.ptempfile import PersistentTemporaryFile, TemporaryDirectory
|
||||||
|
|
||||||
|
|
||||||
def row_factory(cursor, row):
|
def row_factory(cursor: apsw.Cursor, row):
|
||||||
return {k[0]: row[i] for i, k in enumerate(cursor.getdescription())}
|
return {k[0]: row[i] for i, k in enumerate(cursor.getdescription())}
|
||||||
|
|
||||||
|
|
||||||
def copy_db(conn: apsw.Connection, dest_path: str):
|
def copy_db(conn: apsw.Connection, dest_path: str):
|
||||||
with suppress(AttributeError): # need a new enough version of apsw
|
with suppress(AttributeError): # need a new enough version of apsw
|
||||||
conn.cache_flush()
|
conn.cache_flush()
|
||||||
|
# checkpoint all WAL transactions into the main db file and truncate WAL file to zero
|
||||||
|
conn.wal_checkpoint(mode=apsw.SQLITE_CHECKPOINT_TRUNCATE)
|
||||||
with TemporaryDirectory() as tdir:
|
with TemporaryDirectory() as tdir:
|
||||||
tempdb = os.path.join(tdir, 'temp.sqlite')
|
tempdb = os.path.join(tdir, 'temp.sqlite')
|
||||||
with closing(apsw.Connection(tempdb)) as dest, dest.backup('main', conn, 'main') as b:
|
with closing(apsw.Connection(tempdb)) as dest, dest.backup('main', conn, 'main') as b:
|
||||||
@ -25,6 +27,9 @@ def copy_db(conn: apsw.Connection, dest_path: str):
|
|||||||
with suppress(apsw.BusyError, apsw.LockedError):
|
with suppress(apsw.BusyError, apsw.LockedError):
|
||||||
b.step()
|
b.step()
|
||||||
shutil.move(tempdb, dest_path)
|
shutil.move(tempdb, dest_path)
|
||||||
|
dest_wal = dest_path + '-wal'
|
||||||
|
if os.path.exists(dest_wal): # truncate WAL file to zero
|
||||||
|
open(dest_wal, 'w').close()
|
||||||
|
|
||||||
|
|
||||||
class Database:
|
class Database:
|
||||||
@ -33,6 +38,8 @@ class Database:
|
|||||||
self.path_on_device = self.dbpath = path_on_device
|
self.path_on_device = self.dbpath = path_on_device
|
||||||
self.dbversion = 0
|
self.dbversion = 0
|
||||||
def connect(path: str = path_on_device) -> None:
|
def connect(path: str = path_on_device) -> None:
|
||||||
|
if path == path_on_device:
|
||||||
|
raise apsw.IOError('xxx')
|
||||||
with closing(apsw.Connection(path)) as conn:
|
with closing(apsw.Connection(path)) as conn:
|
||||||
conn.setrowtrace(row_factory)
|
conn.setrowtrace(row_factory)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
@ -51,6 +58,9 @@ class Database:
|
|||||||
debug_print(f'Kobo: I/O error connecting to {self.path_on_device} copying it into temporary storage and connecting there')
|
debug_print(f'Kobo: I/O error connecting to {self.path_on_device} copying it into temporary storage and connecting there')
|
||||||
with open(self.path_on_device, 'rb') as src, PersistentTemporaryFile(suffix='-kobo-db.sqlite') as dest:
|
with open(self.path_on_device, 'rb') as src, PersistentTemporaryFile(suffix='-kobo-db.sqlite') as dest:
|
||||||
shutil.copyfileobj(src, dest)
|
shutil.copyfileobj(src, dest)
|
||||||
|
wal = self.path_on_device + '-wal'
|
||||||
|
if os.path.exists(wal):
|
||||||
|
shutil.copy2(wal, dest.name + '-wal')
|
||||||
try:
|
try:
|
||||||
connect(dest.name)
|
connect(dest.name)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user