Skip to content

Commit 024df8c

Browse files
authored
Implement BloomFilter class (#10846)
1 parent 2e78e41 commit 024df8c

File tree

4 files changed

+325
-7
lines changed

4 files changed

+325
-7
lines changed

Firestore/Example/Firestore.xcodeproj/project.pbxproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
048A55EED3241ABC28752F86 /* memory_mutation_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 74FBEFA4FE4B12C435011763 /* memory_mutation_queue_test.cc */; };
3333
04D7D9DB95E66FECF2C0A412 /* bundle_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F7FC06E0A47D393DE1759AE1 /* bundle_cache_test.cc */; };
3434
0500A324CEC854C5B0CF364C /* FIRCollectionReferenceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E045202154AA00B64F25 /* FIRCollectionReferenceTests.mm */; };
35+
0500F75D28C112E4F5EE90ED /* bloom_filter_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ECBF36AA2F0AE1B2C1403D44 /* bloom_filter_test.cc */; };
3536
050FB0783F462CEDD44BEFFD /* document_overlay_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = FFCA39825D9678A03D1845D0 /* document_overlay_cache_test.cc */; };
3637
0535C1B65DADAE1CE47FA3CA /* string_format_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFD366B783AE27B9E79EE7A /* string_format_apple_test.mm */; };
3738
053C11420E49AE1A77E21C20 /* memory_document_overlay_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 29D9C76922DAC6F710BC1EF4 /* memory_document_overlay_cache_test.cc */; };
@@ -677,6 +678,7 @@
677678
6ABB82D43C0728EB095947AF /* geo_point_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB7BAB332012B519001E0872 /* geo_point_test.cc */; };
678679
6AED40FF444F0ACFE3AE96E3 /* target_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5C37696557C81A6C2B7271A /* target_cache_test.cc */; };
679680
6AF739DDA9D33DF756DE7CDE /* autoid_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54740A521FC913E500713A1A /* autoid_test.cc */; };
681+
6B78203C409594CD98CDF3CC /* bloom_filter_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ECBF36AA2F0AE1B2C1403D44 /* bloom_filter_test.cc */; };
680682
6B94E0AE1002C5C9EA0F5582 /* log_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54C2294E1FECABAE007D065B /* log_test.cc */; };
681683
6BA8753F49951D7AEAD70199 /* watch_change_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2D7472BC70C024D736FF74D9 /* watch_change_test.cc */; };
682684
6BFB7A4D37F1B7EB5A7461B0 /* memory_query_engine_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8EF6A33BC2D84233C355F1D0 /* memory_query_engine_test.cc */; };
@@ -1077,6 +1079,7 @@
10771079
BC5AC8890974E0821431267E /* limit_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA129F1F315EE100DD57A1 /* limit_spec_test.json */; };
10781080
BC8DFBCB023DBD914E27AA7D /* query_listener_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7C3F995E040E9E9C5E8514BB /* query_listener_test.cc */; };
10791081
BCA720A0F54D23654F806323 /* ConditionalConformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3228F51DCDC2E90D5C58F97 /* ConditionalConformanceTests.swift */; };
1082+
BD1FF9AD3746627A220E3720 /* bloom_filter_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ECBF36AA2F0AE1B2C1403D44 /* bloom_filter_test.cc */; };
10801083
BD6CC8614970A3D7D2CF0D49 /* exponential_backoff_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D1B68420E2AB1A00B35856 /* exponential_backoff_test.cc */; };
10811084
BDD2D1812BAD962E3C81A53F /* hashing_test_apple.mm in Sources */ = {isa = PBXBuildFile; fileRef = B69CF3F02227386500B281C8 /* hashing_test_apple.mm */; };
10821085
BDDAE67000DBF10E9EA7FED0 /* nanopb_util_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6F5B6C1399F92FD60F2C582B /* nanopb_util_test.cc */; };
@@ -1136,6 +1139,7 @@
11361139
C901A1BFD553B6DD70BB7CC7 /* bundle_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F7FC06E0A47D393DE1759AE1 /* bundle_cache_test.cc */; };
11371140
C961FA581F87000DF674BBC8 /* field_transform_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7515B47C92ABEEC66864B55C /* field_transform_test.cc */; };
11381141
C9F96C511F45851D38EC449C /* status.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 618BBE9920B89AAC00B5BCE7 /* status.pb.cc */; };
1142+
CA077AA69CF12D5170BB05C2 /* bloom_filter_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ECBF36AA2F0AE1B2C1403D44 /* bloom_filter_test.cc */; };
11391143
CA989C0E6020C372A62B7062 /* testutil.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54A0352820A3B3BD003E0143 /* testutil.cc */; };
11401144
CAFB1E0ED514FEF4641E3605 /* log_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54C2294E1FECABAE007D065B /* log_test.cc */; };
11411145
CB2C731116D6C9464220626F /* FIRQueryUnitTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = FF73B39D04D1760190E6B84A /* FIRQueryUnitTests.mm */; };
@@ -1247,6 +1251,7 @@
12471251
E21D819A06D9691A4B313440 /* remote_store_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 3B843E4A1F3930A400548890 /* remote_store_spec_test.json */; };
12481252
E25DCFEF318E003B8B7B9DC8 /* index_backfiller_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1F50E872B3F117A674DA8E94 /* index_backfiller_test.cc */; };
12491253
E27C0996AF6EC6D08D91B253 /* document.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 544129D821C2DDC800EFB9CC /* document.pb.cc */; };
1254+
E288C093C725954581B69325 /* bloom_filter_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ECBF36AA2F0AE1B2C1403D44 /* bloom_filter_test.cc */; };
12501255
E2AE851F9DC4C037CCD05E36 /* remote_document_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7EB299CF85034F09CFD6F3FD /* remote_document_cache_test.cc */; };
12511256
E2B15548A3B6796CE5A01975 /* FIRListenerRegistrationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E06B202154D500B64F25 /* FIRListenerRegistrationTests.mm */; };
12521257
E2B7AEDCAAC5AD74C12E85C1 /* datastore_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3167BD972EFF8EC636530E59 /* datastore_test.cc */; };
@@ -1282,6 +1287,7 @@
12821287
E99D5467483B746D4AA44F74 /* fields_array_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA4CBA48204C9E25B56993BC /* fields_array_test.cc */; };
12831288
EA38690795FBAA182A9AA63E /* FIRDatabaseTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E06C202154D500B64F25 /* FIRDatabaseTests.mm */; };
12841289
EA46611779C3EEF12822508C /* annotations.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 618BBE9520B89AAC00B5BCE7 /* annotations.pb.cc */; };
1290+
EA8C203393B17C238A776133 /* bloom_filter_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ECBF36AA2F0AE1B2C1403D44 /* bloom_filter_test.cc */; };
12851291
EAA1962BFBA0EBFBA53B343F /* bundle_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4F5B96F3ABCD2CA901DB1CD4 /* bundle_builder.cc */; };
12861292
EAC0914B6DCC53008483AEE3 /* leveldb_snappy_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D9D94300B9C02F7069523C00 /* leveldb_snappy_test.cc */; };
12871293
EADD28A7859FBB9BE4D913B0 /* memory_remote_document_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1CA9800A53669EFBFFB824E3 /* memory_remote_document_cache_test.cc */; };
@@ -1804,6 +1810,7 @@
18041810
E42355285B9EF55ABD785792 /* Pods_Firestore_Example_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
18051811
E592181BFD7C53C305123739 /* Pods-Firestore_Tests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests_iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Tests_iOS/Pods-Firestore_Tests_iOS.debug.xcconfig"; sourceTree = "<group>"; };
18061812
E76F0CDF28E5FA62D21DE648 /* leveldb_target_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_target_cache_test.cc; sourceTree = "<group>"; };
1813+
ECBF36AA2F0AE1B2C1403D44 /* bloom_filter_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; path = bloom_filter_test.cc; sourceTree = "<group>"; };
18071814
ECEBABC7E7B693BE808A1052 /* Pods_Firestore_IntegrationTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
18081815
EF79BDA33A25371CD72BCE94 /* bloom_filter.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; path = bloom_filter.pb.cc; sourceTree = "<group>"; };
18091816
EF83ACD5E1E9F25845A9ACED /* leveldb_migrations_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_migrations_test.cc; sourceTree = "<group>"; };
@@ -2025,6 +2032,7 @@
20252032
546854A720A3681B004BDBD5 /* remote */ = {
20262033
isa = PBXGroup;
20272034
children = (
2035+
ECBF36AA2F0AE1B2C1403D44 /* bloom_filter_test.cc */,
20282036
CF39535F2C41AB0006FA6C0E /* create_noop_connectivity_monitor.cc */,
20292037
9098A0C535096F2EE9C35DE0 /* create_noop_connectivity_monitor.h */,
20302038
3167BD972EFF8EC636530E59 /* datastore_test.cc */,
@@ -3649,6 +3657,7 @@
36493657
1733601ECCEA33E730DEAF45 /* autoid_test.cc in Sources */,
36503658
0DAA255C2FEB387895ADEE12 /* bits_test.cc in Sources */,
36513659
FBA8282F8E99C878E4B9E87F /* bloom_filter.pb.cc in Sources */,
3660+
0500F75D28C112E4F5EE90ED /* bloom_filter_test.cc in Sources */,
36523661
394259BB091E1DB5994B91A2 /* bundle.pb.cc in Sources */,
36533662
EBAC5E8D0E2ECD9FBEDB7DAE /* bundle_builder.cc in Sources */,
36543663
5150E9F256E6E82D6F3CB3F1 /* bundle_cache_test.cc in Sources */,
@@ -3857,6 +3866,7 @@
38573866
5D5E24E3FA1128145AA117D2 /* autoid_test.cc in Sources */,
38583867
B6FDE6F91D3F81D045E962A0 /* bits_test.cc in Sources */,
38593868
F8EC78289E8FBC73AC640435 /* bloom_filter.pb.cc in Sources */,
3869+
BD1FF9AD3746627A220E3720 /* bloom_filter_test.cc in Sources */,
38603870
4D1775B7916D4CDAD1BF1876 /* bundle.pb.cc in Sources */,
38613871
474DF520B9859479845C8A4D /* bundle_builder.cc in Sources */,
38623872
04D7D9DB95E66FECF2C0A412 /* bundle_cache_test.cc in Sources */,
@@ -4081,6 +4091,7 @@
40814091
B842780CF42361ACBBB381A9 /* autoid_test.cc in Sources */,
40824092
146C140B254F3837A4DD7AE8 /* bits_test.cc in Sources */,
40834093
B79DDA1869EE15B93C5231F6 /* bloom_filter.pb.cc in Sources */,
4094+
E288C093C725954581B69325 /* bloom_filter_test.cc in Sources */,
40844095
3DDC57212ADBA9AD498EAA4C /* bundle.pb.cc in Sources */,
40854096
F3DEF2DB11FADAABDAA4C8BB /* bundle_builder.cc in Sources */,
40864097
392966346DA5EB3165E16A22 /* bundle_cache_test.cc in Sources */,
@@ -4305,6 +4316,7 @@
43054316
6AF739DDA9D33DF756DE7CDE /* autoid_test.cc in Sources */,
43064317
C1B4621C0820EEB0AC9CCD22 /* bits_test.cc in Sources */,
43074318
CEA99E72C941969C54BE3248 /* bloom_filter.pb.cc in Sources */,
4319+
6B78203C409594CD98CDF3CC /* bloom_filter_test.cc in Sources */,
43084320
01C66732ECCB83AB1D896026 /* bundle.pb.cc in Sources */,
43094321
EAA1962BFBA0EBFBA53B343F /* bundle_builder.cc in Sources */,
43104322
C901A1BFD553B6DD70BB7CC7 /* bundle_cache_test.cc in Sources */,
@@ -4523,6 +4535,7 @@
45234535
54740A581FC914F000713A1A /* autoid_test.cc in Sources */,
45244536
AB380D02201BC69F00D97691 /* bits_test.cc in Sources */,
45254537
22FC2BEE59BEDE4CFF0FAA7E /* bloom_filter.pb.cc in Sources */,
4538+
CA077AA69CF12D5170BB05C2 /* bloom_filter_test.cc in Sources */,
45264539
784FCB02C76096DACCBA11F2 /* bundle.pb.cc in Sources */,
45274540
856A1EAAD674ADBDAAEDAC37 /* bundle_builder.cc in Sources */,
45284541
BB3F35B1510FE5449E50EC8A /* bundle_cache_test.cc in Sources */,
@@ -4766,6 +4779,7 @@
47664779
8F781F527ED72DC6C123689E /* autoid_test.cc in Sources */,
47674780
0B9BD73418289EFF91917934 /* bits_test.cc in Sources */,
47684781
35F32BDF43950B4E715A1BDB /* bloom_filter.pb.cc in Sources */,
4782+
EA8C203393B17C238A776133 /* bloom_filter_test.cc in Sources */,
47694783
F8126CD7308A4B8AEC0F30A8 /* bundle.pb.cc in Sources */,
47704784
5AFA1055E8F6B4E4B1CCE2C4 /* bundle_builder.cc in Sources */,
47714785
AE5E5E4A7BF12C2337AFA13B /* bundle_cache_test.cc in Sources */,
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "Firestore/core/src/remote/bloom_filter.h"
18+
19+
#include <utility>
20+
21+
#include "CommonCrypto/CommonDigest.h"
22+
#include "Firestore/core/src/util/hard_assert.h"
23+
#include "Firestore/core/src/util/statusor.h"
24+
#include "Firestore/core/src/util/warnings.h"
25+
26+
namespace firebase {
27+
namespace firestore {
28+
namespace remote {
29+
30+
using util::Status;
31+
using util::StatusOr;
32+
33+
// TODO(Mila): Replace CommonCrypto with platform based MD5 calculation and
34+
// remove suppress.
35+
SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
36+
37+
BloomFilter::Hash BloomFilter::Md5HashDigest(absl::string_view key) const {
38+
unsigned char md5_digest[CC_MD5_DIGEST_LENGTH];
39+
40+
CC_MD5_CTX context;
41+
CC_MD5_Init(&context);
42+
CC_MD5_Update(&context, key.data(), key.size());
43+
CC_MD5_Final(md5_digest, &context);
44+
45+
// TODO(Mila): Replace this casting with safer function (b/270568625).
46+
uint64_t* hash128 = reinterpret_cast<uint64_t*>(md5_digest);
47+
return Hash{hash128[0], hash128[1]};
48+
}
49+
SUPPRESS_END();
50+
51+
int32_t BloomFilter::GetBitIndex(const Hash& hash, int32_t hash_index) const {
52+
HARD_ASSERT(hash_index >= 0);
53+
uint64_t hash_index_uint64 = static_cast<uint64_t>(hash_index);
54+
uint64_t bit_count_uint64 = static_cast<uint64_t>(bit_count_);
55+
56+
uint64_t combined_hash = hash.h1 + (hash_index_uint64 * hash.h2);
57+
uint64_t bit_index = combined_hash % bit_count_uint64;
58+
59+
HARD_ASSERT(bit_index <= INT32_MAX);
60+
return bit_index;
61+
}
62+
63+
bool BloomFilter::IsBitSet(int32_t index) const {
64+
uint8_t byte_at_index = bitmap_[index / 8];
65+
int32_t offset = index % 8;
66+
return (byte_at_index & (static_cast<uint8_t>(0x01) << offset)) != 0;
67+
}
68+
69+
BloomFilter::BloomFilter(std::vector<uint8_t> bitmap,
70+
int32_t padding,
71+
int32_t hash_count)
72+
: bit_count_(static_cast<int32_t>(bitmap.size()) * 8 - padding),
73+
hash_count_(hash_count),
74+
bitmap_(std::move(bitmap)) {
75+
HARD_ASSERT(padding >= 0 && padding < 8);
76+
HARD_ASSERT(hash_count_ >= 0);
77+
// Only empty bloom filter can have 0 hash count.
78+
HARD_ASSERT(bitmap_.size() == 0 || hash_count_ != 0);
79+
// Empty bloom filter should have 0 padding.
80+
HARD_ASSERT(bitmap_.size() != 0 || padding == 0);
81+
HARD_ASSERT(bit_count_ >= 0);
82+
}
83+
84+
StatusOr<BloomFilter> BloomFilter::Create(std::vector<uint8_t> bitmap,
85+
int32_t padding,
86+
int32_t hash_count) {
87+
if (padding < 0 || padding >= 8) {
88+
return Status(firestore::Error::kErrorInvalidArgument,
89+
"Invalid padding: " + std::to_string(padding));
90+
}
91+
if (hash_count < 0) {
92+
return Status(firestore::Error::kErrorInvalidArgument,
93+
"Invalid hash count: " + std::to_string(hash_count));
94+
}
95+
if (bitmap.size() > 0 && hash_count == 0) {
96+
// Only empty bloom filter can have 0 hash count.
97+
return Status(firestore::Error::kErrorInvalidArgument,
98+
"Invalid hash count: " + std::to_string(hash_count));
99+
}
100+
if (bitmap.size() == 0 && padding != 0) {
101+
// Empty bloom filter should have 0 padding.
102+
return Status(firestore::Error::kErrorInvalidArgument,
103+
"Expected padding of 0 when bitmap length is 0, but got " +
104+
std::to_string(padding));
105+
}
106+
107+
return BloomFilter(std::move(bitmap), padding, hash_count);
108+
}
109+
110+
bool BloomFilter::MightContain(absl::string_view value) const {
111+
// Empty bitmap should return false on membership check.
112+
if (bit_count_ == 0) return false;
113+
Hash hash = Md5HashDigest(value);
114+
// The `hash_count_` and `bit_count_` fields are guaranteed to be
115+
// non-negative when the `BloomFilter` object is constructed.
116+
for (int32_t i = 0; i < hash_count_; ++i) {
117+
int32_t index = GetBitIndex(hash, i);
118+
if (!IsBitSet(index)) {
119+
return false;
120+
}
121+
}
122+
return true;
123+
}
124+
125+
} // namespace remote
126+
} // namespace firestore
127+
} // namespace firebase

Firestore/core/src/remote/bloom_filter.h

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <string>
2121
#include <vector>
22+
#include "Firestore/core/src/util/statusor.h"
2223
#include "absl/strings/string_view.h"
2324

2425
namespace firebase {
@@ -35,6 +36,16 @@ class BloomFilter final {
3536
BloomFilter& operator=(const BloomFilter&) = default;
3637
BloomFilter& operator=(BloomFilter&&) = default;
3738

39+
/**
40+
* Creates a BloomFilter object or returns a status.
41+
*
42+
* @return a new BloomFilter if the inputs are valid, otherwise returns a not
43+
* `ok()` status.
44+
*/
45+
static util::StatusOr<BloomFilter> Create(std::vector<uint8_t> bitmap,
46+
int32_t padding,
47+
int32_t hash_count);
48+
3849
/**
3950
* Check whether the given string is a possible member of the bloom filter. It
4051
* might return false positive result, ie, the given string is not a member of
@@ -46,22 +57,50 @@ class BloomFilter final {
4657
*/
4758
bool MightContain(absl::string_view value) const;
4859

49-
// Get the `bit_count_` field. Used for testing purpose.
60+
/** Get the `bit_count_` field. Used for testing purpose. */
5061
int32_t bit_count() const {
5162
return bit_count_;
5263
}
5364

5465
private:
55-
// The number of bits in the bloom filter. Guaranteed to be non-negative, and
56-
// less than the max number of bits `bitmap_` can represent, i.e.,
57-
// bitmap_.size() * 8.
66+
/**
67+
* When checking membership of a key in bitmap, the first step is to generate
68+
* a 128-bit hash, and treat it as 2 distinct 64-bit hash values, named `h1`
69+
* and `h2`, interpreted as unsigned integers using 2's complement encoding.
70+
*/
71+
struct Hash {
72+
uint64_t h1;
73+
uint64_t h2;
74+
};
75+
76+
/**
77+
* Calculate the MD5 digest of the given string, and return a Hash object.
78+
*/
79+
Hash Md5HashDigest(absl::string_view key) const;
80+
81+
/**
82+
* Calculate the ith hash value based on the hashed 64 bit unsigned integers,
83+
* and calculate its corresponding bit index in the bitmap to be checked.
84+
*/
85+
int32_t GetBitIndex(const Hash& hash, int32_t hash_index) const;
86+
87+
/** Return whether the bit at the given index in the bitmap is set to 1. */
88+
bool IsBitSet(int32_t index) const;
89+
90+
/**
91+
* The number of bits in the bloom filter. Guaranteed to be non-negative, and
92+
* less than the max number of bits `bitmap_` can represent, i.e.,
93+
* bitmap_.size() * 8.
94+
*/
5895
int32_t bit_count_ = 0;
5996

60-
// The number of hash functions used to construct the filter. Guaranteed to be
61-
// non-negative.
97+
/**
98+
* The number of hash functions used to construct the filter. Guaranteed to
99+
* be non-negative.
100+
*/
62101
int32_t hash_count_ = 0;
63102

64-
// Bloom filter's bitmap.
103+
/** Bloom filter's bitmap. */
65104
std::vector<uint8_t> bitmap_;
66105
};
67106

0 commit comments

Comments
 (0)