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-10-04 20:04:04 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             : static inline size_t __attribute__((__pure__))
      29    96145433 :                 nme_hash(const char *key, size_t len)
      30             : {
      31    96145433 :         size_t y = 0;
      32             : 
      33   819179194 :         for (size_t i = 0; i < len && key[i]; i++) {
      34   723033761 :                 y += key[i];
      35   723033761 :                 y += (y << 10);
      36   723033761 :                 y ^= (y >> 6);
      37             :         }
      38    96145433 :         y += (y << 3);
      39    96145433 :         y ^= (y >> 11);
      40    96145433 :         y += (y << 15);
      41    96145433 :         return y & HASHMASK;
      42             : }
      43             : 
      44             : typedef struct NAME {
      45             :         struct NAME *next;
      46             :         char nme[IDLENGTH + 1];
      47             :         unsigned short length;
      48             : } *NamePtr;
      49             : 
      50             : static NamePtr hash[MAXIDENTIFIERS];
      51             : const char *optimizerRef;
      52             : const char *totalRef;
      53             : 
      54             : static struct namespace {
      55             :         struct namespace *next;
      56             :         int count;
      57             :         struct NAME data[4096];
      58             : } namespace1, *namespace = &namespace1;
      59             : 
      60             : void
      61         330 : initNamespace(void)
      62             : {
      63         330 :         optimizerRef = putName("optimizer");
      64         330 :         totalRef = putName("total");
      65         330 : }
      66             : 
      67             : void
      68         328 : mal_namespace_reset(void)
      69             : {
      70         328 :         struct namespace *ns;
      71             : 
      72             :         /* assume we are at the end of the server session */
      73         328 :         MT_lock_set(&mal_namespaceLock);
      74         328 :         memset(hash, 0, sizeof(hash));
      75         656 :         while (namespace) {
      76         328 :                 ns = namespace->next;
      77         328 :                 if (namespace != &namespace1)
      78           0 :                         GDKfree(namespace);
      79         328 :                 namespace = ns;
      80             :         }
      81         328 :         namespace1.count = 0;
      82         328 :         namespace1.next = NULL;
      83         328 :         namespace = &namespace1;
      84         328 :         MT_lock_unset(&mal_namespaceLock);
      85         328 : }
      86             : 
      87             : /*
      88             :  * Before a name is being stored we should check for its occurrence first.
      89             :  * The administration is initialized incrementally.
      90             :  * Beware, the routine getName relies on data structure maintenance that
      91             :  * is conflict free.
      92             :  */
      93             : 
      94             : static const char *
      95    96145750 : findName(const char *nme, size_t len, bool allocate)
      96             : {
      97    96145750 :         NamePtr *n, m;
      98    96145750 :         size_t key;
      99             : 
     100    96145750 :         assert(len == 0 || nme != NULL);
     101    96145750 :         if (len == 0 || nme == NULL)
     102             :                 return NULL;
     103    96145750 :         if (len > IDLENGTH) {
     104             :                 len = IDLENGTH;
     105             :         }
     106    96145750 :         key = nme_hash(nme, len);
     107    96145750 :         MT_lock_set(&mal_namespaceLock);
     108   102013444 :         for (n = &hash[key]; *n; n = &(*n)->next) {
     109   101683367 :                 if (len == (*n)->length && strncmp(nme, (*n)->nme, len) == 0) {
     110    95824681 :                         MT_lock_unset(&mal_namespaceLock);
     111    95823936 :                         return (*n)->nme;
     112             :                 }
     113             :         }
     114             :         /* item not found */
     115      330077 :         if (!allocate) {
     116           0 :                 MT_lock_unset(&mal_namespaceLock);
     117           0 :                 return NULL;
     118             :         }
     119      330077 :         if (namespace == NULL || namespace->count == 4096) {
     120           0 :                 struct namespace *ns = GDKmalloc(sizeof(struct namespace));
     121           0 :                 if (ns == NULL) {
     122           0 :                         MT_lock_unset(&mal_namespaceLock);
     123           0 :                         return NULL;
     124             :                 }
     125           0 :                 ns->next = namespace;
     126           0 :                 ns->count = 0;
     127           0 :                 namespace = ns;
     128             :         }
     129      330077 :         m = &namespace->data[namespace->count++];
     130      330077 :         if (m->nme != nme)
     131      323447 :                 strncpy(m->nme, nme, len);
     132      330077 :         m->nme[len] = 0;
     133      330077 :         m->length = (unsigned short) len;
     134      330077 :         m->next = *n;
     135      330077 :         *n = m;
     136      330077 :         MT_lock_unset(&mal_namespaceLock);
     137      330077 :         return m->nme;
     138             : }
     139             : 
     140             : const char *
     141    36364731 : getName(const char *nme)
     142             : {
     143    36364731 :         if (nme != NULL)
     144    35246933 :                 nme = findName(nme, strlen(nme), false);
     145    36366368 :         return nme;
     146             : }
     147             : 
     148             : const char *
     149           0 : getNameLen(const char *nme, size_t len)
     150             : {
     151           0 :         return findName(nme, len, false);
     152             : }
     153             : 
     154             : const char *
     155    60884786 : putName(const char *nme)
     156             : {
     157    60884786 :         if (nme != NULL)
     158    60884786 :                 nme = findName(nme, strlen(nme), true);
     159    60886644 :         return nme;
     160             : }
     161             : 
     162             : const char *
     163       18236 : putNameLen(const char *nme, size_t len)
     164             : {
     165       18236 :         return findName(nme, len, true);
     166             : }

Generated by: LCOV version 1.14