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