/** * @file db_debug.c * Debug routines for libdb * * @remark Copyright 2002 OProfile authors * @remark Read the file COPYING * * @author Philippe Elie */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "odb.h" static int check_circular_list(odb_data_t const * data) { odb_node_nr_t pos; int do_abort = 0; unsigned char * bitmap = malloc(data->descr->current_size); memset(bitmap, '\0', data->descr->current_size); for (pos = 0 ; pos < data->descr->size * BUCKET_FACTOR ; ++pos) { odb_index_t index = data->hash_base[pos]; if (index && !do_abort) { while (index) { if (bitmap[index]) do_abort = 1; bitmap[index] = 1; index = data->node_base[index].next; } } if (do_abort) { printf("circular list detected size: %d\n", data->descr->current_size); memset(bitmap, '\0', data->descr->current_size); index = data->hash_base[pos]; while (index) { printf("%d ", index); if (bitmap[index]) exit(1); bitmap[index] = 1; index = data->node_base[index].next; } } /* purely an optimization: intead of memset the map reset only * the needed part: not my use to optimize test but here the * test was so slow it was useless */ index = data->hash_base[pos]; while (index) { bitmap[index] = 1; index = data->node_base[index].next; } } free(bitmap); return do_abort; } static int check_redundant_key(odb_data_t const * data, odb_key_t max) { odb_node_nr_t pos; unsigned char * bitmap = malloc(max + 1); memset(bitmap, '\0', max + 1); for (pos = 1 ; pos < data->descr->current_size ; ++pos) { if (bitmap[data->node_base[pos].key]) { printf("redundant key found %lld\n", (unsigned long long)data->node_base[pos].key); return 1; } bitmap[data->node_base[pos].key] = 1; } free(bitmap); return 0; } int odb_check_hash(odb_t const * odb) { odb_node_nr_t pos; odb_node_nr_t nr_node = 0; odb_node_nr_t nr_node_out_of_bound = 0; int ret = 0; odb_key_t max = 0; odb_data_t * data = odb->data; for (pos = 0 ; pos < data->descr->size * BUCKET_FACTOR ; ++pos) { odb_index_t index = data->hash_base[pos]; while (index) { if (index >= data->descr->current_size) { nr_node_out_of_bound++; break; } ++nr_node; if (data->node_base[index].key > max) max = data->node_base[index].key; index = data->node_base[index].next; } } if (nr_node != data->descr->current_size - 1) { printf("hash table walk found %d node expect %d node\n", nr_node, data->descr->current_size - 1); ret = 1; } if (nr_node_out_of_bound) { printf("out of bound node index: %d\n", nr_node_out_of_bound); ret = 1; } if (ret == 0) ret = check_circular_list(data); if (ret == 0) ret = check_redundant_key(data, max); return ret; }