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