/* *------------------------------------------------------------------ * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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... */ if (CLIB_DEBUG > 2) { /* Add a bogus client (pid=0) so the svm won't be deallocated */ clib_warning ("[%d] adding fake client (pid=0) so '%s' won't be unlinked", getpid (), db_rp->region_name); 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 *placeholder_value = 0; svmdb_value_t *value; svmdb_notify_t *np; int i; int rv = 0; ASSERT (a->elsize); region_lock (cli
packet-generator new {
    name x
    limit 5
    size 128-128
    interface local0
    node ip6-lookup
    data {
        ICMP: db00::1 -> db00::2
        incrementing 30
    }
}
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); clib_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: */