Skip to content

Commit 5cf47c0

Browse files
jimwwalkerdaverigby
authored andcommitted
MB-16181: Filters with deleted collections
Upstream integration revealed an issue with the VB::Filter. If we construct a filter with a collection "X" and "X" is actually marked as deleted, "X" should not be part of the filter. We fix this by replacing VB::Manifest::doesCollectionExist with VB::Manifest::isCollectionOpen which performs the correct checks. Tests updated to cover this case. Change-Id: I38d4ba025805da7653bf3a84053d4280f4f547d7 Reviewed-on: http://review.couchbase.org/78570 Reviewed-by: Dave Rigby <daver@couchbase.com> Tested-by: Build Bot <build@couchbase.com>
1 parent a549382 commit 5cf47c0

3 files changed

Lines changed: 48 additions & 11 deletions

File tree

src/collections/vbucket_filter.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,23 @@ Collections::VB::Filter::Filter(const Collections::Filter& filter,
5151
}
5252

5353
for (const auto& c : filter.getFilter()) {
54-
if (rh.doesCollectionExist({c.data(), c.size()})) {
54+
if (rh.isCollectionOpen({c.data(), c.size()})) {
5555
auto m = std::make_unique<std::string>(c);
5656
cb::const_char_buffer b{m->data(), m->size()};
5757
this->filter.emplace(b, std::move(m));
5858
} else {
59-
// The VB::Manifest no longer has the collection so we won't filter
60-
// it
59+
// The VB::Manifest doesn't gave the collection, or the collection
60+
// is deleted
6161
LOG(EXTENSION_LOG_NOTICE,
62-
"VB::Filter::Filter: dropping collection:%s as it's not in the "
63-
"VB::Manifest",
62+
"VB::Filter::Filter: dropping collection:%s as it's not open",
6463
c.c_str());
6564
}
6665
}
66+
67+
// All collections dropped
68+
if (this->filter.empty() && !defaultAllowed) {
69+
throw std::invalid_argument("VB::Filter::Filter: nothing to filter");
70+
}
6771
}
6872

6973
bool Collections::VB::Filter::allow(::DocKey key) const {

src/collections/vbucket_manifest.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ class Manifest {
105105
}
106106

107107
/**
108-
* @returns true/false if the collection exists
108+
* @returns true if collection is open, false if not or unknown
109109
*/
110-
bool doesCollectionExist(cb::const_char_buffer collection) const {
111-
return manifest.doesCollectionExist(collection);
110+
bool isCollectionOpen(cb::const_char_buffer collection) const {
111+
return manifest.isCollectionOpen(collection);
112112
}
113113

114114
private:
@@ -422,10 +422,14 @@ class Manifest {
422422
}
423423

424424
/**
425-
* @returns true/false if the collection exists
425+
* @returns true is the collection isOpen - false if not (or doesn't exist)
426426
*/
427-
bool doesCollectionExist(cb::const_char_buffer collection) const {
428-
return map.count(collection) != 0;
427+
bool isCollectionOpen(cb::const_char_buffer collection) const {
428+
auto itr = map.find(collection);
429+
if (itr != map.end()) {
430+
return itr->second->isOpen();
431+
}
432+
return false;
429433
}
430434

431435
protected:

tests/module_tests/collections/filter_test.cc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,35 @@ TEST_F(CollectionsFilterTest, filter_basic2) {
197197

198198
class CollectionsVBFilterTest : public CollectionsFilterTest {};
199199

200+
/**
201+
* Try and create filter for collections which exist, but have been deleted
202+
* i.e. they aren't writable so should never feature in a new VB::Filter
203+
*/
204+
TEST_F(CollectionsVBFilterTest, deleted_collection) {
205+
Collections::Manifest m1(
206+
R"({"revision":0,"separator":"$",)"
207+
R"("collections":["$default", "vegetable", "fruit", "meat", "dairy"]})");
208+
Collections::Manifest m2(
209+
R"({"revision":1,"separator":"$",)"
210+
R"("collections":["$default", "meat", "dairy"]})");
211+
212+
// Create the "producer" level filter so that we in theory produce at least
213+
// these collections
214+
std::string jsonFilter = R"({"collections":["vegetable", "fruit"]})";
215+
boost::optional<const std::string&> json(jsonFilter);
216+
Collections::Filter f(json, m1);
217+
218+
Collections::VB::Manifest vbm({});
219+
// push creates
220+
vbm.wlock().update(vb, m1);
221+
// push deletes, removing both filtered collections
222+
vbm.wlock().update(vb, m2);
223+
224+
// Construction will fail as the filter would not match anything valid
225+
EXPECT_THROW(std::make_unique<Collections::VB::Filter>(f, vbm),
226+
std::invalid_argument);
227+
}
228+
200229
/**
201230
* Create a filter with collections and check we allow what should be allowed.
202231
*/

0 commit comments

Comments
 (0)