Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Statistics plugin sync: fix bloated null id_books #10749

Merged
merged 5 commits into from Aug 2, 2023

Conversation

weijiuqiao
Copy link
Contributor

@weijiuqiao weijiuqiao commented Jul 26, 2023

This PR is an attempt to fix #10342 and #10656. According to #10656 (comment), the bug could be null id_books in page_stat_data. I didn't really find out why that happened from the sync code but still added some "fail-proofs".
Also it would be great if @libelle1995 and @xsdjt could try out this solution.


This change is Reviewable

@@ -428,6 +428,14 @@ Please wait…
end
end
end
if not self.settings.fixed_null_idbook then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could probably just increment the db version thing (I don't recall the exact name, and am on mobile right now, sorry) instead of adding a setting key that'll stay around.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just that the current migration function will backup the db, which might be 2GB! And I'm reluctant to give that workflow a special case :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good point, I'd forgotten about that.

Perhaps we can just move that whole bit of logic to a onetimemigration block instead of the plug-in itself, then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Didn't really know about the onetime_migration choice.

@Frenzie Frenzie added this to the 2023.07 milestone Jul 26, 2023
@Frenzie Frenzie added the Plugin label Jul 26, 2023
Comment on lines 590 to 593
if last_migration_date < 20230727 then
logger.info("Performing one-time migration for 20230727")
local conn = SQ3.open(DataStorage:getSettingsDir() .. "/statistics.sqlite3")
local ok, value = pcall(conn.exec, conn, "PRAGMA table_info('page_stat_data')")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that OK if the statistics plugin is disabled (and the user has deleted the db) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plugin is disabled

Still performs the deletion, should be fine and intended behavior.

the user has deleted the db

A warning will be shown in the log, seems an empty db will be created due to SQ3.open(). Should not be too big a deal though?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could pcall(SQ3.open, ...) just for consistency ?
(I guess it's more likely to happen than your db not compatible check :) )

Copy link
Member

@NiLuJe NiLuJe Jul 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Could not open blah" warnings are the norm for migration blocks, FWIW. We only pcall stuff that would otherwise crash ;).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added check for existence of file.

Comment on lines +593 to +595
local db_location = DataStorage:getSettingsDir() .. "/statistics.sqlite3"
if util.fileExists(db_location) then
local conn = SQ3.open(db_location)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it happen the file exists, but SQ3.open fails ? ie. db too big, file system full, db corrupted, or fs fuckup and chkdsk makde it empty, would SQ3.open throw an exception or just go on with it ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually guard the actual production code in the plugin far less defensively than this, so I don't think we have anything to worry about ;).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to look how precisely we pcall() plugins when loading them, and if the init() is included - in which case a bad db would just disable the statistics plugin - while this happening here would prevent KOReader from launching ?

Ok, had a look:

function ReaderStatistics:init()
+    abc = def.ghi

07/28/23-18:59:59 ERROR Failed to initialize statistics plugin: plugins/statistics.koplugin/main.lua:105: attempt to index global 'def' (a nil value)
No statistics menu.

Corrupting my statistics.sqlite3 (dd bs=123 count=1), the plugin loads, in spite of:
07/28/23-19:01:51 ERROR Failed to initialize statistics plugin: common/lua-ljsqlite3/init.lua:60: ljsqlite3[corrupt] database disk image is malformed
its menu is shown, some functions does not work, some crash, but reading and changing books work.

Putting this at top of onetime_migration.lua:

local db_location = DataStorage:getSettingsDir() .. "/statistics.sqlite3"
if util.fileExists(db_location) then
    local conn = SQ3.open(db_location)
    logger.warn("DB CORRUPTED BUT I'M OK")
end

have us not crash:
07/28/23-19:07:45 WARN DB CORRUPTED BUT I'M OK

So, I guess it's ok if only what happens after is pcall()ed. (but who knows what happens with some other kind of corruption?)

@poire-z
Copy link
Contributor

poire-z commented Aug 1, 2023

Some conflict preventing the merge. (So, might as well update the date to the current day.)

@weijiuqiao
Copy link
Contributor Author

Updated date and resolved conflict.

@NiLuJe
Copy link
Member

NiLuJe commented Aug 2, 2023

Oops, my bad, thought we had merged this already ;).

@NiLuJe NiLuJe merged commit 416237e into koreader:master Aug 2, 2023
3 checks passed
@mergen3107
Copy link
Contributor

Updated today to -54, works OK.

There are now two new files along statistics.sqlite, one is the same name with -shm suffix, another with -wal suffix. Is this supposed to happen?

@NiLuJe
Copy link
Member

NiLuJe commented Aug 2, 2023

As long as the database has an open handle, yep; that's SQLite's WAL journaling handling.

@NiLuJe
Copy link
Member

NiLuJe commented Aug 2, 2023

open handle

Crap, we don't close that one ;p.

@Frenzie
Copy link
Member

Frenzie commented Aug 2, 2023

I was going to say, should it really be around the entire time the program's open?

NiLuJe added a commit to NiLuJe/koreader that referenced this pull request Aug 2, 2023
@mergen3107
Copy link
Contributor

Thanks! :D
I didn’t see them before even when KOReader is open at the same time, just my observations.

@NiLuJe
Copy link
Member

NiLuJe commented Aug 2, 2023

Yeah, we tend to close them explicitly ASAP instead of relying on the GC to do it for us.

NiLuJe added a commit that referenced this pull request Aug 2, 2023
@mergen3107
Copy link
Contributor

The fix worked OK!
two extra files are gone. Main db shrinked from 1.2M to 1.0M.

Can this debloat be also applied to book cache db? I feel like it is bloated too, 42M.

@poire-z
Copy link
Contributor

poire-z commented Aug 3, 2023

Can this debloat be also applied to book cache db? I feel like it is bloated too, 42M.

It may have stalled stuff from books you have removed or when you rename a directory (the bookinfo cache from all the books would stay duplicated with the old full path and the new full path).
We'd rather not do any cleaning automatically (ie. because of removable storage).

You can do some cleaning yourself:
image
image

@mergen3107
Copy link
Contributor

Thanks! I’ll try prune. Not sure about Compact though, last time I used it (about a year ago), KOReader crashed :D

@mergen3107
Copy link
Contributor

Or I think I asked that question already, now I remember the difference that prune only empties the removed books places, but keeps allocation. So that new books will just replace these empty places. Compact OTOH is supposed to shrink db.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
5 participants