ha0ha.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /************************************************************************
  2. The hash table with external chains
  3. (c) 1994-1997 Innobase Oy
  4. Created 8/22/1994 Heikki Tuuri
  5. *************************************************************************/
  6. #include "ha0ha.h"
  7. #ifdef UNIV_NONINL
  8. #include "ha0ha.ic"
  9. #endif
  10. #include "buf0buf.h"
  11. /*****************************************************************
  12. Creates a hash table with >= n array cells. The actual number of cells is
  13. chosen to be a prime number slightly bigger than n. */
  14. hash_table_t*
  15. ha_create(
  16. /*======*/
  17. /* out, own: created table */
  18. ibool in_btr_search, /* in: TRUE if the hash table is used in
  19. the btr_search module */
  20. ulint n, /* in: number of array cells */
  21. ulint n_mutexes, /* in: number of mutexes to protect the
  22. hash table: must be a power of 2, or 0 */
  23. ulint mutex_level) /* in: level of the mutexes in the latching
  24. order: this is used in the debug version */
  25. {
  26. hash_table_t* table;
  27. ulint i;
  28. table = hash_create(n);
  29. if (n_mutexes == 0) {
  30. if (in_btr_search) {
  31. table->heap = mem_heap_create_in_btr_search(4096);
  32. } else {
  33. table->heap = mem_heap_create_in_buffer(4096);
  34. }
  35. return(table);
  36. }
  37. hash_create_mutexes(table, n_mutexes, mutex_level);
  38. table->heaps = mem_alloc(n_mutexes * sizeof(void*));
  39. for (i = 0; i < n_mutexes; i++) {
  40. if (in_btr_search) {
  41. table->heaps[i] = mem_heap_create_in_btr_search(4096);
  42. } else {
  43. table->heaps[i] = mem_heap_create_in_buffer(4096);
  44. }
  45. }
  46. return(table);
  47. }
  48. /*****************************************************************
  49. Checks that a hash table node is in the chain. */
  50. ibool
  51. ha_node_in_chain(
  52. /*=============*/
  53. /* out: TRUE if in chain */
  54. hash_cell_t* cell, /* in: hash table cell */
  55. ha_node_t* node) /* in: external chain node */
  56. {
  57. ha_node_t* node2;
  58. node2 = cell->node;
  59. while (node2 != NULL) {
  60. if (node2 == node) {
  61. return(TRUE);
  62. }
  63. node2 = node2->next;
  64. }
  65. return(FALSE);
  66. }
  67. /*****************************************************************
  68. Inserts an entry into a hash table. If an entry with the same fold number
  69. is found, its node is updated to point to the new data, and no new node
  70. is inserted. */
  71. ibool
  72. ha_insert_for_fold(
  73. /*===============*/
  74. /* out: TRUE if succeed, FALSE if no more
  75. memory could be allocated */
  76. hash_table_t* table, /* in: hash table */
  77. ulint fold, /* in: folded value of data; if a node with
  78. the same fold value already exists, it is
  79. updated to point to the same data, and no new
  80. node is created! */
  81. void* data) /* in: data, must not be NULL */
  82. {
  83. hash_cell_t* cell;
  84. ha_node_t* node;
  85. ha_node_t* prev_node;
  86. ulint hash;
  87. ut_ad(table && data);
  88. ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
  89. hash = hash_calc_hash(fold, table);
  90. cell = hash_get_nth_cell(table, hash);
  91. prev_node = cell->node;
  92. while (prev_node != NULL) {
  93. if (prev_node->fold == fold) {
  94. prev_node->data = data;
  95. return(TRUE);
  96. }
  97. prev_node = prev_node->next;
  98. }
  99. /* We have to allocate a new chain node */
  100. node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t));
  101. if (node == NULL) {
  102. /* It was a btr search type memory heap and at the moment
  103. no more memory could be allocated: return */
  104. ut_ad(hash_get_heap(table, fold)->type & MEM_HEAP_BTR_SEARCH);
  105. return(FALSE);
  106. }
  107. ha_node_set_data(node, data);
  108. node->fold = fold;
  109. node->next = NULL;
  110. prev_node = cell->node;
  111. if (prev_node == NULL) {
  112. cell->node = node;
  113. return(TRUE);
  114. }
  115. while (prev_node->next != NULL) {
  116. prev_node = prev_node->next;
  117. }
  118. prev_node->next = node;
  119. return(TRUE);
  120. }
  121. /***************************************************************
  122. Deletes a hash node. */
  123. void
  124. ha_delete_hash_node(
  125. /*================*/
  126. hash_table_t* table, /* in: hash table */
  127. ha_node_t* del_node) /* in: node to be deleted */
  128. {
  129. HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node);
  130. }
  131. /*****************************************************************
  132. Deletes an entry from a hash table. */
  133. void
  134. ha_delete(
  135. /*======*/
  136. hash_table_t* table, /* in: hash table */
  137. ulint fold, /* in: folded value of data */
  138. void* data) /* in: data, must not be NULL and must exist
  139. in the hash table */
  140. {
  141. ha_node_t* node;
  142. ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
  143. node = ha_search_with_data(table, fold, data);
  144. ut_ad(node);
  145. ha_delete_hash_node(table, node);
  146. }
  147. /*********************************************************************
  148. Removes from the chain determined by fold all nodes whose data pointer
  149. points to the page given. */
  150. void
  151. ha_remove_all_nodes_to_page(
  152. /*========================*/
  153. hash_table_t* table, /* in: hash table */
  154. ulint fold, /* in: fold value */
  155. page_t* page) /* in: buffer page */
  156. {
  157. ha_node_t* node;
  158. ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
  159. node = ha_chain_get_first(table, fold);
  160. while (node) {
  161. if (buf_frame_align(ha_node_get_data(node)) == page) {
  162. /* Remove the hash node */
  163. ha_delete_hash_node(table, node);
  164. /* Start again from the first node in the chain
  165. because the deletion may compact the heap of
  166. nodes and move other nodes! */
  167. node = ha_chain_get_first(table, fold);
  168. } else {
  169. node = ha_chain_get_next(table, node);
  170. }
  171. }
  172. }
  173. /*****************************************************************
  174. Validates a hash table. */
  175. ibool
  176. ha_validate(
  177. /*========*/
  178. /* out: TRUE if ok */
  179. hash_table_t* table) /* in: hash table */
  180. {
  181. hash_cell_t* cell;
  182. ha_node_t* node;
  183. ulint i;
  184. for (i = 0; i < hash_get_n_cells(table); i++) {
  185. cell = hash_get_nth_cell(table, i);
  186. node = cell->node;
  187. while (node) {
  188. ut_a(hash_calc_hash(node->fold, table) == i);
  189. node = node->next;
  190. }
  191. }
  192. return(TRUE);
  193. }
  194. /*****************************************************************
  195. Prints info of a hash table. */
  196. void
  197. ha_print_info(
  198. /*==========*/
  199. hash_table_t* table) /* in: hash table */
  200. {
  201. hash_cell_t* cell;
  202. ha_node_t* node;
  203. ulint nodes = 0;
  204. ulint cells = 0;
  205. ulint len = 0;
  206. ulint max_len = 0;
  207. ulint i;
  208. for (i = 0; i < hash_get_n_cells(table); i++) {
  209. cell = hash_get_nth_cell(table, i);
  210. if (cell->node) {
  211. cells++;
  212. len = 0;
  213. node = cell->node;
  214. for (;;) {
  215. len++;
  216. nodes++;
  217. if (ha_chain_get_next(table, node) == NULL) {
  218. break;
  219. }
  220. node = node->next;
  221. }
  222. if (len > max_len) {
  223. max_len = len;
  224. }
  225. }
  226. }
  227. printf("Hash table size %lu, used cells %lu, nodes %lun",
  228. hash_get_n_cells(table), cells, nodes);
  229. printf("max chain length %lun", max_len);
  230. ut_a(ha_validate(table));
  231. }