1/* 2 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2007 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. 6 * 7 * This software is available to you under a choice of one of two 8 * licenses. You may choose to be licensed under the terms of the GNU 9 * General Public License (GPL) Version 2, available from the file 10 * COPYING in the main directory of this source tree, or the 11 * OpenIB.org BSD license below: 12 * 13 * Redistribution and use in source and binary forms, with or 14 * without modification, are permitted provided that the following 15 * conditions are met: 16 * 17 * - Redistributions of source code must retain the above 18 * copyright notice, this list of conditions and the following 19 * disclaimer. 20 * 21 * - Redistributions in binary form must reproduce the above 22 * copyright notice, this list of conditions and the following 23 * disclaimer in the documentation and/or other materials 24 * provided with the distribution. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 * SOFTWARE. 34 * 35 */ 36 37/* 38 * Abstract: 39 * Implementation of the osm_db interface using simple text files 40 */ 41 42#if HAVE_CONFIG_H 43# include <config.h> 44#endif /* HAVE_CONFIG_H */ 45 46#include <sys/stat.h> 47#include <sys/types.h> 48#include <errno.h> 49#include <stdlib.h> 50#include <string.h> 51#include <unistd.h> 52#include <opensm/osm_file_ids.h> 53#define FILE_ID OSM_FILE_DB_FILES_C 54#include <opensm/st.h> 55#include <opensm/osm_db.h> 56#include <opensm/osm_log.h> 57 58/****d* Database/OSM_DB_MAX_LINE_LEN 59 * NAME 60 * OSM_DB_MAX_LINE_LEN 61 * 62 * DESCRIPTION 63 * The Maximal line length allowed for the file 64 * 65 * SYNOPSIS 66 */ 67#define OSM_DB_MAX_LINE_LEN 1024 68/**********/ 69 70/****d* Database/OSM_DB_MAX_GUID_LEN 71 * NAME 72 * OSM_DB_MAX_GUID_LEN 73 * 74 * DESCRIPTION 75 * The Maximal word length allowed for the file (guid or lid) 76 * 77 * SYNOPSIS 78 */ 79#define OSM_DB_MAX_GUID_LEN 32 80/**********/ 81 82/****s* OpenSM: Database/osm_db_domain_imp 83 * NAME 84 * osm_db_domain_imp 85 * 86 * DESCRIPTION 87 * An implementation for domain of the database based on text files and 88 * hash tables. 89 * 90 * SYNOPSIS 91 */ 92typedef struct osm_db_domain_imp { 93 char *file_name; 94 st_table *p_hash; 95 cl_spinlock_t lock; 96 boolean_t dirty; 97} osm_db_domain_imp_t; 98/* 99 * FIELDS 100 * 101 * SEE ALSO 102 * osm_db_domain_t 103 *********/ 104 105/****s* OpenSM: Database/osm_db_imp_t 106 * NAME 107 * osm_db_imp_t 108 * 109 * DESCRIPTION 110 * An implementation for file based database 111 * 112 * SYNOPSIS 113 */ 114typedef struct osm_db_imp { 115 const char *db_dir_name; 116} osm_db_imp_t; 117/* 118 * FIELDS 119 * 120 * db_dir_name 121 * The directory holding the database 122 * 123 * SEE ALSO 124 * osm_db_t 125 *********/ 126 127void osm_db_construct(IN osm_db_t * p_db) 128{ 129 memset(p_db, 0, sizeof(osm_db_t)); 130 cl_list_construct(&p_db->domains); 131} 132 133void osm_db_domain_destroy(IN osm_db_domain_t * p_db_domain) 134{ 135 osm_db_domain_imp_t *p_domain_imp; 136 p_domain_imp = (osm_db_domain_imp_t *) p_db_domain->p_domain_imp; 137 138 osm_db_clear(p_db_domain); 139 140 cl_spinlock_destroy(&p_domain_imp->lock); 141 142 st_free_table(p_domain_imp->p_hash); 143 free(p_domain_imp->file_name); 144 free(p_domain_imp); 145} 146 147void osm_db_destroy(IN osm_db_t * p_db) 148{ 149 osm_db_domain_t *p_domain; 150 151 while ((p_domain = cl_list_remove_head(&p_db->domains)) != NULL) { 152 osm_db_domain_destroy(p_domain); 153 free(p_domain); 154 } 155 cl_list_destroy(&p_db->domains); 156 free(p_db->p_db_imp); 157} 158 159int osm_db_init(IN osm_db_t * p_db, IN osm_log_t * p_log) 160{ 161 osm_db_imp_t *p_db_imp; 162 struct stat dstat; 163 164 OSM_LOG_ENTER(p_log); 165 166 p_db_imp = malloc(sizeof(osm_db_imp_t)); 167 if (!p_db_imp) { 168 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6100: " 169 "Failed to allocate db memory\n"); 170 return -1; 171 } 172 173 p_db_imp->db_dir_name = getenv("OSM_CACHE_DIR"); 174 if (!p_db_imp->db_dir_name || !(*p_db_imp->db_dir_name)) 175 p_db_imp->db_dir_name = OSM_DEFAULT_CACHE_DIR; 176 177 /* Create the directory if it doesn't exist */ 178 /* There is a difference in creating directory between windows and linux */ 179#ifdef __WIN__ 180 { 181 int ret; 182 183 ret = SHCreateDirectoryEx(NULL, p_db_imp->db_dir_name, NULL); 184 if (ret != ERROR_SUCCESS && ret != ERROR_ALREADY_EXISTS && 185 ret != ERROR_FILE_EXISTS) 186 goto err; 187 } 188#else /* __WIN__ */ 189 /* make sure the directory exists */ 190 if (lstat(p_db_imp->db_dir_name, &dstat)) { 191 if (mkdir(p_db_imp->db_dir_name, 0755)) 192 goto err; 193 } 194#endif 195 196 p_db->p_log = p_log; 197 p_db->p_db_imp = (void *)p_db_imp; 198 199 cl_list_init(&p_db->domains, 5); 200 201 OSM_LOG_EXIT(p_log); 202 203 return 0; 204 205err: 206 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6101: " 207 "Failed to create the db directory:%s\n", 208 p_db_imp->db_dir_name); 209 free(p_db_imp); 210 OSM_LOG_EXIT(p_log); 211 return 1; 212} 213 214osm_db_domain_t *osm_db_domain_init(IN osm_db_t * p_db, IN const char *domain_name) 215{ 216 osm_db_domain_t *p_domain; 217 osm_db_domain_imp_t *p_domain_imp; 218 size_t path_len; 219 osm_log_t *p_log = p_db->p_log; 220 FILE *p_file; 221 222 OSM_LOG_ENTER(p_log); 223 224 /* allocate a new domain object */ 225 p_domain = malloc(sizeof(osm_db_domain_t)); 226 if (p_domain == NULL) { 227 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610C: " 228 "Failed to allocate domain memory\n"); 229 goto Exit; 230 } 231 232 p_domain_imp = malloc(sizeof(osm_db_domain_imp_t)); 233 if (p_domain_imp == NULL) { 234 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610D: " 235 "Failed to allocate domain_imp memory\n"); 236 free(p_domain); 237 p_domain = NULL; 238 goto Exit; 239 } 240 241 path_len = strlen(((osm_db_imp_t *) p_db->p_db_imp)->db_dir_name) 242 + strlen(domain_name) + 2; 243 244 /* set the domain file name */ 245 p_domain_imp->file_name = malloc(path_len); 246 if (p_domain_imp->file_name == NULL) { 247 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610E: " 248 "Failed to allocate file_name memory\n"); 249 free(p_domain_imp); 250 free(p_domain); 251 p_domain = NULL; 252 goto Exit; 253 } 254 snprintf(p_domain_imp->file_name, path_len, "%s/%s", 255 ((osm_db_imp_t *) p_db->p_db_imp)->db_dir_name, domain_name); 256 257 /* make sure the file exists - or exit if not writable */ 258 p_file = fopen(p_domain_imp->file_name, "a+"); 259 if (!p_file) { 260 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6102: " 261 "Failed to open the db file:%s\n", 262 p_domain_imp->file_name); 263 free(p_domain_imp); 264 free(p_domain); 265 p_domain = NULL; 266 goto Exit; 267 } 268 fclose(p_file); 269 270 /* initialize the hash table object */ 271 p_domain_imp->p_hash = st_init_strtable(); 272 CL_ASSERT(p_domain_imp->p_hash != NULL); 273 p_domain_imp->dirty = FALSE; 274 275 p_domain->p_db = p_db; 276 cl_list_insert_tail(&p_db->domains, p_domain); 277 p_domain->p_domain_imp = p_domain_imp; 278 cl_spinlock_construct(&p_domain_imp->lock); 279 cl_spinlock_init(&p_domain_imp->lock); 280 281Exit: 282 OSM_LOG_EXIT(p_log); 283 return p_domain; 284} 285 286int osm_db_restore(IN osm_db_domain_t * p_domain) 287{ 288 289 osm_log_t *p_log = p_domain->p_db->p_log; 290 osm_db_domain_imp_t *p_domain_imp = 291 (osm_db_domain_imp_t *) p_domain->p_domain_imp; 292 FILE *p_file; 293 int status; 294 char sLine[OSM_DB_MAX_LINE_LEN]; 295 boolean_t before_key; 296 char *p_first_word, *p_rest_of_line, *p_last; 297 char *p_key = NULL; 298 char *p_prev_val = NULL, *p_accum_val = NULL; 299 char *endptr = NULL; 300 unsigned int line_num; 301 302 OSM_LOG_ENTER(p_log); 303 304 /* take the lock on the domain */ 305 cl_spinlock_acquire(&p_domain_imp->lock); 306 307 /* open the file - read mode */ 308 p_file = fopen(p_domain_imp->file_name, "r"); 309 310 if (!p_file) { 311 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6103: " 312 "Failed to open the db file:%s\n", 313 p_domain_imp->file_name); 314 status = 1; 315 goto Exit; 316 } 317 318 /* parse the file allocating new hash tables as required */ 319 /* 320 states: 321 before_key (0) -> in_key (1) 322 323 before_key: if a word on the first byte - it is the key. state=in_key 324 the rest of the line is start of the value. 325 in_key: unless the line is empty - add it (with newlines) to the value. 326 if empty: state=before_key 327 */ 328 status = 0; 329 before_key = TRUE; 330 line_num = 0; 331 /* if we got to EOF in the middle of a key we add a last newline */ 332 while ((fgets(sLine, OSM_DB_MAX_LINE_LEN, p_file) != NULL) || 333 ((before_key == FALSE) && strcpy(sLine, "\n")) 334 ) { 335 line_num++; 336 if (before_key) { 337 if ((sLine[0] != ' ') && (sLine[0] != '\t') 338 && (sLine[0] != '\n')) { 339 /* we got a new key */ 340 before_key = FALSE; 341 342 /* handle the key */ 343 p_first_word = 344 strtok_r(sLine, " \t\n", &p_last); 345 if (!p_first_word) { 346 OSM_LOG(p_log, OSM_LOG_ERROR, 347 "ERR 6104: " 348 "Failed to get key from line:%u : %s (file:%s)\n", 349 line_num, sLine, 350 p_domain_imp->file_name); 351 status = 1; 352 goto EndParsing; 353 } 354 if (strlen(p_first_word) > OSM_DB_MAX_GUID_LEN) { 355 OSM_LOG(p_log, OSM_LOG_ERROR, 356 "ERR 610A: " 357 "Illegal key from line:%u : %s (file:%s)\n", 358 line_num, sLine, 359 p_domain_imp->file_name); 360 status = 1; 361 goto EndParsing; 362 } 363 364 p_key = malloc(sizeof(char) * 365 (strlen(p_first_word) + 1)); 366 strcpy(p_key, p_first_word); 367 368 p_rest_of_line = strtok_r(NULL, "\n", &p_last); 369 if (p_rest_of_line != NULL) { 370 p_accum_val = malloc(sizeof(char) * 371 (strlen(p_rest_of_line) + 1)); 372 strcpy(p_accum_val, p_rest_of_line); 373 } else { 374 p_accum_val = malloc(2); 375 strcpy(p_accum_val, "\0"); 376 } 377 } else if (sLine[0] != '\n') { 378 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6105: " 379 "How did we get here? line:%u : %s (file:%s)\n", 380 line_num, sLine, 381 p_domain_imp->file_name); 382 status = 1; 383 goto EndParsing; 384 } 385 } /* before key */ 386 else { 387 /* we already have a key */ 388 389 if (sLine[0] == '\n') { 390 /* got an end of key */ 391 before_key = TRUE; 392 393 /* make sure the key was not previously used */ 394 if (st_lookup(p_domain_imp->p_hash, 395 (st_data_t) p_key, 396 (void *)&p_prev_val)) { 397 /* if previously used we ignore this guid */ 398 OSM_LOG(p_log, OSM_LOG_ERROR, 399 "ERR 6106: " 400 "Key:%s already exists in:%s with value:%s." 401 " Removing it\n", p_key, 402 p_domain_imp->file_name, 403 p_prev_val); 404 free(p_key); 405 p_key = NULL; 406 free(p_accum_val); 407 p_accum_val = NULL; 408 continue; 409 } else { 410 p_prev_val = NULL; 411 } 412 413 OSM_LOG(p_log, OSM_LOG_DEBUG, 414 "Got key:%s value:%s\n", p_key, 415 p_accum_val); 416 417 /* check that the key is a number */ 418 if (!strtouq(p_key, &endptr, 0) 419 && *endptr != '\0') { 420 OSM_LOG(p_log, OSM_LOG_ERROR, 421 "ERR 610B: " 422 "Key:%s is invalid\n", p_key); 423 free(p_key); 424 p_key = NULL; 425 free(p_accum_val); 426 p_accum_val = NULL; 427 } else { 428 /* store our key and value */ 429 st_insert(p_domain_imp->p_hash, 430 (st_data_t) p_key, 431 (st_data_t) p_accum_val); 432 } 433 } else { 434 /* accumulate into the value */ 435 p_prev_val = p_accum_val; 436 p_accum_val = malloc(strlen(p_prev_val) + 437 strlen(sLine) + 1); 438 strcpy(p_accum_val, p_prev_val); 439 free(p_prev_val); 440 p_prev_val = NULL; 441 strcat(p_accum_val, sLine); 442 } 443 } /* in key */ 444 } /* while lines or last line */ 445 446EndParsing: 447 fclose(p_file); 448 449Exit: 450 cl_spinlock_release(&p_domain_imp->lock); 451 OSM_LOG_EXIT(p_log); 452 return status; 453} 454 455static int dump_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) 456{ 457 FILE *p_file = (FILE *) arg; 458 char *p_key = (char *)key; 459 char *p_val = (char *)val; 460 461 fprintf(p_file, "%s %s\n\n", p_key, p_val); 462 return ST_CONTINUE; 463} 464 465int osm_db_store(IN osm_db_domain_t * p_domain, 466 IN boolean_t fsync_high_avail_files) 467{ 468 osm_log_t *p_log = p_domain->p_db->p_log; 469 osm_db_domain_imp_t *p_domain_imp; 470 FILE *p_file = NULL; 471 int fd, status = 0; 472 char *p_tmp_file_name = NULL; 473 474 OSM_LOG_ENTER(p_log); 475 476 p_domain_imp = (osm_db_domain_imp_t *) p_domain->p_domain_imp; 477 478 p_tmp_file_name = malloc(sizeof(char) * 479 (strlen(p_domain_imp->file_name) + 8)); 480 if (!p_tmp_file_name) { 481 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6113: " 482 "Failed to allocate memory for temporary file name\n"); 483 goto Exit2; 484 } 485 strcpy(p_tmp_file_name, p_domain_imp->file_name); 486 strcat(p_tmp_file_name, ".tmp"); 487 488 cl_spinlock_acquire(&p_domain_imp->lock); 489 490 if (p_domain_imp->dirty == FALSE) 491 goto Exit; 492 493 /* open up the output file */ 494 p_file = fopen(p_tmp_file_name, "w"); 495 if (!p_file) { 496 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6107: " 497 "Failed to open the db file:%s for writing: err:%s\n", 498 p_domain_imp->file_name, strerror(errno)); 499 status = 1; 500 goto Exit; 501 } 502 503 st_foreach(p_domain_imp->p_hash, dump_tbl_entry, (st_data_t) p_file); 504 505 if (fsync_high_avail_files) { 506 if (fflush(p_file) == 0) { 507 fd = fileno(p_file); 508 if (fd != -1) { 509 if (fsync(fd) == -1) 510 OSM_LOG(p_log, OSM_LOG_ERROR, 511 "ERR 6110: fsync() failed (%s) for %s\n", 512 strerror(errno), 513 p_domain_imp->file_name); 514 } else 515 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6111: " 516 "fileno() failed for %s\n", 517 p_domain_imp->file_name); 518 } else 519 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6112: " 520 "fflush() failed (%s) for %s\n", 521 strerror(errno), p_domain_imp->file_name); 522 } 523 524 fclose(p_file); 525 526 status = rename(p_tmp_file_name, p_domain_imp->file_name); 527 if (status) { 528 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6108: " 529 "Failed to rename the db file to:%s (err:%s)\n", 530 p_domain_imp->file_name, strerror(errno)); 531 goto Exit; 532 } 533 p_domain_imp->dirty = FALSE; 534Exit: 535 cl_spinlock_release(&p_domain_imp->lock); 536 free(p_tmp_file_name); 537Exit2: 538 OSM_LOG_EXIT(p_log); 539 return status; 540} 541 542/* simply de-allocate the key and the value and return the code 543 that makes the st_foreach delete the entry */ 544static int clear_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) 545{ 546 free((char *)key); 547 free((char *)val); 548 return ST_DELETE; 549} 550 551int osm_db_clear(IN osm_db_domain_t * p_domain) 552{ 553 osm_db_domain_imp_t *p_domain_imp = 554 (osm_db_domain_imp_t *) p_domain->p_domain_imp; 555 556 cl_spinlock_acquire(&p_domain_imp->lock); 557 st_foreach(p_domain_imp->p_hash, clear_tbl_entry, (st_data_t) NULL); 558 cl_spinlock_release(&p_domain_imp->lock); 559 560 return 0; 561} 562 563static int get_key_of_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) 564{ 565 cl_list_t *p_list = (cl_list_t *) arg; 566 cl_list_insert_tail(p_list, (void *)key); 567 return ST_CONTINUE; 568} 569 570int osm_db_keys(IN osm_db_domain_t * p_domain, OUT cl_list_t * p_key_list) 571{ 572 osm_db_domain_imp_t *p_domain_imp = 573 (osm_db_domain_imp_t *) p_domain->p_domain_imp; 574 575 cl_spinlock_acquire(&p_domain_imp->lock); 576 577 st_foreach(p_domain_imp->p_hash, get_key_of_tbl_entry, 578 (st_data_t) p_key_list); 579 580 cl_spinlock_release(&p_domain_imp->lock); 581 582 return 0; 583} 584 585char *osm_db_lookup(IN osm_db_domain_t * p_domain, IN char *p_key) 586{ 587 osm_db_domain_imp_t *p_domain_imp = 588 (osm_db_domain_imp_t *) p_domain->p_domain_imp; 589 char *p_val = NULL; 590 591 cl_spinlock_acquire(&p_domain_imp->lock); 592 593 if (!st_lookup(p_domain_imp->p_hash, (st_data_t) p_key, (void *)&p_val)) 594 p_val = NULL; 595 596 cl_spinlock_release(&p_domain_imp->lock); 597 598 return p_val; 599} 600 601int osm_db_update(IN osm_db_domain_t * p_domain, IN char *p_key, IN char *p_val) 602{ 603 osm_log_t *p_log = p_domain->p_db->p_log; 604 osm_db_domain_imp_t *p_domain_imp = 605 (osm_db_domain_imp_t *) p_domain->p_domain_imp; 606 char *p_prev_val = NULL; 607 char *p_new_key; 608 char *p_new_val; 609 610 cl_spinlock_acquire(&p_domain_imp->lock); 611 612 if (st_lookup(p_domain_imp->p_hash, 613 (st_data_t) p_key, (void *)&p_prev_val)) { 614 OSM_LOG(p_log, OSM_LOG_DEBUG, 615 "Key:%s previously exists in:%s with value:%s\n", 616 p_key, p_domain_imp->file_name, p_prev_val); 617 p_new_key = p_key; 618 /* same key, same value - nothing to update */ 619 if (p_prev_val && !strcmp(p_val, p_prev_val)) 620 goto Exit; 621 } else { 622 /* need to allocate the key */ 623 p_new_key = malloc(sizeof(char) * (strlen(p_key) + 1)); 624 strcpy(p_new_key, p_key); 625 } 626 627 /* need to arange a new copy of the value */ 628 p_new_val = malloc(sizeof(char) * (strlen(p_val) + 1)); 629 strcpy(p_new_val, p_val); 630 631 st_insert(p_domain_imp->p_hash, (st_data_t) p_new_key, 632 (st_data_t) p_new_val); 633 634 if (p_prev_val) 635 free(p_prev_val); 636 637 p_domain_imp->dirty = TRUE; 638 639Exit: 640 cl_spinlock_release(&p_domain_imp->lock); 641 642 return 0; 643} 644 645int osm_db_delete(IN osm_db_domain_t * p_domain, IN char *p_key) 646{ 647 osm_log_t *p_log = p_domain->p_db->p_log; 648 osm_db_domain_imp_t *p_domain_imp = 649 (osm_db_domain_imp_t *) p_domain->p_domain_imp; 650 char *p_prev_val = NULL; 651 int res; 652 653 OSM_LOG_ENTER(p_log); 654 655 cl_spinlock_acquire(&p_domain_imp->lock); 656 if (st_delete(p_domain_imp->p_hash, 657 (void *)&p_key, (void *)&p_prev_val)) { 658 if (st_lookup(p_domain_imp->p_hash, 659 (st_data_t) p_key, (void *)&p_prev_val)) { 660 OSM_LOG(p_log, OSM_LOG_ERROR, 661 "key:%s still exists in:%s with value:%s\n", 662 p_key, p_domain_imp->file_name, p_prev_val); 663 res = 1; 664 } else { 665 free(p_key); 666 free(p_prev_val); 667 p_domain_imp->dirty = TRUE; 668 res = 0; 669 } 670 } else { 671 OSM_LOG(p_log, OSM_LOG_DEBUG, 672 "fail to find key:%s. delete failed\n", p_key); 673 res = 1; 674 } 675 cl_spinlock_release(&p_domain_imp->lock); 676 677 OSM_LOG_EXIT(p_log); 678 return res; 679} 680 681#ifdef TEST_OSMDB 682#include <stdlib.h> 683#include <math.h> 684 685int main(int argc, char **argv) 686{ 687 osm_db_t db; 688 osm_log_t log; 689 osm_db_domain_t *p_dbd; 690 cl_list_t keys; 691 cl_list_iterator_t kI; 692 char *p_key; 693 char *p_val; 694 int i; 695 696 cl_list_construct(&keys); 697 cl_list_init(&keys, 10); 698 699 osm_log_init_v2(&log, TRUE, 0xff, "/var/log/osm_db_test.log", 0, FALSE); 700 701 osm_db_construct(&db); 702 if (osm_db_init(&db, &log)) { 703 printf("db init failed\n"); 704 exit(1); 705 } 706 707 p_dbd = osm_db_domain_init(&db, "lid_by_guid"); 708 if (!p_dbd) { 709 printf("db domain init failed\n"); 710 exit(1); 711 } 712 713 if (osm_db_restore(p_dbd)) { 714 printf("failed to restore\n"); 715 } 716 717 if (osm_db_keys(p_dbd, &keys)) { 718 printf("failed to get keys\n"); 719 } else { 720 kI = cl_list_head(&keys); 721 while (kI != cl_list_end(&keys)) { 722 p_key = cl_list_obj(kI); 723 kI = cl_list_next(kI); 724 725 p_val = osm_db_lookup(p_dbd, p_key); 726 printf("key = %s val = %s\n", p_key, p_val); 727 } 728 } 729 730 cl_list_remove_all(&keys); 731 732 /* randomly add and remove numbers */ 733 for (i = 0; i < 10; i++) { 734 int k; 735 float v; 736 int is_add; 737 char val_buf[16]; 738 char key_buf[16]; 739 740 k = floor(1.0 * rand() / RAND_MAX * 100); 741 v = rand(); 742 sprintf(key_buf, "%u", k); 743 sprintf(val_buf, "%u", v); 744 745 is_add = (rand() < RAND_MAX / 2); 746 747 if (is_add) { 748 osm_db_update(p_dbd, key_buf, val_buf); 749 } else { 750 osm_db_delete(p_dbd, key_buf); 751 } 752 } 753 if (osm_db_keys(p_dbd, &keys)) { 754 printf("failed to get keys\n"); 755 } else { 756 kI = cl_list_head(&keys); 757 while (kI != cl_list_end(&keys)) { 758 p_key = cl_list_obj(kI); 759 kI = cl_list_next(kI); 760 761 p_val = osm_db_lookup(p_dbd, p_key); 762 printf("key = %s val = %s\n", p_key, p_val); 763 } 764 } 765 if (osm_db_store(p_dbd, FALSE)) 766 printf("failed to store\n"); 767 768 osm_db_destroy(&db); 769 cl_list_destroy(&keys); 770} 771#endif 772