LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_namespace.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 44 50 88.0 %
Date: 2021-09-14 22:17:06 Functions: 6 8 75.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  * (author) M.L. Kersten
      11             :  */
      12             : #include "monetdb_config.h"
      13             : #include "mal_type.h"
      14             : #include "mal_namespace.h"
      15             : #include "mal_exception.h"
      16             : #include "mal_private.h"
      17             : 
      18             : #define MAXIDENTIFIERS 4096
      19             : #define HASHMASK  4095
      20             : 
      21             : MT_Lock mal_namespaceLock = MT_LOCK_INITIALIZER(mal_namespaceLock);
      22             : 
      23             : /* taken from gdk_atoms */
      24             : #define NME_HASH(_key,y,K)                                                              \
      25             :         do {                                                                                            \
      26             :                 size_t _i;                                                                              \
      27             :                 for (_i = y = 0; _i < K && _key[_i]; _i++) { \
      28             :                         y += _key[_i];                                                          \
      29             :                         y += (y << 10);                                                           \
      30             :                         y ^= (y >> 6);                                                            \
      31             :                 }                                                                                               \
      32             :                 y += (y << 3);                                                                    \
      33             :                 y ^= (y >> 11);                                                                   \
      34             :                 y += (y << 15);                                                                   \
      35             :                 y = y & HASHMASK;                                                           \
      36             :         } while (0)
      37             : 
      38             : typedef struct NAME{
      39             :         struct NAME *next;
      40             :         char nme[IDLENGTH + 1];
      41             :         unsigned short length;
      42             : } *NamePtr;
      43             : 
      44             : static NamePtr hash[MAXIDENTIFIERS];
      45             : 
      46             : static struct namespace {
      47             :         struct namespace *next;
      48             :         int count;
      49             :         struct NAME data[4096];
      50             : } *namespace;
      51             : 
      52         266 : void initNamespace(void) {
      53         266 :         namespace = NULL;
      54         266 : }
      55             : 
      56         264 : void mal_namespace_reset(void) {
      57             :         struct namespace *ns;
      58             : 
      59             :         /* assume we are at the end of the server session */
      60         264 :         MT_lock_set(&mal_namespaceLock);
      61         264 :         memset(hash, 0, sizeof(hash));
      62         528 :         while (namespace) {
      63         264 :                 ns = namespace->next;
      64         264 :                 GDKfree(namespace);
      65         264 :                 namespace = ns;
      66             :         }
      67         264 :         MT_lock_unset(&mal_namespaceLock);
      68         264 : }
      69             : 
      70             : /*
      71             :  * Before a name is being stored we should check for its occurrence first.
      72             :  * The administration is initialized incrementally.
      73             :  * Beware, the routine getName relies on data structure maintenance that
      74             :  * is conflict free.
      75             :  */
      76             : 
      77    31320906 : static const char *findName(const char *nme, size_t len, bool allocate)
      78             : {
      79             :         NamePtr *n, m;
      80             :         size_t key;
      81             : 
      82    31320906 :         assert(len == 0 || nme != NULL);
      83    31320906 :         if (len == 0 || nme == NULL)
      84             :                 return NULL;
      85             :         if (len > IDLENGTH) {
      86             :                 len = IDLENGTH;
      87             :         }
      88   210909234 :         NME_HASH(nme, key, len);
      89    31320906 :         MT_lock_set(&mal_namespaceLock);
      90    32051449 :         for (n = &hash[key]; *n; n = &(*n)->next) {
      91             : #ifdef KEEP_SORTED
      92             :                 /* keep each list sorted on length, then name */
      93             :                 if (len < (*n)->length)
      94             :                         continue;
      95             :                 if (len == (*n)->length) {
      96             :                         int c;
      97             :                         if ((c = strncmp(nme, (*n)->nme, len)) < 0)
      98             :                                 continue;
      99             :                         if (c == 0) {
     100             :                                 MT_lock_unset(&mal_namespaceLock);
     101             :                                 return (*n)->nme;
     102             :                         }
     103             :                         break;
     104             :                 }
     105             :                 break;
     106             : #else
     107             :                 /* append entries to list */
     108    31773248 :                 if (len == (*n)->length && strncmp(nme, (*n)->nme, len) == 0) {
     109    31042723 :                         MT_lock_unset(&mal_namespaceLock);
     110    31042723 :                         return (*n)->nme;
     111             :                 }
     112             : #endif
     113             :         }
     114             :         /* item not found */
     115      278201 :         if (!allocate) {
     116        1862 :                 MT_lock_unset(&mal_namespaceLock);
     117        1862 :                 return NULL;
     118             :         }
     119      276339 :         if (namespace == NULL || namespace->count == 4096) {
     120         266 :                 struct namespace *ns = GDKmalloc(sizeof(struct namespace));
     121         266 :                 if (ns == NULL) {
     122             :                         /* error we cannot recover from */
     123           0 :                         TRC_CRITICAL(MAL_SERVER, MAL_MALLOC_FAIL "\n");
     124           0 :                         mal_exit(1);
     125             :                 }
     126         266 :                 ns->next = namespace;
     127         266 :                 ns->count = 0;
     128         266 :                 namespace = ns;
     129             :         }
     130      276339 :         m = &namespace->data[namespace->count++];
     131      276339 :         strncpy(m->nme, nme, len);
     132      276339 :         m->nme[len] = 0;
     133      276339 :         m->length = (unsigned short) len;
     134      276339 :         m->next = *n;
     135      276339 :         *n = m;
     136      276339 :         MT_lock_unset(&mal_namespaceLock);
     137      276339 :         return (*n)->nme;
     138             : }
     139             : 
     140     2440128 : const char *getName(const char *nme) {
     141     2440128 :         return findName(nme, strlen(nme), false);
     142             : }
     143             : 
     144           0 : const char *getNameLen(const char *nme, size_t len)
     145             : {
     146           0 :         return findName(nme, len, false);
     147             : }
     148             : /*
     149             :  * Name deletion from the namespace is tricky, because there may
     150             :  * be multiple threads active on the structure. Moreover, the
     151             :  * symbol may be picked up by a concurrent thread and stored
     152             :  * somewhere.
     153             :  * To avoid all these problems, the namespace should become
     154             :  * private to each Client, but this would mean expensive look ups
     155             :  * deep into the kernel to access the context.
     156             :  */
     157           0 : void delName(const char *nme, size_t len){
     158             :         const char *n;
     159           0 :         n= getNameLen(nme,len);
     160             :         if( nme[0]==0 || n == 0) return ;
     161             :         /*Namespace garbage collection not available yet */
     162             : }
     163             : 
     164    28732120 : const char *putName(const char *nme) {
     165    28732120 :         return findName(nme, strlen(nme), true);
     166             : }
     167             : 
     168      148665 : const char *putNameLen(const char *nme, size_t len)
     169             : {
     170      148665 :         return findName(nme, len, true);
     171             : }

Generated by: LCOV version 1.14