1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * dict.c - simple dictionary facility 29 * 30 * We maintain a dictionary, sorted by name to facilitate rapid id lookup by 31 * name. It is used by both the restarter and graph code. 32 * 33 * Right now, the dictionary is implemented as a sorted linked list which maps 34 * instance names to graph vertex ids. It should eventually be converted to a 35 * better representation for quick lookups. 36 * 37 * For now, FMRIs are never deleted from the dictionary. A service deletion 38 * and insertion of the same instance FMRI will result in reuse of the same 39 * id. To implement dictionary entry delete, the locking strategy for graph 40 * vertex dependency linking must be checked for accuracy, as assumptions may 41 * exist that FMRI to id mapping is retained even after an instance is deleted. 42 */ 43 44 #include <sys/time.h> 45 46 #include <assert.h> 47 #include <libuutil.h> 48 #include <string.h> 49 50 #include "startd.h" 51 52 static uu_list_pool_t *dict_pool; 53 dictionary_t *dictionary; 54 55 static u_longlong_t dictionary_lookups; /* number of lookups */ 56 static u_longlong_t dictionary_ns_total; /* nanoseconds spent */ 57 58 /*ARGSUSED*/ 59 static int 60 dict_compare(const void *lc_arg, const void *rc_arg, void *private) 61 { 62 const char *lc_name = ((const dict_entry_t *)lc_arg)->de_name; 63 const char *rc_name = ((const dict_entry_t *)rc_arg)->de_name; 64 65 return (strcmp(lc_name, rc_name)); 66 } 67 68 int 69 dict_lookup_byname(const char *name) 70 { 71 int id; 72 dict_entry_t *entry, tmp; 73 hrtime_t now = gethrtime(); 74 75 tmp.de_name = name; 76 77 (void) pthread_mutex_lock(&dictionary->dict_lock); 78 if ((entry = uu_list_find(dictionary->dict_list, &tmp, NULL, 79 NULL)) == NULL) 80 id = -1; 81 else 82 id = entry->de_id; 83 84 (void) pthread_mutex_unlock(&dictionary->dict_lock); 85 86 dictionary_lookups++; 87 dictionary_ns_total += gethrtime() - now; 88 89 return (id); 90 } 91 92 /* 93 * int dict_insert(char *) 94 * Returns the ID for name. 95 */ 96 int 97 dict_insert(const char *name) 98 { 99 dict_entry_t *entry, tmp; 100 uu_list_index_t idx; 101 102 assert(name != NULL); 103 104 tmp.de_name = name; 105 106 (void) pthread_mutex_lock(&dictionary->dict_lock); 107 108 if ((entry = uu_list_find(dictionary->dict_list, &tmp, NULL, 109 &idx)) != NULL) { 110 (void) pthread_mutex_unlock(&dictionary->dict_lock); 111 return (entry->de_id); 112 } 113 114 entry = startd_alloc(sizeof (dict_entry_t)); 115 116 entry->de_id = dictionary->dict_new_id++; 117 entry->de_name = startd_alloc(strlen(name) + 1); 118 (void) strcpy((char *)entry->de_name, name); 119 120 uu_list_node_init(entry, &entry->de_link, dict_pool); 121 122 uu_list_insert(dictionary->dict_list, entry, idx); 123 (void) pthread_mutex_unlock(&dictionary->dict_lock); 124 125 return (entry->de_id); 126 } 127 128 void 129 dict_init() 130 { 131 dictionary = startd_zalloc(sizeof (dictionary_t)); 132 133 (void) pthread_mutex_init(&dictionary->dict_lock, NULL); 134 135 dict_pool = startd_list_pool_create("dict", sizeof (dict_entry_t), 136 offsetof(dict_entry_t, de_link), dict_compare, UU_LIST_POOL_DEBUG); 137 assert(dict_pool != NULL); 138 139 dictionary->dict_new_id = 0; 140 dictionary->dict_list = startd_list_create(dict_pool, dictionary, 141 UU_LIST_SORTED); 142 assert(dictionary->dict_list != NULL); 143 } 144