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 2004 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_dictionary.c
36 *
37 * PURPOSE: dictionary data structure
38 *
39 * $Id: dat_dictionary.c,v 1.11 2003/08/05 19:01:48 jlentini Exp $
40 */
41
42
43 #include "dat_dictionary.h"
44
45
46 /*
47 *
48 * Structures
49 *
50 */
51
52 typedef struct DAT_DICTIONARY_NODE
53 {
54 DAT_PROVIDER_INFO key;
55 DAT_DICTIONARY_DATA data;
56 struct DAT_DICTIONARY_NODE *prev;
57 struct DAT_DICTIONARY_NODE *next;
58 } DAT_DICTIONARY_NODE;
59
60
61 struct DAT_DICTIONARY
62 {
63 DAT_DICTIONARY_NODE *head;
64 DAT_DICTIONARY_NODE *tail;
65 DAT_COUNT size;
66 };
67
68 /*
69 *
70 * Function Declarations
71 *
72 */
73
74 static DAT_RETURN
75 dat_dictionary_key_dup(
76 const DAT_PROVIDER_INFO *old_key,
77 DAT_PROVIDER_INFO *new_key);
78
79 static DAT_BOOLEAN
80 dat_dictionary_key_is_equal(
81 const DAT_PROVIDER_INFO *key_a,
82 const DAT_PROVIDER_INFO *key_b);
83
84
85 /*
86 *
87 * External Functions
88 *
89 */
90
91
92 /*
93 * Function: dat_dictionary_create
94 */
95
96 DAT_RETURN
dat_dictionary_create(OUT DAT_DICTIONARY ** pp_dictionary)97 dat_dictionary_create(
98 OUT DAT_DICTIONARY **pp_dictionary)
99 {
100 DAT_DICTIONARY *p_dictionary;
101 DAT_RETURN status;
102
103 dat_os_assert(NULL != pp_dictionary);
104
105 status = DAT_SUCCESS;
106
107 /* create the dictionary */
108 p_dictionary = dat_os_alloc(sizeof (DAT_DICTIONARY));
109 if (NULL == p_dictionary) {
110 status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
111 DAT_RESOURCE_MEMORY);
112 goto bail;
113 }
114
115 (void) dat_os_memset(p_dictionary, '\0', sizeof (DAT_DICTIONARY));
116
117 /* create the head node */
118 p_dictionary->head = dat_os_alloc(sizeof (DAT_DICTIONARY_NODE));
119 if (NULL == p_dictionary->head) {
120 status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
121 DAT_RESOURCE_MEMORY);
122 goto bail;
123 }
124
125 (void) dat_os_memset(p_dictionary->head, '\0',
126 sizeof (DAT_DICTIONARY_NODE));
127
128 /* create the tail node */
129 p_dictionary->tail = dat_os_alloc(sizeof (DAT_DICTIONARY_NODE));
130 if (NULL == p_dictionary->tail) {
131 status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
132 DAT_RESOURCE_MEMORY);
133 goto bail;
134 }
135
136 (void) dat_os_memset(p_dictionary->tail, '\0',
137 sizeof (DAT_DICTIONARY_NODE));
138
139 p_dictionary->head->next = p_dictionary->tail;
140 p_dictionary->tail->prev = p_dictionary->head;
141
142 *pp_dictionary = p_dictionary;
143
144 bail:
145 if (DAT_SUCCESS != status) {
146 if (NULL != p_dictionary) {
147 dat_os_free(p_dictionary, sizeof (DAT_DICTIONARY));
148
149 if (NULL != p_dictionary->head) {
150 dat_os_free(p_dictionary->head,
151 sizeof (DAT_DICTIONARY_NODE));
152 }
153
154 if (NULL != p_dictionary->tail) {
155 dat_os_free(p_dictionary->tail,
156 sizeof (DAT_DICTIONARY_NODE));
157 }
158 }
159 }
160
161 return (status);
162 }
163
164
165 /*
166 * Function: dat_dictionary_destroy
167 */
168
169 DAT_RETURN
dat_dictionary_destroy(IN DAT_DICTIONARY * p_dictionary)170 dat_dictionary_destroy(
171 IN DAT_DICTIONARY *p_dictionary)
172 {
173 DAT_DICTIONARY_NODE *cur_node;
174
175 dat_os_assert(NULL != p_dictionary);
176
177 while (NULL != p_dictionary->head) {
178 cur_node = p_dictionary->head;
179 p_dictionary->head = cur_node->next;
180
181 dat_os_free(cur_node, sizeof (DAT_DICTIONARY_NODE));
182 }
183
184 dat_os_free(p_dictionary, sizeof (DAT_DICTIONARY));
185
186 return (DAT_SUCCESS);
187 }
188
189
190 /*
191 * Function: dat_dictionary_size
192 */
193
194 DAT_RETURN
dat_dictionary_size(IN DAT_DICTIONARY * p_dictionary,OUT DAT_COUNT * p_size)195 dat_dictionary_size(
196 IN DAT_DICTIONARY *p_dictionary,
197 OUT DAT_COUNT *p_size)
198 {
199 dat_os_assert(NULL != p_dictionary);
200 dat_os_assert(NULL != p_size);
201
202 *p_size = p_dictionary->size;
203
204 return (DAT_SUCCESS);
205 }
206
207
208 /*
209 * Function: dat_dictionary_entry_create
210 */
211
212 DAT_RETURN
dat_dictionary_entry_create(OUT DAT_DICTIONARY_ENTRY * p_entry)213 dat_dictionary_entry_create(
214 OUT DAT_DICTIONARY_ENTRY *p_entry)
215 {
216 DAT_DICTIONARY_NODE *node;
217 DAT_RETURN dat_status;
218
219 dat_os_assert(NULL != p_entry);
220
221 dat_status = DAT_SUCCESS;
222
223 node = dat_os_alloc(sizeof (DAT_DICTIONARY_NODE));
224 if (NULL == node) {
225 dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
226 DAT_RESOURCE_MEMORY);
227 goto bail;
228 }
229
230 *p_entry = node;
231
232 bail:
233 return (dat_status);
234 }
235
236
237 /*
238 * Function: dat_dictionary_entry_destroy
239 */
240
241 DAT_RETURN
dat_dictionary_entry_destroy(OUT DAT_DICTIONARY_ENTRY entry)242 dat_dictionary_entry_destroy(
243 OUT DAT_DICTIONARY_ENTRY entry)
244 {
245 dat_os_free(entry, sizeof (DAT_DICTIONARY_NODE));
246 return (DAT_SUCCESS);
247 }
248
249
250 /*
251 * Function: dat_dictionary_insert
252 */
253
254 DAT_RETURN
dat_dictionary_insert(IN DAT_DICTIONARY * p_dictionary,IN DAT_DICTIONARY_ENTRY entry,IN const DAT_PROVIDER_INFO * key,IN DAT_DICTIONARY_DATA data)255 dat_dictionary_insert(
256 IN DAT_DICTIONARY *p_dictionary,
257 IN DAT_DICTIONARY_ENTRY entry,
258 IN const DAT_PROVIDER_INFO *key,
259 IN DAT_DICTIONARY_DATA data)
260 {
261 DAT_RETURN dat_status;
262 DAT_DICTIONARY_NODE *cur_node, *prev_node, *next_node;
263
264 dat_os_assert(NULL != p_dictionary);
265 dat_os_assert(NULL != entry);
266
267 cur_node = entry;
268
269 if (DAT_SUCCESS == dat_dictionary_search(p_dictionary, key, NULL)) {
270 dat_status = DAT_ERROR(DAT_PROVIDER_ALREADY_REGISTERED, 0);
271 goto bail;
272 }
273
274 dat_status = dat_dictionary_key_dup(key, &cur_node->key);
275 if (DAT_SUCCESS != dat_status) {
276 goto bail;
277 }
278
279 /* insert node at end of list to preserve registration order */
280 prev_node = p_dictionary->tail->prev;
281 next_node = p_dictionary->tail;
282
283 cur_node->data = data;
284 cur_node->next = next_node;
285 cur_node->prev = prev_node;
286
287 prev_node->next = cur_node;
288 next_node->prev = cur_node;
289
290 p_dictionary->size++;
291
292 bail:
293 return (dat_status);
294 }
295
296
297 /*
298 * Function: dat_dictionary_search
299 */
300
301 DAT_RETURN
dat_dictionary_search(IN DAT_DICTIONARY * p_dictionary,IN const DAT_PROVIDER_INFO * key,OUT DAT_DICTIONARY_DATA * p_data)302 dat_dictionary_search(
303 IN DAT_DICTIONARY *p_dictionary,
304 IN const DAT_PROVIDER_INFO *key,
305 OUT DAT_DICTIONARY_DATA *p_data)
306 {
307 DAT_DICTIONARY_NODE *cur_node;
308 DAT_RETURN status;
309
310 dat_os_assert(NULL != p_dictionary);
311
312 status = DAT_ERROR(DAT_NAME_NOT_FOUND, 0);
313
314 for (cur_node = p_dictionary->head->next;
315 p_dictionary->tail != cur_node;
316 cur_node = cur_node->next) {
317 if (DAT_TRUE == dat_dictionary_key_is_equal(&cur_node->key,
318 key)) {
319 if (NULL != p_data) {
320 *p_data = cur_node->data;
321 }
322
323 status = DAT_SUCCESS;
324 goto bail;
325 }
326 }
327
328 bail:
329 return (status);
330 }
331
332
333 /*
334 * Function: dat_dictionary_enumerate
335 */
336
337 DAT_RETURN
dat_dictionary_enumerate(IN DAT_DICTIONARY * p_dictionary,IN DAT_DICTIONARY_DATA array[],IN DAT_COUNT array_size)338 dat_dictionary_enumerate(
339 IN DAT_DICTIONARY *p_dictionary,
340 IN DAT_DICTIONARY_DATA array[],
341 IN DAT_COUNT array_size)
342 {
343 DAT_DICTIONARY_NODE *cur_node;
344 DAT_COUNT i;
345 DAT_RETURN status;
346
347 dat_os_assert(NULL != p_dictionary);
348 dat_os_assert(NULL != array);
349
350 status = DAT_SUCCESS;
351
352 if (array_size < p_dictionary->size) {
353 status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 0);
354 goto bail;
355 }
356
357 for (cur_node = p_dictionary->head->next, i = 0;
358 p_dictionary->tail != cur_node;
359 cur_node = cur_node->next, i++) {
360 array[i] = cur_node->data;
361 }
362
363 bail:
364 return (status);
365 }
366
367
368 /*
369 * Function: dat_dictionary_remove
370 */
371
372 DAT_RETURN
dat_dictionary_remove(IN DAT_DICTIONARY * p_dictionary,IN DAT_DICTIONARY_ENTRY * p_entry,IN const DAT_PROVIDER_INFO * key,OUT DAT_DICTIONARY_DATA * p_data)373 dat_dictionary_remove(
374 IN DAT_DICTIONARY *p_dictionary,
375 IN DAT_DICTIONARY_ENTRY *p_entry,
376 IN const DAT_PROVIDER_INFO *key,
377 OUT DAT_DICTIONARY_DATA *p_data)
378 {
379 DAT_DICTIONARY_NODE *cur_node, *prev_node, *next_node;
380 DAT_RETURN status;
381
382 dat_os_assert(NULL != p_dictionary);
383 dat_os_assert(NULL != p_entry);
384
385 status = DAT_ERROR(DAT_NAME_NOT_FOUND, 0);
386
387 for (cur_node = p_dictionary->head->next;
388 p_dictionary->tail != cur_node;
389 cur_node = cur_node->next) {
390 if (DAT_TRUE == dat_dictionary_key_is_equal(&cur_node->key,
391 key)) {
392 if (NULL != p_data) {
393 *p_data = cur_node->data;
394 }
395
396 prev_node = cur_node->prev;
397 next_node = cur_node->next;
398
399 prev_node->next = next_node;
400 next_node->prev = prev_node;
401
402 *p_entry = cur_node;
403
404 p_dictionary->size--;
405
406 status = DAT_SUCCESS;
407 goto bail;
408 }
409 }
410
411 bail:
412 return (status);
413 }
414
415
416 /*
417 *
418 * Internal Function Definitions
419 *
420 */
421
422
423 /*
424 * Function: dat_dictionary_key_create
425 */
426
427 DAT_RETURN
dat_dictionary_key_dup(const DAT_PROVIDER_INFO * old_key,DAT_PROVIDER_INFO * new_key)428 dat_dictionary_key_dup(
429 const DAT_PROVIDER_INFO *old_key,
430 DAT_PROVIDER_INFO *new_key)
431 {
432 dat_os_assert(NULL != old_key);
433 dat_os_assert(NULL != new_key);
434
435 (void) dat_os_strncpy(new_key->ia_name, old_key->ia_name,
436 DAT_NAME_MAX_LENGTH);
437 new_key->dapl_version_major = old_key->dapl_version_major;
438 new_key->dapl_version_minor = old_key->dapl_version_minor;
439 new_key->is_thread_safe = old_key->is_thread_safe;
440
441 return (DAT_SUCCESS);
442 }
443
444
445 /*
446 * Function: dat_dictionary_key_is_equal
447 */
448
449 DAT_BOOLEAN
dat_dictionary_key_is_equal(const DAT_PROVIDER_INFO * key_a,const DAT_PROVIDER_INFO * key_b)450 dat_dictionary_key_is_equal(
451 const DAT_PROVIDER_INFO *key_a,
452 const DAT_PROVIDER_INFO *key_b)
453 {
454 if ((dat_os_strlen(key_a->ia_name) == dat_os_strlen(key_b->ia_name)) &&
455 (!dat_os_strncmp(key_a->ia_name, key_b->ia_name,
456 dat_os_strlen(key_a->ia_name))) &&
457 (key_a->dapl_version_major == key_b->dapl_version_major) &&
458 (key_a->dapl_version_minor == key_b->dapl_version_minor) &&
459 (key_a->is_thread_safe == key_b->is_thread_safe)) {
460 return (DAT_TRUE);
461 } else {
462 return (DAT_FALSE);
463 }
464 }
465