summaryrefslogtreecommitdiff
path: root/usr/src/lib/udapl/libdat/common/udat.c
blob: 869c24591e3d60caa8901086f40aeab1ad91f239 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
 */

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */


/*
 *
 * MODULE: udat.c
 *
 * PURPOSE: DAT Provider and Consumer registry functions.
 *
 * $Id: udat.c,v 1.13 2003/08/20 14:28:40 hobie16 Exp $
 */

#include <dat/udat.h>
#include <dat/dat_registry.h> /* Provider API function prototypes */

#include "dat_dr.h"
#include "dat_init.h"
#include "dat_osd.h"
#ifndef	DAT_NO_STATIC_REGISTRY
#include "dat_sr.h"
#endif


#define	UDAT_IS_BAD_POINTER(p) (NULL == (p))

/*
 *
 * Internal Function Declarations
 *
 */

DAT_BOOLEAN
udat_check_state(void);


/*
 *
 * External Function Definitions
 *
 */


/*
 *
 * Provider API
 *
 */


/*
 * Function: dat_registry_add_provider
 */

DAT_RETURN
dat_registry_add_provider(
	IN DAT_PROVIDER			*provider,
	IN const DAT_PROVIDER_INFO	*provider_info)
{
	DAT_DR_ENTRY 		entry;

	dat_os_dbg_print(DAT_OS_DBG_TYPE_PROVIDER_API,
	    "DAT Registry: dat_registry_add_provider() called\n");

	if (UDAT_IS_BAD_POINTER(provider)) {
		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
	}

	if (UDAT_IS_BAD_POINTER(provider_info)) {
		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2));
	}

	if (DAT_FALSE == udat_check_state()) {
		return (DAT_ERROR(DAT_INVALID_STATE, 0));
	}

	entry.ref_count = 0;
	entry.ia_open_func = provider->ia_open_func;
	entry.info = *provider_info;

	return (dat_dr_insert(provider_info, &entry));
}


/*
 * Function: dat_registry_remove_provider
 */

DAT_RETURN
dat_registry_remove_provider(
	IN DAT_PROVIDER 		*provider,
	IN  const DAT_PROVIDER_INFO	*provider_info)
{
	dat_os_dbg_print(DAT_OS_DBG_TYPE_PROVIDER_API,
	    "DAT Registry: dat_registry_remove_provider() called\n");

	if (UDAT_IS_BAD_POINTER(provider)) {
		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
	}

	if (DAT_FALSE == udat_check_state()) {
		return (DAT_ERROR(DAT_INVALID_STATE, 0));
	}

	return (dat_dr_remove(provider_info));
}


/*
 *
 * Consumer API
 *
 */

/*
 * Function: dat_ia_open
 */

DAT_RETURN
dat_ia_openv(
	IN	const DAT_NAME_PTR	name,
	IN	DAT_COUNT		async_event_qlen,
	INOUT	DAT_EVD_HANDLE		*async_event_handle,
	OUT	DAT_IA_HANDLE		*ia_handle,
	IN	DAT_UINT32		dapl_major,
	IN	DAT_UINT32		dapl_minor,
	IN	DAT_BOOLEAN		thread_safety)
{
	DAT_IA_OPEN_FUNC		ia_open_func;
	DAT_PROVIDER_INFO 		info;
	DAT_RETURN 			status;
	DAT_OS_SIZE 			len;
#define	RO_AWARE_PREFIX	"RO_AWARE_"
	boolean_t			ro_aware_client;
	const char			*_name = name;

	dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
	    "DAT Registry: dat_ia_open() called\n");

	if (UDAT_IS_BAD_POINTER(_name)) {
		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
	}

	len = dat_os_strlen(_name);

	if (DAT_NAME_MAX_LENGTH <= len) {
		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
	}

	if (UDAT_IS_BAD_POINTER(ia_handle)) {
		return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA));
	}

	if (DAT_FALSE == udat_check_state()) {
		return (DAT_ERROR(DAT_INVALID_STATE, 0));
	}

	/* Find out if this is an RO aware client and if so, strip the prefix */
	ro_aware_client =
	    (strncmp(RO_AWARE_PREFIX, _name, sizeof (RO_AWARE_PREFIX) - 1) ==
	    0);

	/* strip off the prefix from the provider's name if present */
	if (ro_aware_client) {
		_name = _name + sizeof (RO_AWARE_PREFIX) - 1;
		len -= sizeof (RO_AWARE_PREFIX) - 1;
	}

	(void) dat_os_strncpy(info.ia_name, _name, len);
	info.ia_name[len] = '\0';

	info.dapl_version_major = dapl_major;
	info.dapl_version_minor = dapl_minor;
	info.is_thread_safe = thread_safety;

	/*
	 * Since DAT allows providers to be loaded by either the static
	 * registry or explicitly through OS dependent methods, do not
	 * return an error if no providers are loaded via the static registry.
	 * Don't even bother calling the static registry if DAT is compiled
	 * with no static registry support.
	 */

#ifndef DAT_NO_STATIC_REGISTRY
	(void) dat_sr_provider_open(&info);
#endif

	status = dat_dr_provider_open(&info, &ia_open_func);
	if (status != DAT_SUCCESS) {
		dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
		    "DAT Registry: dat_ia_open() provider information "
		    "for IA name %s not found in dynamic registry\n",
		    _name);
		return (status);
	}

	return (*ia_open_func)((const DAT_NAME_PTR) _name,
	    async_event_qlen,
	    async_event_handle,
	    ia_handle,
	    ro_aware_client);
}


/*
 * Function: dat_ia_close
 */

DAT_RETURN
dat_ia_close(
	IN DAT_IA_HANDLE	ia_handle,
	IN DAT_CLOSE_FLAGS	ia_flags)
{
	DAT_PROVIDER	*provider;
	DAT_PROVIDER_ATTR   provider_attr = {0};
	DAT_RETURN 		status;
	const char 		*ia_name;

	dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
	    "DAT Registry: dat_ia_close() called\n");

	if (UDAT_IS_BAD_POINTER(ia_handle)) {
		return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA));
	}

	if (DAT_FALSE == udat_check_state()) {
		return (DAT_ERROR(DAT_INVALID_STATE, 0));
	}

	provider = DAT_HANDLE_TO_PROVIDER(ia_handle);
	ia_name = provider->device_name;

	if (DAT_SUCCESS != (status = dat_ia_query(ia_handle,
	    NULL,
	    0,
	    NULL,
	    DAT_PROVIDER_FIELD_ALL,
	    &provider_attr))) {
		dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
		    "DAT Registry: query function for %s provider failed\n",
		    ia_name);
	} else if (DAT_SUCCESS != (status =
	    (*provider->ia_close_func)(ia_handle, ia_flags))) {
		dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
		    "DAT Registry: close function for %s provider failed\n",
		    ia_name);
	} else {
		DAT_PROVIDER_INFO info;
		DAT_OS_SIZE len;

		len = dat_os_strlen(ia_name);

		dat_os_assert(len <= DAT_NAME_MAX_LENGTH);

		(void) dat_os_strncpy(info.ia_name, ia_name, len);
		info.ia_name[len] = '\0';

		info.dapl_version_major = provider_attr.dapl_version_major;
		info.dapl_version_minor = provider_attr.dapl_version_minor;
		info.is_thread_safe = provider_attr.is_thread_safe;

		status = dat_dr_provider_close(&info);
		if (DAT_SUCCESS != status) {
			dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
			    "DAT Registry: dynamic registry unable to close "
			    "provider for IA name %s\n",
			    ia_name);
		}

#ifndef DAT_NO_STATIC_REGISTRY
		status = dat_sr_provider_close(&info);
		if (DAT_SUCCESS != status) {
			dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
			    "DAT Registry: static registry unable to close "
			    "provider for IA name %s\n",
			    ia_name);
		}
#endif
	}

	return (status);
}


/*
 * Function: dat_registry_list_providers
 */

DAT_RETURN
dat_registry_list_providers(
	IN  DAT_COUNT   		max_to_return,
	    OUT DAT_COUNT   		*entries_returned,
	    OUT	DAT_PROVIDER_INFO 	*(dat_provider_list[]))
{
	DAT_RETURN	dat_status;

	dat_status = DAT_SUCCESS;
	dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
	    "DAT Registry: dat_registry_list_providers() called\n");

	if (DAT_FALSE == udat_check_state()) {
			return (DAT_ERROR(DAT_INVALID_STATE, 0));
	}

	if ((UDAT_IS_BAD_POINTER(entries_returned))) {
		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2));
	}

	if (0 != max_to_return && (UDAT_IS_BAD_POINTER(dat_provider_list))) {
		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3));
	}

	if (0 == max_to_return) {
		/*
		 * the user is allowed to call with max_to_return set to zero.
		 * in which case we simply return (in *entries_returned) the
		 * number of providers currently installed.  We must also
		 * (per spec) return an error
		 */
#ifndef DAT_NO_STATIC_REGISTRY
		(void) dat_sr_size(entries_returned);
#else
		(void) dat_dr_size(entries_returned);
#endif
		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
	} else {
#ifndef DAT_NO_STATIC_REGISTRY
		dat_status = dat_sr_list(max_to_return,
		    entries_returned,
		    dat_provider_list);
#else
		dat_status = dat_dr_list(max_to_return,
		    entries_returned,
		    dat_provider_list);
#endif
	}
	return (dat_status);
}


/*
 *
 * Internal Function Definitions
 *
 */


/*
 * Function: udat_check_state
 */

/*
 * This function returns TRUE if the DAT registry is in a state capable
 * of handling DAT API calls and false otherwise.
 */

DAT_BOOLEAN
udat_check_state(void)
{
	DAT_MODULE_STATE 		state;
	DAT_BOOLEAN 		status;

	state = dat_module_get_state();

	if (DAT_MODULE_STATE_UNINITIALIZED == state) {
		dat_init();
		status = DAT_TRUE;
	} else if (DAT_MODULE_STATE_DEINITIALIZED == state) {
		status = DAT_FALSE;
	} else {
		status = DAT_TRUE;
	}

	return (status);
}


/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 8
 * End:
 */