1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "ipc.h"
22 #include "log.h"
23
24 #include "zbxalgo.h"
25 #include "memalloc.h"
26
27 #include "strpool.h"
28
29 extern char *CONFIG_FILE;
30
31 static zbx_strpool_t strpool;
32
33 static zbx_hash_t __strpool_hash_func(const void *data);
34 static int __strpool_compare_func(const void *d1, const void *d2);
35
36 ZBX_MEM_FUNC_DECL(__strpool);
37
38 #define INIT_HASHSET_SIZE 100
39 #define REFCOUNT_FIELD_SIZE sizeof(zbx_uint32_t)
40
41 /* private strpool functions */
42
__strpool_hash_func(const void * data)43 static zbx_hash_t __strpool_hash_func(const void *data)
44 {
45 return ZBX_DEFAULT_STRING_HASH_FUNC((char *)data + REFCOUNT_FIELD_SIZE);
46 }
47
__strpool_compare_func(const void * d1,const void * d2)48 static int __strpool_compare_func(const void *d1, const void *d2)
49 {
50 return strcmp((char *)d1 + REFCOUNT_FIELD_SIZE, (char *)d2 + REFCOUNT_FIELD_SIZE);
51 }
52
53 ZBX_MEM_FUNC_IMPL(__strpool, strpool.mem_info);
54
55 /* public strpool interface */
56
zbx_strpool_create(size_t size)57 void zbx_strpool_create(size_t size)
58 {
59 const char *__function_name = "zbx_strpool_create";
60
61 key_t shm_key;
62
63 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
64
65 if (-1 == (shm_key = zbx_ftok(CONFIG_FILE, ZBX_IPC_STRPOOL_ID)))
66 {
67 zabbix_log(LOG_LEVEL_CRIT, "cannot create IPC key for string pool");
68 exit(EXIT_FAILURE);
69 }
70
71 zbx_mem_create(&strpool.mem_info, shm_key, ZBX_NO_MUTEX, size, "string pool", "CacheSize", 0);
72
73 strpool.hashset = __strpool_mem_malloc_func(NULL, sizeof(zbx_hashset_t));
74 zbx_hashset_create_ext(strpool.hashset, INIT_HASHSET_SIZE,
75 __strpool_hash_func, __strpool_compare_func, NULL,
76 __strpool_mem_malloc_func, __strpool_mem_realloc_func, __strpool_mem_free_func);
77
78 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
79 }
80
zbx_strpool_destroy()81 void zbx_strpool_destroy()
82 {
83 const char *__function_name = "zbx_strpool_destroy";
84
85 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
86
87 zbx_mem_destroy(strpool.mem_info);
88
89 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
90 }
91
zbx_strpool_intern(const char * str)92 const char *zbx_strpool_intern(const char *str)
93 {
94 void *record;
95 zbx_uint32_t *refcount;
96
97 record = zbx_hashset_search(strpool.hashset, str - REFCOUNT_FIELD_SIZE);
98
99 if (NULL == record)
100 {
101 record = zbx_hashset_insert_ext(strpool.hashset, str - REFCOUNT_FIELD_SIZE,
102 REFCOUNT_FIELD_SIZE + strlen(str) + 1, REFCOUNT_FIELD_SIZE);
103 *(zbx_uint32_t *)record = 0;
104 }
105
106 refcount = (zbx_uint32_t *)record;
107 (*refcount)++;
108
109 return (char *)record + REFCOUNT_FIELD_SIZE;
110 }
111
zbx_strpool_acquire(const char * str)112 const char *zbx_strpool_acquire(const char *str)
113 {
114 zbx_uint32_t *refcount;
115
116 refcount = (zbx_uint32_t *)(str - REFCOUNT_FIELD_SIZE);
117 (*refcount)++;
118
119 return str;
120 }
121
zbx_strpool_release(const char * str)122 void zbx_strpool_release(const char *str)
123 {
124 zbx_uint32_t *refcount;
125
126 refcount = (zbx_uint32_t *)(str - REFCOUNT_FIELD_SIZE);
127 if (0 == --(*refcount))
128 zbx_hashset_remove(strpool.hashset, str - REFCOUNT_FIELD_SIZE);
129 }
130
zbx_strpool_clear()131 void zbx_strpool_clear()
132 {
133 const char *__function_name = "zbx_strpool_clear";
134
135 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
136
137 zbx_mem_clear(strpool.mem_info);
138
139 strpool.hashset = __strpool_mem_malloc_func(NULL, sizeof(zbx_hashset_t));
140 zbx_hashset_create_ext(strpool.hashset, INIT_HASHSET_SIZE,
141 __strpool_hash_func, __strpool_compare_func, NULL,
142 __strpool_mem_malloc_func, __strpool_mem_realloc_func, __strpool_mem_free_func);
143
144 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
145 }
146
zbx_strpool_info()147 const zbx_strpool_t *zbx_strpool_info()
148 {
149 return &strpool;
150 }
151