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 86607298 : nme_hash(const char *key, size_t len) 31 : { 32 86607298 : size_t y = 0; 33 : 34 739779456 : for (size_t i = 0; i < len && key[i]; i++) { 35 653172158 : y += key[i]; 36 653172158 : y += (y << 10); 37 653172158 : y ^= (y >> 6); 38 : } 39 86607298 : y += (y << 3); 40 86607298 : y ^= (y >> 11); 41 86607298 : y += (y << 15); 42 86607298 : 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 315 : initNamespace(void) 63 : { 64 315 : optimizerRef = putName("optimizer"); 65 315 : totalRef = putName("total"); 66 315 : } 67 : 68 : void 69 297 : mal_namespace_reset(void) 70 : { 71 297 : struct namespace *ns; 72 : 73 : /* assume we are at the end of the server session */ 74 297 : MT_lock_set(&mal_namespaceLock); 75 297 : memset(hash, 0, sizeof(hash)); 76 594 : while (namespace) { 77 297 : ns = namespace->next; 78 297 : if (namespace != &namespace1) 79 0 : GDKfree(namespace); 80 297 : namespace = ns; 81 : } 82 297 : namespace1.count = 0; 83 297 : namespace1.next = NULL; 84 297 : namespace = &namespace1; 85 297 : MT_lock_unset(&mal_namespaceLock); 86 297 : } 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 86607515 : findName(const char *nme, size_t len, bool allocate) 97 : { 98 86607515 : NamePtr *n, m; 99 86607515 : size_t key; 100 : 101 86607515 : assert(len == 0 || nme != NULL); 102 86607515 : if (len == 0 || nme == NULL) 103 : return NULL; 104 86607515 : if (len > IDLENGTH) { 105 : len = IDLENGTH; 106 : } 107 86607515 : key = nme_hash(nme, len); 108 86607515 : MT_lock_set(&mal_namespaceLock); 109 91832695 : for (n = &hash[key]; *n; n = &(*n)->next) { 110 91517360 : if (len == (*n)->length && strncmp(nme, (*n)->nme, len) == 0) { 111 86300792 : MT_lock_unset(&mal_namespaceLock); 112 86300182 : return (*n)->nme; 113 : } 114 : } 115 : /* item not found */ 116 315335 : if (!allocate) { 117 0 : MT_lock_unset(&mal_namespaceLock); 118 0 : return NULL; 119 : } 120 315335 : 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 315335 : m = &namespace->data[namespace->count++]; 131 315335 : if (m->nme != nme) 132 308695 : strncpy(m->nme, nme, len); 133 315335 : m->nme[len] = 0; 134 315335 : m->length = (unsigned short) len; 135 315335 : m->next = *n; 136 315335 : *n = m; 137 315335 : MT_lock_unset(&mal_namespaceLock); 138 315335 : return m->nme; 139 : } 140 : 141 : const char * 142 32844910 : getName(const char *nme) 143 : { 144 32844910 : if (nme != NULL) 145 31758400 : nme = findName(nme, strlen(nme), false); 146 32846413 : 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 54834962 : putName(const char *nme) 157 : { 158 54834962 : if (nme != NULL) 159 54834962 : nme = findName(nme, strlen(nme), true); 160 54837004 : return nme; 161 : } 162 : 163 : const char * 164 18235 : putNameLen(const char *nme, size_t len) 165 : { 166 18235 : return findName(nme, len, true); 167 : }