LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_namespace.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 60 72 83.3 %
Date: 2024-11-12 21:42:17 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : /*
      14             :  * (author) M.L. Kersten
      15             :  */
      16             : #include "monetdb_config.h"
      17             : #include "mal_type.h"
      18             : #include "mal_namespace.h"
      19             : #include "mal_exception.h"
      20             : #include "mal_private.h"
      21             : 
      22             : #define MAXIDENTIFIERS 4096
      23             : #define HASHMASK  4095
      24             : 
      25             : MT_Lock mal_namespaceLock = MT_LOCK_INITIALIZER(mal_namespaceLock);
      26             : 
      27             : /* taken from gdk_atoms */
      28             : __attribute__((__pure__))
      29             : static inline size_t
      30    96319837 : nme_hash(const char *key, size_t len)
      31             : {
      32    96319837 :         size_t y = 0;
      33             : 
      34   820834694 :         for (size_t i = 0; i < len && key[i]; i++) {
      35   724514857 :                 y += key[i];
      36   724514857 :                 y += (y << 10);
      37   724514857 :                 y ^= (y >> 6);
      38             :         }
      39    96319837 :         y += (y << 3);
      40    96319837 :         y ^= (y >> 11);
      41    96319837 :         y += (y << 15);
      42    96319837 :         return y & HASHMASK;
      43             : }
      44             : 
      45             : typedef struct NAME {
      46             :         struct NAME *next;
      47             :         char nme[IDLENGTH + 1];
      48             :         unsigned short length;
      49             : } *NamePtr;
      50             : 
      51             : static NamePtr hash[MAXIDENTIFIERS];
      52             : const char *optimizerRef;
      53             : const char *totalRef;
      54             : 
      55             : static struct namespace {
      56             :         struct namespace *next;
      57             :         int count;
      58             :         struct NAME data[4096];
      59             : } namespace1, *namespace = &namespace1;
      60             : 
      61             : void
      62         331 : initNamespace(void)
      63             : {
      64         331 :         optimizerRef = putName("optimizer");
      65         331 :         totalRef = putName("total");
      66         331 : }
      67             : 
      68             : void
      69         329 : mal_namespace_reset(void)
      70             : {
      71         329 :         struct namespace *ns;
      72             : 
      73             :         /* assume we are at the end of the server session */
      74         329 :         MT_lock_set(&mal_namespaceLock);
      75         329 :         memset(hash, 0, sizeof(hash));
      76         658 :         while (namespace) {
      77         329 :                 ns = namespace->next;
      78         329 :                 if (namespace != &namespace1)
      79           0 :                         GDKfree(namespace);
      80         329 :                 namespace = ns;
      81             :         }
      82         329 :         namespace1.count = 0;
      83         329 :         namespace1.next = NULL;
      84         329 :         namespace = &namespace1;
      85         329 :         MT_lock_unset(&mal_namespaceLock);
      86         329 : }
      87             : 
      88             : /*
      89             :  * Before a name is being stored we should check for its occurrence first.
      90             :  * The administration is initialized incrementally.
      91             :  * Beware, the routine getName relies on data structure maintenance that
      92             :  * is conflict free.
      93             :  */
      94             : 
      95             : static const char *
      96    96320088 : findName(const char *nme, size_t len, bool allocate)
      97             : {
      98    96320088 :         NamePtr *n, m;
      99    96320088 :         size_t key;
     100             : 
     101    96320088 :         assert(len == 0 || nme != NULL);
     102    96320088 :         if (len == 0 || nme == NULL)
     103             :                 return NULL;
     104    96320088 :         if (len > IDLENGTH) {
     105             :                 len = IDLENGTH;
     106             :         }
     107    96320088 :         key = nme_hash(nme, len);
     108    96320088 :         MT_lock_set(&mal_namespaceLock);
     109   102193100 :         for (n = &hash[key]; *n; n = &(*n)->next) {
     110   101861685 :                 if (len == (*n)->length && strncmp(nme, (*n)->nme, len) == 0) {
     111    95997175 :                         MT_lock_unset(&mal_namespaceLock);
     112    95996474 :                         return (*n)->nme;
     113             :                 }
     114             :         }
     115             :         /* item not found */
     116      331415 :         if (!allocate) {
     117           0 :                 MT_lock_unset(&mal_namespaceLock);
     118           0 :                 return NULL;
     119             :         }
     120      331415 :         if (namespace == NULL || namespace->count == 4096) {
     121           0 :                 struct namespace *ns = GDKmalloc(sizeof(struct namespace));
     122           0 :                 if (ns == NULL) {
     123           0 :                         MT_lock_unset(&mal_namespaceLock);
     124           0 :                         return NULL;
     125             :                 }
     126           0 :                 ns->next = namespace;
     127           0 :                 ns->count = 0;
     128           0 :                 namespace = ns;
     129             :         }
     130      331415 :         m = &namespace->data[namespace->count++];
     131      331415 :         if (m->nme != nme)
     132      324775 :                 strncpy(m->nme, nme, len);
     133      331415 :         m->nme[len] = 0;
     134      331415 :         m->length = (unsigned short) len;
     135      331415 :         m->next = *n;
     136      331415 :         *n = m;
     137      331415 :         MT_lock_unset(&mal_namespaceLock);
     138      331415 :         return m->nme;
     139             : }
     140             : 
     141             : const char *
     142    36446007 : getName(const char *nme)
     143             : {
     144    36446007 :         if (nme != NULL)
     145    35321686 :                 nme = findName(nme, strlen(nme), false);
     146    36447442 :         return nme;
     147             : }
     148             : 
     149             : const char *
     150           0 : getNameLen(const char *nme, size_t len)
     151             : {
     152           0 :         return findName(nme, len, false);
     153             : }
     154             : 
     155             : const char *
     156    60984077 : putName(const char *nme)
     157             : {
     158    60984077 :         if (nme != NULL)
     159    60984077 :                 nme = findName(nme, strlen(nme), true);
     160    60986138 :         return nme;
     161             : }
     162             : 
     163             : const char *
     164       18236 : putNameLen(const char *nme, size_t len)
     165             : {
     166       18236 :         return findName(nme, len, true);
     167             : }

Generated by: LCOV version 1.14