xref: /titanic_50/usr/src/cmd/svc/startd/dict.c (revision 549ec3fff108310966327d1dc9004551b63210b7)
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  #pragma ident	"%Z%%M%	%I%	%E% SMI"
28  
29  /*
30   * dict.c - simple dictionary facility
31   *
32   * We maintain a dictionary, sorted by name to facilitate rapid id lookup by
33   * name. It is used by both the restarter and graph code.
34   *
35   * Right now, the dictionary is implemented as a sorted linked list which maps
36   * instance names to graph vertex ids.  It should eventually be converted to a
37   * better representation for quick lookups.
38   *
39   * For now, FMRIs are never deleted from the dictionary. A service deletion
40   * and insertion of the same instance FMRI will result in reuse of the same
41   * id. To implement dictionary entry delete, the locking strategy for graph
42   * vertex dependency linking must be checked for accuracy, as assumptions may
43   * exist that FMRI to id mapping is retained even after an instance is deleted.
44   */
45  
46  #include <sys/time.h>
47  
48  #include <assert.h>
49  #include <libuutil.h>
50  #include <string.h>
51  
52  #include "startd.h"
53  
54  static uu_list_pool_t *dict_pool;
55  dictionary_t *dictionary;
56  
57  static u_longlong_t dictionary_lookups;		/* number of lookups */
58  static u_longlong_t dictionary_ns_total;	/* nanoseconds spent */
59  
60  /*ARGSUSED*/
61  static int
62  dict_compare(const void *lc_arg, const void *rc_arg, void *private)
63  {
64  	const char *lc_name = ((const dict_entry_t *)lc_arg)->de_name;
65  	const char *rc_name = ((const dict_entry_t *)rc_arg)->de_name;
66  
67  	return (strcmp(lc_name, rc_name));
68  }
69  
70  int
71  dict_lookup_byname(const char *name)
72  {
73  	int id;
74  	dict_entry_t *entry, tmp;
75  	hrtime_t now = gethrtime();
76  
77  	tmp.de_name = name;
78  
79  	(void) pthread_mutex_lock(&dictionary->dict_lock);
80  	if ((entry = uu_list_find(dictionary->dict_list, &tmp, NULL,
81  	    NULL)) == NULL)
82  		id = -1;
83  	else
84  		id = entry->de_id;
85  
86  	(void) pthread_mutex_unlock(&dictionary->dict_lock);
87  
88  	dictionary_lookups++;
89  	dictionary_ns_total += gethrtime() - now;
90  
91  	return (id);
92  }
93  
94  /*
95   * int dict_insert(char *)
96   *   Returns the ID for name.
97   */
98  int
99  dict_insert(const char *name)
100  {
101  	dict_entry_t *entry, tmp;
102  	uu_list_index_t idx;
103  
104  	assert(name != NULL);
105  
106  	tmp.de_name = name;
107  
108  	(void) pthread_mutex_lock(&dictionary->dict_lock);
109  
110  	if ((entry = uu_list_find(dictionary->dict_list, &tmp, NULL,
111  	    &idx)) != NULL) {
112  		(void) pthread_mutex_unlock(&dictionary->dict_lock);
113  		return (entry->de_id);
114  	}
115  
116  	entry = startd_alloc(sizeof (dict_entry_t));
117  
118  	entry->de_id = dictionary->dict_new_id++;
119  	entry->de_name = startd_alloc(strlen(name) + 1);
120  	(void) strcpy((char *)entry->de_name, name);
121  
122  	uu_list_node_init(entry, &entry->de_link, dict_pool);
123  
124  	uu_list_insert(dictionary->dict_list, entry, idx);
125  	(void) pthread_mutex_unlock(&dictionary->dict_lock);
126  
127  	return (entry->de_id);
128  }
129  
130  void
131  dict_init()
132  {
133  	dictionary = startd_zalloc(sizeof (dictionary_t));
134  
135  	(void) pthread_mutex_init(&dictionary->dict_lock, NULL);
136  
137  	dict_pool = startd_list_pool_create("dict", sizeof (dict_entry_t),
138  	    offsetof(dict_entry_t, de_link), dict_compare, UU_LIST_POOL_DEBUG);
139  	assert(dict_pool != NULL);
140  
141  	dictionary->dict_new_id = 0;
142  	dictionary->dict_list = startd_list_create(dict_pool, dictionary,
143  	    UU_LIST_SORTED);
144  	assert(dictionary->dict_list != NULL);
145  }
146