1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3219820Sjeff * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. 4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5219820Sjeff * 6219820Sjeff * This software is available to you under a choice of one of two 7219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 8219820Sjeff * General Public License (GPL) Version 2, available from the file 9219820Sjeff * COPYING in the main directory of this source tree, or the 10219820Sjeff * OpenIB.org BSD license below: 11219820Sjeff * 12219820Sjeff * Redistribution and use in source and binary forms, with or 13219820Sjeff * without modification, are permitted provided that the following 14219820Sjeff * conditions are met: 15219820Sjeff * 16219820Sjeff * - Redistributions of source code must retain the above 17219820Sjeff * copyright notice, this list of conditions and the following 18219820Sjeff * disclaimer. 19219820Sjeff * 20219820Sjeff * - Redistributions in binary form must reproduce the above 21219820Sjeff * copyright notice, this list of conditions and the following 22219820Sjeff * disclaimer in the documentation and/or other materials 23219820Sjeff * provided with the distribution. 24219820Sjeff * 25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32219820Sjeff * SOFTWARE. 33219820Sjeff * 34219820Sjeff */ 35219820Sjeff 36219820Sjeff/* 37219820Sjeff * Abstract: 38219820Sjeff * Implementation of the osm_db interface using simple text files 39219820Sjeff */ 40219820Sjeff 41219820Sjeff#if HAVE_CONFIG_H 42219820Sjeff# include <config.h> 43219820Sjeff#endif /* HAVE_CONFIG_H */ 44219820Sjeff 45219820Sjeff#include <sys/stat.h> 46219820Sjeff#include <sys/types.h> 47219820Sjeff#include <stdlib.h> 48219820Sjeff#include <string.h> 49219820Sjeff#include <opensm/st.h> 50219820Sjeff#include <opensm/osm_db.h> 51219820Sjeff 52219820Sjeff/****d* Database/OSM_DB_MAX_LINE_LEN 53219820Sjeff * NAME 54219820Sjeff * OSM_DB_MAX_LINE_LEN 55219820Sjeff * 56219820Sjeff * DESCRIPTION 57219820Sjeff * The Maximal line length allowed for the file 58219820Sjeff * 59219820Sjeff * SYNOPSIS 60219820Sjeff */ 61219820Sjeff#define OSM_DB_MAX_LINE_LEN 1024 62219820Sjeff/**********/ 63219820Sjeff 64219820Sjeff/****d* Database/OSM_DB_MAX_GUID_LEN 65219820Sjeff * NAME 66219820Sjeff * OSM_DB_MAX_GUID_LEN 67219820Sjeff * 68219820Sjeff * DESCRIPTION 69219820Sjeff * The Maximal word length allowed for the file (guid or lid) 70219820Sjeff * 71219820Sjeff * SYNOPSIS 72219820Sjeff */ 73219820Sjeff#define OSM_DB_MAX_GUID_LEN 32 74219820Sjeff/**********/ 75219820Sjeff 76219820Sjeff/****s* OpenSM: Database/osm_db_domain_imp 77219820Sjeff * NAME 78219820Sjeff * osm_db_domain_imp 79219820Sjeff * 80219820Sjeff * DESCRIPTION 81219820Sjeff * An implementation for domain of the database based on text files and 82219820Sjeff * hash tables. 83219820Sjeff * 84219820Sjeff * SYNOPSIS 85219820Sjeff */ 86219820Sjefftypedef struct osm_db_domain_imp { 87219820Sjeff char *file_name; 88219820Sjeff st_table *p_hash; 89219820Sjeff cl_spinlock_t lock; 90219820Sjeff} osm_db_domain_imp_t; 91219820Sjeff/* 92219820Sjeff * FIELDS 93219820Sjeff * 94219820Sjeff * SEE ALSO 95219820Sjeff * osm_db_domain_t 96219820Sjeff *********/ 97219820Sjeff 98219820Sjeff/****s* OpenSM: Database/osm_db_imp_t 99219820Sjeff * NAME 100219820Sjeff * osm_db_imp_t 101219820Sjeff * 102219820Sjeff * DESCRIPTION 103219820Sjeff * An implementation for file based database 104219820Sjeff * 105219820Sjeff * SYNOPSIS 106219820Sjeff */ 107219820Sjefftypedef struct osm_db_imp { 108219820Sjeff char *db_dir_name; 109219820Sjeff} osm_db_imp_t; 110219820Sjeff/* 111219820Sjeff * FIELDS 112219820Sjeff * 113219820Sjeff * db_dir_name 114219820Sjeff * The directory holding the database 115219820Sjeff * 116219820Sjeff * SEE ALSO 117219820Sjeff * osm_db_t 118219820Sjeff *********/ 119219820Sjeff 120219820Sjeff/*************************************************************************** 121219820Sjeff ***************************************************************************/ 122219820Sjeffvoid osm_db_construct(IN osm_db_t * const p_db) 123219820Sjeff{ 124219820Sjeff memset(p_db, 0, sizeof(osm_db_t)); 125219820Sjeff cl_list_construct(&p_db->domains); 126219820Sjeff} 127219820Sjeff 128219820Sjeff/*************************************************************************** 129219820Sjeff ***************************************************************************/ 130219820Sjeffvoid osm_db_domain_destroy(IN osm_db_domain_t * const p_db_domain) 131219820Sjeff{ 132219820Sjeff osm_db_domain_imp_t *p_domain_imp; 133219820Sjeff p_domain_imp = (osm_db_domain_imp_t *) p_db_domain->p_domain_imp; 134219820Sjeff 135219820Sjeff osm_db_clear(p_db_domain); 136219820Sjeff 137219820Sjeff cl_spinlock_destroy(&p_domain_imp->lock); 138219820Sjeff 139219820Sjeff st_free_table(p_domain_imp->p_hash); 140219820Sjeff free(p_domain_imp->file_name); 141219820Sjeff free(p_domain_imp); 142219820Sjeff} 143219820Sjeff 144219820Sjeff/*************************************************************************** 145219820Sjeff ***************************************************************************/ 146219820Sjeffvoid osm_db_destroy(IN osm_db_t * const p_db) 147219820Sjeff{ 148219820Sjeff osm_db_domain_t *p_domain; 149219820Sjeff 150219820Sjeff while ((p_domain = cl_list_remove_head(&p_db->domains)) != NULL) { 151219820Sjeff osm_db_domain_destroy(p_domain); 152219820Sjeff free(p_domain); 153219820Sjeff } 154219820Sjeff cl_list_destroy(&p_db->domains); 155219820Sjeff free(p_db->p_db_imp); 156219820Sjeff} 157219820Sjeff 158219820Sjeff/*************************************************************************** 159219820Sjeff ***************************************************************************/ 160219820Sjeffint osm_db_init(IN osm_db_t * const p_db, IN osm_log_t * p_log) 161219820Sjeff{ 162219820Sjeff osm_db_imp_t *p_db_imp; 163219820Sjeff struct stat dstat; 164219820Sjeff 165219820Sjeff OSM_LOG_ENTER(p_log); 166219820Sjeff 167219820Sjeff p_db_imp = (osm_db_imp_t *) malloc(sizeof(osm_db_imp_t)); 168219820Sjeff CL_ASSERT(p_db_imp != NULL); 169219820Sjeff 170219820Sjeff p_db_imp->db_dir_name = getenv("OSM_CACHE_DIR"); 171219820Sjeff if (!p_db_imp->db_dir_name || !(*p_db_imp->db_dir_name)) 172219820Sjeff p_db_imp->db_dir_name = OSM_DEFAULT_CACHE_DIR; 173219820Sjeff 174219820Sjeff /* Create the directory if it doesn't exist */ 175219820Sjeff /* There is a difference in creating directory between windows and linux */ 176219820Sjeff#ifdef __WIN__ 177219820Sjeff /* Check if the directory exists. If not - create it. */ 178219820Sjeff CreateDirectory(p_db_imp->db_dir_name, NULL); 179219820Sjeff#else /* __WIN__ */ 180219820Sjeff /* make sure the directory exists */ 181219820Sjeff if (lstat(p_db_imp->db_dir_name, &dstat)) { 182219820Sjeff if (mkdir(p_db_imp->db_dir_name, 0755)) { 183219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6101: " 184219820Sjeff "Failed to create the db directory:%s\n", 185219820Sjeff p_db_imp->db_dir_name); 186219820Sjeff OSM_LOG_EXIT(p_log); 187219820Sjeff return 1; 188219820Sjeff } 189219820Sjeff } 190219820Sjeff#endif 191219820Sjeff 192219820Sjeff p_db->p_log = p_log; 193219820Sjeff p_db->p_db_imp = (void *)p_db_imp; 194219820Sjeff 195219820Sjeff cl_list_init(&p_db->domains, 5); 196219820Sjeff 197219820Sjeff OSM_LOG_EXIT(p_log); 198219820Sjeff 199219820Sjeff return 0; 200219820Sjeff} 201219820Sjeff 202219820Sjeff/*************************************************************************** 203219820Sjeff ***************************************************************************/ 204219820Sjeffosm_db_domain_t *osm_db_domain_init(IN osm_db_t * const p_db, 205219820Sjeff IN char *domain_name) 206219820Sjeff{ 207219820Sjeff osm_db_domain_t *p_domain; 208219820Sjeff osm_db_domain_imp_t *p_domain_imp; 209219820Sjeff int dir_name_len; 210219820Sjeff osm_log_t *p_log = p_db->p_log; 211219820Sjeff FILE *p_file; 212219820Sjeff 213219820Sjeff OSM_LOG_ENTER(p_log); 214219820Sjeff 215219820Sjeff /* allocate a new domain object */ 216219820Sjeff p_domain = (osm_db_domain_t *) malloc(sizeof(osm_db_domain_t)); 217219820Sjeff CL_ASSERT(p_domain != NULL); 218219820Sjeff 219219820Sjeff p_domain_imp = 220219820Sjeff (osm_db_domain_imp_t *) malloc(sizeof(osm_db_domain_imp_t)); 221219820Sjeff CL_ASSERT(p_domain_imp != NULL); 222219820Sjeff 223219820Sjeff dir_name_len = strlen(((osm_db_imp_t *) p_db->p_db_imp)->db_dir_name); 224219820Sjeff 225219820Sjeff /* set the domain file name */ 226219820Sjeff p_domain_imp->file_name = 227219820Sjeff (char *)malloc(sizeof(char) * (dir_name_len) + strlen(domain_name) + 228219820Sjeff 2); 229219820Sjeff CL_ASSERT(p_domain_imp->file_name != NULL); 230219820Sjeff strcpy(p_domain_imp->file_name, 231219820Sjeff ((osm_db_imp_t *) p_db->p_db_imp)->db_dir_name); 232219820Sjeff strcat(p_domain_imp->file_name, domain_name); 233219820Sjeff 234219820Sjeff /* make sure the file exists - or exit if not writable */ 235219820Sjeff p_file = fopen(p_domain_imp->file_name, "a+"); 236219820Sjeff if (!p_file) { 237219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6102: " 238219820Sjeff "Failed to open the db file:%s\n", 239219820Sjeff p_domain_imp->file_name); 240219820Sjeff free(p_domain_imp); 241219820Sjeff free(p_domain); 242219820Sjeff p_domain = NULL; 243219820Sjeff goto Exit; 244219820Sjeff } 245219820Sjeff fclose(p_file); 246219820Sjeff 247219820Sjeff /* initialize the hash table object */ 248219820Sjeff p_domain_imp->p_hash = st_init_strtable(); 249219820Sjeff CL_ASSERT(p_domain_imp->p_hash != NULL); 250219820Sjeff 251219820Sjeff p_domain->p_db = p_db; 252219820Sjeff cl_list_insert_tail(&p_db->domains, p_domain); 253219820Sjeff p_domain->p_domain_imp = p_domain_imp; 254219820Sjeff cl_spinlock_construct(&p_domain_imp->lock); 255219820Sjeff cl_spinlock_init(&p_domain_imp->lock); 256219820Sjeff 257219820SjeffExit: 258219820Sjeff OSM_LOG_EXIT(p_log); 259219820Sjeff return p_domain; 260219820Sjeff} 261219820Sjeff 262219820Sjeff/*************************************************************************** 263219820Sjeff ***************************************************************************/ 264219820Sjeffint osm_db_restore(IN osm_db_domain_t * p_domain) 265219820Sjeff{ 266219820Sjeff 267219820Sjeff osm_log_t *p_log = p_domain->p_db->p_log; 268219820Sjeff osm_db_domain_imp_t *p_domain_imp = 269219820Sjeff (osm_db_domain_imp_t *) p_domain->p_domain_imp; 270219820Sjeff FILE *p_file; 271219820Sjeff int status; 272219820Sjeff char sLine[OSM_DB_MAX_LINE_LEN]; 273219820Sjeff boolean_t before_key; 274219820Sjeff char *p_first_word, *p_rest_of_line, *p_last; 275219820Sjeff char *p_key = NULL; 276219820Sjeff char *p_prev_val, *p_accum_val = NULL; 277219820Sjeff char *endptr = NULL; 278219820Sjeff unsigned int line_num; 279219820Sjeff 280219820Sjeff OSM_LOG_ENTER(p_log); 281219820Sjeff 282219820Sjeff /* take the lock on the domain */ 283219820Sjeff cl_spinlock_acquire(&p_domain_imp->lock); 284219820Sjeff 285219820Sjeff /* open the file - read mode */ 286219820Sjeff p_file = fopen(p_domain_imp->file_name, "r"); 287219820Sjeff 288219820Sjeff if (!p_file) { 289219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6103: " 290219820Sjeff "Failed to open the db file:%s\n", 291219820Sjeff p_domain_imp->file_name); 292219820Sjeff status = 1; 293219820Sjeff goto Exit; 294219820Sjeff } 295219820Sjeff 296219820Sjeff /* parse the file allocating new hash tables as required */ 297219820Sjeff /* 298219820Sjeff states: 299219820Sjeff before_key (0) -> in_key (1) 300219820Sjeff 301219820Sjeff before_key: if a word on the first byte - it is the key. state=in_key 302219820Sjeff the rest of the line is start of the value. 303219820Sjeff in_key: unless the line is empty - add it (with newlines) to the value. 304219820Sjeff if empty: state=before_key 305219820Sjeff */ 306219820Sjeff status = 0; 307219820Sjeff before_key = TRUE; 308219820Sjeff line_num = 0; 309219820Sjeff /* if we got to EOF in the middle of a key we add a last newline */ 310219820Sjeff while ((fgets(sLine, OSM_DB_MAX_LINE_LEN, p_file) != NULL) || 311219820Sjeff ((before_key == FALSE) && strcpy(sLine, "\n")) 312219820Sjeff ) { 313219820Sjeff line_num++; 314219820Sjeff if (before_key) { 315219820Sjeff if ((sLine[0] != ' ') && (sLine[0] != '\t') 316219820Sjeff && (sLine[0] != '\n')) { 317219820Sjeff /* we got a new key */ 318219820Sjeff before_key = FALSE; 319219820Sjeff 320219820Sjeff /* handle the key */ 321219820Sjeff p_first_word = 322219820Sjeff strtok_r(sLine, " \t\n", &p_last); 323219820Sjeff if (!p_first_word) { 324219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6104: " 325219820Sjeff "Failed to get key from line:%u : %s (file:%s)\n", 326219820Sjeff line_num, sLine, 327219820Sjeff p_domain_imp->file_name); 328219820Sjeff status = 1; 329219820Sjeff goto EndParsing; 330219820Sjeff } 331219820Sjeff if (strlen(p_first_word) > OSM_DB_MAX_GUID_LEN) { 332219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610A: " 333219820Sjeff "Illegal key from line:%u : %s (file:%s)\n", 334219820Sjeff line_num, sLine, 335219820Sjeff p_domain_imp->file_name); 336219820Sjeff status = 1; 337219820Sjeff goto EndParsing; 338219820Sjeff } 339219820Sjeff 340219820Sjeff p_key = 341219820Sjeff (char *)malloc(sizeof(char) * 342219820Sjeff (strlen(p_first_word) + 1)); 343219820Sjeff strcpy(p_key, p_first_word); 344219820Sjeff 345219820Sjeff p_rest_of_line = strtok_r(NULL, "\n", &p_last); 346219820Sjeff if (p_rest_of_line != NULL) { 347219820Sjeff p_accum_val = 348219820Sjeff (char *)malloc(sizeof(char) * 349219820Sjeff (strlen 350219820Sjeff (p_rest_of_line) + 351219820Sjeff 1)); 352219820Sjeff strcpy(p_accum_val, p_rest_of_line); 353219820Sjeff } else { 354219820Sjeff p_accum_val = (char *)malloc(2); 355219820Sjeff strcpy(p_accum_val, "\0"); 356219820Sjeff } 357219820Sjeff } else if (sLine[0] != '\n') { 358219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6105: " 359219820Sjeff "How did we get here? line:%u : %s (file:%s)\n", 360219820Sjeff line_num, sLine, 361219820Sjeff p_domain_imp->file_name); 362219820Sjeff status = 1; 363219820Sjeff goto EndParsing; 364219820Sjeff } 365219820Sjeff } /* before key */ 366219820Sjeff else { 367219820Sjeff /* we already have a key */ 368219820Sjeff 369219820Sjeff if (sLine[0] == '\n') { 370219820Sjeff /* got an end of key */ 371219820Sjeff before_key = TRUE; 372219820Sjeff 373219820Sjeff /* make sure the key was not previously used */ 374219820Sjeff if (st_lookup(p_domain_imp->p_hash, 375219820Sjeff (st_data_t) p_key, 376219820Sjeff (void *) & p_prev_val)) { 377219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6106: " 378219820Sjeff "Key:%s already exists in:%s with value:%s." 379219820Sjeff " Removing it\n", 380219820Sjeff p_key, 381219820Sjeff p_domain_imp->file_name, 382219820Sjeff p_prev_val); 383219820Sjeff } else { 384219820Sjeff p_prev_val = NULL; 385219820Sjeff } 386219820Sjeff 387219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 388219820Sjeff "Got key:%s value:%s\n", p_key, 389219820Sjeff p_accum_val); 390219820Sjeff 391219820Sjeff /* check that the key is a number */ 392219820Sjeff if (!strtouq(p_key, &endptr, 0) 393219820Sjeff && *endptr != '\0') { 394219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610B: " 395219820Sjeff "Key:%s is invalid\n", p_key); 396219820Sjeff } else { 397219820Sjeff /* store our key and value */ 398219820Sjeff st_insert(p_domain_imp->p_hash, 399219820Sjeff (st_data_t) p_key, 400219820Sjeff (st_data_t) p_accum_val); 401219820Sjeff } 402219820Sjeff } else { 403219820Sjeff /* accumulate into the value */ 404219820Sjeff p_prev_val = p_accum_val; 405219820Sjeff p_accum_val = 406219820Sjeff (char *)malloc(strlen(p_prev_val) + 407219820Sjeff strlen(sLine) + 1); 408219820Sjeff strcpy(p_accum_val, p_prev_val); 409219820Sjeff free(p_prev_val); 410219820Sjeff strcat(p_accum_val, sLine); 411219820Sjeff } 412219820Sjeff } /* in key */ 413219820Sjeff } /* while lines or last line */ 414219820Sjeff 415219820SjeffEndParsing: 416219820Sjeff fclose(p_file); 417219820Sjeff 418219820SjeffExit: 419219820Sjeff cl_spinlock_release(&p_domain_imp->lock); 420219820Sjeff OSM_LOG_EXIT(p_log); 421219820Sjeff return status; 422219820Sjeff} 423219820Sjeff 424219820Sjeff/*************************************************************************** 425219820Sjeff ***************************************************************************/ 426219820Sjeffstatic int __osm_dump_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) 427219820Sjeff{ 428219820Sjeff FILE *p_file = (FILE *) arg; 429219820Sjeff char *p_key = (char *)key; 430219820Sjeff char *p_val = (char *)val; 431219820Sjeff 432219820Sjeff fprintf(p_file, "%s %s\n\n", p_key, p_val); 433219820Sjeff return ST_CONTINUE; 434219820Sjeff} 435219820Sjeff 436219820Sjeffint osm_db_store(IN osm_db_domain_t * p_domain) 437219820Sjeff{ 438219820Sjeff osm_log_t *p_log = p_domain->p_db->p_log; 439219820Sjeff osm_db_domain_imp_t *p_domain_imp; 440219820Sjeff FILE *p_file; 441219820Sjeff int status = 0; 442219820Sjeff char *p_tmp_file_name; 443219820Sjeff 444219820Sjeff OSM_LOG_ENTER(p_log); 445219820Sjeff 446219820Sjeff p_domain_imp = (osm_db_domain_imp_t *) p_domain->p_domain_imp; 447219820Sjeff p_tmp_file_name = 448219820Sjeff (char *)malloc(sizeof(char) * 449219820Sjeff (strlen(p_domain_imp->file_name) + 8)); 450219820Sjeff strcpy(p_tmp_file_name, p_domain_imp->file_name); 451219820Sjeff strcat(p_tmp_file_name, ".tmp"); 452219820Sjeff 453219820Sjeff cl_spinlock_acquire(&p_domain_imp->lock); 454219820Sjeff 455219820Sjeff /* open up the output file */ 456219820Sjeff p_file = fopen(p_tmp_file_name, "w"); 457219820Sjeff if (!p_file) { 458219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6107: " 459219820Sjeff "Failed to open the db file:%s for writing\n", 460219820Sjeff p_domain_imp->file_name); 461219820Sjeff status = 1; 462219820Sjeff goto Exit; 463219820Sjeff } 464219820Sjeff 465219820Sjeff st_foreach(p_domain_imp->p_hash, __osm_dump_tbl_entry, 466219820Sjeff (st_data_t) p_file); 467219820Sjeff fclose(p_file); 468219820Sjeff 469219820Sjeff /* move the domain file */ 470219820Sjeff status = remove(p_domain_imp->file_name); 471219820Sjeff if (status) { 472219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6109: " 473219820Sjeff "Failed to remove file:%s (err:%u)\n", 474219820Sjeff p_domain_imp->file_name, status); 475219820Sjeff } 476219820Sjeff 477219820Sjeff status = rename(p_tmp_file_name, p_domain_imp->file_name); 478219820Sjeff if (status) { 479219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6108: " 480219820Sjeff "Failed to rename the db file to:%s (err:%u)\n", 481219820Sjeff p_domain_imp->file_name, status); 482219820Sjeff } 483219820SjeffExit: 484219820Sjeff cl_spinlock_release(&p_domain_imp->lock); 485219820Sjeff free(p_tmp_file_name); 486219820Sjeff OSM_LOG_EXIT(p_log); 487219820Sjeff return status; 488219820Sjeff} 489219820Sjeff 490219820Sjeff/*************************************************************************** 491219820Sjeff ***************************************************************************/ 492219820Sjeff/* simply de-allocate the key and the value and return the code 493219820Sjeff that makes the st_foreach delete the entry */ 494219820Sjeffstatic int __osm_clear_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) 495219820Sjeff{ 496219820Sjeff free((char *)key); 497219820Sjeff free((char *)val); 498219820Sjeff return ST_DELETE; 499219820Sjeff} 500219820Sjeff 501219820Sjeffint osm_db_clear(IN osm_db_domain_t * p_domain) 502219820Sjeff{ 503219820Sjeff osm_db_domain_imp_t *p_domain_imp = 504219820Sjeff (osm_db_domain_imp_t *) p_domain->p_domain_imp; 505219820Sjeff 506219820Sjeff cl_spinlock_acquire(&p_domain_imp->lock); 507219820Sjeff st_foreach(p_domain_imp->p_hash, __osm_clear_tbl_entry, 508219820Sjeff (st_data_t) NULL); 509219820Sjeff cl_spinlock_release(&p_domain_imp->lock); 510219820Sjeff 511219820Sjeff return 0; 512219820Sjeff} 513219820Sjeff 514219820Sjeff/*************************************************************************** 515219820Sjeff ***************************************************************************/ 516219820Sjeffstatic int __osm_get_key_of_tbl_entry(st_data_t key, st_data_t val, 517219820Sjeff st_data_t arg) 518219820Sjeff{ 519219820Sjeff cl_list_t *p_list = (cl_list_t *) arg; 520219820Sjeff cl_list_insert_tail(p_list, (void *)key); 521219820Sjeff return ST_CONTINUE; 522219820Sjeff} 523219820Sjeff 524219820Sjeffint osm_db_keys(IN osm_db_domain_t * p_domain, OUT cl_list_t * p_key_list) 525219820Sjeff{ 526219820Sjeff osm_db_domain_imp_t *p_domain_imp = 527219820Sjeff (osm_db_domain_imp_t *) p_domain->p_domain_imp; 528219820Sjeff 529219820Sjeff cl_spinlock_acquire(&p_domain_imp->lock); 530219820Sjeff 531219820Sjeff st_foreach(p_domain_imp->p_hash, 532219820Sjeff __osm_get_key_of_tbl_entry, (st_data_t) p_key_list); 533219820Sjeff 534219820Sjeff cl_spinlock_release(&p_domain_imp->lock); 535219820Sjeff 536219820Sjeff return 0; 537219820Sjeff} 538219820Sjeff 539219820Sjeff/*************************************************************************** 540219820Sjeff ***************************************************************************/ 541219820Sjeffchar *osm_db_lookup(IN osm_db_domain_t * p_domain, IN char *const p_key) 542219820Sjeff{ 543219820Sjeff osm_db_domain_imp_t *p_domain_imp = 544219820Sjeff (osm_db_domain_imp_t *) p_domain->p_domain_imp; 545219820Sjeff char *p_val = NULL; 546219820Sjeff 547219820Sjeff cl_spinlock_acquire(&p_domain_imp->lock); 548219820Sjeff 549219820Sjeff if (!st_lookup 550219820Sjeff (p_domain_imp->p_hash, (st_data_t) p_key, (void *) & p_val)) 551219820Sjeff p_val = NULL; 552219820Sjeff 553219820Sjeff cl_spinlock_release(&p_domain_imp->lock); 554219820Sjeff 555219820Sjeff return p_val; 556219820Sjeff} 557219820Sjeff 558219820Sjeff/*************************************************************************** 559219820Sjeff ***************************************************************************/ 560219820Sjeffint 561219820Sjeffosm_db_update(IN osm_db_domain_t * p_domain, 562219820Sjeff IN char *const p_key, IN char *const p_val) 563219820Sjeff{ 564219820Sjeff osm_log_t *p_log = p_domain->p_db->p_log; 565219820Sjeff osm_db_domain_imp_t *p_domain_imp = 566219820Sjeff (osm_db_domain_imp_t *) p_domain->p_domain_imp; 567219820Sjeff char *p_prev_val = NULL; 568219820Sjeff char *p_new_key; 569219820Sjeff char *p_new_val; 570219820Sjeff 571219820Sjeff cl_spinlock_acquire(&p_domain_imp->lock); 572219820Sjeff 573219820Sjeff if (st_lookup(p_domain_imp->p_hash, 574219820Sjeff (st_data_t) p_key, (void *) & p_prev_val)) { 575219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 576219820Sjeff "Key:%s previously exists in:%s with value:%s\n", 577219820Sjeff p_key, p_domain_imp->file_name, p_prev_val); 578219820Sjeff p_new_key = p_key; 579219820Sjeff } else { 580219820Sjeff /* need to allocate the key */ 581219820Sjeff p_new_key = malloc(sizeof(char) * (strlen(p_key) + 1)); 582219820Sjeff strcpy(p_new_key, p_key); 583219820Sjeff } 584219820Sjeff 585219820Sjeff /* need to arange a new copy of the value */ 586219820Sjeff p_new_val = malloc(sizeof(char) * (strlen(p_val) + 1)); 587219820Sjeff strcpy(p_new_val, p_val); 588219820Sjeff 589219820Sjeff st_insert(p_domain_imp->p_hash, (st_data_t) p_new_key, 590219820Sjeff (st_data_t) p_new_val); 591219820Sjeff 592219820Sjeff if (p_prev_val) 593219820Sjeff free(p_prev_val); 594219820Sjeff 595219820Sjeff cl_spinlock_release(&p_domain_imp->lock); 596219820Sjeff 597219820Sjeff return 0; 598219820Sjeff} 599219820Sjeff 600219820Sjeff/*************************************************************************** 601219820Sjeff ***************************************************************************/ 602219820Sjeffint osm_db_delete(IN osm_db_domain_t * p_domain, IN char *const p_key) 603219820Sjeff{ 604219820Sjeff osm_log_t *p_log = p_domain->p_db->p_log; 605219820Sjeff osm_db_domain_imp_t *p_domain_imp = 606219820Sjeff (osm_db_domain_imp_t *) p_domain->p_domain_imp; 607219820Sjeff char *p_prev_val = NULL; 608219820Sjeff int res; 609219820Sjeff 610219820Sjeff OSM_LOG_ENTER(p_log); 611219820Sjeff 612219820Sjeff cl_spinlock_acquire(&p_domain_imp->lock); 613219820Sjeff if (st_delete(p_domain_imp->p_hash, 614219820Sjeff (void *) & p_key, (void *) & p_prev_val)) { 615219820Sjeff if (st_lookup(p_domain_imp->p_hash, 616219820Sjeff (st_data_t) p_key, (void *) & p_prev_val)) { 617219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, 618219820Sjeff "key:%s still exists in:%s with value:%s\n", 619219820Sjeff p_key, p_domain_imp->file_name, p_prev_val); 620219820Sjeff res = 1; 621219820Sjeff } else { 622219820Sjeff free(p_key); 623219820Sjeff free(p_prev_val); 624219820Sjeff res = 0; 625219820Sjeff } 626219820Sjeff } else { 627219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 628219820Sjeff "fail to find key:%s. delete failed\n", p_key); 629219820Sjeff res = 1; 630219820Sjeff } 631219820Sjeff cl_spinlock_release(&p_domain_imp->lock); 632219820Sjeff 633219820Sjeff OSM_LOG_EXIT(p_log); 634219820Sjeff return res; 635219820Sjeff} 636219820Sjeff 637219820Sjeff#ifdef TEST_OSMDB 638219820Sjeff#include <stdlib.h> 639219820Sjeff#include <math.h> 640219820Sjeff 641219820Sjeffint main(int argc, char **argv) 642219820Sjeff{ 643219820Sjeff osm_db_t db; 644219820Sjeff osm_log_t log; 645219820Sjeff osm_db_domain_t *p_dbd; 646219820Sjeff cl_list_t keys; 647219820Sjeff cl_list_iterator_t kI; 648219820Sjeff char *p_key; 649219820Sjeff char *p_val; 650219820Sjeff int i; 651219820Sjeff 652219820Sjeff cl_list_construct(&keys); 653219820Sjeff cl_list_init(&keys, 10); 654219820Sjeff 655219820Sjeff osm_log_init_v2(&log, TRUE, 0xff, "/var/log/osm_db_test.log", 0, FALSE); 656219820Sjeff 657219820Sjeff osm_db_construct(&db); 658219820Sjeff if (osm_db_init(&db, &log)) { 659219820Sjeff printf("db init failed\n"); 660219820Sjeff exit(1); 661219820Sjeff } 662219820Sjeff 663219820Sjeff p_dbd = osm_db_domain_init(&db, "lid_by_guid"); 664219820Sjeff 665219820Sjeff if (osm_db_restore(p_dbd)) { 666219820Sjeff printf("failed to restore\n"); 667219820Sjeff } 668219820Sjeff 669219820Sjeff if (osm_db_keys(p_dbd, &keys)) { 670219820Sjeff printf("failed to get keys\n"); 671219820Sjeff } else { 672219820Sjeff kI = cl_list_head(&keys); 673219820Sjeff while (kI != cl_list_end(&keys)) { 674219820Sjeff p_key = cl_list_obj(kI); 675219820Sjeff kI = cl_list_next(kI); 676219820Sjeff 677219820Sjeff p_val = osm_db_lookup(p_dbd, p_key); 678219820Sjeff printf("key = %s val = %s\n", p_key, p_val); 679219820Sjeff } 680219820Sjeff } 681219820Sjeff 682219820Sjeff cl_list_remove_all(&keys); 683219820Sjeff 684219820Sjeff /* randomly add and remove numbers */ 685219820Sjeff for (i = 0; i < 10; i++) { 686219820Sjeff int k; 687219820Sjeff float v; 688219820Sjeff int is_add; 689219820Sjeff char val_buf[16]; 690219820Sjeff char key_buf[16]; 691219820Sjeff 692219820Sjeff k = floor(1.0 * rand() / RAND_MAX * 100); 693219820Sjeff v = rand(); 694219820Sjeff sprintf(key_buf, "%u", k); 695219820Sjeff sprintf(val_buf, "%u", v); 696219820Sjeff 697219820Sjeff is_add = (rand() < RAND_MAX / 2); 698219820Sjeff 699219820Sjeff if (is_add) { 700219820Sjeff osm_db_update(p_dbd, key_buf, val_buf); 701219820Sjeff } else { 702219820Sjeff osm_db_delete(p_dbd, key_buf); 703219820Sjeff } 704219820Sjeff } 705219820Sjeff if (osm_db_keys(p_dbd, &keys)) { 706219820Sjeff printf("failed to get keys\n"); 707219820Sjeff } else { 708219820Sjeff kI = cl_list_head(&keys); 709219820Sjeff while (kI != cl_list_end(&keys)) { 710219820Sjeff p_key = cl_list_obj(kI); 711219820Sjeff kI = cl_list_next(kI); 712219820Sjeff 713219820Sjeff p_val = osm_db_lookup(p_dbd, p_key); 714219820Sjeff printf("key = %s val = %s\n", p_key, p_val); 715219820Sjeff } 716219820Sjeff } 717219820Sjeff if (osm_db_store(p_dbd)) 718219820Sjeff printf("failed to store\n"); 719219820Sjeff 720219820Sjeff osm_db_destroy(&db); 721219820Sjeff cl_list_destroy(&keys); 722219820Sjeff} 723219820Sjeff#endif 724