trx0rseg.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. Rollback segment
  3. (c) 1996 Innobase Oy
  4. Created 3/26/1996 Heikki Tuuri
  5. *******************************************************/
  6. #include "trx0rseg.h"
  7. #ifdef UNIV_NONINL
  8. #include "trx0rseg.ic"
  9. #endif
  10. #include "trx0undo.h"
  11. #include "fut0lst.h"
  12. #include "srv0srv.h"
  13. #include "trx0purge.h"
  14. /**********************************************************************
  15. Looks for a rollback segment, based on the rollback segment id. */
  16. trx_rseg_t*
  17. trx_rseg_get_on_id(
  18. /*===============*/
  19. /* out: rollback segment */
  20. ulint id) /* in: rollback segment id */
  21. {
  22. trx_rseg_t* rseg;
  23. rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
  24. ut_ad(rseg);
  25. while (rseg->id != id) {
  26. rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
  27. ut_ad(rseg);
  28. }
  29. return(rseg);
  30. }
  31. /********************************************************************
  32. Creates a rollback segment header. This function is called only when
  33. a new rollback segment is created in the database. */
  34. ulint
  35. trx_rseg_header_create(
  36. /*===================*/
  37. /* out: page number of the created segment,
  38. FIL_NULL if fail */
  39. ulint space, /* in: space id */
  40. ulint max_size, /* in: max size in pages */
  41. ulint* slot_no, /* out: rseg id == slot number in trx sys */
  42. mtr_t* mtr) /* in: mtr */
  43. {
  44. ulint page_no;
  45. trx_rsegf_t* rsegf;
  46. trx_sysf_t* sys_header;
  47. ulint i;
  48. page_t* page;
  49. ut_ad(mtr);
  50. #ifdef UNIV_SYNC_DEBUG
  51. ut_ad(mutex_own(&kernel_mutex));
  52. #endif /* UNIV_SYNC_DEBUG */
  53. ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space),
  54. MTR_MEMO_X_LOCK));
  55. sys_header = trx_sysf_get(mtr);
  56. *slot_no = trx_sysf_rseg_find_free(mtr);
  57. if (*slot_no == ULINT_UNDEFINED) {
  58. return(FIL_NULL);
  59. }
  60. /* Allocate a new file segment for the rollback segment */
  61. page = fseg_create(space, 0, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr);
  62. if (page == NULL) {
  63. /* No space left */
  64. return(FIL_NULL);
  65. }
  66. #ifdef UNIV_SYNC_DEBUG
  67. buf_page_dbg_add_level(page, SYNC_RSEG_HEADER_NEW);
  68. #endif /* UNIV_SYNC_DEBUG */
  69. page_no = buf_frame_get_page_no(page);
  70. /* Get the rollback segment file page */
  71. rsegf = trx_rsegf_get_new(space, page_no, mtr);
  72.     
  73. /* Initialize max size field */
  74. mlog_write_ulint(rsegf + TRX_RSEG_MAX_SIZE, max_size, MLOG_4BYTES, mtr);
  75. /* Initialize the history list */
  76. mlog_write_ulint(rsegf + TRX_RSEG_HISTORY_SIZE, 0, MLOG_4BYTES, mtr);
  77. flst_init(rsegf + TRX_RSEG_HISTORY, mtr);
  78. /* Reset the undo log slots */
  79. for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
  80. trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
  81. }
  82. /* Add the rollback segment info to the free slot in the trx system
  83. header */
  84. trx_sysf_rseg_set_space(sys_header, *slot_no, space, mtr);
  85. trx_sysf_rseg_set_page_no(sys_header, *slot_no, page_no, mtr);
  86. return(page_no);
  87. }
  88. /***************************************************************************
  89. Creates and initializes a rollback segment object. The values for the
  90. fields are read from the header. The object is inserted to the rseg
  91. list of the trx system object and a pointer is inserted in the rseg
  92. array in the trx system object. */
  93. static
  94. trx_rseg_t*
  95. trx_rseg_mem_create(
  96. /*================*/
  97. /* out, own: rollback segment object */
  98. ulint id, /* in: rollback segment id */
  99. ulint space, /* in: space where the segment placed */
  100. ulint page_no, /* in: page number of the segment header */
  101. mtr_t* mtr) /* in: mtr */
  102. {
  103. trx_rsegf_t* rseg_header;
  104. trx_rseg_t* rseg;
  105. trx_ulogf_t* undo_log_hdr;
  106. fil_addr_t node_addr;
  107. ulint sum_of_undo_sizes;
  108. ulint len;
  109. #ifdef UNIV_SYNC_DEBUG
  110. ut_ad(mutex_own(&kernel_mutex));
  111. #endif /* UNIV_SYNC_DEBUG */
  112. rseg = mem_alloc(sizeof(trx_rseg_t));
  113. rseg->id = id;
  114. rseg->space = space;
  115. rseg->page_no = page_no;
  116. mutex_create(&(rseg->mutex));
  117. mutex_set_level(&(rseg->mutex), SYNC_RSEG);
  118. UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg);
  119. trx_sys_set_nth_rseg(trx_sys, id, rseg);
  120. rseg_header = trx_rsegf_get_new(space, page_no, mtr);
  121. rseg->max_size = mtr_read_ulint(rseg_header + TRX_RSEG_MAX_SIZE,
  122. MLOG_4BYTES, mtr);
  123. /* Initialize the undo log lists according to the rseg header */
  124. sum_of_undo_sizes = trx_undo_lists_init(rseg);
  125. rseg->curr_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
  126. MLOG_4BYTES, mtr)
  127.   + 1 + sum_of_undo_sizes;
  128. len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr);
  129. if (len > 0) {
  130. trx_sys->rseg_history_len += len;
  131. node_addr = trx_purge_get_log_from_hist(
  132.       flst_get_last(rseg_header + TRX_RSEG_HISTORY,
  133. mtr));
  134. rseg->last_page_no = node_addr.page;
  135. rseg->last_offset = node_addr.boffset;
  136. undo_log_hdr = trx_undo_page_get(rseg->space, node_addr.page,
  137. mtr)
  138.        + node_addr.boffset;
  139.        
  140. rseg->last_trx_no = mtr_read_dulint(
  141. undo_log_hdr + TRX_UNDO_TRX_NO, mtr);
  142. rseg->last_del_marks = mtr_read_ulint(
  143. undo_log_hdr + TRX_UNDO_DEL_MARKS,
  144. MLOG_2BYTES, mtr);
  145. } else {
  146. rseg->last_page_no = FIL_NULL;
  147. }
  148. return(rseg);
  149. }
  150. /*************************************************************************
  151. Creates the memory copies for rollback segments and initializes the
  152. rseg list and array in trx_sys at a database startup. */
  153. void
  154. trx_rseg_list_and_array_init(
  155. /*=========================*/
  156. trx_sysf_t* sys_header, /* in: trx system header */
  157. mtr_t* mtr) /* in: mtr */
  158. {
  159. ulint i;
  160. ulint page_no;
  161. ulint space;
  162. UT_LIST_INIT(trx_sys->rseg_list);
  163. trx_sys->rseg_history_len = 0;
  164. for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
  165. page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
  166. if (page_no == FIL_NULL) {
  167. trx_sys_set_nth_rseg(trx_sys, i, NULL);
  168. } else {
  169. space = trx_sysf_rseg_get_space(sys_header, i, mtr);
  170. trx_rseg_mem_create(i, space, page_no, mtr);
  171. }
  172. }
  173. }
  174. /********************************************************************
  175. Creates a new rollback segment to the database. */
  176. trx_rseg_t*
  177. trx_rseg_create(
  178. /*============*/
  179. /* out: the created segment object, NULL if
  180. fail */
  181. ulint space, /* in: space id */
  182. ulint max_size, /* in: max size in pages */
  183. ulint* id, /* out: rseg id */
  184. mtr_t* mtr) /* in: mtr */
  185. {
  186. ulint page_no;
  187. trx_rseg_t* rseg;
  188. mtr_x_lock(fil_space_get_latch(space), mtr);
  189. mutex_enter(&kernel_mutex);
  190. page_no = trx_rseg_header_create(space, max_size, id, mtr);
  191. if (page_no == FIL_NULL) {
  192. mutex_exit(&kernel_mutex);
  193. return(NULL);
  194. }
  195. rseg = trx_rseg_mem_create(*id, space, page_no, mtr);
  196. mutex_exit(&kernel_mutex);
  197. return(rseg);
  198. }