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 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 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 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 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 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 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 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 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 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 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 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 }