blob: 2c3d351f0c7d7f69bb35af6302934d528e2e65b0 [file] [log] [blame]
Dave Barach8a7fb0c2016-07-08 14:44:23 -04001/*
Ed Warnickecb9cada2015-12-08 15:45:58 -07002 *------------------------------------------------------------------
3 * svmdb.c -- simple shared memory database
4 *
5 * Copyright (c) 2009 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <sys/types.h>
23#include <sys/mman.h>
24#include <sys/stat.h>
25#include <netinet/in.h>
26#include <signal.h>
27#include <pthread.h>
28#include <unistd.h>
29#include <time.h>
30#include <fcntl.h>
31#include <string.h>
32#include <vppinfra/clib.h>
33#include <vppinfra/vec.h>
34#include <vppinfra/hash.h>
35#include <vppinfra/bitmap.h>
36#include <vppinfra/fifo.h>
37#include <vppinfra/time.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070038#include <vppinfra/heap.h>
39#include <vppinfra/pool.h>
40#include <vppinfra/format.h>
Dave Barach23a74122016-11-24 16:34:20 -050041#include <vppinfra/serialize.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070042
43#include "svmdb.h"
44
Dave Barach8a7fb0c2016-07-08 14:44:23 -040045static void local_set_variable_nolock (svmdb_client_t * client,
46 svmdb_namespace_t namespace,
47 u8 * var, u8 * val, u32 elsize);
Ed Warnickecb9cada2015-12-08 15:45:58 -070048
Dave Barach8a7fb0c2016-07-08 14:44:23 -040049always_inline void
50region_lock (svm_region_t * rp, int tag)
Ed Warnickecb9cada2015-12-08 15:45:58 -070051{
Dave Barach8a7fb0c2016-07-08 14:44:23 -040052 pthread_mutex_lock (&rp->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -070053#ifdef MUTEX_DEBUG
Dave Barach8a7fb0c2016-07-08 14:44:23 -040054 rp->mutex_owner_pid = getpid ();
55 rp->mutex_owner_tag = tag;
56#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -070057}
58
Dave Barach8a7fb0c2016-07-08 14:44:23 -040059always_inline void
60region_unlock (svm_region_t * rp)
Ed Warnickecb9cada2015-12-08 15:45:58 -070061{
62#ifdef MUTEX_DEBUG
Dave Barach8a7fb0c2016-07-08 14:44:23 -040063 rp->mutex_owner_pid = 0;
64 rp->mutex_owner_tag = 0;
65#endif
66 pthread_mutex_unlock (&rp->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -070067}
68
Dave Barach98cfc1a2016-07-18 14:23:36 -040069svmdb_client_t *
70svmdb_map (svmdb_map_args_t * dba)
Ed Warnickecb9cada2015-12-08 15:45:58 -070071{
Dave Barach8a7fb0c2016-07-08 14:44:23 -040072 svmdb_client_t *client = 0;
73 svm_map_region_args_t *a = 0;
74 svm_region_t *db_rp;
75 void *oldheap;
76 svmdb_shm_hdr_t *hp = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070077
Dave Barach8a7fb0c2016-07-08 14:44:23 -040078 vec_validate (client, 0);
79 vec_validate (a, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -070080
Dave Barach98cfc1a2016-07-18 14:23:36 -040081 svm_region_init_chroot_uid_gid (dba->root_path, dba->uid, dba->gid);
Ed Warnickecb9cada2015-12-08 15:45:58 -070082
Dave Barach98cfc1a2016-07-18 14:23:36 -040083 a->root_path = dba->root_path;
Dave Barach8a7fb0c2016-07-08 14:44:23 -040084 a->name = "/db";
Dave Barach98cfc1a2016-07-18 14:23:36 -040085 a->size = dba->size ? dba->size : SVMDB_DEFAULT_SIZE;
Dave Barach8a7fb0c2016-07-08 14:44:23 -040086 a->flags = SVM_FLAGS_MHEAP;
Dave Barach98cfc1a2016-07-18 14:23:36 -040087 a->uid = dba->uid;
88 a->gid = dba->gid;
Ed Warnickecb9cada2015-12-08 15:45:58 -070089
Dave Barach8a7fb0c2016-07-08 14:44:23 -040090 db_rp = client->db_rp = svm_region_find_or_create (a);
Ed Warnickecb9cada2015-12-08 15:45:58 -070091
Dave Barach8a7fb0c2016-07-08 14:44:23 -040092 ASSERT (db_rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -070093
Dave Barach8a7fb0c2016-07-08 14:44:23 -040094 vec_free (a);
95
96 region_lock (client->db_rp, 10);
97 /* Has someone else set up the shared-memory variable table? */
98 if (db_rp->user_ctx)
99 {
100 client->shm = (void *) db_rp->user_ctx;
101 client->pid = getpid ();
102 region_unlock (client->db_rp);
103 ASSERT (client->shm->version == SVMDB_SHM_VERSION);
104 return (client);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400106 /* Nope, it's our problem... */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700107
Dave Wallaced756b352017-07-03 13:11:38 -0400108 if (CLIB_DEBUG > 2)
109 {
110 /* Add a bogus client (pid=0) so the svm won't be deallocated */
111 clib_warning
112 ("[%d] adding fake client (pid=0) so '%s' won't be unlinked",
113 getpid (), db_rp->region_name);
114 oldheap = svm_push_pvt_heap (db_rp);
115 vec_add1 (client->db_rp->client_pids, 0);
116 svm_pop_heap (oldheap);
117 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400118 oldheap = svm_push_data_heap (db_rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700119
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400120 vec_validate (hp, 0);
121 hp->version = SVMDB_SHM_VERSION;
122 hp->namespaces[SVMDB_NAMESPACE_STRING]
123 = hash_create_string (0, sizeof (uword));
124 hp->namespaces[SVMDB_NAMESPACE_VEC]
125 = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700126
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400127 db_rp->user_ctx = hp;
128 client->shm = hp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700129
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400130 svm_pop_heap (oldheap);
131 region_unlock (client->db_rp);
132 client->pid = getpid ();
133
134 return (client);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700135}
136
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400137void
138svmdb_unmap (svmdb_client_t * client)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700139{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400140 ASSERT (client);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700141
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400142 if (!svm_get_root_rp ())
143 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700144
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400145 svm_region_unmap ((void *) client->db_rp);
146 svm_region_exit ();
147 vec_free (client);
148}
149
150static void
151notify_value (svmdb_value_t * v, svmdb_action_t a)
152{
153 int i;
154 int rv;
155 union sigval sv;
156 u32 value;
157 u32 *dead_registrations = 0;
158
159 svmdb_notify_t *np;
160
161 for (i = 0; i < vec_len (v->notifications); i++)
162 {
163 np = vec_elt_at_index (v->notifications, i);
164 if (np->action == a)
165 {
166 value = (np->action << 28) | (np->opaque);
167 sv.sival_ptr = (void *) (uword) value;
168 do
169 {
170 rv = 0;
171 if (sigqueue (np->pid, np->signum, sv) == 0)
172 break;
173 rv = errno;
174 }
175 while (rv == EAGAIN);
176 if (rv == 0)
177 continue;
178 vec_add1 (dead_registrations, i);
179 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700180 }
181
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400182 for (i = 0; i < vec_len (dead_registrations); i++)
183 {
184 np = vec_elt_at_index (v->notifications, dead_registrations[i]);
185 clib_warning ("dead reg pid %d sig %d action %d opaque %x",
186 np->pid, np->signum, np->action, np->opaque);
187 vec_delete (v->notifications, 1, dead_registrations[i]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700188 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400189 vec_free (dead_registrations);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700190}
191
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400192int
193svmdb_local_add_del_notification (svmdb_client_t * client,
194 svmdb_notification_args_t * a)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700195{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400196 uword *h;
197 void *oldheap;
198 hash_pair_t *hp;
199 svmdb_shm_hdr_t *shm;
Dave Barach11fb09e2020-08-06 12:10:09 -0400200 u8 *placeholder_value = 0;
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400201 svmdb_value_t *value;
202 svmdb_notify_t *np;
203 int i;
204 int rv = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700205
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400206 ASSERT (a->elsize);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700207
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400208 region_lock (client->db_rp, 18);
209 shm = client->shm;
210 oldheap = svm_push_data_heap (client->db_rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700211
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400212 h = shm->namespaces[a->nspace];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700213
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400214 hp = hash_get_pair_mem (h, a->var);
215 if (hp == 0)
216 {
217 local_set_variable_nolock (client, a->nspace, (u8 *) a->var,
Dave Barach11fb09e2020-08-06 12:10:09 -0400218 placeholder_value, a->elsize);
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400219 /* might have moved */
220 h = shm->namespaces[a->nspace];
221 hp = hash_get_pair_mem (h, a->var);
222 ASSERT (hp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400224
225 value = pool_elt_at_index (shm->values, hp->value[0]);
226
227 for (i = 0; i < vec_len (value->notifications); i++)
228 {
229 np = vec_elt_at_index (value->notifications, i);
230 if ((np->pid == client->pid)
231 && (np->signum == a->signum)
232 && (np->action == a->action) && (np->opaque == a->opaque))
233 {
234 if (a->add_del == 0 /* delete */ )
235 {
236 vec_delete (value->notifications, 1, i);
237 goto out;
238 }
239 else
240 { /* add */
241 clib_warning
242 ("%s: ignore dup reg pid %d signum %d action %d opaque %x",
243 a->var, client->pid, a->signum, a->action, a->opaque);
244 rv = -2;
245 goto out;
246 }
247 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700248 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400249 if (a->add_del == 0)
250 {
251 rv = -3;
252 goto out;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700253 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400254
255 vec_add2 (value->notifications, np, 1);
256 np->pid = client->pid;
257 np->signum = a->signum;
258 np->action = a->action;
259 np->opaque = a->opaque;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700260
261out:
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400262 svm_pop_heap (oldheap);
263 region_unlock (client->db_rp);
264 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700265}
266
267
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400268static void
269local_unset_variable_nolock (svmdb_client_t * client,
270 svmdb_namespace_t namespace, char *var)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700271{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400272 uword *h;
273 svmdb_value_t *oldvalue;
274 hash_pair_t *hp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700275
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400276 h = client->shm->namespaces[namespace];
277 hp = hash_get_pair_mem (h, var);
278 if (hp)
279 {
280 oldvalue = pool_elt_at_index (client->shm->values, hp->value[0]);
281 if (vec_len (oldvalue->notifications))
282 notify_value (oldvalue, SVMDB_ACTION_UNSET);
283 /* zero length value means unset */
284 _vec_len (oldvalue->value) = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400286 client->shm->namespaces[namespace] = h;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700287}
288
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400289void
290svmdb_local_unset_string_variable (svmdb_client_t * client, char *var)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700291{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400292 void *oldheap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700293
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400294 region_lock (client->db_rp, 11);
295 oldheap = svm_push_data_heap (client->db_rp);
296 local_unset_variable_nolock (client, SVMDB_NAMESPACE_STRING, var);
297 svm_pop_heap (oldheap);
298 region_unlock (client->db_rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700299}
300
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400301static void
302local_set_variable_nolock (svmdb_client_t * client,
303 svmdb_namespace_t namespace,
304 u8 * var, u8 * val, u32 elsize)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700305{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400306 uword *h;
307 hash_pair_t *hp;
308 u8 *name;
309 svmdb_shm_hdr_t *shm;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700310
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400311 shm = client->shm;
312 h = shm->namespaces[namespace];
313 hp = hash_get_pair_mem (h, var);
314 if (hp)
315 {
316 svmdb_value_t *oldvalue;
317 oldvalue = pool_elt_at_index (client->shm->values, hp->value[0]);
318 vec_alloc (oldvalue->value, vec_len (val) * elsize);
319 clib_memcpy (oldvalue->value, val, vec_len (val) * elsize);
320 _vec_len (oldvalue->value) = vec_len (val);
321 notify_value (oldvalue, SVMDB_ACTION_SET);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700322 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400323 else
324 {
325 svmdb_value_t *newvalue;
326 pool_get (shm->values, newvalue);
Dave Barachb7b92992018-10-17 10:38:51 -0400327 clib_memset (newvalue, 0, sizeof (*newvalue));
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400328 newvalue->elsize = elsize;
329 vec_alloc (newvalue->value, vec_len (val) * elsize);
330 clib_memcpy (newvalue->value, val, vec_len (val) * elsize);
331 _vec_len (newvalue->value) = vec_len (val);
332 name = format (0, "%s%c", var, 0);
333 hash_set_mem (h, name, newvalue - shm->values);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700334 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400335 shm->namespaces[namespace] = h;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700336}
337
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400338void
339svmdb_local_set_string_variable (svmdb_client_t * client,
340 char *var, char *val)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700341{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400342 void *oldheap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700343
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400344 region_lock (client->db_rp, 12);
345 oldheap = svm_push_data_heap (client->db_rp);
346
347 local_unset_variable_nolock (client, SVMDB_NAMESPACE_STRING, var);
348
349 local_set_variable_nolock (client, SVMDB_NAMESPACE_STRING,
350 (u8 *) var, (u8 *) val, 1 /* elsize */ );
351 svm_pop_heap (oldheap);
352 region_unlock (client->db_rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700353}
354
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400355static u8 *
356local_get_variable_nolock (svmdb_client_t * client,
357 svmdb_namespace_t namespace, u8 * var)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700358{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400359 uword *h;
360 uword *p;
361 svmdb_shm_hdr_t *shm;
362 svmdb_value_t *oldvalue;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700363
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400364 shm = client->shm;
365 h = shm->namespaces[namespace];
366 p = hash_get_mem (h, var);
367 if (p)
368 {
369 oldvalue = pool_elt_at_index (shm->values, p[0]);
370 notify_value (oldvalue, SVMDB_ACTION_GET);
371 return (oldvalue->value);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700372 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400373 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700374}
375
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400376void *
377svmdb_local_get_variable_reference (svmdb_client_t * client,
378 svmdb_namespace_t namespace, char *var)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700379{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400380 u8 *rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700381
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400382 region_lock (client->db_rp, 19);
383 rv = local_get_variable_nolock (client, namespace, (u8 *) var);
384 region_unlock (client->db_rp);
385 return (void *) rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700386}
387
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400388char *
389svmdb_local_get_string_variable (svmdb_client_t * client, char *var)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400391 u8 *rv = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700392
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400393 region_lock (client->db_rp, 13);
394 rv = local_get_variable_nolock (client, SVMDB_NAMESPACE_STRING, (u8 *) var);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700395
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400396 if (rv && vec_len (rv))
397 {
398 rv = format (0, "%s", rv);
399 vec_add1 (rv, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700400 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400401 region_unlock (client->db_rp);
402 return ((char *) rv);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700403}
404
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400405void
406svmdb_local_dump_strings (svmdb_client_t * client)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700407{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400408 uword *h;
409 u8 *key;
410 u32 value;
411 svmdb_shm_hdr_t *shm = client->shm;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700412
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400413 region_lock (client->db_rp, 14);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400415 h = client->shm->namespaces[SVMDB_NAMESPACE_STRING];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700416
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400417 /* *INDENT-OFF* */
418 hash_foreach_mem(key, value, h,
419 ({
420 svmdb_value_t *v = pool_elt_at_index (shm->values, value);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700421
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400422 fformat(stdout, "%s: %s\n", key,
423 vec_len(v->value) ? v->value : (u8 *)"(nil)");
424 }));
425 /* *INDENT-ON* */
426 region_unlock (client->db_rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700427}
428
Dave Barach23a74122016-11-24 16:34:20 -0500429int
430svmdb_local_serialize_strings (svmdb_client_t * client, char *filename)
431{
432 uword *h;
433 u8 *key;
434 u32 value;
435 svmdb_shm_hdr_t *shm = client->shm;
436 serialize_main_t _sm, *sm = &_sm;
437 clib_error_t *error = 0;
438 u8 *sanitized_name = 0;
439 int fd = 0;
440
441 if (strstr (filename, "..") || index (filename, '/'))
442 {
443 error = clib_error_return (0, "Illegal characters in filename '%s'",
444 filename);
445 goto out;
446 }
447
448 sanitized_name = format (0, "/tmp/%s%c", filename, 0);
449
450 fd = creat ((char *) sanitized_name, 0644);
451
452 if (fd < 0)
453 {
454 error = clib_error_return_unix (0, "Create '%s'", sanitized_name);
455 goto out;
456 }
457
Dave Barach59b25652017-09-10 15:04:27 -0400458 serialize_open_clib_file_descriptor (sm, fd);
Dave Barach23a74122016-11-24 16:34:20 -0500459
460 region_lock (client->db_rp, 20);
461
462 h = client->shm->namespaces[SVMDB_NAMESPACE_STRING];
463
464 serialize_likely_small_unsigned_integer (sm, hash_elts (h));
465
466 /* *INDENT-OFF* */
467 hash_foreach_mem(key, value, h,
468 ({
469 svmdb_value_t *v = pool_elt_at_index (shm->values, value);
470
471 /* Omit names with nil values */
472 if (vec_len(v->value))
473 {
474 serialize_cstring (sm, (char *)key);
475 serialize_cstring (sm, (char *)v->value);
476 }
477 }));
478 /* *INDENT-ON* */
479 region_unlock (client->db_rp);
480
481 serialize_close (sm);
482
483out:
484 if (fd > 0 && close (fd) < 0)
485 error = clib_error_return_unix (0, "close fd %d", fd);
486
487 if (error)
488 {
489 clib_error_report (error);
490 return -1;
491 }
492 return 0;
493}
494
495int
496svmdb_local_unserialize_strings (svmdb_client_t * client, char *filename)
497{
498 serialize_main_t _sm, *sm = &_sm;
499 void *oldheap;
500 clib_error_t *error = 0;
501 u8 *key, *value;
502 int fd = 0;
503 u32 nelts;
504 int i;
505
506 fd = open (filename, O_RDONLY);
507
508 if (fd < 0)
509 {
510 error = clib_error_return_unix (0, "Failed to open '%s'", filename);
511 goto out;
512 }
513
Dave Barach59b25652017-09-10 15:04:27 -0400514 unserialize_open_clib_file_descriptor (sm, fd);
Dave Barach23a74122016-11-24 16:34:20 -0500515
516 region_lock (client->db_rp, 21);
517 oldheap = svm_push_data_heap (client->db_rp);
518
519 nelts = unserialize_likely_small_unsigned_integer (sm);
520
521 for (i = 0; i < nelts; i++)
522 {
523 unserialize_cstring (sm, (char **) &key);
524 unserialize_cstring (sm, (char **) &value);
525 local_set_variable_nolock (client, SVMDB_NAMESPACE_STRING,
526 key, value, 1 /* elsize */ );
527 vec_free (key);
528 vec_free (value);
529 }
530 svm_pop_heap (oldheap);
531 region_unlock (client->db_rp);
532
533 serialize_close (sm);
534
535out:
536 if (fd > 0 && close (fd) < 0)
537 error = clib_error_return_unix (0, "close fd %d", fd);
538
539 if (error)
540 {
541 clib_error_report (error);
542 return -1;
543 }
544 return 0;
545}
546
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400547void
548svmdb_local_unset_vec_variable (svmdb_client_t * client, char *var)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700549{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400550 void *oldheap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700551
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400552 region_lock (client->db_rp, 15);
553 oldheap = svm_push_data_heap (client->db_rp);
554 local_unset_variable_nolock (client, SVMDB_NAMESPACE_VEC, var);
555 svm_pop_heap (oldheap);
556 region_unlock (client->db_rp);
557}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700558
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400559void
560svmdb_local_set_vec_variable (svmdb_client_t * client,
561 char *var, void *val_arg, u32 elsize)
562{
563 u8 *val = (u8 *) val_arg;
564 void *oldheap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700565
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400566 region_lock (client->db_rp, 16);
567 oldheap = svm_push_data_heap (client->db_rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700568
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400569 local_unset_variable_nolock (client, SVMDB_NAMESPACE_VEC, var);
570 local_set_variable_nolock (client, SVMDB_NAMESPACE_VEC, (u8 *) var,
571 val, elsize);
572
573 svm_pop_heap (oldheap);
574 region_unlock (client->db_rp);
575}
576
577void *
578svmdb_local_get_vec_variable (svmdb_client_t * client, char *var, u32 elsize)
579{
580 u8 *rv = 0;
581 u8 *copy = 0;
582
583 region_lock (client->db_rp, 17);
584
585 rv = local_get_variable_nolock (client, SVMDB_NAMESPACE_VEC, (u8 *) var);
586
587 if (rv && vec_len (rv))
588 {
589 /* Make a copy in process-local memory */
590 vec_alloc (copy, vec_len (rv) * elsize);
591 clib_memcpy (copy, rv, vec_len (rv) * elsize);
592 _vec_len (copy) = vec_len (rv);
593 region_unlock (client->db_rp);
594 return (copy);
595 }
596 region_unlock (client->db_rp);
597 return (0);
598}
599
600void
601svmdb_local_dump_vecs (svmdb_client_t * client)
602{
603 uword *h;
604 u8 *key;
605 u32 value;
606 svmdb_shm_hdr_t *shm;
607
608 region_lock (client->db_rp, 17);
609 shm = client->shm;
610
611 h = client->shm->namespaces[SVMDB_NAMESPACE_VEC];
612
613 /* *INDENT-OFF* */
614 hash_foreach_mem(key, value, h,
615 ({
616 svmdb_value_t *v = pool_elt_at_index (shm->values, value);
617 (void) fformat(stdout, "%s:\n %U (%.2f)\n", key,
618 format_hex_bytes, v->value,
619 vec_len(v->value)*v->elsize, ((f64 *)(v->value))[0]);
620 }));
621 /* *INDENT-ON* */
622
623 region_unlock (client->db_rp);
624}
625
626void *
627svmdb_local_find_or_add_vec_variable (svmdb_client_t * client,
628 char *var, u32 nbytes)
629{
630 void *oldheap;
631 u8 *rv = 0;
632
633 region_lock (client->db_rp, 18);
634 oldheap = svm_push_data_heap (client->db_rp);
635
636 rv = local_get_variable_nolock (client, SVMDB_NAMESPACE_VEC, (u8 *) var);
637
638 if (rv)
639 {
640 goto out;
641 }
642 else
643 {
644 uword *h;
645 u8 *name;
646 svmdb_shm_hdr_t *shm;
647 svmdb_value_t *newvalue;
648
649 shm = client->shm;
650 h = shm->namespaces[SVMDB_NAMESPACE_VEC];
651
652 pool_get (shm->values, newvalue);
Dave Barachb7b92992018-10-17 10:38:51 -0400653 clib_memset (newvalue, 0, sizeof (*newvalue));
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400654 newvalue->elsize = 1;
655 vec_alloc (newvalue->value, nbytes);
656 _vec_len (newvalue->value) = nbytes;
657 name = format (0, "%s%c", var, 0);
658 hash_set_mem (h, name, newvalue - shm->values);
659 shm->namespaces[SVMDB_NAMESPACE_VEC] = h;
660 rv = newvalue->value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700661 }
662
663out:
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400664 svm_pop_heap (oldheap);
665 region_unlock (client->db_rp);
666 return (rv);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700667}
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400668
669/*
670 * fd.io coding-style-patch-verification: ON
671 *
672 * Local Variables:
673 * eval: (c-set-style "gnu")
674 * End:
675 */