Enter Library::removeBooksNotUpdatedSince()

This commit is contained in:
Veloman Yunkan 2021-11-28 20:40:52 +04:00
parent 1d5383435d
commit 262e13845c
3 changed files with 94 additions and 2 deletions

View File

@ -147,8 +147,20 @@ private: // functions
*/
class LibraryBase
{
protected: // types
typedef uint64_t LibraryRevision;
struct Entry : Book
{
LibraryRevision lastUpdatedRevision = 0;
// May also keep the Archive and Reader pointers here and get
// rid of the m_readers and m_archives data members in Library
};
protected: // data
std::map<std::string, kiwix::Book> m_books;
LibraryRevision m_revision;
std::map<std::string, Entry> m_books;
std::map<std::string, std::shared_ptr<Reader>> m_readers;
std::map<std::string, std::shared_ptr<zim::Archive>> m_archives;
std::vector<kiwix::Bookmark> m_bookmarks;
@ -172,6 +184,7 @@ class Library : private LibraryBase
mutable std::mutex m_mutex;
public:
typedef LibraryRevision Revision;
typedef std::vector<std::string> BookIdCollection;
typedef std::map<std::string, int> AttributeCounts;
@ -368,6 +381,24 @@ class Library : private LibraryBase
const std::vector<std::string>& tags = {},
size_t maxSize = 0) const;
/**
* Return the current revision of the library.
*
* The revision of the library is updated (incremented by one) only by
* the addBook() operation.
*
* @return Current revision of the library.
*/
LibraryRevision getRevision() const;
/**
* Remove books that have not been updated since the specified revision.
*
* @param rev the library revision to use
* @return Count of books that were removed by this operation.
*/
uint32_t removeBooksNotUpdatedSince(LibraryRevision rev);
friend class OPDSDumper;
friend class libXMLDumper;

View File

@ -101,6 +101,7 @@ Library::~Library()
bool Library::addBook(const Book& book)
{
std::lock_guard<std::mutex> lock(m_mutex);
++m_revision;
/* Try to find it */
updateBookDB(book);
try {
@ -111,9 +112,12 @@ bool Library::addBook(const Book& book)
oldbook.update(book); // XXX: This may have no effect if oldbook is readonly
// XXX: Then m_bookDB will become out-of-sync with
// XXX: the real contents of the library.
oldbook.lastUpdatedRevision = m_revision;
return false;
} catch (std::out_of_range&) {
m_books[book.getId()] = book;
Entry& newEntry = m_books[book.getId()];
static_cast<Book&>(newEntry) = book;
newEntry.lastUpdatedRevision = m_revision;
return true;
}
}
@ -151,6 +155,32 @@ bool Library::removeBookById(const std::string& id)
return m_books.erase(id) == 1;
}
Library::Revision Library::getRevision() const
{
std::lock_guard<std::mutex> lock(m_mutex);
return m_revision;
}
uint32_t Library::removeBooksNotUpdatedSince(LibraryRevision libraryRevision)
{
BookIdCollection booksToRemove;
{
std::lock_guard<std::mutex> lock(m_mutex);
for ( const auto& entry : m_books) {
if ( entry.second.lastUpdatedRevision <= libraryRevision ) {
booksToRemove.push_back(entry.first);
}
}
}
uint32_t countOfRemovedBooks = 0;
for ( const auto& id : booksToRemove ) {
if ( removeBookById(id) )
++countOfRemovedBooks;
}
return countOfRemovedBooks;
}
const Book& Library::getBookById(const std::string& id) const
{
// XXX: Doesn't make sense to lock this operation since it cannot

View File

@ -707,4 +707,35 @@ TEST_F(LibraryTest, removeBookByIdUpdatesTheSearchDB)
EXPECT_THROW(lib.getBookById("raycharles"), std::out_of_range);
};
TEST_F(LibraryTest, removeBooksNotUpdatedSince)
{
EXPECT_FILTER_RESULTS(kiwix::Filter(),
"An example ZIM archive",
"Encyclopédie de la Tunisie",
"Granblue Fantasy Wiki",
"Géographie par Wikipédia",
"Islam Stack Exchange",
"Mathématiques",
"Movies & TV Stack Exchange",
"Mythology & Folklore Stack Exchange",
"Ray Charles",
"TED talks - Business",
"Tania Louis",
"Wikiquote"
);
const uint64_t rev = lib.getRevision();
for ( const auto& id : lib.filter(kiwix::Filter().query("exchange")) ) {
lib.addBook(lib.getBookByIdThreadSafe(id));
}
EXPECT_EQ(9u, lib.removeBooksNotUpdatedSince(rev));
EXPECT_FILTER_RESULTS(kiwix::Filter(),
"Islam Stack Exchange",
"Movies & TV Stack Exchange",
"Mythology & Folklore Stack Exchange",
);
};
};