LCOV - code coverage report
Current view: top level - girepository/cmph - brz.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 0.0 % 613 0
Test Date: 2024-11-26 05:23:01 Functions: 0.0 % 25 0
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : #include "graph.h"
       2                 :             : #include "fch.h"
       3                 :             : #include "fch_structs.h"
       4                 :             : #include "bmz8.h"
       5                 :             : #include "bmz8_structs.h"
       6                 :             : #include "brz.h"
       7                 :             : #include "cmph_structs.h"
       8                 :             : #include "brz_structs.h"
       9                 :             : #include "buffer_manager.h"
      10                 :             : #include "cmph.h"
      11                 :             : #include "hash.h"
      12                 :             : #include "bitbool.h"
      13                 :             : #include <math.h>
      14                 :             : #include <stdlib.h>
      15                 :             : #include <stdint.h>
      16                 :             : #include <stdio.h>
      17                 :             : #include <assert.h>
      18                 :             : #include <string.h>
      19                 :             : #include <errno.h>
      20                 :             : #define MAX_BUCKET_SIZE 255
      21                 :             : //#define DEBUG
      22                 :             : #include "debug.h"
      23                 :             : 
      24                 :             : 
      25                 :             : static int brz_gen_mphf(cmph_config_t *mph);
      26                 :             : static cmph_uint32 brz_min_index(cmph_uint32 * vector, cmph_uint32 n);
      27                 :             : static void brz_destroy_keys_vd(cmph_uint8 ** keys_vd, cmph_uint32 nkeys);
      28                 :             : static char * brz_copy_partial_fch_mphf(brz_config_data_t *brz, fch_data_t * fchf, cmph_uint32 index,  cmph_uint32 *buflen);
      29                 :             : static char * brz_copy_partial_bmz8_mphf(brz_config_data_t *brz, bmz8_data_t * bmzf, cmph_uint32 index,  cmph_uint32 *buflen);
      30                 :           0 : brz_config_data_t *brz_config_new(void)
      31                 :             : {
      32                 :           0 :         brz_config_data_t *brz = NULL;  
      33                 :           0 :         brz = (brz_config_data_t *)malloc(sizeof(brz_config_data_t));
      34                 :           0 :         brz->algo = CMPH_FCH;
      35                 :           0 :         brz->b = 128;
      36                 :           0 :         brz->hashfuncs[0] = CMPH_HASH_JENKINS;
      37                 :           0 :         brz->hashfuncs[1] = CMPH_HASH_JENKINS;
      38                 :           0 :         brz->hashfuncs[2] = CMPH_HASH_JENKINS;
      39                 :           0 :         brz->size   = NULL;
      40                 :           0 :         brz->offset = NULL;
      41                 :           0 :         brz->g      = NULL;
      42                 :           0 :         brz->h1 = NULL;
      43                 :           0 :         brz->h2 = NULL;
      44                 :           0 :         brz->h0 = NULL;
      45                 :           0 :         brz->memory_availability = 1024*1024;
      46                 :           0 :         brz->tmp_dir = (cmph_uint8 *)calloc((size_t)10, sizeof(cmph_uint8));
      47                 :           0 :         brz->mphf_fd = NULL;
      48                 :           0 :         strcpy((char *)(brz->tmp_dir), "/var/tmp/"); 
      49                 :           0 :         assert(brz);
      50                 :           0 :         return brz;
      51                 :             : }
      52                 :             : 
      53                 :           0 : void brz_config_destroy(cmph_config_t *mph)
      54                 :             : {
      55                 :           0 :         brz_config_data_t *data = (brz_config_data_t *)mph->data;
      56                 :           0 :         free(data->tmp_dir);
      57                 :             :         DEBUGP("Destroying algorithm dependent data\n");
      58                 :           0 :         free(data);
      59                 :           0 : }
      60                 :             : 
      61                 :           0 : void brz_config_set_hashfuncs(cmph_config_t *mph, CMPH_HASH *hashfuncs)
      62                 :             : {
      63                 :           0 :         brz_config_data_t *brz = (brz_config_data_t *)mph->data;
      64                 :           0 :         CMPH_HASH *hashptr = hashfuncs;
      65                 :           0 :         cmph_uint32 i = 0;
      66                 :           0 :         while(*hashptr != CMPH_HASH_COUNT)
      67                 :             :         {
      68                 :           0 :                 if (i >= 3) break; //brz only uses three hash functions
      69                 :           0 :                 brz->hashfuncs[i] = *hashptr;        
      70                 :           0 :                 ++i, ++hashptr;
      71                 :             :         }
      72                 :           0 : }
      73                 :             : 
      74                 :           0 : void brz_config_set_memory_availability(cmph_config_t *mph, cmph_uint32 memory_availability)
      75                 :             : {
      76                 :           0 :         brz_config_data_t *brz = (brz_config_data_t *)mph->data;
      77                 :           0 :         if(memory_availability > 0) brz->memory_availability = memory_availability*1024*1024;
      78                 :           0 : }
      79                 :             : 
      80                 :           0 : void brz_config_set_tmp_dir(cmph_config_t *mph, cmph_uint8 *tmp_dir)
      81                 :             : {
      82                 :           0 :         brz_config_data_t *brz = (brz_config_data_t *)mph->data;
      83                 :           0 :         if(tmp_dir)
      84                 :             :         {
      85                 :           0 :                 size_t len = strlen((char *)tmp_dir);
      86                 :           0 :                 free(brz->tmp_dir);
      87                 :           0 :                 if(tmp_dir[len-1] != '/')
      88                 :             :                 {
      89                 :           0 :                         brz->tmp_dir = (cmph_uint8 *)calloc((size_t)len+2, sizeof(cmph_uint8));
      90                 :           0 :                         sprintf((char *)(brz->tmp_dir), "%s/", (char *)tmp_dir); 
      91                 :             :                 }
      92                 :             :                 else
      93                 :             :                 {
      94                 :           0 :                         brz->tmp_dir = (cmph_uint8 *)calloc((size_t)len+1, sizeof(cmph_uint8));
      95                 :           0 :                         sprintf((char *)(brz->tmp_dir), "%s", (char *)tmp_dir); 
      96                 :             :                 }
      97                 :             :                 
      98                 :             :         }
      99                 :           0 : }
     100                 :             : 
     101                 :           0 : void brz_config_set_mphf_fd(cmph_config_t *mph, FILE *mphf_fd)
     102                 :             : {
     103                 :           0 :         brz_config_data_t *brz = (brz_config_data_t *)mph->data;
     104                 :           0 :         brz->mphf_fd = mphf_fd;
     105                 :           0 :         assert(brz->mphf_fd);
     106                 :           0 : }
     107                 :             : 
     108                 :           0 : void brz_config_set_b(cmph_config_t *mph, cmph_uint32 b)
     109                 :             : {
     110                 :           0 :         brz_config_data_t *brz = (brz_config_data_t *)mph->data;
     111                 :           0 :         if(b <= 64 || b >= 175) 
     112                 :             :         {
     113                 :           0 :                 b =  128;
     114                 :             :         }
     115                 :           0 :         brz->b = (cmph_uint8)b;
     116                 :           0 : }
     117                 :             : 
     118                 :           0 : void brz_config_set_algo(cmph_config_t *mph, CMPH_ALGO algo) 
     119                 :             : {
     120                 :           0 :         if (algo == CMPH_BMZ8 || algo == CMPH_FCH) // supported algorithms
     121                 :             :         {
     122                 :           0 :                 brz_config_data_t *brz = (brz_config_data_t *)mph->data;
     123                 :           0 :                 brz->algo = algo;
     124                 :             :         }
     125                 :           0 : }
     126                 :             : 
     127                 :           0 : cmph_t *brz_new(cmph_config_t *mph, double c)
     128                 :             : {
     129                 :           0 :         cmph_t *mphf = NULL;
     130                 :           0 :         brz_data_t *brzf = NULL;
     131                 :             :         cmph_uint32 i;
     132                 :           0 :         cmph_uint32 iterations = 20;
     133                 :             :         brz_config_data_t *brz;
     134                 :             : 
     135                 :             :         DEBUGP("c: %f\n", c);
     136                 :           0 :         brz = (brz_config_data_t *)mph->data;
     137                 :           0 :         switch(brz->algo) // validating restrictions over parameter c.
     138                 :             :         {
     139                 :           0 :                 case CMPH_BMZ8:
     140                 :           0 :                         if (c == 0 || c >= 2.0) c = 1;
     141                 :           0 :                         break;
     142                 :           0 :                 case CMPH_FCH:
     143                 :           0 :                         if (c <= 2.0) c = 2.6;
     144                 :           0 :                         break;
     145                 :           0 :                 default:
     146                 :           0 :                         assert(0);
     147                 :             :         }
     148                 :           0 :         brz->c = c;
     149                 :           0 :         brz->m = mph->key_source->nkeys;
     150                 :             :         DEBUGP("m: %u\n", brz->m);
     151                 :           0 :         brz->k = (cmph_uint32)ceil(brz->m/((double)brz->b));
     152                 :             :         DEBUGP("k: %u\n", brz->k);
     153                 :           0 :         brz->size   = (cmph_uint8 *) calloc((size_t)brz->k, sizeof(cmph_uint8));
     154                 :             :         
     155                 :             :         // Clustering the keys by graph id.
     156                 :           0 :         if (mph->verbosity)
     157                 :             :         {
     158                 :           0 :                 fprintf(stderr, "Partitioning the set of keys.\n");
     159                 :             :         }
     160                 :             :                 
     161                 :             :         while(1)
     162                 :           0 :         {
     163                 :             :                 int ok;
     164                 :             :                 DEBUGP("hash function 3\n");
     165                 :           0 :                 brz->h0 = hash_state_new(brz->hashfuncs[2], brz->k);
     166                 :             :                 DEBUGP("Generating graphs\n");
     167                 :           0 :                 ok = brz_gen_mphf(mph);
     168                 :           0 :                 if (!ok)
     169                 :             :                 {
     170                 :           0 :                         --iterations;
     171                 :           0 :                         hash_state_destroy(brz->h0);
     172                 :           0 :                         brz->h0 = NULL;
     173                 :             :                         DEBUGP("%u iterations remaining to create the graphs in a external file\n", iterations);
     174                 :           0 :                         if (mph->verbosity)
     175                 :             :                         {
     176                 :           0 :                                 fprintf(stderr, "Failure: A graph with more than 255 keys was created - %u iterations remaining\n", iterations);
     177                 :             :                         }
     178                 :           0 :                         if (iterations == 0) break;
     179                 :             :                 } 
     180                 :           0 :                 else break;     
     181                 :             :         }
     182                 :           0 :         if (iterations == 0) 
     183                 :             :         {
     184                 :             :                 DEBUGP("Graphs with more than 255 keys were created in all 20 iterations\n");
     185                 :           0 :                 free(brz->size);
     186                 :           0 :                 return NULL;
     187                 :             :         }
     188                 :             :         DEBUGP("Graphs generated\n");
     189                 :             :         
     190                 :           0 :         brz->offset = (cmph_uint32 *)calloc((size_t)brz->k, sizeof(cmph_uint32));
     191                 :           0 :         for (i = 1; i < brz->k; ++i)
     192                 :             :         {
     193                 :           0 :                 brz->offset[i] = brz->size[i-1] + brz->offset[i-1];
     194                 :             :         }
     195                 :             :         // Generating a mphf
     196                 :           0 :         mphf = (cmph_t *)malloc(sizeof(cmph_t));
     197                 :           0 :         mphf->algo = mph->algo;
     198                 :           0 :         brzf = (brz_data_t *)malloc(sizeof(brz_data_t));
     199                 :           0 :         brzf->g = brz->g;
     200                 :           0 :         brz->g = NULL; //transfer memory ownership
     201                 :           0 :         brzf->h1 = brz->h1;
     202                 :           0 :         brz->h1 = NULL; //transfer memory ownership
     203                 :           0 :         brzf->h2 = brz->h2;
     204                 :           0 :         brz->h2 = NULL; //transfer memory ownership
     205                 :           0 :         brzf->h0 = brz->h0;
     206                 :           0 :         brz->h0 = NULL; //transfer memory ownership
     207                 :           0 :         brzf->size = brz->size;
     208                 :           0 :         brz->size = NULL; //transfer memory ownership
     209                 :           0 :         brzf->offset = brz->offset;
     210                 :           0 :         brz->offset = NULL; //transfer memory ownership
     211                 :           0 :         brzf->k = brz->k;
     212                 :           0 :         brzf->c = brz->c;
     213                 :           0 :         brzf->m = brz->m;
     214                 :           0 :         brzf->algo = brz->algo;
     215                 :           0 :         mphf->data = brzf;
     216                 :           0 :         mphf->size = brz->m;      
     217                 :             :         DEBUGP("Successfully generated minimal perfect hash\n");
     218                 :           0 :         if (mph->verbosity)
     219                 :             :         {
     220                 :           0 :                 fprintf(stderr, "Successfully generated minimal perfect hash function\n");
     221                 :             :         }
     222                 :           0 :         return mphf;
     223                 :             : }
     224                 :             : 
     225                 :           0 : static int brz_gen_mphf(cmph_config_t *mph)
     226                 :             : {
     227                 :             :         cmph_uint32 i, e, error;
     228                 :           0 :         brz_config_data_t *brz = (brz_config_data_t *)mph->data;
     229                 :           0 :         cmph_uint32 memory_usage = 0;
     230                 :           0 :         cmph_uint32 nkeys_in_buffer = 0;
     231                 :           0 :         cmph_uint8 *buffer = (cmph_uint8 *)malloc((size_t)brz->memory_availability);
     232                 :           0 :         cmph_uint32 *buckets_size = (cmph_uint32 *)calloc((size_t)brz->k, sizeof(cmph_uint32));
     233                 :           0 :         cmph_uint32 *keys_index = NULL;
     234                 :           0 :         cmph_uint8 **buffer_merge = NULL;
     235                 :           0 :         cmph_uint32 *buffer_h0 = NULL;
     236                 :           0 :         cmph_uint32 nflushes = 0;
     237                 :             :         cmph_uint32 h0;
     238                 :             :         register size_t nbytes;
     239                 :           0 :         FILE *  tmp_fd = NULL;
     240                 :           0 :         buffer_manager_t * buff_manager = NULL;
     241                 :           0 :         char *filename = NULL;
     242                 :           0 :         char *key = NULL;
     243                 :             :         cmph_uint32 keylen;
     244                 :           0 :         cmph_uint32 cur_bucket = 0;
     245                 :           0 :         cmph_uint8 nkeys_vd = 0;
     246                 :           0 :         cmph_uint8 ** keys_vd = NULL;
     247                 :             :         
     248                 :           0 :         mph->key_source->rewind(mph->key_source->data);
     249                 :             :         DEBUGP("Generating graphs from %u keys\n", brz->m);
     250                 :             :         // Partitioning
     251                 :           0 :         for (e = 0; e < brz->m; ++e)
     252                 :             :         {
     253                 :           0 :                 mph->key_source->read(mph->key_source->data, &key, &keylen);
     254                 :             : 
     255                 :             :                 /* Buffers management */
     256                 :           0 :                 if (memory_usage + keylen + sizeof(keylen) > brz->memory_availability) // flush buffers 
     257                 :             :                 {
     258                 :             :                         cmph_uint32 value, sum, keylen1;
     259                 :           0 :                         if(mph->verbosity)
     260                 :             :                         {
     261                 :           0 :                                 fprintf(stderr, "Flushing  %u\n", nkeys_in_buffer);
     262                 :             :                         }
     263                 :           0 :                         value = buckets_size[0];
     264                 :           0 :                         sum = 0;
     265                 :           0 :                         keylen1 = 0;
     266                 :           0 :                         buckets_size[0]   = 0;
     267                 :           0 :                         for(i = 1; i < brz->k; i++)
     268                 :             :                         {
     269                 :           0 :                                 if(buckets_size[i] == 0) continue;
     270                 :           0 :                                 sum += value;
     271                 :           0 :                                 value = buckets_size[i];
     272                 :           0 :                                 buckets_size[i] = sum;
     273                 :             :                                 
     274                 :             :                         }       
     275                 :           0 :                         memory_usage = 0;
     276                 :           0 :                         keys_index = (cmph_uint32 *)calloc((size_t)nkeys_in_buffer, sizeof(cmph_uint32));
     277                 :           0 :                         for(i = 0; i < nkeys_in_buffer; i++)
     278                 :             :                         {
     279                 :           0 :                                 memcpy(&keylen1, buffer + memory_usage, sizeof(keylen1));
     280                 :           0 :                                 h0 = hash(brz->h0, (char *)(buffer + memory_usage + sizeof(keylen1)), keylen1) % brz->k;
     281                 :           0 :                                 keys_index[buckets_size[h0]] = memory_usage;
     282                 :           0 :                                 buckets_size[h0]++;
     283                 :           0 :                                 memory_usage +=  keylen1 + (cmph_uint32)sizeof(keylen1);
     284                 :             :                         }
     285                 :           0 :                         filename = (char *)calloc(strlen((char *)(brz->tmp_dir)) + 11, sizeof(char));
     286                 :           0 :                         sprintf(filename, "%s%u.cmph",brz->tmp_dir, nflushes);
     287                 :           0 :                         tmp_fd = fopen(filename, "wb");
     288                 :           0 :                         free(filename);
     289                 :           0 :                         filename = NULL;
     290                 :           0 :                         for(i = 0; i < nkeys_in_buffer; i++)
     291                 :             :                         {
     292                 :           0 :                                 memcpy(&keylen1, buffer + keys_index[i], sizeof(keylen1));
     293                 :           0 :                                 nbytes = fwrite(buffer + keys_index[i], (size_t)1, keylen1 + sizeof(keylen1), tmp_fd);
     294                 :             :                         }
     295                 :           0 :                         nkeys_in_buffer = 0;
     296                 :           0 :                         memory_usage = 0;
     297                 :           0 :                         memset((void *)buckets_size, 0, brz->k*sizeof(cmph_uint32));
     298                 :           0 :                         nflushes++;
     299                 :           0 :                         free(keys_index);
     300                 :           0 :                         fclose(tmp_fd);
     301                 :             :                 }
     302                 :           0 :                 memcpy(buffer + memory_usage, &keylen, sizeof(keylen));
     303                 :           0 :                 memcpy(buffer + memory_usage + sizeof(keylen), key, (size_t)keylen);
     304                 :           0 :                 memory_usage += keylen + (cmph_uint32)sizeof(keylen);
     305                 :           0 :                 h0 = hash(brz->h0, key, keylen) % brz->k;
     306                 :             :                 
     307                 :           0 :                 if ((brz->size[h0] == MAX_BUCKET_SIZE) || (brz->algo == CMPH_BMZ8 && ((brz->c >= 1.0) && (cmph_uint8)(brz->c * brz->size[h0]) < brz->size[h0]))) 
     308                 :             :                 {
     309                 :           0 :                         free(buffer);
     310                 :           0 :                         free(buckets_size);
     311                 :           0 :                         return 0;
     312                 :             :                 }
     313                 :           0 :                 brz->size[h0] = (cmph_uint8)(brz->size[h0] + 1U);
     314                 :           0 :                 buckets_size[h0] ++;
     315                 :           0 :                 nkeys_in_buffer++;
     316                 :           0 :                 mph->key_source->dispose(mph->key_source->data, key, keylen);
     317                 :             :         }
     318                 :           0 :         if (memory_usage != 0) // flush buffers 
     319                 :             :         {
     320                 :             :                 cmph_uint32 value;
     321                 :             :                 cmph_uint32 sum, keylen1;
     322                 :           0 :                 if(mph->verbosity)
     323                 :             :                 {
     324                 :           0 :                         fprintf(stderr, "Flushing  %u\n", nkeys_in_buffer);
     325                 :             :                 }
     326                 :           0 :                 value = buckets_size[0];
     327                 :           0 :                 sum = 0;
     328                 :           0 :                 keylen1 = 0;
     329                 :           0 :                 buckets_size[0]   = 0;
     330                 :           0 :                 for(i = 1; i < brz->k; i++)
     331                 :             :                 {
     332                 :           0 :                         if(buckets_size[i] == 0) continue;
     333                 :           0 :                         sum += value;
     334                 :           0 :                         value = buckets_size[i];
     335                 :           0 :                         buckets_size[i] = sum;
     336                 :             :                 }
     337                 :           0 :                 memory_usage = 0;
     338                 :           0 :                 keys_index = (cmph_uint32 *)calloc((size_t)nkeys_in_buffer, sizeof(cmph_uint32));
     339                 :           0 :                 for(i = 0; i < nkeys_in_buffer; i++)
     340                 :             :                 {
     341                 :           0 :                         memcpy(&keylen1, buffer + memory_usage, sizeof(keylen1));
     342                 :           0 :                         h0 = hash(brz->h0, (char *)(buffer + memory_usage + sizeof(keylen1)), keylen1) % brz->k;
     343                 :           0 :                         keys_index[buckets_size[h0]] = memory_usage;
     344                 :           0 :                         buckets_size[h0]++;
     345                 :           0 :                         memory_usage +=  keylen1 + (cmph_uint32)sizeof(keylen1);
     346                 :             :                 }
     347                 :           0 :                 filename = (char *)calloc(strlen((char *)(brz->tmp_dir)) + 11, sizeof(char));
     348                 :           0 :                 sprintf(filename, "%s%u.cmph",brz->tmp_dir, nflushes);
     349                 :           0 :                 tmp_fd = fopen(filename, "wb");
     350                 :           0 :                 free(filename);
     351                 :           0 :                 filename = NULL;
     352                 :           0 :                 for(i = 0; i < nkeys_in_buffer; i++)
     353                 :             :                 {
     354                 :           0 :                         memcpy(&keylen1, buffer + keys_index[i], sizeof(keylen1));
     355                 :           0 :                         nbytes = fwrite(buffer + keys_index[i], (size_t)1, keylen1 + sizeof(keylen1), tmp_fd);
     356                 :             :                 }
     357                 :           0 :                 nkeys_in_buffer = 0;
     358                 :           0 :                 memory_usage = 0;
     359                 :           0 :                 memset((void *)buckets_size, 0, brz->k*sizeof(cmph_uint32));
     360                 :           0 :                 nflushes++;
     361                 :           0 :                 free(keys_index);
     362                 :           0 :                 fclose(tmp_fd);
     363                 :             :         }
     364                 :             : 
     365                 :           0 :         free(buffer);
     366                 :           0 :         free(buckets_size);
     367                 :           0 :         if(nflushes > 1024) return 0; // Too many files generated.
     368                 :             :         // mphf generation
     369                 :           0 :         if(mph->verbosity)
     370                 :             :         {
     371                 :           0 :                 fprintf(stderr, "\nMPHF generation \n");
     372                 :             :         }
     373                 :             :         /* Starting to dump to disk the resultant MPHF: __cmph_dump function */
     374                 :           0 :         nbytes = fwrite(cmph_names[CMPH_BRZ], (size_t)(strlen(cmph_names[CMPH_BRZ]) + 1), (size_t)1, brz->mphf_fd);
     375                 :           0 :         nbytes = fwrite(&(brz->m), sizeof(brz->m), (size_t)1, brz->mphf_fd);
     376                 :           0 :         nbytes = fwrite(&(brz->c), sizeof(double), (size_t)1, brz->mphf_fd);
     377                 :           0 :         nbytes = fwrite(&(brz->algo), sizeof(brz->algo), (size_t)1, brz->mphf_fd);
     378                 :           0 :         nbytes = fwrite(&(brz->k), sizeof(cmph_uint32), (size_t)1, brz->mphf_fd); // number of MPHFs
     379                 :           0 :         nbytes = fwrite(brz->size, sizeof(cmph_uint8)*(brz->k), (size_t)1, brz->mphf_fd);
     380                 :           0 :   if (nbytes == 0 && ferror(brz->mphf_fd)) {
     381                 :           0 :           fprintf(stderr, "ERROR: %s\n", strerror(errno));
     382                 :           0 :           return 0;
     383                 :             :         }
     384                 :             : 
     385                 :             :         //tmp_fds = (FILE **)calloc(nflushes, sizeof(FILE *));
     386                 :           0 :         buff_manager = buffer_manager_new(brz->memory_availability, nflushes);
     387                 :           0 :         buffer_merge = (cmph_uint8 **)calloc((size_t)nflushes, sizeof(cmph_uint8 *));
     388                 :           0 :         buffer_h0    = (cmph_uint32 *)calloc((size_t)nflushes, sizeof(cmph_uint32));
     389                 :             :         
     390                 :           0 :         memory_usage = 0;
     391                 :           0 :         for(i = 0; i < nflushes; i++)
     392                 :             :         {
     393                 :           0 :                 filename = (char *)calloc(strlen((char *)(brz->tmp_dir)) + 11, sizeof(char));
     394                 :           0 :                 sprintf(filename, "%s%u.cmph",brz->tmp_dir, i);
     395                 :           0 :                 buffer_manager_open(buff_manager, i, filename);
     396                 :           0 :                 free(filename);
     397                 :           0 :                 filename = NULL;
     398                 :           0 :                 key = (char *)buffer_manager_read_key(buff_manager, i, &keylen);
     399                 :           0 :                 h0 = hash(brz->h0, key+sizeof(keylen), keylen) % brz->k;
     400                 :           0 :                 buffer_h0[i] = h0;
     401                 :           0 :                 buffer_merge[i] = (cmph_uint8 *)key;
     402                 :           0 :                 key = NULL; //transfer memory ownership                 
     403                 :             :         }
     404                 :           0 :         e = 0;
     405                 :           0 :         keys_vd = (cmph_uint8 **)calloc((size_t)MAX_BUCKET_SIZE, sizeof(cmph_uint8 *));
     406                 :           0 :         nkeys_vd = 0;
     407                 :           0 :         error = 0;
     408                 :           0 :         while(e < brz->m)
     409                 :             :         {
     410                 :           0 :                 i = brz_min_index(buffer_h0, nflushes);
     411                 :           0 :                 cur_bucket = buffer_h0[i];
     412                 :           0 :                 key = (char *)buffer_manager_read_key(buff_manager, i, &keylen);
     413                 :           0 :                 if(key)
     414                 :             :                 {
     415                 :           0 :                         while(key)
     416                 :             :                         {
     417                 :             :                                 //keylen = strlen(key);
     418                 :           0 :                                 h0 = hash(brz->h0, key+sizeof(keylen), keylen) % brz->k;
     419                 :           0 :                                 if (h0 != buffer_h0[i]) break;
     420                 :           0 :                                 keys_vd[nkeys_vd++] = (cmph_uint8 *)key;
     421                 :           0 :                                 key = NULL; //transfer memory ownership
     422                 :           0 :                                 e++;
     423                 :           0 :                                 key = (char *)buffer_manager_read_key(buff_manager, i, &keylen);
     424                 :             :                         }
     425                 :           0 :                         if (key)
     426                 :             :                         {
     427                 :           0 :                                 assert(nkeys_vd < brz->size[cur_bucket]);
     428                 :           0 :                                 keys_vd[nkeys_vd++] = buffer_merge[i];
     429                 :           0 :                                 buffer_merge[i] = NULL; //transfer memory ownership
     430                 :           0 :                                 e++;
     431                 :           0 :                                 buffer_h0[i] = h0;
     432                 :           0 :                                 buffer_merge[i] = (cmph_uint8 *)key;
     433                 :             :                         }
     434                 :             :                 }
     435                 :           0 :                 if(!key)
     436                 :             :                 {
     437                 :           0 :                         assert(nkeys_vd < brz->size[cur_bucket]);
     438                 :           0 :                         keys_vd[nkeys_vd++] = buffer_merge[i];
     439                 :           0 :                         buffer_merge[i] = NULL; //transfer memory ownership
     440                 :           0 :                         e++;
     441                 :           0 :                         buffer_h0[i] = UINT_MAX;
     442                 :             :                 }
     443                 :             :                 
     444                 :           0 :                 if(nkeys_vd == brz->size[cur_bucket]) // Generating mphf for each bucket.
     445                 :             :                 {
     446                 :           0 :                         cmph_io_adapter_t *source = NULL;
     447                 :           0 :                         cmph_config_t *config = NULL;
     448                 :           0 :                         cmph_t *mphf_tmp = NULL;
     449                 :           0 :                         char *bufmphf = NULL;
     450                 :           0 :                         cmph_uint32 buflenmphf = 0;
     451                 :             :                         // Source of keys
     452                 :           0 :                         source = cmph_io_byte_vector_adapter(keys_vd, (cmph_uint32)nkeys_vd);
     453                 :           0 :                         config = cmph_config_new(source);
     454                 :           0 :                         cmph_config_set_algo(config, brz->algo);
     455                 :             :                         //cmph_config_set_algo(config, CMPH_BMZ8);
     456                 :           0 :                         cmph_config_set_graphsize(config, brz->c);
     457                 :           0 :                         mphf_tmp = cmph_new(config);
     458                 :           0 :                         if (mphf_tmp == NULL) 
     459                 :             :                         {
     460                 :           0 :                                 if(mph->verbosity) fprintf(stderr, "ERROR: Can't generate MPHF for bucket %u out of %u\n", cur_bucket + 1, brz->k);
     461                 :           0 :                                 error = 1;
     462                 :           0 :                                 cmph_config_destroy(config);
     463                 :           0 :                                 brz_destroy_keys_vd(keys_vd, nkeys_vd);
     464                 :           0 :                                 cmph_io_byte_vector_adapter_destroy(source);
     465                 :           0 :                                 break;
     466                 :             :                         }
     467                 :           0 :                         if(mph->verbosity) 
     468                 :             :                         {
     469                 :           0 :                           if (cur_bucket % 1000 == 0) 
     470                 :             :                           {
     471                 :           0 :                                 fprintf(stderr, "MPHF for bucket %u out of %u was generated.\n", cur_bucket + 1, brz->k);
     472                 :             :                           }
     473                 :             :                         }
     474                 :           0 :                         switch(brz->algo)
     475                 :             :                         {
     476                 :           0 :                                 case CMPH_FCH:
     477                 :             :                                 {
     478                 :           0 :                                         fch_data_t * fchf = NULL;
     479                 :           0 :                                         fchf = (fch_data_t *)mphf_tmp->data;                 
     480                 :           0 :                                         bufmphf = brz_copy_partial_fch_mphf(brz, fchf, cur_bucket, &buflenmphf);
     481                 :             :                                 }
     482                 :           0 :                                         break;
     483                 :           0 :                                 case CMPH_BMZ8:
     484                 :             :                                 {
     485                 :           0 :                                         bmz8_data_t * bmzf = NULL;
     486                 :           0 :                                         bmzf = (bmz8_data_t *)mphf_tmp->data;
     487                 :           0 :                                         bufmphf = brz_copy_partial_bmz8_mphf(brz, bmzf, cur_bucket,  &buflenmphf);
     488                 :             :                                 }
     489                 :           0 :                                         break;
     490                 :           0 :                                 default: assert(0);
     491                 :             :                         }
     492                 :           0 :                         nbytes = fwrite(bufmphf, (size_t)buflenmphf, (size_t)1, brz->mphf_fd);
     493                 :           0 :                         free(bufmphf);
     494                 :           0 :                         bufmphf = NULL;
     495                 :           0 :                         cmph_config_destroy(config);
     496                 :           0 :                         brz_destroy_keys_vd(keys_vd, nkeys_vd);
     497                 :           0 :                         cmph_destroy(mphf_tmp);
     498                 :           0 :                         cmph_io_byte_vector_adapter_destroy(source);
     499                 :           0 :                         nkeys_vd = 0;
     500                 :             :                 }
     501                 :             :         }
     502                 :           0 :         buffer_manager_destroy(buff_manager);
     503                 :           0 :         free(keys_vd);
     504                 :           0 :         free(buffer_merge);
     505                 :           0 :         free(buffer_h0);
     506                 :           0 :         if (error) return 0;
     507                 :           0 :         return 1;
     508                 :             : }
     509                 :             : 
     510                 :           0 : static cmph_uint32 brz_min_index(cmph_uint32 * vector, cmph_uint32 n)
     511                 :             : {
     512                 :           0 :         cmph_uint32 i, min_index = 0;
     513                 :           0 :         for(i = 1; i < n; i++)
     514                 :             :         {
     515                 :           0 :                 if(vector[i] < vector[min_index]) min_index = i;
     516                 :             :         }
     517                 :           0 :         return min_index;
     518                 :             : }
     519                 :             : 
     520                 :           0 : static void brz_destroy_keys_vd(cmph_uint8 ** keys_vd, cmph_uint32 nkeys)
     521                 :             : {
     522                 :             :         cmph_uint8 i;
     523                 :           0 :         for(i = 0; i < nkeys; i++) { free(keys_vd[i]); keys_vd[i] = NULL;}
     524                 :           0 : }
     525                 :             : 
     526                 :           0 : static char * brz_copy_partial_fch_mphf(brz_config_data_t *brz, fch_data_t * fchf, cmph_uint32 index,  cmph_uint32 *buflen)
     527                 :             : {
     528                 :           0 :         cmph_uint32 i = 0;
     529                 :           0 :         cmph_uint32 buflenh1 = 0;
     530                 :           0 :         cmph_uint32 buflenh2 = 0; 
     531                 :           0 :         char * bufh1 = NULL;
     532                 :           0 :         char * bufh2 = NULL;
     533                 :           0 :         char * buf   = NULL;
     534                 :           0 :         cmph_uint32 n  = fchf->b;//brz->size[index];
     535                 :           0 :         hash_state_dump(fchf->h1, &bufh1, &buflenh1);
     536                 :           0 :         hash_state_dump(fchf->h2, &bufh2, &buflenh2);
     537                 :           0 :         *buflen = buflenh1 + buflenh2 + n + 2U * (cmph_uint32)sizeof(cmph_uint32);
     538                 :           0 :         buf = (char *)malloc((size_t)(*buflen));
     539                 :           0 :         memcpy(buf, &buflenh1, sizeof(cmph_uint32));
     540                 :           0 :         memcpy(buf+sizeof(cmph_uint32), bufh1, (size_t)buflenh1);
     541                 :           0 :         memcpy(buf+sizeof(cmph_uint32)+buflenh1, &buflenh2, sizeof(cmph_uint32));
     542                 :           0 :         memcpy(buf+2*sizeof(cmph_uint32)+buflenh1, bufh2, (size_t)buflenh2);    
     543                 :           0 :         for (i = 0; i < n; i++) memcpy(buf+2*sizeof(cmph_uint32)+buflenh1+buflenh2+i,(fchf->g + i), (size_t)1);
     544                 :           0 :         free(bufh1);
     545                 :           0 :         free(bufh2);
     546                 :           0 :         return buf;
     547                 :             : }
     548                 :           0 : static char * brz_copy_partial_bmz8_mphf(brz_config_data_t *brz, bmz8_data_t * bmzf, cmph_uint32 index,  cmph_uint32 *buflen)
     549                 :             : {
     550                 :           0 :         cmph_uint32 buflenh1 = 0;
     551                 :           0 :         cmph_uint32 buflenh2 = 0; 
     552                 :           0 :         char * bufh1 = NULL;
     553                 :           0 :         char * bufh2 = NULL;
     554                 :           0 :         char * buf   = NULL;
     555                 :           0 :         cmph_uint32 n = (cmph_uint32)ceil(brz->c * brz->size[index]);
     556                 :           0 :         hash_state_dump(bmzf->hashes[0], &bufh1, &buflenh1);
     557                 :           0 :         hash_state_dump(bmzf->hashes[1], &bufh2, &buflenh2);
     558                 :           0 :         *buflen = buflenh1 + buflenh2 + n + 2U * (cmph_uint32)sizeof(cmph_uint32);
     559                 :           0 :         buf = (char *)malloc((size_t)(*buflen));
     560                 :           0 :         memcpy(buf, &buflenh1, sizeof(cmph_uint32));
     561                 :           0 :         memcpy(buf+sizeof(cmph_uint32), bufh1, (size_t)buflenh1);
     562                 :           0 :         memcpy(buf+sizeof(cmph_uint32)+buflenh1, &buflenh2, sizeof(cmph_uint32));
     563                 :           0 :         memcpy(buf+2*sizeof(cmph_uint32)+buflenh1, bufh2, (size_t)buflenh2);
     564                 :           0 :         memcpy(buf+2*sizeof(cmph_uint32)+buflenh1+buflenh2,bmzf->g, (size_t)n);
     565                 :           0 :         free(bufh1);
     566                 :           0 :         free(bufh2);
     567                 :           0 :         return buf;
     568                 :             : }
     569                 :             : 
     570                 :             : 
     571                 :           0 : int brz_dump(cmph_t *mphf, FILE *fd)
     572                 :             : {
     573                 :           0 :         brz_data_t *data = (brz_data_t *)mphf->data;
     574                 :           0 :         char *buf = NULL;
     575                 :             :         cmph_uint32 buflen;
     576                 :             :         register size_t nbytes;
     577                 :             :         DEBUGP("Dumping brzf\n");
     578                 :             :         // The initial part of the MPHF have already been dumped to disk during construction
     579                 :             :         // Dumping h0
     580                 :           0 :         hash_state_dump(data->h0, &buf, &buflen);
     581                 :             :         DEBUGP("Dumping hash state with %u bytes to disk\n", buflen);
     582                 :           0 :         nbytes = fwrite(&buflen, sizeof(cmph_uint32), (size_t)1, fd);
     583                 :           0 :         nbytes = fwrite(buf, (size_t)buflen, (size_t)1, fd);
     584                 :           0 :         free(buf);
     585                 :             :         // Dumping m and the vector offset.
     586                 :           0 :         nbytes = fwrite(&(data->m), sizeof(cmph_uint32), (size_t)1, fd); 
     587                 :           0 :         nbytes = fwrite(data->offset, sizeof(cmph_uint32)*(data->k), (size_t)1, fd);
     588                 :           0 :         if (nbytes == 0 && ferror(fd)) {
     589                 :           0 :           fprintf(stderr, "ERROR: %s\n", strerror(errno));
     590                 :           0 :           return 0;
     591                 :             :         }
     592                 :           0 :         return 1;
     593                 :             : }
     594                 :             : 
     595                 :           0 : void brz_load(FILE *f, cmph_t *mphf)
     596                 :             : {
     597                 :           0 :         char *buf = NULL;
     598                 :             :         cmph_uint32 buflen;
     599                 :             :         register size_t nbytes;
     600                 :             :         cmph_uint32 i, n;
     601                 :           0 :         brz_data_t *brz = (brz_data_t *)malloc(sizeof(brz_data_t));
     602                 :             : 
     603                 :             :         DEBUGP("Loading brz mphf\n");
     604                 :           0 :         mphf->data = brz;
     605                 :           0 :         nbytes = fread(&(brz->c), sizeof(double), (size_t)1, f);
     606                 :           0 :         nbytes = fread(&(brz->algo), sizeof(brz->algo), (size_t)1, f); // Reading algo.
     607                 :           0 :         nbytes = fread(&(brz->k), sizeof(cmph_uint32), (size_t)1, f);
     608                 :           0 :         brz->size   = (cmph_uint8 *) malloc(sizeof(cmph_uint8)*brz->k);
     609                 :           0 :         nbytes = fread(brz->size, sizeof(cmph_uint8)*(brz->k), (size_t)1, f);     
     610                 :           0 :         brz->h1 = (hash_state_t **)malloc(sizeof(hash_state_t *)*brz->k);
     611                 :           0 :         brz->h2 = (hash_state_t **)malloc(sizeof(hash_state_t *)*brz->k);
     612                 :           0 :         brz->g  = (cmph_uint8 **)  calloc((size_t)brz->k, sizeof(cmph_uint8 *));
     613                 :             :         DEBUGP("Reading c = %f   k = %u   algo = %u \n", brz->c, brz->k, brz->algo);
     614                 :             :         //loading h_i1, h_i2 and g_i.
     615                 :           0 :         for(i = 0; i < brz->k; i++)
     616                 :             :         {
     617                 :             :                 // h1
     618                 :           0 :                 nbytes = fread(&buflen, sizeof(cmph_uint32), (size_t)1, f);
     619                 :             :                 DEBUGP("Hash state 1 has %u bytes\n", buflen);
     620                 :           0 :                 buf = (char *)malloc((size_t)buflen);
     621                 :           0 :                 nbytes = fread(buf, (size_t)buflen, (size_t)1, f);
     622                 :           0 :                 brz->h1[i] = hash_state_load(buf, buflen);
     623                 :           0 :                 free(buf);
     624                 :             :                 //h2
     625                 :           0 :                 nbytes = fread(&buflen, sizeof(cmph_uint32), (size_t)1, f);
     626                 :             :                 DEBUGP("Hash state 2 has %u bytes\n", buflen);
     627                 :           0 :                 buf = (char *)malloc((size_t)buflen);
     628                 :           0 :                 nbytes = fread(buf, (size_t)buflen, (size_t)1, f);
     629                 :           0 :                 brz->h2[i] = hash_state_load(buf, buflen);
     630                 :           0 :                 free(buf);
     631                 :           0 :                 switch(brz->algo)
     632                 :             :                 {
     633                 :           0 :                         case CMPH_FCH:
     634                 :           0 :                                 n = fch_calc_b(brz->c, brz->size[i]);
     635                 :           0 :                                 break;
     636                 :           0 :                         case CMPH_BMZ8:
     637                 :           0 :                                 n = (cmph_uint32)ceil(brz->c * brz->size[i]);
     638                 :           0 :                                 break;
     639                 :           0 :                         default: assert(0);
     640                 :             :                 }
     641                 :             :                 DEBUGP("g_i has %u bytes\n", n);
     642                 :           0 :                 brz->g[i] = (cmph_uint8 *)calloc((size_t)n, sizeof(cmph_uint8));
     643                 :           0 :                 nbytes = fread(brz->g[i], sizeof(cmph_uint8)*n, (size_t)1, f);
     644                 :             :         }
     645                 :             :         //loading h0
     646                 :           0 :         nbytes = fread(&buflen, sizeof(cmph_uint32), (size_t)1, f);
     647                 :             :         DEBUGP("Hash state has %u bytes\n", buflen);
     648                 :           0 :         buf = (char *)malloc((size_t)buflen);
     649                 :           0 :         nbytes = fread(buf, (size_t)buflen, (size_t)1, f);
     650                 :           0 :         brz->h0 = hash_state_load(buf, buflen);
     651                 :           0 :         free(buf);
     652                 :             : 
     653                 :             :         //loading c, m, and the vector offset.  
     654                 :           0 :         nbytes = fread(&(brz->m), sizeof(cmph_uint32), (size_t)1, f);
     655                 :           0 :         brz->offset = (cmph_uint32 *)malloc(sizeof(cmph_uint32)*brz->k);
     656                 :           0 :         nbytes = fread(brz->offset, sizeof(cmph_uint32)*(brz->k), (size_t)1, f);
     657                 :           0 :         if (nbytes == 0 && ferror(f)) {
     658                 :           0 :           fprintf(stderr, "ERROR: %s\n", strerror(errno));
     659                 :             :         }
     660                 :             : 
     661                 :           0 :         return;
     662                 :             : }
     663                 :             : 
     664                 :           0 : static cmph_uint32 brz_bmz8_search(brz_data_t *brz, const char *key, cmph_uint32 keylen, cmph_uint32 * fingerprint)
     665                 :             : {
     666                 :             :         register cmph_uint32 h0;
     667                 :             :         register cmph_uint32 m, n, h1, h2;
     668                 :             :         register cmph_uint8 mphf_bucket;
     669                 :             : 
     670                 :           0 :         hash_vector(brz->h0, key, keylen, fingerprint);
     671                 :           0 :         h0 = fingerprint[2] % brz->k;
     672                 :             : 
     673                 :           0 :         m = brz->size[h0];
     674                 :           0 :         n = (cmph_uint32)ceil(brz->c * m);
     675                 :           0 :         h1 = hash(brz->h1[h0], key, keylen) % n;
     676                 :           0 :         h2 = hash(brz->h2[h0], key, keylen) % n;
     677                 :             :         
     678                 :           0 :         if (h1 == h2 && ++h2 >= n) h2 = 0;
     679                 :           0 :         mphf_bucket = (cmph_uint8)(brz->g[h0][h1] + brz->g[h0][h2]); 
     680                 :             :         DEBUGP("key: %s h1: %u h2: %u h0: %u\n", key, h1, h2, h0);
     681                 :             :         DEBUGP("key: %s g[h1]: %u g[h2]: %u offset[h0]: %u edges: %u\n", key, brz->g[h0][h1], brz->g[h0][h2], brz->offset[h0], brz->m);
     682                 :             :         DEBUGP("Address: %u\n", mphf_bucket + brz->offset[h0]);
     683                 :           0 :         return (mphf_bucket + brz->offset[h0]);
     684                 :             : }
     685                 :             : 
     686                 :           0 : static cmph_uint32 brz_fch_search(brz_data_t *brz, const char *key, cmph_uint32 keylen, cmph_uint32 * fingerprint)
     687                 :             : {
     688                 :             :         register cmph_uint32 h0;
     689                 :             :         register cmph_uint32 m, b, h1, h2;
     690                 :             :         register double p1, p2;
     691                 :             :         register cmph_uint8 mphf_bucket;
     692                 :             : 
     693                 :           0 :         hash_vector(brz->h0, key, keylen, fingerprint);
     694                 :           0 :         h0 = fingerprint[2] % brz->k;
     695                 :             : 
     696                 :           0 :         m = brz->size[h0];
     697                 :           0 :         b = fch_calc_b(brz->c, m);
     698                 :           0 :         p1 = fch_calc_p1(m);
     699                 :           0 :         p2 = fch_calc_p2(b);
     700                 :           0 :         h1 = hash(brz->h1[h0], key, keylen) % m;
     701                 :           0 :         h2 = hash(brz->h2[h0], key, keylen) % m;
     702                 :           0 :         mphf_bucket = 0;
     703                 :           0 :         h1 = mixh10h11h12(b, p1, p2, h1);
     704                 :           0 :         mphf_bucket = (cmph_uint8)((h2 + brz->g[h0][h1]) % m);
     705                 :           0 :         return (mphf_bucket + brz->offset[h0]);
     706                 :             : }
     707                 :             : 
     708                 :           0 : cmph_uint32 brz_search(cmph_t *mphf, const char *key, cmph_uint32 keylen)
     709                 :             : {
     710                 :           0 :         brz_data_t *brz = mphf->data;
     711                 :             :         cmph_uint32 fingerprint[3];
     712                 :           0 :         switch(brz->algo)
     713                 :             :         {
     714                 :           0 :                 case CMPH_FCH:
     715                 :           0 :                         return brz_fch_search(brz, key, keylen, fingerprint);
     716                 :           0 :                 case CMPH_BMZ8:
     717                 :           0 :                         return brz_bmz8_search(brz, key, keylen, fingerprint);
     718                 :           0 :                 default: assert(0);
     719                 :             :         }
     720                 :             :         return 0;
     721                 :             : }
     722                 :           0 : void brz_destroy(cmph_t *mphf)
     723                 :             : {
     724                 :             :         cmph_uint32 i;
     725                 :           0 :         brz_data_t *data = (brz_data_t *)mphf->data;
     726                 :           0 :         if(data->g)
     727                 :             :         {
     728                 :           0 :                 for(i = 0; i < data->k; i++)
     729                 :             :                 {
     730                 :           0 :                         free(data->g[i]);
     731                 :           0 :                         hash_state_destroy(data->h1[i]);
     732                 :           0 :                         hash_state_destroy(data->h2[i]);
     733                 :             :                 }
     734                 :           0 :                 free(data->g);
     735                 :           0 :                 free(data->h1);
     736                 :           0 :                 free(data->h2);
     737                 :             :         }
     738                 :           0 :         hash_state_destroy(data->h0);
     739                 :           0 :         free(data->size);
     740                 :           0 :         free(data->offset);
     741                 :           0 :         free(data);
     742                 :           0 :         free(mphf);
     743                 :           0 : }
     744                 :             : 
     745                 :             : /** \fn void brz_pack(cmph_t *mphf, void *packed_mphf);
     746                 :             :  *  \brief Support the ability to pack a perfect hash function into a preallocated contiguous memory space pointed by packed_mphf.
     747                 :             :  *  \param mphf pointer to the resulting mphf
     748                 :             :  *  \param packed_mphf pointer to the contiguous memory area used to store the resulting mphf. The size of packed_mphf must be at least cmph_packed_size() 
     749                 :             :  */
     750                 :           0 : void brz_pack(cmph_t *mphf, void *packed_mphf)
     751                 :             : {
     752                 :           0 :         brz_data_t *data = (brz_data_t *)mphf->data;
     753                 :           0 :         cmph_uint8 * ptr = packed_mphf;
     754                 :             :         cmph_uint32 i,n;
     755                 :             :         CMPH_HASH h0_type, h1_type, h2_type;
     756                 :             :         uintptr_t *g_is_ptr;
     757                 :             :         cmph_uint8 * g_i;
     758                 :             :         
     759                 :             :         // packing internal algo type
     760                 :           0 :         memcpy(ptr, &(data->algo), sizeof(data->algo));
     761                 :           0 :         ptr += sizeof(data->algo);
     762                 :             : 
     763                 :             :         // packing h0 type
     764                 :           0 :         h0_type = hash_get_type(data->h0);
     765                 :           0 :         memcpy(ptr, &h0_type, sizeof(h0_type));
     766                 :           0 :         ptr += sizeof(h0_type);
     767                 :             : 
     768                 :             :         // packing h0
     769                 :           0 :         hash_state_pack(data->h0, ptr);
     770                 :           0 :         ptr += hash_state_packed_size(h0_type);
     771                 :             :         
     772                 :             :         // packing k
     773                 :           0 :         memcpy(ptr, &(data->k), sizeof(data->k));
     774                 :           0 :         ptr += sizeof(data->k);
     775                 :             : 
     776                 :             :         // packing c
     777                 :           0 :         *((cmph_uint64 *)ptr) = (cmph_uint64)data->c; 
     778                 :           0 :         ptr += sizeof(data->c);
     779                 :             : 
     780                 :             :         // packing h1 type
     781                 :           0 :         h1_type = hash_get_type(data->h1[0]);
     782                 :           0 :         memcpy(ptr, &h1_type, sizeof(h1_type));
     783                 :           0 :         ptr += sizeof(h1_type);
     784                 :             : 
     785                 :             :         // packing h2 type
     786                 :           0 :         h2_type = hash_get_type(data->h2[0]);
     787                 :           0 :         memcpy(ptr, &h2_type, sizeof(h2_type));
     788                 :           0 :         ptr += sizeof(h2_type);
     789                 :             : 
     790                 :             :         // packing size
     791                 :           0 :         memcpy(ptr, data->size, sizeof(cmph_uint8)*data->k);      
     792                 :           0 :         ptr += data->k;
     793                 :             :         
     794                 :             :         // packing offset
     795                 :           0 :         memcpy(ptr, data->offset, sizeof(cmph_uint32)*data->k);   
     796                 :           0 :         ptr += sizeof(cmph_uint32)*data->k;
     797                 :             :         
     798                 :           0 :         g_is_ptr = (uintptr_t *)ptr;
     799                 :             : 
     800                 :           0 :         g_i = (cmph_uint8 *) (g_is_ptr + data->k);
     801                 :             :         
     802                 :           0 :         for(i = 0; i < data->k; i++)
     803                 :             :         {
     804                 :           0 :                 *g_is_ptr++ = (uintptr_t)g_i;
     805                 :             :                 // packing h1[i]
     806                 :           0 :                 hash_state_pack(data->h1[i], g_i);
     807                 :           0 :                 g_i += hash_state_packed_size(h1_type);
     808                 :             :                 
     809                 :             :                 // packing h2[i]
     810                 :           0 :                 hash_state_pack(data->h2[i], g_i);
     811                 :           0 :                 g_i += hash_state_packed_size(h2_type);
     812                 :             : 
     813                 :             :                 // packing g_i
     814                 :           0 :                 switch(data->algo)
     815                 :             :                 {
     816                 :           0 :                         case CMPH_FCH:
     817                 :           0 :                                 n = fch_calc_b(data->c, data->size[i]);
     818                 :           0 :                                 break;
     819                 :           0 :                         case CMPH_BMZ8:
     820                 :           0 :                                 n = (cmph_uint32)ceil(data->c * data->size[i]);
     821                 :           0 :                                 break;
     822                 :           0 :                         default: assert(0);
     823                 :             :                 }
     824                 :           0 :                 memcpy(g_i, data->g[i], sizeof(cmph_uint8)*n);       
     825                 :           0 :                 g_i += n;
     826                 :             :                 
     827                 :             :         }
     828                 :             : 
     829                 :           0 : }
     830                 :             : 
     831                 :             : /** \fn cmph_uint32 brz_packed_size(cmph_t *mphf);
     832                 :             :  *  \brief Return the amount of space needed to pack mphf.
     833                 :             :  *  \param mphf pointer to a mphf
     834                 :             :  *  \return the size of the packed function or zero for failures
     835                 :             :  */ 
     836                 :           0 : cmph_uint32 brz_packed_size(cmph_t *mphf)
     837                 :             : {
     838                 :             :         cmph_uint32 i;
     839                 :           0 :         cmph_uint32 size = 0;
     840                 :           0 :         brz_data_t *data = (brz_data_t *)mphf->data;
     841                 :           0 :         CMPH_HASH h0_type = hash_get_type(data->h0); 
     842                 :           0 :         CMPH_HASH h1_type = hash_get_type(data->h1[0]); 
     843                 :           0 :         CMPH_HASH h2_type = hash_get_type(data->h2[0]);
     844                 :             :         cmph_uint32 n;
     845                 :           0 :         size = (cmph_uint32)(2*sizeof(CMPH_ALGO) + 3*sizeof(CMPH_HASH) + hash_state_packed_size(h0_type) + sizeof(cmph_uint32) + 
     846                 :           0 :                         sizeof(double) + sizeof(cmph_uint8)*data->k + sizeof(cmph_uint32)*data->k);
     847                 :             :         // pointers to g_is
     848                 :           0 :         size +=  (cmph_uint32) sizeof(uintptr_t) * data->k;
     849                 :           0 :         size += hash_state_packed_size(h1_type) * data->k;
     850                 :           0 :         size += hash_state_packed_size(h2_type) * data->k;
     851                 :             :         
     852                 :           0 :         n = 0;
     853                 :           0 :         for(i = 0; i < data->k; i++)
     854                 :             :         {
     855                 :           0 :                 switch(data->algo)
     856                 :             :                 {
     857                 :           0 :                         case CMPH_FCH:
     858                 :           0 :                                 n = fch_calc_b(data->c, data->size[i]);
     859                 :           0 :                                 break;
     860                 :           0 :                         case CMPH_BMZ8:
     861                 :           0 :                                 n = (cmph_uint32)ceil(data->c * data->size[i]);
     862                 :           0 :                                 break;
     863                 :           0 :                         default: assert(0);
     864                 :             :                 }
     865                 :           0 :                 size += n;      
     866                 :             :         }
     867                 :           0 :         return size;
     868                 :             : }
     869                 :             : 
     870                 :             : 
     871                 :             : 
     872                 :           0 : static cmph_uint32 brz_bmz8_search_packed(cmph_uint32 *packed_mphf, const char *key, cmph_uint32 keylen, cmph_uint32 * fingerprint)
     873                 :             : {
     874                 :           0 :         register CMPH_HASH h0_type = *packed_mphf++;
     875                 :           0 :         register cmph_uint32 *h0_ptr = packed_mphf;
     876                 :             :         register cmph_uint32 k, h0, m, n, h1, h2;
     877                 :             :         register cmph_uint32 *offset;
     878                 :             :         register double c;
     879                 :             :         register CMPH_HASH h1_type, h2_type;
     880                 :             :         register cmph_uint8 * size;
     881                 :             :         register uintptr_t *g_is_ptr;
     882                 :             :         register cmph_uint8 *h1_ptr, *h2_ptr, *g;
     883                 :             :         register cmph_uint8 mphf_bucket;
     884                 :             : 
     885                 :           0 :         packed_mphf = (cmph_uint32 *)(((cmph_uint8 *)packed_mphf) + hash_state_packed_size(h0_type)); 
     886                 :             :         
     887                 :           0 :         k = *packed_mphf++;
     888                 :             : 
     889                 :           0 :         c = (double)(*((cmph_uint64*)packed_mphf));
     890                 :           0 :         packed_mphf += 2;
     891                 :             : 
     892                 :           0 :         h1_type = *packed_mphf++;
     893                 :             :         
     894                 :           0 :         h2_type = *packed_mphf++;
     895                 :             : 
     896                 :           0 :         size = (cmph_uint8 *) packed_mphf;
     897                 :           0 :         packed_mphf = (cmph_uint32 *)(size + k);  
     898                 :             :         
     899                 :           0 :         offset = packed_mphf;
     900                 :           0 :         packed_mphf += k;
     901                 :             : 
     902                 :             :         
     903                 :           0 :         hash_vector_packed(h0_ptr, h0_type, key, keylen, fingerprint);
     904                 :           0 :         h0 = fingerprint[2] % k;
     905                 :             :         
     906                 :           0 :         m = size[h0];
     907                 :           0 :         n = (cmph_uint32)ceil(c * m);
     908                 :             : 
     909                 :           0 :         g_is_ptr = (uintptr_t *)packed_mphf;
     910                 :             : 
     911                 :           0 :         h1_ptr = (cmph_uint8 *) g_is_ptr[h0];
     912                 :             :         
     913                 :           0 :         h2_ptr = h1_ptr + hash_state_packed_size(h1_type);
     914                 :             : 
     915                 :           0 :         g = h2_ptr + hash_state_packed_size(h2_type);
     916                 :             :         
     917                 :           0 :         h1 = hash_packed(h1_ptr, h1_type, key, keylen) % n;
     918                 :           0 :         h2 = hash_packed(h2_ptr, h2_type, key, keylen) % n;
     919                 :             :                 
     920                 :           0 :         if (h1 == h2 && ++h2 >= n) h2 = 0;
     921                 :           0 :         mphf_bucket = (cmph_uint8)(g[h1] + g[h2]); 
     922                 :             :         DEBUGP("key: %s h1: %u h2: %u h0: %u\n", key, h1, h2, h0);
     923                 :             :         DEBUGP("Address: %u\n", mphf_bucket + offset[h0]);
     924                 :           0 :         return (mphf_bucket + offset[h0]);      
     925                 :             : }
     926                 :             : 
     927                 :           0 : static cmph_uint32 brz_fch_search_packed(cmph_uint32 *packed_mphf, const char *key, cmph_uint32 keylen, cmph_uint32 * fingerprint)
     928                 :             : {
     929                 :           0 :         register CMPH_HASH h0_type = *packed_mphf++;
     930                 :             :         
     931                 :           0 :         register cmph_uint32 *h0_ptr = packed_mphf;
     932                 :             :         register cmph_uint32 k, h0, m, b, h1, h2;
     933                 :             :         register double c, p1, p2;
     934                 :             :         register CMPH_HASH h1_type, h2_type;
     935                 :             :         register cmph_uint8 *size, *h1_ptr, *h2_ptr, *g;
     936                 :             :         register cmph_uint32 *offset;
     937                 :             :         register uintptr_t *g_is_ptr;
     938                 :             :         register cmph_uint8 mphf_bucket;
     939                 :             : 
     940                 :           0 :         packed_mphf = (cmph_uint32 *)(((cmph_uint8 *)packed_mphf) + hash_state_packed_size(h0_type)); 
     941                 :             :         
     942                 :           0 :         k = *packed_mphf++;
     943                 :             : 
     944                 :           0 :         c = (double)(*((cmph_uint64*)packed_mphf));
     945                 :           0 :         packed_mphf += 2;
     946                 :             : 
     947                 :           0 :         h1_type = *packed_mphf++;
     948                 :             : 
     949                 :           0 :         h2_type = *packed_mphf++;
     950                 :             : 
     951                 :           0 :         size = (cmph_uint8 *) packed_mphf;
     952                 :           0 :         packed_mphf = (cmph_uint32 *)(size + k);  
     953                 :             :         
     954                 :           0 :         offset = packed_mphf;
     955                 :           0 :         packed_mphf += k;
     956                 :             :         
     957                 :           0 :         hash_vector_packed(h0_ptr, h0_type, key, keylen, fingerprint);
     958                 :           0 :         h0 = fingerprint[2] % k;
     959                 :             :         
     960                 :           0 :         m = size[h0];
     961                 :           0 :         b = fch_calc_b(c, m);
     962                 :           0 :         p1 = fch_calc_p1(m);
     963                 :           0 :         p2 = fch_calc_p2(b);
     964                 :             :         
     965                 :           0 :         g_is_ptr = (uintptr_t *)packed_mphf;
     966                 :             : 
     967                 :           0 :         h1_ptr = (cmph_uint8 *) g_is_ptr[h0];
     968                 :             :         
     969                 :           0 :         h2_ptr = h1_ptr + hash_state_packed_size(h1_type);
     970                 :             : 
     971                 :           0 :         g = h2_ptr + hash_state_packed_size(h2_type);
     972                 :             :         
     973                 :           0 :         h1 = hash_packed(h1_ptr, h1_type, key, keylen) % m;
     974                 :           0 :         h2 = hash_packed(h2_ptr, h2_type, key, keylen) % m;
     975                 :             : 
     976                 :           0 :         mphf_bucket = 0;
     977                 :           0 :         h1 = mixh10h11h12(b, p1, p2, h1);
     978                 :           0 :         mphf_bucket = (cmph_uint8)((h2 + g[h1]) % m);
     979                 :           0 :         return (mphf_bucket + offset[h0]);
     980                 :             : }
     981                 :             : 
     982                 :             : /** cmph_uint32 brz_search(void *packed_mphf, const char *key, cmph_uint32 keylen);
     983                 :             :  *  \brief Use the packed mphf to do a search. 
     984                 :             :  *  \param  packed_mphf pointer to the packed mphf
     985                 :             :  *  \param key key to be hashed
     986                 :             :  *  \param keylen key length in bytes
     987                 :             :  *  \return The mphf value
     988                 :             :  */
     989                 :           0 : cmph_uint32 brz_search_packed(void *packed_mphf, const char *key, cmph_uint32 keylen)
     990                 :             : {
     991                 :           0 :         register cmph_uint32 *ptr = (cmph_uint32 *)packed_mphf; 
     992                 :           0 :         register CMPH_ALGO algo = *ptr++;
     993                 :             :         cmph_uint32 fingerprint[3];
     994                 :           0 :         switch(algo)
     995                 :             :         {
     996                 :           0 :                 case CMPH_FCH:
     997                 :           0 :                         return brz_fch_search_packed(ptr, key, keylen, fingerprint);
     998                 :           0 :                 case CMPH_BMZ8:
     999                 :           0 :                         return brz_bmz8_search_packed(ptr, key, keylen, fingerprint);
    1000                 :           0 :                 default:
    1001                 :           0 :                         assert(0);
    1002                 :             :                         return 0; /* To avoid warnings that value must be returned */
    1003                 :             :         }
    1004                 :             : }
    1005                 :             : 
        

Generated by: LCOV version 2.0-1