-
-
Notifications
You must be signed in to change notification settings - Fork 56
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
OPDS name mapper #830
base: main
Are you sure you want to change the base?
OPDS name mapper #830
Conversation
Codecov ReportBase: 70.60% // Head: 71.31% // Increases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## master #830 +/- ##
==========================================
+ Coverage 70.60% 71.31% +0.71%
==========================================
Files 53 53
Lines 3664 3668 +4
Branches 2046 2038 -8
==========================================
+ Hits 2587 2616 +29
+ Misses 1075 1050 -25
Partials 2 2
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
src/opds_dumper.cpp
Outdated
@@ -94,24 +95,24 @@ kainjow::mustache::object getSingleBookData(const Book& book) | |||
}; | |||
} | |||
|
|||
std::string getSingleBookEntryXML(const Book& book, bool withXMLHeader, const std::string& rootLocation, const std::string& endpointRoot, bool partial) | |||
std::string getSingleBookEntryXML(const Book& book, const NameMapper& nameMapper, bool withXMLHeader, const std::string& rootLocation, const std::string& endpointRoot, bool partial) |
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 started #829 in order to avoid ending up with such a function receiving 6 parameters.
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, that's why I've started a factorization after this commit :)
172e1da
to
30dcd93
Compare
src/opds_dumper.cpp
Outdated
@@ -71,7 +72,7 @@ IllustrationInfo getBookIllustrationInfo(const Book& book) | |||
return illustrations; | |||
} | |||
|
|||
std::string fullEntryXML(const Book& book, const std::string& rootLocation) | |||
std::string fullEntryXML(const Book& book, const std::string& rootLocation, const std::string& bookName) |
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.
bookName
is not a good name for this new parameter (taking into account the line {"name", book.getName()},
below.
I would convert fullEntryXML()
and partialEntryXML()
into member functions of a small helper class EntryXMLGenerator
that is initialized with rootLocation
and NameMapper
, with name mapping applied inside fullEntryXML()
. That way the need for an extra parameter is eliminated.
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.
Update: I see that this concern was later on addressed in a slightly different way.
@@ -112,15 +113,16 @@ std::string partialEntryXML(const Book& book, const std::string& rootLocation) | |||
return render_template(xmlTemplate, data); | |||
} | |||
|
|||
BooksData getBooksData(const Library* library, const std::vector<std::string>& bookIds, const std::string& rootLocation, bool partial) | |||
BooksData getBooksData(const Library* library, const NameMapper& nameMapper, const std::vector<std::string>& bookIds, const std::string& rootLocation, bool partial) | |||
{ |
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 count of function parameters is a code smell. EntryXMLGenerator
proposed in the previous comment allows to replace the pair nameMapper
and rootLocation
with a single higher-level parameter. It may even make sense to push partial
into EntryXMLGenerator
constructor, too, effectively reducing the arity of this function to 3 (which IMO is the upper limit on what can be tolerated for the number of parameters).
Update: I wrote this comment before getting to the commit where a similar refactoring was done with the help of ServerConfiguration
. I think that passing ServerConfiguration
into this function obfuscates the actual inputs used by it.
src/opds_dumper.cpp
Outdated
@@ -99,12 +100,12 @@ std::string fullEntryXML(const Book& book, const std::string& rootLocation, cons | |||
return render_template(RESOURCE::templates::catalog_v2_entry_xml, data); | |||
} | |||
|
|||
std::string partialEntryXML(const Book& book, const std::string& rootLocation) | |||
std::string partialEntryXML(const ServerConfiguration& configuration, const Book& book) |
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 don't agree with this change.
Cons:
- access to more data than needed by this function
Pros:
- ???
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 made this for consistency.
The idea is that those set of free functions to generate xml are black box function generating the xml in accordance with the ServerConfiguration, what ever is actually used.
I have no strong opinion on this,except that passing the actual needed data may leads to too much parameters.
And if several functions are using a ServerConfiguration I prefer having all functions using them.
30dcd93
to
1b1c140
Compare
Ready for a new review. |
It is used to store the server configuration instead of passing (a lot of) arguments to functions/creators. Please note that this remove the thread protected on m_verbose. m_verbose is initialized once and never modified, be don't need to protect access.
Move from `ServerConfiguration` to `Server::Configuration`.
While it was "ok" to store raw pointer as, in our use case, the library always live longer than object using it; it is not safe to store raw pointer on object than may be deleted. All classes storing a library now store a shared_ptr. Functionr only using the library (as `HumanReadableNameMapper`) continue to use a (const) reference.
While it was "ok" to store raw pointer as, in our use case, the nameMapper always live longer than object using it; it is not safe to store raw pointer on object than may be deleted. All classes storing a NameMapper now store a shared_ptr. Functions only using the library (as `HumanReadableNameMapper`) continue to use a (const) reference.
This move the defaulting to IdNameMapper in the configuration instead of in the InternalServer. This also create a default shared_ptr per Configuration instead of using a static default one.
This avoid a lot of silly `m_configuration.foo`.
`kiwix::Server` is now a simple exposition of a public API on top of the private `InternalServer`.
1b1c140
to
d112470
Compare
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.
Please rebase&fixup. I think that the clean version has to be reviewed due to significant reversal of some changes.
template<class T> | ||
class NotOwned : public std::shared_ptr<T> { | ||
public: | ||
NotOwned(T& object) : | ||
std::shared_ptr<T>(&object, NoDelete()) {}; | ||
}; |
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 you convert this helper class into a function you won't be forced to provide the template argument:
template<class T>
std::shared_ptr<T> shareWithoutOwnership(T& object) {
return std::shared_ptr<T>(&object, NoDelete());
}
kiwix::Manager manager{shareWithoutOwnership(lib)};
const auto bookIds = Library::BookIdSet{m_configuration.mp_nameMapper->getIdForName(bookName)}; | ||
const auto bookIds = Library::BookIdSet{mp_nameMapper->getIdForName(bookName)}; |
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.
This comment applies to the commit "[NEW] Make InternalServer inherite Server::Configuration.". It would be better to follow this approach from the very beginning, instead of making a lot of changes and then undoing them.
@@ -30,7 +30,7 @@ namespace kiwix | |||
{ | |||
|
|||
/* Constructor */ | |||
OPDSDumper::OPDSDumper(Library* library, NameMapper* nameMapper) | |||
OPDSDumper::OPDSDumper(std::shared_ptr<Library> library, NameMapper* nameMapper) |
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.
OPDSDumper
shouldn't need non-const access to library.
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.
While reviewing kiwix/kiwix-tools#580 and kiwix/kiwix-desktop#894 I got the impression that this PR goes too far with passing Library
and NameMapper
via shared pointers into some objects.
OPDSDumper
and SearchRenderer
are cheap-to-instantiate one-shot-use helper classes with the (current) mere purpose of avoiding free functions dumpOPDSFeed()
, renderSearchResults()
with too many parameters. Objects of those classes should be created, used and destroyed within a single function call, and therefore storing the references to Library
and NameMapper
as shared pointers is not justified. In case of OPDSDumper
this concern is somewhat masked by replacing individual references to Library
and NameMapper
by an entire Server::Configuration
object, but the result is that OPDSDumper
gains non-const access to Library
which it doesn't really need.
Regarding Manager
, a scenario where it may turn out to be the last object keeping a reference to Library
doesn't make much sense (at least, for the case of a manager object instantiated via the Manager(Library*)
constructor). In such a situation, the modification of the library via the Manager
should have ended before other clients of the library die.
I was more concerned by the But I agree that There is also the This may me think to #740. I'm afraid this PR will become more complex to solve that I was initially thinking. I will move the actual fix in another PR to have it quickly merged and will take time to discuss the best design here. |
While reviewing #837, I had a new idea. Why do we need to pass In short, the proposal is to get rid of the |
Yes, at least for now. The namemapper is used for two different (but related) things:
The problem is that routing is not part of the "whole" library (libkiwix). It is part of server only. kiwix-desktop has it own routing and it use the namemapper to generate search result in correspondance to its routing. In the same time, kiwix-desktop can serve the same library (set of books) with kiwix-serve (and so with a different namemapper). And it is the same thing for kiwix-android (but I'm not sure kiwix-android is generating search result with When we implement #740 with some kind of generic routing system, we may rethink this as we could provide of full set (consistant) of features. |
Fixes #828