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 (c) 2002-2003, Network Appliance, Inc. All rights reserved.
24  */
25 
26 /*
27  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 /*
32  *
33  * MODULE: dat_dr.c
34  *
35  * PURPOSE: dynamic registry implementation
36  *
37  * $Id: dat_dr.c,v 1.12 2003/08/20 14:28:40 hobie16 Exp $
38  */
39 
40 
41 #include "dat_dr.h"
42 
43 #include "dat_dictionary.h"
44 
45 
46 /*
47  *
48  * Global Variables
49  *
50  */
51 
52 static DAT_OS_LOCK 		g_dr_lock;
53 static DAT_DICTIONARY 		*g_dr_dictionary = NULL;
54 
55 
56 /*
57  *
58  * External Functions
59  *
60  */
61 
62 
63 /*
64  * Function: dat_dr_init
65  */
66 
67 DAT_RETURN
dat_dr_init(void)68 dat_dr_init(void)
69 {
70 	DAT_RETURN 	status;
71 
72 	status = dat_os_lock_init(&g_dr_lock);
73 	if (DAT_SUCCESS != status) {
74 		return (status);
75 	}
76 
77 	status = dat_dictionary_create(&g_dr_dictionary);
78 	if (DAT_SUCCESS != status) {
79 		return (status);
80 	}
81 
82 	return (DAT_SUCCESS);
83 }
84 
85 
86 /*
87  * Function: dat_dr_fini
88  */
89 
90 DAT_RETURN
dat_dr_fini(void)91 dat_dr_fini(void)
92 {
93 	DAT_RETURN 			status;
94 
95 	status = dat_os_lock_destroy(&g_dr_lock);
96 	if (DAT_SUCCESS != status) {
97 		return (status);
98 	}
99 
100 	status = dat_dictionary_destroy(g_dr_dictionary);
101 	if (DAT_SUCCESS != status) {
102 		return (status);
103 	}
104 
105 	return (DAT_SUCCESS);
106 }
107 
108 
109 /*
110  * Function: dat_dr_insert
111  */
112 
113 extern DAT_RETURN
dat_dr_insert(IN const DAT_PROVIDER_INFO * info,IN DAT_DR_ENTRY * entry)114 dat_dr_insert(
115     IN  const DAT_PROVIDER_INFO *info,
116     IN  DAT_DR_ENTRY 		*entry)
117 {
118 	DAT_RETURN 		status;
119 	DAT_DICTIONARY_ENTRY 	dict_entry;
120 	DAT_DR_ENTRY		*data;
121 
122 	data = dat_os_alloc(sizeof (DAT_DR_ENTRY));
123 	if (NULL == data) {
124 		status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
125 		    DAT_RESOURCE_MEMORY);
126 		goto bail;
127 	}
128 
129 	*data = *entry;
130 
131 	dict_entry = NULL;
132 	status = dat_dictionary_entry_create(&dict_entry);
133 	if (DAT_SUCCESS != status) {
134 		goto bail;
135 	}
136 
137 	dat_os_lock(&g_dr_lock);
138 
139 	status = dat_dictionary_insert(g_dr_dictionary,
140 		dict_entry,
141 		info,
142 		(DAT_DICTIONARY_DATA *) data);
143 
144 	dat_os_unlock(&g_dr_lock);
145 
146 bail:
147 	if (DAT_SUCCESS != status) {
148 		if (NULL != data) {
149 			dat_os_free(data, sizeof (DAT_DR_ENTRY));
150 		}
151 
152 
153 		if (NULL != dict_entry) {
154 			(void) dat_dictionary_entry_destroy(dict_entry);
155 		}
156 	}
157 
158 	return (status);
159 }
160 
161 
162 /*
163  * Function: dat_dr_remove
164  */
165 
166 extern DAT_RETURN
dat_dr_remove(IN const DAT_PROVIDER_INFO * info)167 dat_dr_remove(
168     IN  const DAT_PROVIDER_INFO *info)
169 {
170 	DAT_DR_ENTRY 		*data;
171 	DAT_DICTIONARY_ENTRY 	dict_entry;
172 	DAT_RETURN 		status;
173 
174 	dat_os_lock(&g_dr_lock);
175 
176 	status = dat_dictionary_search(g_dr_dictionary,
177 	    info,
178 	    (DAT_DICTIONARY_DATA *) &data);
179 
180 	if (DAT_SUCCESS != status) {
181 		/* return status from dat_dictionary_search() */
182 		goto bail;
183 	}
184 
185 	if (0 != data->ref_count) {
186 		status = DAT_ERROR(DAT_PROVIDER_IN_USE, 0);
187 		goto bail;
188 	}
189 
190 	dict_entry = NULL;
191 	status = dat_dictionary_remove(g_dr_dictionary,
192 	    &dict_entry,
193 	    info,
194 	    (DAT_DICTIONARY_DATA *) &data);
195 
196 	if (DAT_SUCCESS != status) {
197 		/* return status from dat_dictionary_remove() */
198 		goto bail;
199 	}
200 
201 	dat_os_free(data, sizeof (DAT_DR_ENTRY));
202 
203 bail:
204 	dat_os_unlock(&g_dr_lock);
205 
206 	if (NULL != dict_entry) {
207 		(void) dat_dictionary_entry_destroy(dict_entry);
208 	}
209 
210 	return (status);
211 }
212 
213 
214 /*
215  * Function: dat_dr_provider_open
216  */
217 
218 extern DAT_RETURN
dat_dr_provider_open(IN const DAT_PROVIDER_INFO * info,OUT DAT_IA_OPEN_FUNC * p_ia_open_func)219 dat_dr_provider_open(
220     IN  const DAT_PROVIDER_INFO *info,
221     OUT DAT_IA_OPEN_FUNC	*p_ia_open_func)
222 {
223 	DAT_RETURN 		status;
224 	DAT_DR_ENTRY 		*data;
225 
226 	dat_os_lock(&g_dr_lock);
227 
228 	status = dat_dictionary_search(g_dr_dictionary,
229 				info,
230 				(DAT_DICTIONARY_DATA *) &data);
231 
232 	dat_os_unlock(&g_dr_lock);
233 
234 	if (DAT_SUCCESS == status) {
235 		data->ref_count++;
236 		*p_ia_open_func = data->ia_open_func;
237 	}
238 
239 	return (status);
240 }
241 
242 
243 /*
244  * Function: dat_dr_provider_close
245  */
246 
247 extern DAT_RETURN
dat_dr_provider_close(IN const DAT_PROVIDER_INFO * info)248 dat_dr_provider_close(
249     IN  const DAT_PROVIDER_INFO *info)
250 {
251 	DAT_RETURN 		status;
252 	DAT_DR_ENTRY 		*data;
253 
254 	dat_os_lock(&g_dr_lock);
255 
256 	status = dat_dictionary_search(g_dr_dictionary,
257 	    info,
258 	    (DAT_DICTIONARY_DATA *) &data);
259 
260 	dat_os_unlock(&g_dr_lock);
261 
262 	if (DAT_SUCCESS == status) {
263 		data->ref_count--;
264 	}
265 
266 	return (status);
267 }
268 
269 
270 /*
271  * Function: dat_dr_size
272  */
273 
274 DAT_RETURN
dat_dr_size(OUT DAT_COUNT * size)275 dat_dr_size(
276     OUT	DAT_COUNT		*size)
277 {
278 	return (dat_dictionary_size(g_dr_dictionary, size));
279 }
280 
281 
282 /*
283  * Function: dat_dr_list
284  */
285 
286 DAT_RETURN
dat_dr_list(IN DAT_COUNT max_to_return,OUT DAT_COUNT * entries_returned,OUT DAT_PROVIDER_INFO * (dat_provider_list[]))287 dat_dr_list(
288     IN  DAT_COUNT		max_to_return,
289     OUT DAT_COUNT		*entries_returned,
290     OUT DAT_PROVIDER_INFO	* (dat_provider_list[]))
291 {
292 	DAT_DR_ENTRY		**array;
293 	DAT_COUNT 		array_size;
294 	DAT_COUNT 		i;
295 	DAT_RETURN 		status;
296 
297 	array = NULL;
298 	status = DAT_SUCCESS;
299 
300 	/*
301 	 * The dictionary size may increase between the call to
302 	 * dat_dictionary_size() and dat_dictionary_enumerate().
303 	 * Therefore we loop until a successful enumeration is made.
304 	 */
305 	*entries_returned = 0;
306 	for (;;) {
307 		status = dat_dictionary_size(g_dr_dictionary, &array_size);
308 		if (status != DAT_SUCCESS) {
309 			goto bail;
310 		}
311 
312 		if (array_size == 0) {
313 			status = DAT_SUCCESS;
314 			goto bail;
315 		}
316 
317 		array = dat_os_alloc(array_size * sizeof (DAT_DR_ENTRY *));
318 		if (array == NULL) {
319 			status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
320 			    DAT_RESOURCE_MEMORY);
321 			goto bail;
322 		}
323 
324 		dat_os_lock(&g_dr_lock);
325 
326 		status = dat_dictionary_enumerate(g_dr_dictionary,
327 		    (DAT_DICTIONARY_DATA *) array,
328 		    array_size);
329 
330 		dat_os_unlock(&g_dr_lock);
331 
332 		if (DAT_SUCCESS == status) {
333 			break;
334 		} else {
335 			dat_os_free(array,
336 			    array_size * sizeof (DAT_DR_ENTRY *));
337 			array = NULL;
338 			continue;
339 		}
340 	}
341 
342 	for (i = 0; (i < max_to_return) && (i < array_size); i++) {
343 		if (NULL == dat_provider_list[i]) {
344 			status = DAT_ERROR(DAT_INVALID_PARAMETER,
345 			    DAT_INVALID_ARG3);
346 			goto bail;
347 		}
348 
349 		*dat_provider_list[i] = array[i]->info;
350 	}
351 
352 	*entries_returned = i;
353 
354 bail:
355 	if (NULL != array) {
356 		dat_os_free(array, array_size * sizeof (DAT_DR_ENTRY *));
357 	}
358 
359 	return (status);
360 }
361 
362 /*
363  * Local variables:
364  *  c-indent-level: 4
365  *  c-basic-offset: 4
366  *  tab-width: 8
367  * End:
368  */
369