LCOV - code coverage report
Current view: top level - nsas - hash.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 32 33 97.0 %
Date: 2012-05-15 Functions: 2 2 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 18 24 75.0 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : /*! \file
      16                 :            :  * Some parts of this code were copied from BIND-9, which in turn was derived
      17                 :            :  * from universal hash function libraries of Rice University.
      18                 :            : 
      19                 :            : \section license UH Universal Hashing Library
      20                 :            : 
      21                 :            : Copyright ((c)) 2002, Rice University
      22                 :            : All rights reserved.
      23                 :            : 
      24                 :            : Redistribution and use in source and binary forms, with or without
      25                 :            : modification, are permitted provided that the following conditions are
      26                 :            : met:
      27                 :            : 
      28                 :            :     * Redistributions of source code must retain the above copyright
      29                 :            :     notice, this list of conditions and the following disclaimer.
      30                 :            : 
      31                 :            :     * Redistributions in binary form must reproduce the above
      32                 :            :     copyright notice, this list of conditions and the following
      33                 :            :     disclaimer in the documentation and/or other materials provided
      34                 :            :     with the distribution.
      35                 :            : 
      36                 :            :     * Neither the name of Rice University (RICE) nor the names of its
      37                 :            :     contributors may be used to endorse or promote products derived
      38                 :            :     from this software without specific prior written permission.
      39                 :            : 
      40                 :            : 
      41                 :            : This software is provided by RICE and the contributors on an "as is"
      42                 :            : basis, without any representations or warranties of any kind, express
      43                 :            : or implied including, but not limited to, representations or
      44                 :            : warranties of non-infringement, merchantability or fitness for a
      45                 :            : particular purpose. In no event shall RICE or contributors be liable
      46                 :            : for any direct, indirect, incidental, special, exemplary, or
      47                 :            : consequential damages (including, but not limited to, procurement of
      48                 :            : substitute goods or services; loss of use, data, or profits; or
      49                 :            : business interruption) however caused and on any theory of liability,
      50                 :            : whether in contract, strict liability, or tort (including negligence
      51                 :            : or otherwise) arising in any way out of the use of this software, even
      52                 :            : if advised of the possibility of such damage.
      53                 :            : */
      54                 :            : 
      55                 :            : #include <cassert>
      56                 :            : #include <stdlib.h>
      57                 :            : #include <algorithm>
      58                 :            : #include <cassert>
      59                 :            : #include <string>
      60                 :            : 
      61                 :            : #include <config.h>
      62                 :            : 
      63                 :            : #include "hash.h"
      64                 :            : 
      65                 :            : using namespace std;
      66                 :            : 
      67                 :            : namespace isc {
      68                 :            : namespace nsas {
      69                 :            : 
      70                 :            : // Constructor.
      71                 :            : 
      72                 :        233 : Hash::Hash(uint32_t tablesize, uint32_t maxkeylen, bool randomise) :
      73                 :            :     tablesize_(tablesize), maxkeylen_(min<uint32_t>(maxkeylen,
      74                 :        699 :         (255 - sizeof(uint16_t))))
      75                 :            : {
      76                 :            :     // (Code taken from BIND-9)
      77                 :            :     //
      78                 :            :     // Check to see that we can cope with the maximum key length which, due
      79                 :            :     // to the limitations, should not be more than 255 in total.  The actual
      80                 :            :     // number of characters in the name that are considered is reduced to
      81                 :            :     // ensure that the class is taken into account in the hash.  (This accounts
      82                 :            :     // for the "+ sizeof(uint16_t)" in the calculations below.
      83                 :            :     //
      84                 :            :     // Overflow check.  Since our implementation only does a modulo
      85                 :            :     // operation at the last stage of hash calculation, the accumulator
      86                 :            :     // must not overflow.
      87                 :            :     hash_accum_t overflow_limit =
      88                 :        233 :         1 << (((sizeof(hash_accum_t) - sizeof(hash_random_t))) * 8);
      89         [ -  + ]:        233 :     if (overflow_limit < (maxkeylen_ + sizeof(uint16_t) + 1) * 0xff) {
      90 [ #  # ][ #  # ]:          0 :         isc_throw(KeyLengthTooLong, "Hash key length too long for Hash class");
      91                 :            :     }
      92                 :            : 
      93                 :            :     // Initialize the random number generator with the current time.
      94                 :            :     // TODO: Use something other than pseudo-random numbers.
      95                 :            :     union {
      96                 :            :         unsigned int    seed;
      97                 :            :         time_t          curtime;
      98                 :            :     } init_value;
      99                 :            : 
     100         [ +  + ]:        233 :     if (randomise) {
     101                 :        230 :         init_value.curtime = time(NULL);
     102                 :            :     } else {
     103                 :          3 :         init_value.seed = 1;
     104                 :            :     }
     105                 :        233 :     srandom(init_value.seed);
     106                 :            : 
     107                 :            :     // Fill in the random vector.
     108         [ +  - ]:        233 :     randvec_.reserve(maxkeylen_ + sizeof(uint16_t) + 1);
     109         [ +  + ]:      60119 :     for (uint32_t i = 0; i < (maxkeylen + sizeof(uint16_t) + 1); ++i) {
     110                 :      59886 :         randvec_.push_back(static_cast<hash_random_t>(random() & 0xffff));
     111                 :            :     }
     112                 :            :     assert(sizeof(hash_random_t) == 2); // So that the "& 0xffff" is valid
     113                 :            : 
     114                 :            :     // Finally, initialize the mapping table for uppercase to lowercase
     115                 :            :     // characters.  A table is used as indexing a table is faster than calling
     116                 :            :     // the tolower() function.
     117                 :        233 :     casemap_.reserve(256);
     118         [ +  + ]:      59881 :     for (int i = 0; i < 256; ++i) {
     119                 :      59648 :         casemap_.push_back(i);
     120                 :            :     }
     121         [ +  + ]:       6291 :     for (int i = 'A'; i <= 'Z'; ++i) {
     122                 :      12116 :         casemap_[i] += ('a' - 'A');
     123                 :            :     }
     124                 :        233 : }
     125                 :            : 
     126                 :            : 
     127                 :       2856 : uint32_t Hash::operator()(const HashKey& key, bool ignorecase) const
     128                 :            : {
     129                 :            :     // Calculation as given in BIND-9.
     130                 :       2856 :     hash_accum_t partial_sum = 0;
     131                 :       2856 :     uint32_t i = 0;                 // Used after the end of the loop
     132                 :            : 
     133                 :            :     // Perform the hashing.  If the key length if more than the maximum we set
     134                 :            :     // up this hash for, ignore the excess.
     135         [ +  + ]:       2856 :     if (ignorecase) {
     136         [ +  + ]:      77506 :         for (i = 0; i < min(key.keylen, maxkeylen_); ++i) {
     137                 :      37326 :             partial_sum += mapLower(key.key[i]) * randvec_[i];
     138                 :            :         }
     139                 :            :     } else {
     140         [ +  + ]:         38 :         for (i = 0; i < min(key.keylen, maxkeylen_); ++i) {
     141                 :         72 :             partial_sum += key.key[i] * randvec_[i];
     142                 :            :         }
     143                 :            :     }
     144                 :            : 
     145                 :            :     // Add the hash of the class code
     146                 :            :     union {
     147                 :            :         uint16_t    class_code;                 // Copy of the class code
     148                 :            :         char        bytes[sizeof(uint16_t)];    // Byte equivalent
     149                 :            :     } convert;
     150                 :            : 
     151                 :       5712 :     convert.class_code = key.class_code.getCode();
     152         [ +  + ]:       8568 :     for (int j = 0; j < sizeof(uint16_t); ++j, ++i) {
     153                 :      11424 :         partial_sum += convert.bytes[j] * randvec_[i];
     154                 :            :     }
     155                 :            : 
     156                 :            :     // ... and finish up.
     157                 :       5712 :     partial_sum += randvec_[i];
     158                 :            : 
     159                 :            :     // Determine the hash value
     160                 :       2856 :     uint32_t value = partial_sum % prime32_;
     161                 :            : 
     162                 :            :     // ... and round it to fit the table size
     163                 :       2856 :     return (value % tablesize_);
     164                 :            : }
     165                 :            : 
     166                 :            : } // namespace nsas
     167                 :      91632 : } // namespace isc

Generated by: LCOV version 1.9