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 98090983 : nme_hash(const char *key, size_t len) 30 : { 31 98090983 : size_t y = 0; 32 : 33 850241754 : for (size_t i = 0; i < len && key[i]; i++) { 34 752150771 : y += key[i]; 35 752150771 : y += (y << 10); 36 752150771 : y ^= (y >> 6); 37 : } 38 98090983 : y += (y << 3); 39 98090983 : y ^= (y >> 11); 40 98090983 : y += (y << 15); 41 98090983 : 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 98089420 : findName(const char *nme, size_t len, bool allocate) 96 : { 97 98089420 : NamePtr *n, m; 98 98089420 : size_t key; 99 : 100 98089420 : assert(len == 0 || nme != NULL); 101 98089420 : if (len == 0 || nme == NULL) 102 : return NULL; 103 98089420 : if (len > IDLENGTH) { 104 : len = IDLENGTH; 105 : } 106 98089420 : key = nme_hash(nme, len); 107 98089420 : MT_lock_set(&mal_namespaceLock); 108 104003600 : for (n = &hash[key]; *n; n = &(*n)->next) { 109 103673205 : if (len == (*n)->length && strncmp(nme, (*n)->nme, len) == 0) { 110 97834084 : MT_lock_unset(&mal_namespaceLock); 111 97827199 : return (*n)->nme; 112 : } 113 : } 114 : /* item not found */ 115 330395 : if (!allocate) { 116 0 : MT_lock_unset(&mal_namespaceLock); 117 0 : return NULL; 118 : } 119 330395 : 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 330395 : m = &namespace->data[namespace->count++]; 130 330395 : if (m->nme != nme) 131 323755 : strncpy(m->nme, nme, len); 132 330395 : m->nme[len] = 0; 133 330395 : m->length = (unsigned short) len; 134 330395 : m->next = *n; 135 330395 : *n = m; 136 330395 : MT_lock_unset(&mal_namespaceLock); 137 330395 : return m->nme; 138 : } 139 : 140 : const char * 141 38695315 : getName(const char *nme) 142 : { 143 38695315 : if (nme != NULL) 144 37414397 : nme = findName(nme, strlen(nme), false); 145 38703423 : 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 60688771 : putName(const char *nme) 156 : { 157 60688771 : if (nme != NULL) 158 60688771 : nme = findName(nme, strlen(nme), true); 159 60720009 : return nme; 160 : } 161 : 162 : const char * 163 18233 : putNameLen(const char *nme, size_t len) 164 : { 165 18233 : return findName(nme, len, true); 166 : }