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