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-04-26 00:35:57 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    95115588 :                 nme_hash(const char *key, size_t len)
      30             : {
      31    95115588 :         size_t y = 0;
      32             : 
      33   823175389 :         for (size_t i = 0; i < len && key[i]; i++) {
      34   728059801 :                 y += key[i];
      35   728059801 :                 y += (y << 10);
      36   728059801 :                 y ^= (y >> 6);
      37             :         }
      38    95115588 :         y += (y << 3);
      39    95115588 :         y ^= (y >> 11);
      40    95115588 :         y += (y << 15);
      41    95115588 :         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         341 : initNamespace(void)
      62             : {
      63         341 :         optimizerRef = putName("optimizer");
      64         341 :         totalRef = putName("total");
      65         341 : }
      66             : 
      67             : void
      68         339 : mal_namespace_reset(void)
      69             : {
      70         339 :         struct namespace *ns;
      71             : 
      72             :         /* assume we are at the end of the server session */
      73         339 :         MT_lock_set(&mal_namespaceLock);
      74         339 :         memset(hash, 0, sizeof(hash));
      75         678 :         while (namespace) {
      76         339 :                 ns = namespace->next;
      77         339 :                 if (namespace != &namespace1)
      78           0 :                         GDKfree(namespace);
      79         339 :                 namespace = ns;
      80             :         }
      81         339 :         namespace1.count = 0;
      82         339 :         namespace1.next = NULL;
      83         339 :         namespace = &namespace1;
      84         339 :         MT_lock_unset(&mal_namespaceLock);
      85         339 : }
      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    95113527 : findName(const char *nme, size_t len, bool allocate)
      96             : {
      97    95113527 :         NamePtr *n, m;
      98    95113527 :         size_t key;
      99             : 
     100    95113527 :         assert(len == 0 || nme != NULL);
     101    95113527 :         if (len == 0 || nme == NULL)
     102             :                 return NULL;
     103    95113527 :         if (len > IDLENGTH) {
     104             :                 len = IDLENGTH;
     105             :         }
     106    95113527 :         key = nme_hash(nme, len);
     107    95113527 :         MT_lock_set(&mal_namespaceLock);
     108   100852638 :         for (n = &hash[key]; *n; n = &(*n)->next) {
     109   100511924 :                 if (len == (*n)->length && strncmp(nme, (*n)->nme, len) == 0) {
     110    94857869 :                         MT_lock_unset(&mal_namespaceLock);
     111    94841632 :                         return (*n)->nme;
     112             :                 }
     113             :         }
     114             :         /* item not found */
     115      340714 :         if (!allocate) {
     116           0 :                 MT_lock_unset(&mal_namespaceLock);
     117           0 :                 return NULL;
     118             :         }
     119      340714 :         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      340714 :         m = &namespace->data[namespace->count++];
     130      340714 :         if (m->nme != nme)
     131      334084 :                 strncpy(m->nme, nme, len);
     132      340714 :         m->nme[len] = 0;
     133      340714 :         m->length = (unsigned short) len;
     134      340714 :         m->next = *n;
     135      340714 :         *n = m;
     136      340714 :         MT_lock_unset(&mal_namespaceLock);
     137      340714 :         return m->nme;
     138             : }
     139             : 
     140             : const char *
     141    37383039 : getName(const char *nme)
     142             : {
     143    37383039 :         if (nme != NULL)
     144    36227978 :                 nme = findName(nme, strlen(nme), false);
     145    37391247 :         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    58903649 : putName(const char *nme)
     156             : {
     157    58903649 :         if (nme != NULL)
     158    58903649 :                 nme = findName(nme, strlen(nme), true);
     159    58934650 :         return nme;
     160             : }
     161             : 
     162             : const char *
     163       18205 : putNameLen(const char *nme, size_t len)
     164             : {
     165       18205 :         return findName(nme, len, true);
     166             : }

Generated by: LCOV version 1.14