@@ -107,7 +107,7 @@ int load_bloom_filter_from_graph(struct commit_graph *g,
107107 * Not considered to be cryptographically secure.
108108 * Implemented as described in https://en.wikipedia.org/wiki/MurmurHash#Algorithm
109109 */
110- uint32_t murmur3_seeded_v2 (uint32_t seed , const char * data , size_t len )
110+ static uint32_t murmur3_seeded_v2 (uint32_t seed , const char * data , size_t len )
111111{
112112 const uint32_t c1 = 0xcc9e2d51 ;
113113 const uint32_t c2 = 0x1b873593 ;
@@ -221,9 +221,7 @@ static uint32_t murmur3_seeded_v1(uint32_t seed, const char *data, size_t len)
221221 return seed ;
222222}
223223
224- void fill_bloom_key (const char * data ,
225- size_t len ,
226- struct bloom_key * key ,
224+ void bloom_key_fill (struct bloom_key * key , const char * data , size_t len ,
227225 const struct bloom_filter_settings * settings )
228226{
229227 int i ;
@@ -243,7 +241,7 @@ void fill_bloom_key(const char *data,
243241 key -> hashes [i ] = hash0 + i * hash1 ;
244242}
245243
246- void clear_bloom_key (struct bloom_key * key )
244+ void bloom_key_clear (struct bloom_key * key )
247245{
248246 FREE_AND_NULL (key -> hashes );
249247}
@@ -280,6 +278,55 @@ void deinit_bloom_filters(void)
280278 deep_clear_bloom_filter_slab (& bloom_filters , free_one_bloom_filter );
281279}
282280
281+ struct bloom_keyvec * bloom_keyvec_new (const char * path , size_t len ,
282+ const struct bloom_filter_settings * settings )
283+ {
284+ struct bloom_keyvec * vec ;
285+ const char * p ;
286+ size_t sz ;
287+ size_t nr = 1 ;
288+
289+ p = path ;
290+ while (* p ) {
291+ /*
292+ * At this point, the path is normalized to use Unix-style
293+ * path separators. This is required due to how the
294+ * changed-path Bloom filters store the paths.
295+ */
296+ if (* p == '/' )
297+ nr ++ ;
298+ p ++ ;
299+ }
300+
301+ sz = sizeof (struct bloom_keyvec );
302+ sz += nr * sizeof (struct bloom_key );
303+ vec = (struct bloom_keyvec * )xcalloc (1 , sz );
304+ if (!vec )
305+ return NULL ;
306+ vec -> count = nr ;
307+
308+ bloom_key_fill (& vec -> key [0 ], path , len , settings );
309+ nr = 1 ;
310+ p = path + len - 1 ;
311+ while (p > path ) {
312+ if (* p == '/' ) {
313+ bloom_key_fill (& vec -> key [nr ++ ], path , p - path , settings );
314+ }
315+ p -- ;
316+ }
317+ assert (nr == vec -> count );
318+ return vec ;
319+ }
320+
321+ void bloom_keyvec_free (struct bloom_keyvec * vec )
322+ {
323+ if (!vec )
324+ return ;
325+ for (size_t nr = 0 ; nr < vec -> count ; nr ++ )
326+ bloom_key_clear (& vec -> key [nr ]);
327+ free (vec );
328+ }
329+
283330static int pathmap_cmp (const void * hashmap_cmp_fn_data UNUSED ,
284331 const struct hashmap_entry * eptr ,
285332 const struct hashmap_entry * entry_or_key ,
@@ -500,9 +547,9 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
500547
501548 hashmap_for_each_entry (& pathmap , & iter , e , entry ) {
502549 struct bloom_key key ;
503- fill_bloom_key ( e -> path , strlen (e -> path ), & key , settings );
550+ bloom_key_fill ( & key , e -> path , strlen (e -> path ), settings );
504551 add_key_to_filter (& key , filter , settings );
505- clear_bloom_key (& key );
552+ bloom_key_clear (& key );
506553 }
507554
508555 cleanup :
@@ -540,3 +587,26 @@ int bloom_filter_contains(const struct bloom_filter *filter,
540587
541588 return 1 ;
542589}
590+
591+ int bloom_filter_contains_vec (const struct bloom_filter * filter ,
592+ const struct bloom_keyvec * vec ,
593+ const struct bloom_filter_settings * settings )
594+ {
595+ int ret = 1 ;
596+
597+ for (size_t nr = 0 ; ret > 0 && nr < vec -> count ; nr ++ )
598+ ret = bloom_filter_contains (filter , & vec -> key [nr ], settings );
599+
600+ return ret ;
601+ }
602+
603+ uint32_t test_bloom_murmur3_seeded (uint32_t seed , const char * data , size_t len ,
604+ int version )
605+ {
606+ assert (version == 1 || version == 2 );
607+
608+ if (version == 2 )
609+ return murmur3_seeded_v2 (seed , data , len );
610+ else
611+ return murmur3_seeded_v1 (seed , data , len );
612+ }
0 commit comments