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
| } | ||
|
|
||
| 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.
I started #829 in order to avoid ending up with such a function receiving 6 parameters.
There was a problem hiding this comment.
Yes, that's why I've started a factorization after this commit :)
172e1da to
30dcd93
Compare
src/opds_dumper.cpp
Outdated
| } | ||
|
|
||
| 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.
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.
Update: I see that this concern was later on addressed in a slightly different way.
|
|
||
| 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.
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
| } | ||
|
|
||
| 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.
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.
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
veloman-yunkan
left a comment
There was a problem hiding this comment.
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.
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)};
src/server/internalServer.cpp
Outdated
| auto bookName = request.get_argument("content"); | ||
| try { | ||
| 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.
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.
src/opds_dumper.cpp
Outdated
|
|
||
| /* Constructor */ | ||
| OPDSDumper::OPDSDumper(Library* library, NameMapper* nameMapper) | ||
| OPDSDumper::OPDSDumper(std::shared_ptr<Library> library, NameMapper* nameMapper) |
There was a problem hiding this comment.
OPDSDumper shouldn't need non-const access to library.
veloman-yunkan
left a comment
There was a problem hiding this comment.
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