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
54static DAT_OS_LOCK 		g_dr_lock;
55static 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
69DAT_RETURN
70dat_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
92DAT_RETURN
93dat_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
115extern DAT_RETURN
116dat_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
148bail:
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
168extern DAT_RETURN
169dat_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
205bail:
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
220extern DAT_RETURN
221dat_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
249extern DAT_RETURN
250dat_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
276DAT_RETURN
277dat_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
288DAT_RETURN
289dat_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
356bail:
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