diff options
Diffstat (limited to 'svm/svmdb.c')
-rw-r--r-- | svm/svmdb.c | 671 |
1 files changed, 0 insertions, 671 deletions
diff --git a/svm/svmdb.c b/svm/svmdb.c deleted file mode 100644 index 03dfe7c33d3..00000000000 --- a/svm/svmdb.c +++ /dev/null @@ -1,671 +0,0 @@ -/* - *------------------------------------------------------------------ - * svmdb.c -- simple shared memory database - * - * Copyright (c) 2009 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <netinet/in.h> -#include <signal.h> -#include <pthread.h> -#include <unistd.h> -#include <time.h> -#include <fcntl.h> -#include <string.h> -#include <vppinfra/clib.h> -#include <vppinfra/vec.h> -#include <vppinfra/hash.h> -#include <vppinfra/bitmap.h> -#include <vppinfra/fifo.h> -#include <vppinfra/time.h> -#include <vppinfra/mheap.h> -#include <vppinfra/heap.h> -#include <vppinfra/pool.h> -#include <vppinfra/format.h> -#include <vppinfra/serialize.h> - -#include "svmdb.h" - -static void local_set_variable_nolock (svmdb_client_t * client, - svmdb_namespace_t namespace, - u8 * var, u8 * val, u32 elsize); - -always_inline void -region_lock (svm_region_t * rp, int tag) -{ - pthread_mutex_lock (&rp->mutex); -#ifdef MUTEX_DEBUG - rp->mutex_owner_pid = getpid (); - rp->mutex_owner_tag = tag; -#endif -} - -always_inline void -region_unlock (svm_region_t * rp) -{ -#ifdef MUTEX_DEBUG - rp->mutex_owner_pid = 0; - rp->mutex_owner_tag = 0; -#endif - pthread_mutex_unlock (&rp->mutex); -} - -svmdb_client_t * -svmdb_map (svmdb_map_args_t * dba) -{ - svmdb_client_t *client = 0; - svm_map_region_args_t *a = 0; - svm_region_t *db_rp; - void *oldheap; - svmdb_shm_hdr_t *hp = 0; - - vec_validate (client, 0); - vec_validate (a, 0); - - svm_region_init_chroot_uid_gid (dba->root_path, dba->uid, dba->gid); - - a->root_path = dba->root_path; - a->name = "/db"; - a->size = dba->size ? dba->size : SVMDB_DEFAULT_SIZE; - a->flags = SVM_FLAGS_MHEAP; - a->uid = dba->uid; - a->gid = dba->gid; - - db_rp = client->db_rp = svm_region_find_or_create (a); - - ASSERT (db_rp); - - vec_free (a); - - region_lock (client->db_rp, 10); - /* Has someone else set up the shared-memory variable table? */ - if (db_rp->user_ctx) - { - client->shm = (void *) db_rp->user_ctx; - client->pid = getpid (); - region_unlock (client->db_rp); - ASSERT (client->shm->version == SVMDB_SHM_VERSION); - return (client); - } - /* Nope, it's our problem... */ - - /* Add a bogus client (pid=0) so the svm won't be deallocated */ - oldheap = svm_push_pvt_heap (db_rp); - vec_add1 (client->db_rp->client_pids, 0); - svm_pop_heap (oldheap); - - oldheap = svm_push_data_heap (db_rp); - - vec_validate (hp, 0); - hp->version = SVMDB_SHM_VERSION; - hp->namespaces[SVMDB_NAMESPACE_STRING] - = hash_create_string (0, sizeof (uword)); - hp->namespaces[SVMDB_NAMESPACE_VEC] - = hash_create_string (0, sizeof (uword)); - - db_rp->user_ctx = hp; - client->shm = hp; - - svm_pop_heap (oldheap); - region_unlock (client->db_rp); - client->pid = getpid (); - - return (client); -} - -void -svmdb_unmap (svmdb_client_t * client) -{ - ASSERT (client); - - if (!svm_get_root_rp ()) - return; - - svm_region_unmap ((void *) client->db_rp); - svm_region_exit (); - vec_free (client); -} - -static void -notify_value (svmdb_value_t * v, svmdb_action_t a) -{ - int i; - int rv; - union sigval sv; - u32 value; - u32 *dead_registrations = 0; - - svmdb_notify_t *np; - - for (i = 0; i < vec_len (v->notifications); i++) - { - np = vec_elt_at_index (v->notifications, i); - if (np->action == a) - { - value = (np->action << 28) | (np->opaque); - sv.sival_ptr = (void *) (uword) value; - do - { - rv = 0; - if (sigqueue (np->pid, np->signum, sv) == 0) - break; - rv = errno; - } - while (rv == EAGAIN); - if (rv == 0) - continue; - vec_add1 (dead_registrations, i); - } - } - - for (i = 0; i < vec_len (dead_registrations); i++) - { - np = vec_elt_at_index (v->notifications, dead_registrations[i]); - clib_warning ("dead reg pid %d sig %d action %d opaque %x", - np->pid, np->signum, np->action, np->opaque); - vec_delete (v->notifications, 1, dead_registrations[i]); - } - vec_free (dead_registrations); -} - -int -svmdb_local_add_del_notification (svmdb_client_t * client, - svmdb_notification_args_t * a) -{ - uword *h; - void *oldheap; - hash_pair_t *hp; - svmdb_shm_hdr_t *shm; - u8 *dummy_value = 0; - svmdb_value_t *value; - svmdb_notify_t *np; - int i; - int rv = 0; - - ASSERT (a->elsize); - - region_lock (client->db_rp, 18); - shm = client->shm; - oldheap = svm_push_data_heap (client->db_rp); - - h = shm->namespaces[a->nspace]; - - hp = hash_get_pair_mem (h, a->var); - if (hp == 0) - { - local_set_variable_nolock (client, a->nspace, (u8 *) a->var, - dummy_value, a->elsize); - /* might have moved */ - h = shm->namespaces[a->nspace]; - hp = hash_get_pair_mem (h, a->var); - ASSERT (hp); - } - - value = pool_elt_at_index (shm->values, hp->value[0]); - - for (i = 0; i < vec_len (value->notifications); i++) - { - np = vec_elt_at_index (value->notifications, i); - if ((np->pid == client->pid) - && (np->signum == a->signum) - && (np->action == a->action) && (np->opaque == a->opaque)) - { - if (a->add_del == 0 /* delete */ ) - { - vec_delete (value->notifications, 1, i); - goto out; - } - else - { /* add */ - clib_warning - ("%s: ignore dup reg pid %d signum %d action %d opaque %x", - a->var, client->pid, a->signum, a->action, a->opaque); - rv = -2; - goto out; - } - } - } - if (a->add_del == 0) - { - rv = -3; - goto out; - } - - vec_add2 (value->notifications, np, 1); - np->pid = client->pid; - np->signum = a->signum; - np->action = a->action; - np->opaque = a->opaque; - -out: - svm_pop_heap (oldheap); - region_unlock (client->db_rp); - return rv; -} - - -static void -local_unset_variable_nolock (svmdb_client_t * client, - svmdb_namespace_t namespace, char *var) -{ - uword *h; - svmdb_value_t *oldvalue; - hash_pair_t *hp; - - h = client->shm->namespaces[namespace]; - hp = hash_get_pair_mem (h, var); - if (hp) - { - oldvalue = pool_elt_at_index (client->shm->values, hp->value[0]); - if (vec_len (oldvalue->notifications)) - notify_value (oldvalue, SVMDB_ACTION_UNSET); - /* zero length value means unset */ - _vec_len (oldvalue->value) = 0; - } - client->shm->namespaces[namespace] = h; -} - -void -svmdb_local_unset_string_variable (svmdb_client_t * client, char *var) -{ - void *oldheap; - - region_lock (client->db_rp, 11); - oldheap = svm_push_data_heap (client->db_rp); - local_unset_variable_nolock (client, SVMDB_NAMESPACE_STRING, var); - svm_pop_heap (oldheap); - region_unlock (client->db_rp); -} - -static void -local_set_variable_nolock (svmdb_client_t * client, - svmdb_namespace_t namespace, - u8 * var, u8 * val, u32 elsize) -{ - uword *h; - hash_pair_t *hp; - u8 *name; - svmdb_shm_hdr_t *shm; - - shm = client->shm; - h = shm->namespaces[namespace]; - hp = hash_get_pair_mem (h, var); - if (hp) - { - svmdb_value_t *oldvalue; - oldvalue = pool_elt_at_index (client->shm->values, hp->value[0]); - vec_alloc (oldvalue->value, vec_len (val) * elsize); - clib_memcpy (oldvalue->value, val, vec_len (val) * elsize); - _vec_len (oldvalue->value) = vec_len (val); - notify_value (oldvalue, SVMDB_ACTION_SET); - } - else - { - svmdb_value_t *newvalue; - pool_get (shm->values, newvalue); - memset (newvalue, 0, sizeof (*newvalue)); - newvalue->elsize = elsize; - vec_alloc (newvalue->value, vec_len (val) * elsize); - clib_memcpy (newvalue->value, val, vec_len (val) * elsize); - _vec_len (newvalue->value) = vec_len (val); - name = format (0, "%s%c", var, 0); - hash_set_mem (h, name, newvalue - shm->values); - } - shm->namespaces[namespace] = h; -} - -void -svmdb_local_set_string_variable (svmdb_client_t * client, - char *var, char *val) -{ - void *oldheap; - - region_lock (client->db_rp, 12); - oldheap = svm_push_data_heap (client->db_rp); - - local_unset_variable_nolock (client, SVMDB_NAMESPACE_STRING, var); - - local_set_variable_nolock (client, SVMDB_NAMESPACE_STRING, - (u8 *) var, (u8 *) val, 1 /* elsize */ ); - svm_pop_heap (oldheap); - region_unlock (client->db_rp); -} - -static u8 * -local_get_variable_nolock (svmdb_client_t * client, - svmdb_namespace_t namespace, u8 * var) -{ - uword *h; - uword *p; - svmdb_shm_hdr_t *shm; - svmdb_value_t *oldvalue; - - shm = client->shm; - h = shm->namespaces[namespace]; - p = hash_get_mem (h, var); - if (p) - { - oldvalue = pool_elt_at_index (shm->values, p[0]); - notify_value (oldvalue, SVMDB_ACTION_GET); - return (oldvalue->value); - } - return 0; -} - -void * -svmdb_local_get_variable_reference (svmdb_client_t * client, - svmdb_namespace_t namespace, char *var) -{ - u8 *rv; - - region_lock (client->db_rp, 19); - rv = local_get_variable_nolock (client, namespace, (u8 *) var); - region_unlock (client->db_rp); - return (void *) rv; -} - -char * -svmdb_local_get_string_variable (svmdb_client_t * client, char *var) -{ - u8 *rv = 0; - - region_lock (client->db_rp, 13); - rv = local_get_variable_nolock (client, SVMDB_NAMESPACE_STRING, (u8 *) var); - - if (rv && vec_len (rv)) - { - rv = format (0, "%s", rv); - vec_add1 (rv, 0); - } - region_unlock (client->db_rp); - return ((char *) rv); -} - -void -svmdb_local_dump_strings (svmdb_client_t * client) -{ - uword *h; - u8 *key; - u32 value; - svmdb_shm_hdr_t *shm = client->shm; - - region_lock (client->db_rp, 14); - - h = client->shm->namespaces[SVMDB_NAMESPACE_STRING]; - - /* *INDENT-OFF* */ - hash_foreach_mem(key, value, h, - ({ - svmdb_value_t *v = pool_elt_at_index (shm->values, value); - - fformat(stdout, "%s: %s\n", key, - vec_len(v->value) ? v->value : (u8 *)"(nil)"); - })); - /* *INDENT-ON* */ - region_unlock (client->db_rp); -} - -int -svmdb_local_serialize_strings (svmdb_client_t * client, char *filename) -{ - uword *h; - u8 *key; - u32 value; - svmdb_shm_hdr_t *shm = client->shm; - serialize_main_t _sm, *sm = &_sm; - clib_error_t *error = 0; - u8 *sanitized_name = 0; - int fd = 0; - - if (strstr (filename, "..") || index (filename, '/')) - { - error = clib_error_return (0, "Illegal characters in filename '%s'", - filename); - goto out; - } - - sanitized_name = format (0, "/tmp/%s%c", filename, 0); - - fd = creat ((char *) sanitized_name, 0644); - - if (fd < 0) - { - error = clib_error_return_unix (0, "Create '%s'", sanitized_name); - goto out; - } - - serialize_open_unix_file_descriptor (sm, fd); - - region_lock (client->db_rp, 20); - - h = client->shm->namespaces[SVMDB_NAMESPACE_STRING]; - - serialize_likely_small_unsigned_integer (sm, hash_elts (h)); - - /* *INDENT-OFF* */ - hash_foreach_mem(key, value, h, - ({ - svmdb_value_t *v = pool_elt_at_index (shm->values, value); - - /* Omit names with nil values */ - if (vec_len(v->value)) - { - serialize_cstring (sm, (char *)key); - serialize_cstring (sm, (char *)v->value); - } - })); - /* *INDENT-ON* */ - region_unlock (client->db_rp); - - serialize_close (sm); - -out: - if (fd > 0 && close (fd) < 0) - error = clib_error_return_unix (0, "close fd %d", fd); - - if (error) - { - clib_error_report (error); - return -1; - } - return 0; -} - -int -svmdb_local_unserialize_strings (svmdb_client_t * client, char *filename) -{ - serialize_main_t _sm, *sm = &_sm; - void *oldheap; - clib_error_t *error = 0; - u8 *key, *value; - int fd = 0; - u32 nelts; - int i; - - fd = open (filename, O_RDONLY); - - if (fd < 0) - { - error = clib_error_return_unix (0, "Failed to open '%s'", filename); - goto out; - } - - unserialize_open_unix_file_descriptor (sm, fd); - - region_lock (client->db_rp, 21); - oldheap = svm_push_data_heap (client->db_rp); - - nelts = unserialize_likely_small_unsigned_integer (sm); - - for (i = 0; i < nelts; i++) - { - unserialize_cstring (sm, (char **) &key); - unserialize_cstring (sm, (char **) &value); - local_set_variable_nolock (client, SVMDB_NAMESPACE_STRING, - key, value, 1 /* elsize */ ); - vec_free (key); - vec_free (value); - } - svm_pop_heap (oldheap); - region_unlock (client->db_rp); - - serialize_close (sm); - -out: - if (fd > 0 && close (fd) < 0) - error = clib_error_return_unix (0, "close fd %d", fd); - - if (error) - { - clib_error_report (error); - return -1; - } - return 0; -} - -void -svmdb_local_unset_vec_variable (svmdb_client_t * client, char *var) -{ - void *oldheap; - - region_lock (client->db_rp, 15); - oldheap = svm_push_data_heap (client->db_rp); - local_unset_variable_nolock (client, SVMDB_NAMESPACE_VEC, var); - svm_pop_heap (oldheap); - region_unlock (client->db_rp); -} - -void -svmdb_local_set_vec_variable (svmdb_client_t * client, - char *var, void *val_arg, u32 elsize) -{ - u8 *val = (u8 *) val_arg; - void *oldheap; - - region_lock (client->db_rp, 16); - oldheap = svm_push_data_heap (client->db_rp); - - local_unset_variable_nolock (client, SVMDB_NAMESPACE_VEC, var); - local_set_variable_nolock (client, SVMDB_NAMESPACE_VEC, (u8 *) var, - val, elsize); - - svm_pop_heap (oldheap); - region_unlock (client->db_rp); -} - -void * -svmdb_local_get_vec_variable (svmdb_client_t * client, char *var, u32 elsize) -{ - u8 *rv = 0; - u8 *copy = 0; - - region_lock (client->db_rp, 17); - - rv = local_get_variable_nolock (client, SVMDB_NAMESPACE_VEC, (u8 *) var); - - if (rv && vec_len (rv)) - { - /* Make a copy in process-local memory */ - vec_alloc (copy, vec_len (rv) * elsize); - clib_memcpy (copy, rv, vec_len (rv) * elsize); - _vec_len (copy) = vec_len (rv); - region_unlock (client->db_rp); - return (copy); - } - region_unlock (client->db_rp); - return (0); -} - -void -svmdb_local_dump_vecs (svmdb_client_t * client) -{ - uword *h; - u8 *key; - u32 value; - svmdb_shm_hdr_t *shm; - - region_lock (client->db_rp, 17); - shm = client->shm; - - h = client->shm->namespaces[SVMDB_NAMESPACE_VEC]; - - /* *INDENT-OFF* */ - hash_foreach_mem(key, value, h, - ({ - svmdb_value_t *v = pool_elt_at_index (shm->values, value); - (void) fformat(stdout, "%s:\n %U (%.2f)\n", key, - format_hex_bytes, v->value, - vec_len(v->value)*v->elsize, ((f64 *)(v->value))[0]); - })); - /* *INDENT-ON* */ - - region_unlock (client->db_rp); -} - -void * -svmdb_local_find_or_add_vec_variable (svmdb_client_t * client, - char *var, u32 nbytes) -{ - void *oldheap; - u8 *rv = 0; - - region_lock (client->db_rp, 18); - oldheap = svm_push_data_heap (client->db_rp); - - rv = local_get_variable_nolock (client, SVMDB_NAMESPACE_VEC, (u8 *) var); - - if (rv) - { - goto out; - } - else - { - uword *h; - u8 *name; - svmdb_shm_hdr_t *shm; - svmdb_value_t *newvalue; - - shm = client->shm; - h = shm->namespaces[SVMDB_NAMESPACE_VEC]; - - pool_get (shm->values, newvalue); - memset (newvalue, 0, sizeof (*newvalue)); - newvalue->elsize = 1; - vec_alloc (newvalue->value, nbytes); - _vec_len (newvalue->value) = nbytes; - name = format (0, "%s%c", var, 0); - hash_set_mem (h, name, newvalue - shm->values); - shm->namespaces[SVMDB_NAMESPACE_VEC] = h; - rv = newvalue->value; - } - -out: - svm_pop_heap (oldheap); - region_unlock (client->db_rp); - return (rv); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |