-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Docsettings: add centralized sdr storage #10074
Conversation
If the conception is approved I will add support of it to file copy/move/rename/delete, Exporter etc. |
I will fix docsettings unit tests after discussion. |
frontend/docsettings.lua
Outdated
-- New sidecar file in doc folder | ||
sidecar_file_doc or "", | ||
-- Backup file of new sidecar file in doc folder | ||
sidecar_file_doc and (sidecar_file_doc..".old") or "", | ||
-- Legacy sidecar file | ||
new.legacy_sidecar_file or "", | ||
legacy_sidecar_file or "", | ||
-- New sidecar file in sidecars folder | ||
sidecar_file_sidecars or "", | ||
-- Backup file of new sidecar file in sidecars folder | ||
sidecar_file_sidecars and (sidecar_file_sidecars..".old") or "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the ordering here doesn't matter and dont enforce a priority - and that it's the mtime of the files found that will set the priority order, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The priority is always enforced; as a practical example, if you were to migrate from sidecar to centralized sidecar while preserving mtime and leaving the old sidecar files in place (and not touching the document so as to affect said sidecar data), the doc's sidecar would be preferred because they have higher priority (that rule only applies if mtime matches, otherwise the primary sort order is by MRU).
(Which leads to an obvious conclusion: if you do intend to create a migration path, the previous location should be cleared, or the new location files "touched" so as to get an updated mtime).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd better have sidecar.lua
before sidecar.lua.old
koreader/frontend/docsettings.lua
Lines 26 to 39 in 50b2267
local mtime = lfs.attributes(file_path, "modification") | |
-- NOTE: Extra trickery: if we're inserting a "backup" file, and its primary buddy exists, | |
-- make sure it will *never* sort ahead of it by using the same mtime. | |
-- This aims to avoid weird UTC/localtime issues when USBMS is involved, | |
-- c.f., https://github.com/koreader/koreader/issues/9227#issuecomment-1345263324 | |
if file_path:sub(-4) == ".old" and previous_entry_exists then | |
local primary_mtime = candidates[#candidates].mtime | |
-- Only proceed with the switcheroo when necessary, and warn about it. | |
if primary_mtime < mtime then | |
logger.warn("DocSettings: Backup", file_path, "is newer (", mtime, ") than its primary (", primary_mtime, "), fudging timestamps!") | |
-- Use the most recent timestamp for both (i.e., the backup's). | |
candidates[#candidates].mtime = mtime | |
end | |
end |
And finally the candidates are sorted by
mtime
, yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't think about the migration of sidecar files for all books. Is it needed?
The migration for a certain book is done by opening it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, please, no migration ! :)
We don't know all possible book locations.
And there's always the case of removable SD cards, that may not be plugged in at the time when the migration is done.
The priority is always enforced; as a practical example, if you were to migrate from sidecar to centralized sidecar while preserving mtime and leaving the old sidecar files in place (and not touching the document so as to affect said sidecar data), the doc's sidecar would be preferred because they have higher priority (that rule only applies if mtime matches, otherwise the primary sort order is by MRU).
So, I guess this is bad ? :/
The case we want to handle is:
we have book A and book B with "alongside doc" sidecars.user changes setting to "centralized" (no migration is done)user opens book A: "no centralized sidecar" found, "alongside doc" is found, use thatuser closes book A: "centralized sidecar" is saved (should "alongside doc" be deleted?)user changes setting to "alongside docs" (no migration is done)user opens book A: "alongside doc" is found and used first, but "centralized sidecar" is newer and should have been used
Scratch that, if you really mean MRU (Most Recently User), which is what I wanted :)
(that is, the order the sidecar candidates are listed in the code does not matter - we don't copy preserving mtime, so there will always be a newer, that will be used).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the order the sidecar candidates are listed in the code does not matter
It does (in a technical sense, at least), but it's only used as a tie-breaker if there's an mtime conflict.
If there's no mtime conflict, mtime wins ;).
@@ -246,77 +242,47 @@ function DocSettings:flush() | |||
ffiutil.fsyncOpenedFile(f_out) -- force flush to the storage device |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor (?) issue with koreader/sidecars/: we won't be fsync'ing the intermediate directories created by util.makePath(s[1])
.
(Which might be a non-issue, as we only create them the first time, and it's not really an issue if the device soon after crash and we lose nearly new docsettings - it only matters for later flush when the user had the time to make some highlights, etc...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it safer to replace util.makePath
with mkdir -p
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Safer in what way ?
I don't think mkdir -p
would do any sync
.
Moreover, there's more risks executing other programs (like launching mkdir
) than doing things internally from the koreader process in Lua, because executing needs more memory and so may fail if not able to get it. See #2239 (comment)
local metadata_folder_str = { | ||
[":doc"] = _("book folder"), | ||
[":sidecars"] = "koreader/sidecars", | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These menu items will probably need a help_text
(or the menu needs a 3rd item to display this help_text) explaining the pros and cons of each option (or/and even a confirmation when changeing it?).
That’s a lot of changes :D
|
|
|
Thanks @hius07 For 4), I mean currently my home folder is at /storage/emulated/0/Books. Inside, there are books as well as other folders with books. That “folder structure I meant”. E.g. will the sdr at $HOME/Collection1/Book1.sdr move to /koreader/sidecar or to /koreader/sidecar/Collection1 ? |
To /koreader/sidecar/$HOME/Collection1/Book1.sdr |
Updates in accordance with the reviews. |
Thank you! Looks very promising then, can’t wait to test |
Generally, what is better to check if a file exists: Lines 745 to 751 in c5997a6
|
I guess |
The previous iteration, besides failing to handle leaf-only input, was relying on splitFilePathName, which just doesn't do what's required to incrementally build the directory tree the right way around ;). This should more closely match mkdir -p, i.e., it will *fail* if any part (or all of it) of the path exists but is *not* a directory. Re koreader#10074
The previous iteration, besides failing to handle leaf-only input, was relying on splitFilePathName, which just doesn't do what's required to incrementally build the directory tree the right way around ;). This should more closely match mkdir -p, i.e., it will *fail* if any part (or all of it) of the path exists but is *not* a directory. Re koreader#10074
The previous iteration, besides failing to handle leaf-only input, was relying on splitFilePathName, which just doesn't do what's required to incrementally build the directory tree the right way around ;). This should more closely match mkdir -p, i.e., it will *fail* if any part (or all of it) of the path exists but is *not* a directory. Re #10074
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good for you @NiLuJe ?
common_settings.document_metadata_folder = { | ||
text_func = function() | ||
local value = G_reader_settings:readSetting("document_metadata_folder", "doc") | ||
return T(_("Book metadata folder: %1"), metadata_folder_str[value]) | ||
end, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd rather see "Book settings folder", document_settings_folder, used instead of "metadata" all around there, it feels less ambiguous than book metadata (ie. author, title).
Unless it's confusing in other ways to use "settings" in the code .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But may be it expresses more clearly where the "metadata".epub.lua
will be kept ? :)
(maybe not for this PR, but something to think about) Do you think there should be at least warning about the migration if:
Or maybe the migration of these specific file formats should be avoided if that’s not too hard? Not that it concerns myself since I don’t have a Kindle anymore, but I think KOReader should probably be friendly to native reader as well :D |
(By migration, you mean individual migration on book opening right ? I hope you got that we won't do a batch migration :) - or if we do (or a pluging does), it should be a batch opening of books in History.) Oh, and yes, there's the |
The initial plan AFAIK is yes, to migrate only on book-by-book basis when the book is reopened after the new settings is enabled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 3 of 3 files at r12, all commit messages.
Reviewable status: all files reviewed, 12 unresolved discussions (waiting on @hius07 and @poire-z)
frontend/ui/elements/common_settings_menu_table.lua
line 529 at r12 (raw file):
Previously, poire-z wrote…
But may be it expresses more clearly where the
"metadata".epub.lua
will be kept ? :)
It kinda does both in practice, and metadata feels slightly more generic and safe to me?
Nope, some of the previous review comments still need to be addressed ;). (Plus, help_text stuff. I might try my hand at it tomorrow if nobody beats me to it). |
(1) Fixed: build |
for _, f in ipairs(serials) do | ||
local s_out = dump(data or self.data, nil, true) | ||
for _, s in ipairs(serials) do | ||
util.makePath(s[1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If i understand correctly, this would create a folder under koreader/docsettings
for no reason even if using doc
Also purgeDir
will only delete the immediate folder koreader/docsettings/path/to/file.sdr/
only file.sdr
is deleted, leaving empty folders.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If i understand correctly, this would create a folder under
koreader/docsettings
for no reason even if usingdoc
I believe no, we have a break of the loop if the "doc" sidecar has been saved.
Also
purgeDir
will only delete the immediate folderkoreader/docsettings/path/to/file.sdr/
onlyfile.sdr
is deleted, leaving empty folders.
That's true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good ;).
I forgot about help_text
again, might have some time for it later.
The purgeDir
issue that was just raised may indeed require more thinking ;).
Reviewed 2 of 2 files at r13, all commit messages.
Reviewable status: all files reviewed, 13 unresolved discussions (waiting on @hius07, @poire-z, and @yparitcher)
I do not think it is a big issue because usually library subfolders contain several books and after deleting a book we can keep a (empty) sdr path to be used by other books now or in the future. But yes, for the sake of good order we need smth like This (and |
@NiLuJe : OK with merging and to be continued in another PR? |
Yup, fine with me ;). |
"data", "data/dict", "data/tessdata", | ||
"history", "ota", "plugins", | ||
"data", "data/dict", "data/tessdata", "docsettings", | ||
"history", "ota", "patches", "plugins", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any special reason to have added "patches" in there ?
I think it was supposed to be explicitely created by the hardcore users who would need user patches, and the absence of this directory keeps the PatchManager plugin disabled, so to not lead softcore users into temptation :)
(Pinging @zwim)
Minor thought: |
The same for "clipboard" folder used by the Exporter plugin only. |
Discussed in #9265.
New centralized sdr storage for a book metadata:
koreader/sidecars/full/path/to/book/<book_name_without_suffix>.sdr
Also used as a fallback if book folder is readonly.
Default storage: book folder.
Closes #4831
Closes #5222
Closes #7648
Closes #8577
Closes #9265
This change is