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

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. The index tree persistent cursor
  3. (c) 1996 Innobase Oy
  4. Created 2/23/1996 Heikki Tuuri
  5. *******************************************************/
  6. #include "btr0pcur.h"
  7. #ifdef UNIV_NONINL
  8. #include "btr0pcur.ic"
  9. #endif
  10. #include "ut0byte.h"
  11. #include "rem0cmp.h"
  12. /******************************************************************
  13. Allocates memory for a persistent cursor object and initializes the cursor. */
  14. btr_pcur_t*
  15. btr_pcur_create_for_mysql(void)
  16. /*============================*/
  17. /* out, own: persistent cursor */
  18. {
  19. btr_pcur_t* pcur;
  20. pcur = mem_alloc(sizeof(btr_pcur_t));
  21. pcur->btr_cur.index = NULL;
  22. btr_pcur_init(pcur);
  23. return(pcur);
  24. }
  25. /******************************************************************
  26. Frees the memory for a persistent cursor object. */
  27. void
  28. btr_pcur_free_for_mysql(
  29. /*====================*/
  30. btr_pcur_t* cursor) /* in, own: persistent cursor */
  31. {
  32. if (cursor->old_rec_buf != NULL) {
  33. mem_free(cursor->old_rec_buf);
  34. cursor->old_rec = NULL;
  35. cursor->old_rec_buf = NULL;
  36. }
  37. cursor->btr_cur.page_cur.rec = NULL;
  38. cursor->old_rec = NULL;
  39. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  40. cursor->latch_mode = BTR_NO_LATCHES;
  41. cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
  42. mem_free(cursor);
  43. }
  44. /******************************************************************
  45. The position of the cursor is stored by taking an initial segment of the
  46. record the cursor is positioned on, before, or after, and copying it to the
  47. cursor data structure. NOTE that the page where the cursor is positioned
  48. must not be empty! */
  49. void
  50. btr_pcur_store_position(
  51. /*====================*/
  52. btr_pcur_t* cursor, /* in: persistent cursor */
  53. mtr_t* mtr) /* in: mtr */
  54. {
  55. page_cur_t* page_cursor;
  56. rec_t* rec;
  57. dict_tree_t* tree;
  58. page_t* page;
  59. ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  60. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  61. tree = btr_cur_get_tree(btr_pcur_get_btr_cur(cursor));
  62. page_cursor = btr_pcur_get_page_cur(cursor);
  63. rec = page_cur_get_rec(page_cursor);
  64. page = buf_frame_align(rec);
  65. ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
  66. MTR_MEMO_PAGE_S_FIX)
  67.       || mtr_memo_contains(mtr, buf_block_align(page),
  68. MTR_MEMO_PAGE_X_FIX));
  69. ut_a(cursor->latch_mode != BTR_NO_LATCHES);
  70. if (page_get_n_recs(page) == 0) {
  71. /* Cannot store position! */
  72. btr_pcur_close(cursor);
  73. return;
  74. if (rec == page_get_supremum_rec(page)) {
  75. rec = page_rec_get_prev(rec);
  76. cursor->rel_pos = BTR_PCUR_AFTER;
  77. } else if (rec == page_get_infimum_rec(page)) {
  78. rec = page_rec_get_next(rec);
  79. cursor->rel_pos = BTR_PCUR_BEFORE;
  80. } else {
  81. cursor->rel_pos = BTR_PCUR_ON;
  82. }
  83. cursor->old_stored = BTR_PCUR_OLD_STORED;
  84. cursor->old_rec = dict_tree_copy_rec_order_prefix(tree, rec,
  85. &(cursor->old_rec_buf),
  86. &(cursor->buf_size));
  87. cursor->modify_clock = buf_frame_get_modify_clock(page);
  88. }
  89. /******************************************************************
  90. Copies the stored position of a pcur to another pcur. */
  91. void
  92. btr_pcur_copy_stored_position(
  93. /*==========================*/
  94. btr_pcur_t* pcur_receive, /* in: pcur which will receive the
  95. position info */
  96. btr_pcur_t* pcur_donate) /* in: pcur from which the info is
  97. copied */
  98. {
  99. if (pcur_receive->old_rec_buf) {
  100. mem_free(pcur_receive->old_rec_buf);
  101. }
  102. ut_memcpy((byte*)pcur_receive, (byte*)pcur_donate, sizeof(btr_pcur_t));
  103. pcur_receive->old_rec_buf = mem_alloc(pcur_donate->buf_size);
  104. ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf,
  105. pcur_donate->buf_size);
  106. pcur_receive->old_rec = pcur_receive->old_rec_buf
  107. + (pcur_donate->old_rec - pcur_donate->old_rec_buf);
  108. }
  109. /******************************************************************
  110. Restores the stored position of a persistent cursor bufferfixing the page and
  111. obtaining the specified latches. If the cursor position was saved when the
  112. (1) cursor was positioned on a user record: this function restores the position
  113. to the last record LESS OR EQUAL to the stored record;
  114. (2) cursor was positioned on a page infimum record: restores the position to
  115. the last record LESS than the user record which was the successor of the page
  116. infimum;
  117. (3) cursor was positioned on the page supremum: restores to the first record
  118. GREATER than the user record which was the predecessor of the supremum. */
  119. ibool
  120. btr_pcur_restore_position(
  121. /*======================*/
  122. /* out: TRUE if the cursor position
  123. was stored when it was on a user record
  124. and it can be restored on a user record
  125. whose ordering fields are identical to
  126. the ones of the original user record */
  127. ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
  128. btr_pcur_t* cursor,  /* in: detached persistent cursor */
  129. mtr_t* mtr) /* in: mtr */
  130. {
  131. dict_tree_t* tree;
  132. page_t* page;
  133. dtuple_t* tuple;
  134. ulint mode;
  135. ulint old_mode;
  136. mem_heap_t* heap;
  137. ut_a((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
  138. || (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
  139. ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED);
  140. ut_a(cursor->old_rec);
  141. page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor));
  142. if ((latch_mode == BTR_SEARCH_LEAF)
  143. || (latch_mode == BTR_MODIFY_LEAF)) {
  144. /* Try optimistic restoration */
  145.     
  146. if (buf_page_optimistic_get(latch_mode, page,
  147. cursor->modify_clock, mtr)) {
  148. cursor->pos_state = BTR_PCUR_IS_POSITIONED;
  149. buf_page_dbg_add_level(page, SYNC_TREE_NODE);
  150. if (cursor->rel_pos == BTR_PCUR_ON) {
  151. cursor->latch_mode = latch_mode;
  152. ut_ad(cmp_rec_rec(cursor->old_rec,
  153. btr_pcur_get_rec(cursor),
  154. dict_tree_find_index(
  155.     btr_cur_get_tree(
  156. btr_pcur_get_btr_cur(cursor)),
  157.     btr_pcur_get_rec(cursor)))
  158. == 0); 
  159. return(TRUE);
  160. }
  161. return(FALSE);
  162. }
  163. }
  164. /* If optimistic restoration did not succeed, open the cursor anew */
  165. heap = mem_heap_create(256);
  166. tree = btr_cur_get_tree(btr_pcur_get_btr_cur(cursor));
  167. tuple = dict_tree_build_data_tuple(tree, cursor->old_rec, heap);
  168. /* Save the old search mode of the cursor */
  169. old_mode = cursor->search_mode;
  170. if (cursor->rel_pos == BTR_PCUR_ON) {
  171. mode = PAGE_CUR_LE;
  172. } else if (cursor->rel_pos == BTR_PCUR_AFTER) {
  173. mode = PAGE_CUR_G;
  174. } else {
  175. ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
  176. mode = PAGE_CUR_L;
  177. }
  178. btr_pcur_open_with_no_init(btr_pcur_get_btr_cur(cursor)->index, tuple,
  179. mode, latch_mode, cursor, 0, mtr);
  180. cursor->old_stored = BTR_PCUR_OLD_STORED;
  181. /* Restore the old search mode */
  182. cursor->search_mode = old_mode;
  183. if ((cursor->rel_pos == BTR_PCUR_ON)
  184. && btr_pcur_is_on_user_rec(cursor, mtr)
  185. && (0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor)))) {
  186. mem_heap_free(heap);
  187. return(TRUE);
  188. }
  189. mem_heap_free(heap);
  190. return(FALSE);
  191. }
  192. /******************************************************************
  193. If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
  194. releases the page latch and bufferfix reserved by the cursor.
  195. NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
  196. made by the current mini-transaction to the data protected by the
  197. cursor latch, as then the latch must not be released until mtr_commit. */
  198. void
  199. btr_pcur_release_leaf(
  200. /*==================*/
  201. btr_pcur_t* cursor, /* in: persistent cursor */
  202. mtr_t* mtr) /* in: mtr */
  203. {
  204. page_t* page;
  205. ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  206. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  207. page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor));
  208. btr_leaf_page_release(page, cursor->latch_mode, mtr);
  209. cursor->latch_mode = BTR_NO_LATCHES;
  210. cursor->pos_state = BTR_PCUR_WAS_POSITIONED;
  211. }
  212. /*************************************************************
  213. Moves the persistent cursor to the first record on the next page. Releases the
  214. latch on the current page, and bufferunfixes it. Note that there must not be
  215. modifications on the current page, as then the x-latch can be released only in
  216. mtr_commit. */
  217. void
  218. btr_pcur_move_to_next_page(
  219. /*=======================*/
  220. btr_pcur_t* cursor, /* in: persistent cursor; must be on the
  221. last record of the current page */
  222. mtr_t* mtr) /* in: mtr */
  223. {
  224. ulint next_page_no;
  225. ulint space;
  226. page_t* page;
  227. page_t* next_page;
  228. ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  229. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  230. ut_ad(btr_pcur_is_after_last_on_page(cursor, mtr));
  231. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  232. page = btr_pcur_get_page(cursor);
  233. next_page_no = btr_page_get_next(page, mtr);
  234. space = buf_frame_get_space_id(page);
  235. ut_ad(next_page_no != FIL_NULL);
  236. next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr);
  237. btr_leaf_page_release(page, cursor->latch_mode, mtr);
  238. page_cur_set_before_first(next_page, btr_pcur_get_page_cur(cursor));
  239. }
  240. /*************************************************************
  241. Moves the persistent cursor backward if it is on the first record of the page.
  242. Commits mtr. Note that to prevent a possible deadlock, the operation
  243. first stores the position of the cursor, commits mtr, acquires the necessary
  244. latches and restores the cursor position again before returning. The
  245. alphabetical position of the cursor is guaranteed to be sensible on
  246. return, but it may happen that the cursor is not positioned on the last
  247. record of any page, because the structure of the tree may have changed
  248. during the time when the cursor had no latches. */
  249. void
  250. btr_pcur_move_backward_from_page(
  251. /*=============================*/
  252. btr_pcur_t* cursor, /* in: persistent cursor, must be on the first
  253. record of the current page */
  254. mtr_t* mtr) /* in: mtr */
  255. {
  256. ulint prev_page_no;
  257. ulint space;
  258. page_t* page;
  259. page_t* prev_page;
  260. ulint latch_mode;
  261. ulint latch_mode2;
  262. ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  263. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  264. ut_ad(btr_pcur_is_before_first_on_page(cursor, mtr));
  265. ut_ad(!btr_pcur_is_before_first_in_tree(cursor, mtr));
  266. latch_mode = cursor->latch_mode;
  267. if (latch_mode == BTR_SEARCH_LEAF) {
  268. latch_mode2 = BTR_SEARCH_PREV;
  269. } else if (latch_mode == BTR_MODIFY_LEAF) {
  270. latch_mode2 = BTR_MODIFY_PREV;
  271. } else {
  272. ut_error;
  273. }
  274. btr_pcur_store_position(cursor, mtr);
  275. mtr_commit(mtr);
  276. mtr_start(mtr);
  277. btr_pcur_restore_position(latch_mode2, cursor, mtr);
  278. page = btr_pcur_get_page(cursor);
  279. prev_page_no = btr_page_get_prev(page, mtr);
  280. space = buf_frame_get_space_id(page);
  281. if (btr_pcur_is_before_first_on_page(cursor, mtr)
  282. && (prev_page_no != FIL_NULL)) {
  283. prev_page = btr_pcur_get_btr_cur(cursor)->left_page;
  284. btr_leaf_page_release(page, latch_mode, mtr);
  285. page_cur_set_after_last(prev_page,
  286. btr_pcur_get_page_cur(cursor));
  287. } else if (prev_page_no != FIL_NULL) {
  288. /* The repositioned cursor did not end on an infimum record on
  289. a page. Cursor repositioning acquired a latch also on the
  290. previous page, but we do not need the latch: release it. */
  291. prev_page = btr_pcur_get_btr_cur(cursor)->left_page;
  292. btr_leaf_page_release(prev_page, latch_mode, mtr);
  293. }
  294. cursor->latch_mode = latch_mode;
  295. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  296. }
  297. /*************************************************************
  298. Moves the persistent cursor to the previous record in the tree. If no records
  299. are left, the cursor stays 'before first in tree'. */
  300. ibool
  301. btr_pcur_move_to_prev(
  302. /*==================*/
  303. /* out: TRUE if the cursor was not before first
  304. in tree */
  305. btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
  306. function may release the page latch */
  307. mtr_t* mtr) /* in: mtr */
  308. {
  309. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  310. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  311. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  312. if (btr_pcur_is_before_first_on_page(cursor, mtr)) {
  313. if (btr_pcur_is_before_first_in_tree(cursor, mtr)) {
  314. return(FALSE);
  315. }
  316. btr_pcur_move_backward_from_page(cursor, mtr);
  317. return(TRUE);
  318. }
  319. btr_pcur_move_to_prev_on_page(cursor, mtr);
  320. return(TRUE);
  321. }
  322. /******************************************************************
  323. If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
  324. user record satisfying the search condition, in the case PAGE_CUR_L or
  325. PAGE_CUR_LE, on the last user record. If no such user record exists, then
  326. in the first case sets the cursor after last in tree, and in the latter case
  327. before first in tree. The latching mode must be BTR_SEARCH_LEAF or
  328. BTR_MODIFY_LEAF. */
  329. void
  330. btr_pcur_open_on_user_rec(
  331. /*======================*/
  332. dict_index_t* index, /* in: index */
  333. dtuple_t* tuple, /* in: tuple on which search done */
  334. ulint mode, /* in: PAGE_CUR_L, ... */
  335. ulint latch_mode, /* in: BTR_SEARCH_LEAF or
  336. BTR_MODIFY_LEAF */
  337. btr_pcur_t* cursor,  /* in: memory buffer for persistent
  338. cursor */
  339. mtr_t* mtr) /* in: mtr */
  340. {
  341. btr_pcur_open(index, tuple, mode, latch_mode, cursor, mtr);
  342. if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) {
  343. if (btr_pcur_is_after_last_on_page(cursor, mtr)) {
  344. btr_pcur_move_to_next_user_rec(cursor, mtr);
  345. }
  346. } else {
  347. ut_ad((mode == PAGE_CUR_LE) || (mode == PAGE_CUR_L));
  348. /* Not implemented yet */
  349. ut_error;
  350. }
  351. }