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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
23 */
24
25/*
26 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
27 * Use is subject to license terms.
28 */
29
30
31/*
32 *
33 * MODULE: udat.c
34 *
35 * PURPOSE: DAT Provider and Consumer registry functions.
36 *
37 * $Id: udat.c,v 1.13 2003/08/20 14:28:40 hobie16 Exp $
38 */
39
40#include <dat/udat.h>
41#include <dat/dat_registry.h> /* Provider API function prototypes */
42
43#include "dat_dr.h"
44#include "dat_init.h"
45#include "dat_osd.h"
46#ifndef	DAT_NO_STATIC_REGISTRY
47#include "dat_sr.h"
48#endif
49
50
51#define	UDAT_IS_BAD_POINTER(p) (NULL == (p))
52
53/*
54 *
55 * Internal Function Declarations
56 *
57 */
58
59DAT_BOOLEAN
60udat_check_state(void);
61
62
63/*
64 *
65 * External Function Definitions
66 *
67 */
68
69
70/*
71 *
72 * Provider API
73 *
74 */
75
76
77/*
78 * Function: dat_registry_add_provider
79 */
80
81DAT_RETURN
82dat_registry_add_provider(
83	IN DAT_PROVIDER			*provider,
84	IN const DAT_PROVIDER_INFO	*provider_info)
85{
86	DAT_DR_ENTRY 		entry;
87
88	dat_os_dbg_print(DAT_OS_DBG_TYPE_PROVIDER_API,
89	    "DAT Registry: dat_registry_add_provider() called\n");
90
91	if (UDAT_IS_BAD_POINTER(provider)) {
92		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
93	}
94
95	if (UDAT_IS_BAD_POINTER(provider_info)) {
96		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2));
97	}
98
99	if (DAT_FALSE == udat_check_state()) {
100		return (DAT_ERROR(DAT_INVALID_STATE, 0));
101	}
102
103	entry.ref_count = 0;
104	entry.ia_open_func = provider->ia_open_func;
105	entry.info = *provider_info;
106
107	return (dat_dr_insert(provider_info, &entry));
108}
109
110
111/*
112 * Function: dat_registry_remove_provider
113 */
114
115DAT_RETURN
116dat_registry_remove_provider(
117	IN DAT_PROVIDER 		*provider,
118	IN  const DAT_PROVIDER_INFO	*provider_info)
119{
120	dat_os_dbg_print(DAT_OS_DBG_TYPE_PROVIDER_API,
121	    "DAT Registry: dat_registry_remove_provider() called\n");
122
123	if (UDAT_IS_BAD_POINTER(provider)) {
124		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
125	}
126
127	if (DAT_FALSE == udat_check_state()) {
128		return (DAT_ERROR(DAT_INVALID_STATE, 0));
129	}
130
131	return (dat_dr_remove(provider_info));
132}
133
134
135/*
136 *
137 * Consumer API
138 *
139 */
140
141/*
142 * Function: dat_ia_open
143 */
144
145DAT_RETURN
146dat_ia_openv(
147	IN	const DAT_NAME_PTR	name,
148	IN	DAT_COUNT		async_event_qlen,
149	INOUT	DAT_EVD_HANDLE		*async_event_handle,
150	OUT	DAT_IA_HANDLE		*ia_handle,
151	IN	DAT_UINT32		dapl_major,
152	IN	DAT_UINT32		dapl_minor,
153	IN	DAT_BOOLEAN		thread_safety)
154{
155	DAT_IA_OPEN_FUNC		ia_open_func;
156	DAT_PROVIDER_INFO 		info;
157	DAT_RETURN 			status;
158	DAT_OS_SIZE 			len;
159#define	RO_AWARE_PREFIX	"RO_AWARE_"
160	boolean_t			ro_aware_client;
161	const char			*_name = name;
162
163	dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
164	    "DAT Registry: dat_ia_open() called\n");
165
166	if (UDAT_IS_BAD_POINTER(_name)) {
167		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
168	}
169
170	len = dat_os_strlen(_name);
171
172	if (DAT_NAME_MAX_LENGTH <= len) {
173		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
174	}
175
176	if (UDAT_IS_BAD_POINTER(ia_handle)) {
177		return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA));
178	}
179
180	if (DAT_FALSE == udat_check_state()) {
181		return (DAT_ERROR(DAT_INVALID_STATE, 0));
182	}
183
184	/* Find out if this is an RO aware client and if so, strip the prefix */
185	ro_aware_client =
186	    (strncmp(RO_AWARE_PREFIX, _name, sizeof (RO_AWARE_PREFIX) - 1) ==
187	    0);
188
189	/* strip off the prefix from the provider's name if present */
190	if (ro_aware_client) {
191		_name = _name + sizeof (RO_AWARE_PREFIX) - 1;
192		len -= sizeof (RO_AWARE_PREFIX) - 1;
193	}
194
195	(void) dat_os_strncpy(info.ia_name, _name, len);
196	info.ia_name[len] = '\0';
197
198	info.dapl_version_major = dapl_major;
199	info.dapl_version_minor = dapl_minor;
200	info.is_thread_safe = thread_safety;
201
202	/*
203	 * Since DAT allows providers to be loaded by either the static
204	 * registry or explicitly through OS dependent methods, do not
205	 * return an error if no providers are loaded via the static registry.
206	 * Don't even bother calling the static registry if DAT is compiled
207	 * with no static registry support.
208	 */
209
210#ifndef DAT_NO_STATIC_REGISTRY
211	(void) dat_sr_provider_open(&info);
212#endif
213
214	status = dat_dr_provider_open(&info, &ia_open_func);
215	if (status != DAT_SUCCESS) {
216		dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
217		    "DAT Registry: dat_ia_open() provider information "
218		    "for IA name %s not found in dynamic registry\n",
219		    _name);
220		return (status);
221	}
222
223	return (*ia_open_func)((const DAT_NAME_PTR) _name,
224	    async_event_qlen,
225	    async_event_handle,
226	    ia_handle,
227	    ro_aware_client);
228}
229
230
231/*
232 * Function: dat_ia_close
233 */
234
235DAT_RETURN
236dat_ia_close(
237	IN DAT_IA_HANDLE	ia_handle,
238	IN DAT_CLOSE_FLAGS	ia_flags)
239{
240	DAT_PROVIDER	*provider;
241	DAT_PROVIDER_ATTR   provider_attr = {0};
242	DAT_RETURN 		status;
243	const char 		*ia_name;
244
245	dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
246	    "DAT Registry: dat_ia_close() called\n");
247
248	if (UDAT_IS_BAD_POINTER(ia_handle)) {
249		return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA));
250	}
251
252	if (DAT_FALSE == udat_check_state()) {
253		return (DAT_ERROR(DAT_INVALID_STATE, 0));
254	}
255
256	provider = DAT_HANDLE_TO_PROVIDER(ia_handle);
257	ia_name = provider->device_name;
258
259	if (DAT_SUCCESS != (status = dat_ia_query(ia_handle,
260	    NULL,
261	    0,
262	    NULL,
263	    DAT_PROVIDER_FIELD_ALL,
264	    &provider_attr))) {
265		dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
266		    "DAT Registry: query function for %s provider failed\n",
267		    ia_name);
268	} else if (DAT_SUCCESS != (status =
269	    (*provider->ia_close_func)(ia_handle, ia_flags))) {
270		dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
271		    "DAT Registry: close function for %s provider failed\n",
272		    ia_name);
273	} else {
274		DAT_PROVIDER_INFO info;
275		DAT_OS_SIZE len;
276
277		len = dat_os_strlen(ia_name);
278
279		dat_os_assert(len <= DAT_NAME_MAX_LENGTH);
280
281		(void) dat_os_strncpy(info.ia_name, ia_name, len);
282		info.ia_name[len] = '\0';
283
284		info.dapl_version_major = provider_attr.dapl_version_major;
285		info.dapl_version_minor = provider_attr.dapl_version_minor;
286		info.is_thread_safe = provider_attr.is_thread_safe;
287
288		status = dat_dr_provider_close(&info);
289		if (DAT_SUCCESS != status) {
290			dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
291			    "DAT Registry: dynamic registry unable to close "
292			    "provider for IA name %s\n",
293			    ia_name);
294		}
295
296#ifndef DAT_NO_STATIC_REGISTRY
297		status = dat_sr_provider_close(&info);
298		if (DAT_SUCCESS != status) {
299			dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
300			    "DAT Registry: static registry unable to close "
301			    "provider for IA name %s\n",
302			    ia_name);
303		}
304#endif
305	}
306
307	return (status);
308}
309
310
311/*
312 * Function: dat_registry_list_providers
313 */
314
315DAT_RETURN
316dat_registry_list_providers(
317	IN  DAT_COUNT   		max_to_return,
318	    OUT DAT_COUNT   		*entries_returned,
319	    OUT	DAT_PROVIDER_INFO 	*(dat_provider_list[]))
320{
321	DAT_RETURN	dat_status;
322
323	dat_status = DAT_SUCCESS;
324	dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
325	    "DAT Registry: dat_registry_list_providers() called\n");
326
327	if (DAT_FALSE == udat_check_state()) {
328			return (DAT_ERROR(DAT_INVALID_STATE, 0));
329	}
330
331	if ((UDAT_IS_BAD_POINTER(entries_returned))) {
332		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2));
333	}
334
335	if (0 != max_to_return && (UDAT_IS_BAD_POINTER(dat_provider_list))) {
336		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3));
337	}
338
339	if (0 == max_to_return) {
340		/*
341		 * the user is allowed to call with max_to_return set to zero.
342		 * in which case we simply return (in *entries_returned) the
343		 * number of providers currently installed.  We must also
344		 * (per spec) return an error
345		 */
346#ifndef DAT_NO_STATIC_REGISTRY
347		(void) dat_sr_size(entries_returned);
348#else
349		(void) dat_dr_size(entries_returned);
350#endif
351		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
352	} else {
353#ifndef DAT_NO_STATIC_REGISTRY
354		dat_status = dat_sr_list(max_to_return,
355		    entries_returned,
356		    dat_provider_list);
357#else
358		dat_status = dat_dr_list(max_to_return,
359		    entries_returned,
360		    dat_provider_list);
361#endif
362	}
363	return (dat_status);
364}
365
366
367/*
368 *
369 * Internal Function Definitions
370 *
371 */
372
373
374/*
375 * Function: udat_check_state
376 */
377
378/*
379 * This function returns TRUE if the DAT registry is in a state capable
380 * of handling DAT API calls and false otherwise.
381 */
382
383DAT_BOOLEAN
384udat_check_state(void)
385{
386	DAT_MODULE_STATE 		state;
387	DAT_BOOLEAN 		status;
388
389	state = dat_module_get_state();
390
391	if (DAT_MODULE_STATE_UNINITIALIZED == state) {
392		dat_init();
393		status = DAT_TRUE;
394	} else if (DAT_MODULE_STATE_DEINITIALIZED == state) {
395		status = DAT_FALSE;
396	} else {
397		status = DAT_TRUE;
398	}
399
400	return (status);
401}
402
403
404/*
405 * Local variables:
406 *  c-indent-level: 4
407 *  c-basic-offset: 4
408 *  tab-width: 8
409 * End:
410 */
411