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