LCOV - code coverage report
Current view: top level - subprojects/tinycdb-0.81 - cdb_make.c (source / functions) Coverage Total Hit
Test: 2 coverage DB files Lines: 79.0 % 105 83
Test Date: 2025-09-15 13:55:46 Functions: 100.0 % 7 7
Branches: 62.9 % 62 39

             Branch data     Line data    Source code
       1                 :             : /* cdb_make.c: basic cdb creation routines
       2                 :             :  *
       3                 :             :  * This file is a part of tinycdb package.
       4                 :             :  * Copyright (C) 2001-2023 Michael Tokarev <mjt+cdb@corpit.ru>
       5                 :             :  *
       6                 :             :  * Permission is hereby granted, free of charge, to any person obtaining a
       7                 :             :  * copy of this software and associated documentation files (the "Software"),
       8                 :             :  * to deal in the Software without restriction, including without limitation
       9                 :             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      10                 :             :  * and/or sell copies of the Software, and to permit persons to whom the
      11                 :             :  * Software is furnished to do so, subject to the following conditions:
      12                 :             :  *
      13                 :             :  * The above copyright notice and this permission notice shall be included
      14                 :             :  * in all copies or substantial portions of the Software.
      15                 :             :  *
      16                 :             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      17                 :             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      18                 :             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      19                 :             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      20                 :             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      21                 :             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      22                 :             :  * DEALINGS IN THE SOFTWARE.
      23                 :             :  */
      24                 :             : 
      25                 :             : #include <unistd.h>
      26                 :             : #include <stdlib.h>
      27                 :             : #include <string.h>
      28                 :             : #include "cdb_int.h"
      29                 :             : 
      30                 :             : int
      31                 :           9 : cdb_make_start(struct cdb_make *cdbmp, int fd)
      32                 :             : {
      33                 :           9 :   memset(cdbmp, 0, sizeof(*cdbmp));
      34                 :           9 :   cdbmp->cdb_fd = fd;
      35                 :           9 :   cdbmp->cdb_dpos = 2048;
      36                 :           9 :   cdbmp->cdb_bpos = cdbmp->cdb_buf + 2048;
      37                 :           9 :   return lseek(fd, 0, SEEK_SET);
      38                 :             : }
      39                 :             : 
      40                 :             : int internal_function
      41                 :          18 : _cdb_make_fullwrite(int fd, const unsigned char *buf, unsigned len)
      42                 :             : {
      43         [ +  + ]:          36 :   while(len) {
      44                 :          18 :     int l = write(fd, buf, len);
      45         [ +  - ]:          18 :     if (l > 0) {
      46                 :          18 :       len -= l;
      47                 :          18 :       buf += l;
      48                 :             :     }
      49   [ #  #  #  # ]:           0 :     else if (l < 0 && errno != EINTR)
      50                 :           0 :       return -1;
      51                 :             :   }
      52                 :          18 :   return 0;
      53                 :             : }
      54                 :             : 
      55                 :             : int internal_function
      56                 :           9 : _cdb_make_flush(struct cdb_make *cdbmp) {
      57                 :           9 :   unsigned len = cdbmp->cdb_bpos - cdbmp->cdb_buf;
      58         [ +  - ]:           9 :   if (len) {
      59         [ -  + ]:           9 :     if (_cdb_make_fullwrite(cdbmp->cdb_fd, cdbmp->cdb_buf, len) < 0)
      60                 :           0 :       return -1;
      61                 :           9 :     cdbmp->cdb_bpos = cdbmp->cdb_buf;
      62                 :             :   }
      63                 :           9 :   return 0;
      64                 :             : }
      65                 :             : 
      66                 :             : int internal_function
      67                 :          32 : _cdb_make_write(struct cdb_make *cdbmp, const unsigned char *ptr, unsigned len)
      68                 :             : {
      69                 :          32 :   unsigned l = sizeof(cdbmp->cdb_buf) - (cdbmp->cdb_bpos - cdbmp->cdb_buf);
      70                 :          32 :   cdbmp->cdb_dpos += len;
      71         [ -  + ]:          32 :   if (len > l) {
      72                 :           0 :     memcpy(cdbmp->cdb_bpos, ptr, l);
      73                 :           0 :     cdbmp->cdb_bpos += l;
      74         [ #  # ]:           0 :     if (_cdb_make_flush(cdbmp) < 0)
      75                 :           0 :       return -1;
      76                 :           0 :     ptr += l; len -= l;
      77                 :           0 :     l = len / sizeof(cdbmp->cdb_buf);
      78         [ #  # ]:           0 :     if (l) {
      79                 :           0 :       l *= sizeof(cdbmp->cdb_buf);
      80         [ #  # ]:           0 :       if (_cdb_make_fullwrite(cdbmp->cdb_fd, ptr, l) < 0)
      81                 :           0 :         return -1;
      82                 :           0 :       ptr += l; len -= l;
      83                 :             :     }
      84                 :             :   }
      85         [ +  + ]:          32 :   if (len) {
      86                 :          26 :     memcpy(cdbmp->cdb_bpos, ptr, len);
      87                 :          26 :     cdbmp->cdb_bpos += len;
      88                 :             :   }
      89                 :          32 :   return 0;
      90                 :             : }
      91                 :             : 
      92                 :             : static int
      93                 :           9 : cdb_make_finish_internal(struct cdb_make *cdbmp)
      94                 :             : {
      95                 :             :   unsigned hcnt[256];           /* hash table counts */
      96                 :             :   unsigned hpos[256];           /* hash table positions */
      97                 :             :   struct cdb_rec *htab;
      98                 :             :   unsigned char *p;
      99                 :             :   struct cdb_rl *rl;
     100                 :             :   unsigned hsize;
     101                 :             :   unsigned t, i;
     102                 :             : 
     103         [ -  + ]:           9 :   if (((0xffffffff - cdbmp->cdb_dpos) >> 3) < cdbmp->cdb_rcnt)
     104                 :           0 :     return errno = ENOMEM, -1;
     105                 :             : 
     106                 :             :   /* count htab sizes and reorder reclists */
     107                 :           9 :   hsize = 0;
     108         [ +  + ]:        2313 :   for (t = 0; t < 256; ++t) {
     109                 :        2304 :     struct cdb_rl *rlt = NULL;
     110                 :        2304 :     i = 0;
     111                 :        2304 :     rl = cdbmp->cdb_rec[t];
     112         [ +  + ]:        2312 :     while(rl) {
     113                 :           8 :       struct cdb_rl *rln = rl->next;
     114                 :           8 :       rl->next = rlt;
     115                 :           8 :       rlt = rl;
     116                 :           8 :       i += rl->cnt;
     117                 :           8 :       rl = rln;
     118                 :             :     }
     119                 :        2304 :     cdbmp->cdb_rec[t] = rlt;
     120         [ +  + ]:        2304 :     if (hsize < (hcnt[t] = i << 1))
     121                 :           6 :       hsize = hcnt[t];
     122                 :             :   }
     123                 :             : 
     124                 :             :   /* allocate memory to hold max htable */
     125                 :           9 :   htab = (struct cdb_rec*)malloc((hsize + 2) * sizeof(struct cdb_rec));
     126         [ -  + ]:           9 :   if (!htab)
     127                 :           0 :     return errno = ENOENT, -1;
     128                 :           9 :   p = (unsigned char *)htab;
     129                 :           9 :   htab += 2;
     130                 :             : 
     131                 :             :   /* build hash tables */
     132         [ +  + ]:        2313 :   for (t = 0; t < 256; ++t) {
     133                 :             :     unsigned len, hi;
     134                 :        2304 :     hpos[t] = cdbmp->cdb_dpos;
     135         [ +  + ]:        2304 :     if ((len = hcnt[t]) == 0)
     136                 :        2296 :       continue;
     137         [ +  + ]:          24 :     for (i = 0; i < len; ++i)
     138                 :          16 :       htab[i].hval = htab[i].rpos = 0;
     139         [ +  + ]:          16 :     for (rl = cdbmp->cdb_rec[t]; rl; rl = rl->next)
     140         [ +  + ]:          16 :       for (i = 0; i < rl->cnt; ++i) {
     141                 :           8 :        hi = (rl->rec[i].hval >> 8) % len;
     142         [ -  + ]:          16 :         while(htab[hi].rpos)
     143         [ #  # ]:           0 :           if (++hi == len)
     144                 :           0 :             hi = 0;
     145                 :           8 :         htab[hi] = rl->rec[i];
     146                 :             :       }
     147         [ +  + ]:          24 :     for (i = 0; i < len; ++i) {
     148                 :          16 :       cdb_pack(htab[i].hval, p + (i << 3));
     149                 :          16 :       cdb_pack(htab[i].rpos, p + (i << 3) + 4);
     150                 :             :     }
     151         [ -  + ]:           8 :     if (_cdb_make_write(cdbmp, p, len << 3) < 0) {
     152                 :           0 :       free(p);
     153                 :           0 :       return -1;
     154                 :             :     }
     155                 :             :   }
     156                 :           9 :   free(p);
     157         [ -  + ]:           9 :   if (_cdb_make_flush(cdbmp) < 0)
     158                 :           0 :     return -1;
     159                 :           9 :   p = cdbmp->cdb_buf;
     160         [ +  + ]:        2313 :   for (t = 0; t < 256; ++t) {
     161                 :        2304 :     cdb_pack(hpos[t], p + (t << 3));
     162                 :        2304 :     cdb_pack(hcnt[t], p + (t << 3) + 4);
     163                 :             :   }
     164   [ +  -  -  + ]:          18 :   if (lseek(cdbmp->cdb_fd, 0, SEEK_SET) != 0 ||
     165                 :           9 :       _cdb_make_fullwrite(cdbmp->cdb_fd, p, 2048) != 0)
     166                 :           0 :     return -1;
     167                 :             : 
     168                 :           9 :   return fsync(cdbmp->cdb_fd);
     169                 :             : }
     170                 :             : 
     171                 :             : static void
     172                 :           9 : cdb_make_free(struct cdb_make *cdbmp)
     173                 :             : {
     174                 :             :   unsigned t;
     175         [ +  + ]:        2313 :   for(t = 0; t < 256; ++t) {
     176                 :        2304 :     struct cdb_rl *rl = cdbmp->cdb_rec[t];
     177         [ +  + ]:        2312 :     while(rl) {
     178                 :           8 :       struct cdb_rl *tm = rl;
     179                 :           8 :       rl = rl->next;
     180                 :           8 :       free(tm);
     181                 :             :     }
     182                 :             :   }
     183                 :           9 : }
     184                 :             : 
     185                 :             : int
     186                 :           9 : cdb_make_finish(struct cdb_make *cdbmp)
     187                 :             : {
     188                 :           9 :   int r = cdb_make_finish_internal(cdbmp);
     189                 :           9 :   cdb_make_free(cdbmp);
     190                 :           9 :   return r;
     191                 :             : }
     192                 :             : 
        

Generated by: LCOV version 2.0-1