LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-bloom.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 59 63 93.7 %
Date: 2015-07-29 18:47:03 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2013 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include "util.h"
      23             : #include "siphash24.h"
      24             : #include "bus-bloom.h"
      25             : 
      26        4008 : static inline void set_bit(uint64_t filter[], unsigned long b) {
      27        4008 :         filter[b >> 6] |= 1ULL << (b & 63);
      28        4008 : }
      29             : 
      30             : static const sd_id128_t hash_keys[] = {
      31             :         SD_ID128_ARRAY(b9,66,0b,f0,46,70,47,c1,88,75,c4,9c,54,b9,bd,15),
      32             :         SD_ID128_ARRAY(aa,a1,54,a2,e0,71,4b,39,bf,e1,dd,2e,9f,c5,4a,3b),
      33             :         SD_ID128_ARRAY(63,fd,ae,be,cd,82,48,12,a1,6e,41,26,cb,fa,a0,c8),
      34             :         SD_ID128_ARRAY(23,be,45,29,32,d2,46,2d,82,03,52,28,fe,37,17,f5),
      35             :         SD_ID128_ARRAY(56,3b,bf,ee,5a,4f,43,39,af,aa,94,08,df,f0,fc,10),
      36             :         SD_ID128_ARRAY(31,80,c8,73,c7,ea,46,d3,aa,25,75,0f,9e,4c,09,29),
      37             :         SD_ID128_ARRAY(7d,f7,18,4b,7b,a4,44,d5,85,3c,06,e0,65,53,96,6d),
      38             :         SD_ID128_ARRAY(f2,77,e9,6f,93,b5,4e,71,9a,0c,34,88,39,25,bf,35),
      39             : };
      40             : 
      41         501 : static void bloom_add_data(
      42             :                 uint64_t filter[],     /* The filter bits */
      43             :                 size_t size,           /* Size of the filter in bytes */
      44             :                 unsigned k,            /* Number of hash functions */
      45             :                 const void *data,      /* Data to hash */
      46             :                 size_t n) {            /* Size of data to hash in bytes */
      47             : 
      48             :         uint8_t h[8];
      49             :         uint64_t m;
      50         501 :         unsigned w, i, c = 0;
      51             :         unsigned hash_index;
      52             : 
      53         501 :         assert(size > 0);
      54         501 :         assert(k > 0);
      55             : 
      56             :         /* Determine bits in filter */
      57         501 :         m = size * 8;
      58             : 
      59             :         /* Determine how many bytes we need to generate a bit index 0..m for this filter */
      60         501 :         w = (u64log2(m) + 7) / 8;
      61             : 
      62         501 :         assert(w <= sizeof(uint64_t));
      63             : 
      64             :         /* Make sure we have enough hash keys to generate m * k bits
      65             :          * of hash value. Note that SipHash24 generates 64 bits of
      66             :          * hash value for each 128 bits of hash key. */
      67         501 :         assert(k * w <= ELEMENTSOF(hash_keys) * 8);
      68             : 
      69        4509 :         for (i = 0, hash_index = 0; i < k; i++) {
      70        4008 :                 uint64_t p = 0;
      71             :                 unsigned d;
      72             : 
      73       12024 :                 for (d = 0; d < w; d++) {
      74        8016 :                         if (c <= 0) {
      75        1002 :                                 siphash24(h, data, n, hash_keys[hash_index++].bytes);
      76        1002 :                                 c += 8;
      77             :                         }
      78             : 
      79        8016 :                         p = (p << 8ULL) | (uint64_t) h[8 - c];
      80        8016 :                         c--;
      81             :                 }
      82             : 
      83        4008 :                 p &= m - 1;
      84        4008 :                 set_bit(filter, p);
      85             :         }
      86             : 
      87             :         /* log_debug("bloom: adding <%.*s>", (int) n, (char*) data); */
      88         501 : }
      89             : 
      90         237 : void bloom_add_pair(uint64_t filter[], size_t size, unsigned k, const char *a, const char *b) {
      91             :         size_t n;
      92             :         char *c;
      93             : 
      94         237 :         assert(filter);
      95         237 :         assert(a);
      96         237 :         assert(b);
      97             : 
      98         237 :         n = strlen(a) + 1 + strlen(b);
      99         237 :         c = alloca(n + 1);
     100         237 :         strcpy(stpcpy(stpcpy(c, a), ":"), b);
     101             : 
     102         237 :         bloom_add_data(filter, size, k, c, n);
     103         237 : }
     104             : 
     105          97 : void bloom_add_prefixes(uint64_t filter[], size_t size, unsigned k, const char *a, const char *b, char sep) {
     106             :         size_t n;
     107             :         char *c, *p;
     108             : 
     109          97 :         assert(filter);
     110          97 :         assert(a);
     111          97 :         assert(b);
     112             : 
     113          97 :         n = strlen(a) + 1 + strlen(b);
     114          97 :         c = alloca(n + 1);
     115             : 
     116          97 :         p = stpcpy(stpcpy(c, a), ":");
     117          97 :         strcpy(p, b);
     118             : 
     119          97 :         bloom_add_data(filter, size, k, c, n);
     120             : 
     121             :         for (;;) {
     122             :                 char *e;
     123             : 
     124         162 :                 e = strrchr(p, sep);
     125         162 :                 if (!e)
     126          60 :                         break;
     127             : 
     128         102 :                 *(e + 1) = 0;
     129         102 :                 bloom_add_data(filter, size, k, c, e - c + 1);
     130             : 
     131         102 :                 if (e == p)
     132          37 :                         break;
     133             : 
     134          65 :                 *e = 0;
     135          65 :                 bloom_add_data(filter, size, k, c, e - c);
     136          65 :         }
     137          97 : }
     138             : 
     139          76 : bool bloom_validate_parameters(size_t size, unsigned k) {
     140             :         uint64_t m;
     141             :         unsigned w;
     142             : 
     143          76 :         if (size <= 0)
     144           0 :                 return false;
     145             : 
     146          76 :         if (k <= 0)
     147           0 :                 return false;
     148             : 
     149          76 :         m = size * 8;
     150          76 :         w = (u64log2(m) + 7) / 8;
     151          76 :         if (w > sizeof(uint64_t))
     152           0 :                 return false;
     153             : 
     154          76 :         if (k * w > ELEMENTSOF(hash_keys) * 8)
     155           0 :                 return false;
     156             : 
     157          76 :         return true;
     158             : }

Generated by: LCOV version 1.11