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 */
92 typedef 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 */
114 typedef 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
osm_db_construct(IN osm_db_t * p_db)127 void 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
osm_db_domain_destroy(IN osm_db_domain_t * p_db_domain)133 void 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
osm_db_destroy(IN osm_db_t * p_db)147 void 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
osm_db_init(IN osm_db_t * p_db,IN osm_log_t * p_log)159 int 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
205 err:
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
osm_db_domain_init(IN osm_db_t * p_db,IN const char * domain_name)214 osm_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
281 Exit:
282 OSM_LOG_EXIT(p_log);
283 return p_domain;
284 }
285
osm_db_restore(IN osm_db_domain_t * p_domain)286 int 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
446 EndParsing:
447 fclose(p_file);
448
449 Exit:
450 cl_spinlock_release(&p_domain_imp->lock);
451 OSM_LOG_EXIT(p_log);
452 return status;
453 }
454
dump_tbl_entry(st_data_t key,st_data_t val,st_data_t arg)455 static 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
osm_db_store(IN osm_db_domain_t * p_domain,IN boolean_t fsync_high_avail_files)465 int 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;
534 Exit:
535 cl_spinlock_release(&p_domain_imp->lock);
536 free(p_tmp_file_name);
537 Exit2:
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 */
clear_tbl_entry(st_data_t key,st_data_t val,st_data_t arg)544 static 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
osm_db_clear(IN osm_db_domain_t * p_domain)551 int 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
get_key_of_tbl_entry(st_data_t key,st_data_t val,st_data_t arg)563 static 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
osm_db_keys(IN osm_db_domain_t * p_domain,OUT cl_list_t * p_key_list)570 int 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
osm_db_lookup(IN osm_db_domain_t * p_domain,IN char * p_key)585 char *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
osm_db_update(IN osm_db_domain_t * p_domain,IN char * p_key,IN char * p_val)601 int 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
639 Exit:
640 cl_spinlock_release(&p_domain_imp->lock);
641
642 return 0;
643 }
644
osm_db_delete(IN osm_db_domain_t * p_domain,IN char * p_key)645 int 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
main(int argc,char ** argv)685 int 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