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

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. The index tree persistent cursor
  3. (c) 1996 Innobase Oy
  4. Created 2/23/1996 Heikki Tuuri
  5. *******************************************************/
  6. /*************************************************************
  7. Gets the rel_pos field for a cursor whose position has been stored. */
  8. UNIV_INLINE
  9. ulint
  10. btr_pcur_get_rel_pos(
  11. /*=================*/
  12. /* out: BTR_PCUR_ON, ... */
  13. btr_pcur_t* cursor) /* in: persistent cursor */
  14. {
  15. ut_ad(cursor);
  16. ut_ad(cursor->old_rec);
  17. ut_ad(cursor->old_stored == BTR_PCUR_OLD_STORED);
  18. ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
  19. || cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  20. return(cursor->rel_pos);
  21. }
  22. /*************************************************************
  23. Sets the mtr field for a pcur. */
  24. UNIV_INLINE
  25. void
  26. btr_pcur_set_mtr(
  27. /*=============*/
  28. btr_pcur_t* cursor, /* in: persistent cursor */
  29. mtr_t* mtr) /* in, own: mtr */
  30. {
  31. ut_ad(cursor);
  32. cursor->mtr = mtr;
  33. }
  34. /*************************************************************
  35. Gets the mtr field for a pcur. */
  36. UNIV_INLINE
  37. mtr_t*
  38. btr_pcur_get_mtr(
  39. /*=============*/
  40. /* out: mtr */
  41. btr_pcur_t* cursor) /* in: persistent cursor */
  42. {
  43. ut_ad(cursor);
  44. return(cursor->mtr);
  45. }
  46. /*************************************************************
  47. Returns the btr cursor component of a persistent cursor. */
  48. UNIV_INLINE
  49. btr_cur_t*
  50. btr_pcur_get_btr_cur(
  51. /*=================*/
  52. /* out: pointer to btr cursor component */
  53. btr_pcur_t* cursor) /* in: persistent cursor */
  54. {
  55. return(&(cursor->btr_cur));
  56. }
  57. /*************************************************************
  58. Returns the page cursor component of a persistent cursor. */
  59. UNIV_INLINE
  60. page_cur_t*
  61. btr_pcur_get_page_cur(
  62. /*==================*/
  63. /* out: pointer to page cursor component */
  64. btr_pcur_t* cursor) /* in: persistent cursor */
  65. {
  66. return(btr_cur_get_page_cur(&(cursor->btr_cur)));
  67. }
  68. /*************************************************************
  69. Returns the page of a persistent cursor. */
  70. UNIV_INLINE
  71. page_t*
  72. btr_pcur_get_page(
  73. /*==============*/
  74. /* out: pointer to the page */
  75. btr_pcur_t* cursor) /* in: persistent cursor */
  76. {
  77. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  78. return(page_cur_get_page(btr_pcur_get_page_cur(cursor)));
  79. }
  80. /*************************************************************
  81. Returns the record of a persistent cursor. */
  82. UNIV_INLINE
  83. rec_t*
  84. btr_pcur_get_rec(
  85. /*=============*/
  86. /* out: pointer to the record */
  87. btr_pcur_t* cursor) /* in: persistent cursor */
  88. {
  89. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  90. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  91. return(page_cur_get_rec(btr_pcur_get_page_cur(cursor)));
  92. }
  93. /******************************************************************
  94. Gets the up_match value for a pcur after a search. */
  95. UNIV_INLINE
  96. ulint
  97. btr_pcur_get_up_match(
  98. /*==================*/
  99. /* out: number of matched fields at the cursor
  100. or to the right if search mode was PAGE_CUR_GE,
  101. otherwise undefined */
  102. btr_pcur_t* cursor) /* in: memory buffer for persistent cursor */
  103. {
  104. btr_cur_t* btr_cursor;
  105. ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
  106. || (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
  107. btr_cursor = btr_pcur_get_btr_cur(cursor);
  108. ut_ad(btr_cursor->up_match != ULINT_UNDEFINED);
  109. return(btr_cursor->up_match);
  110. }
  111. /******************************************************************
  112. Gets the low_match value for a pcur after a search. */
  113. UNIV_INLINE
  114. ulint
  115. btr_pcur_get_low_match(
  116. /*===================*/
  117. /* out: number of matched fields at the cursor
  118. or to the right if search mode was PAGE_CUR_LE,
  119. otherwise undefined */
  120. btr_pcur_t* cursor) /* in: memory buffer for persistent cursor */
  121. {
  122. btr_cur_t* btr_cursor;
  123. ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
  124. || (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
  125. btr_cursor = btr_pcur_get_btr_cur(cursor);
  126. ut_ad(btr_cursor->low_match != ULINT_UNDEFINED);
  127. return(btr_cursor->low_match);
  128. }
  129. /*************************************************************
  130. Checks if the persistent cursor is after the last user record on 
  131. a page. */
  132. UNIV_INLINE
  133. ibool
  134. btr_pcur_is_after_last_on_page(
  135. /*===========================*/
  136. btr_pcur_t* cursor, /* in: persistent cursor */
  137. mtr_t* mtr) /* in: mtr */
  138. {
  139. UT_NOT_USED(mtr);
  140. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  141. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  142. return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
  143. }
  144. /*************************************************************
  145. Checks if the persistent cursor is before the first user record on 
  146. a page. */
  147. UNIV_INLINE
  148. ibool
  149. btr_pcur_is_before_first_on_page(
  150. /*=============================*/
  151. btr_pcur_t* cursor, /* in: persistent cursor */
  152. mtr_t* mtr) /* in: mtr */
  153. {
  154. UT_NOT_USED(mtr);
  155. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  156. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  157. return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
  158. }
  159. /*************************************************************
  160. Checks if the persistent cursor is on a user record. */
  161. UNIV_INLINE
  162. ibool
  163. btr_pcur_is_on_user_rec(
  164. /*====================*/
  165. btr_pcur_t* cursor, /* in: persistent cursor */
  166. mtr_t* mtr) /* in: mtr */
  167. {
  168. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  169. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  170. if ((btr_pcur_is_before_first_on_page(cursor, mtr))
  171.     || (btr_pcur_is_after_last_on_page(cursor, mtr))) {
  172. return(FALSE);
  173. }
  174. return(TRUE);
  175. }
  176. /*************************************************************
  177. Checks if the persistent cursor is before the first user record in
  178. the index tree. */
  179. UNIV_INLINE
  180. ibool
  181. btr_pcur_is_before_first_in_tree(
  182. /*=============================*/
  183. btr_pcur_t* cursor, /* in: persistent cursor */
  184. mtr_t* mtr) /* in: mtr */
  185. {
  186. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  187. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  188. if (btr_page_get_prev(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
  189. return(FALSE);
  190. }
  191. return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
  192. }
  193. /*************************************************************
  194. Checks if the persistent cursor is after the last user record in
  195. the index tree. */
  196. UNIV_INLINE
  197. ibool
  198. btr_pcur_is_after_last_in_tree(
  199. /*===========================*/
  200. btr_pcur_t* cursor, /* in: persistent cursor */
  201. mtr_t* mtr) /* in: mtr */
  202. {
  203. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  204. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  205. if (btr_page_get_next(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
  206. return(FALSE);
  207. }
  208. return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
  209. }
  210. /*************************************************************
  211. Moves the persistent cursor to the next record on the same page. */
  212. UNIV_INLINE
  213. void
  214. btr_pcur_move_to_next_on_page(
  215. /*==========================*/
  216. btr_pcur_t* cursor, /* in: persistent cursor */
  217. mtr_t* mtr) /* in: mtr */
  218. {
  219. UT_NOT_USED(mtr);
  220. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  221. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  222. page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
  223. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  224. }
  225. /*************************************************************
  226. Moves the persistent cursor to the previous record on the same page. */
  227. UNIV_INLINE
  228. void
  229. btr_pcur_move_to_prev_on_page(
  230. /*==========================*/
  231. btr_pcur_t* cursor, /* in: persistent cursor */
  232. mtr_t* mtr) /* in: mtr */
  233. {
  234. UT_NOT_USED(mtr);
  235. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  236. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  237. page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
  238. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  239. }
  240. /*************************************************************
  241. Moves the persistent cursor to the last record on the same page. */
  242. UNIV_INLINE
  243. void
  244. btr_pcur_move_to_last_on_page(
  245. /*==========================*/
  246. btr_pcur_t* cursor, /* in: persistent cursor */
  247. mtr_t* mtr) /* in: mtr */
  248. {
  249. UT_NOT_USED(mtr);
  250. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  251. page_cur_set_after_last(buf_frame_align(btr_pcur_get_rec(cursor)),
  252. btr_pcur_get_page_cur(cursor));
  253. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  254. }
  255. /*************************************************************
  256. Moves the persistent cursor to the next user record in the tree. If no user
  257. records are left, the cursor ends up 'after last in tree'. */
  258. UNIV_INLINE
  259. ibool
  260. btr_pcur_move_to_next_user_rec(
  261. /*===========================*/
  262. /* out: TRUE if the cursor moved forward,
  263. ending on a user record */
  264. btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
  265. function may release the page latch */
  266. mtr_t* mtr) /* in: mtr */
  267. {
  268. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  269. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  270. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  271. loop:
  272. if (btr_pcur_is_after_last_on_page(cursor, mtr)) {
  273. if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
  274. return(FALSE);
  275. }
  276. btr_pcur_move_to_next_page(cursor, mtr);
  277. } else {
  278. btr_pcur_move_to_next_on_page(cursor, mtr);
  279. }
  280. if (btr_pcur_is_on_user_rec(cursor, mtr)) {
  281. return(TRUE);
  282. }
  283. goto loop;
  284. }
  285. /*************************************************************
  286. Moves the persistent cursor to the next record in the tree. If no records are
  287. left, the cursor stays 'after last in tree'. */
  288. UNIV_INLINE
  289. ibool
  290. btr_pcur_move_to_next(
  291. /*==================*/
  292. /* out: TRUE if the cursor was not after last
  293. in tree */
  294. btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
  295. function may release the page latch */
  296. mtr_t* mtr) /* in: mtr */
  297. {
  298. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  299. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  300. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  301. if (btr_pcur_is_after_last_on_page(cursor, mtr)) {
  302. if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
  303. return(FALSE);
  304. }
  305. btr_pcur_move_to_next_page(cursor, mtr);
  306. return(TRUE);
  307. }
  308. btr_pcur_move_to_next_on_page(cursor, mtr);
  309. return(TRUE);
  310. }
  311. /******************************************************************
  312. Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
  313. that is, the cursor becomes detached. If there have been modifications
  314. to the page where pcur is positioned, this can be used instead of
  315. btr_pcur_release_leaf. Function btr_pcur_store_position should be used
  316. before calling this, if restoration of cursor is wanted later. */
  317. UNIV_INLINE
  318. void
  319. btr_pcur_commit(
  320. /*============*/
  321. btr_pcur_t* pcur) /* in: persistent cursor */
  322. {
  323. ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
  324. pcur->latch_mode = BTR_NO_LATCHES;
  325. mtr_commit(pcur->mtr);
  326. pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
  327. }
  328. /******************************************************************
  329. Differs from btr_pcur_commit in that we can specify the mtr to commit. */
  330. UNIV_INLINE
  331. void
  332. btr_pcur_commit_specify_mtr(
  333. /*========================*/
  334. btr_pcur_t* pcur, /* in: persistent cursor */
  335. mtr_t* mtr) /* in: mtr to commit */
  336. {
  337. ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
  338. pcur->latch_mode = BTR_NO_LATCHES;
  339. mtr_commit(mtr);
  340. pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
  341. }
  342. /******************************************************************
  343. Sets the pcur latch mode to BTR_NO_LATCHES. */
  344. UNIV_INLINE
  345. void
  346. btr_pcur_detach(
  347. /*============*/
  348. btr_pcur_t* pcur) /* in: persistent cursor */
  349. {
  350. ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
  351. pcur->latch_mode = BTR_NO_LATCHES;
  352. pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
  353. }
  354. /******************************************************************
  355. Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES. */
  356. UNIV_INLINE
  357. ibool
  358. btr_pcur_is_detached(
  359. /*=================*/
  360. /* out: TRUE if detached */
  361. btr_pcur_t* pcur) /* in: persistent cursor */
  362. {
  363. if (pcur->latch_mode == BTR_NO_LATCHES) {
  364. return(TRUE);
  365. }
  366. return(FALSE);
  367. }
  368. /******************************************************************
  369. Sets the old_rec_buf field to NULL. */
  370. UNIV_INLINE
  371. void
  372. btr_pcur_init(
  373. /*==========*/
  374. btr_pcur_t* pcur) /* in: persistent cursor */
  375. {
  376. pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
  377. pcur->old_rec_buf = NULL;
  378. pcur->old_rec = NULL;
  379. }
  380. /******************************************************************
  381. Initializes and opens a persistent cursor to an index tree. It should be
  382. closed with btr_pcur_close. */
  383. UNIV_INLINE
  384. void
  385. btr_pcur_open(
  386. /*==========*/
  387. dict_index_t* index, /* in: index */
  388. dtuple_t* tuple, /* in: tuple on which search done */
  389. ulint mode, /* in: PAGE_CUR_L, ...;
  390. NOTE that if the search is made using a unique
  391. prefix of a record, mode should be
  392. PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
  393. may end up on the previous page from the
  394. record! */
  395. ulint latch_mode,/* in: BTR_SEARCH_LEAF, ... */
  396. btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
  397. mtr_t* mtr) /* in: mtr */
  398. {
  399. btr_cur_t* btr_cursor;
  400. /* Initialize the cursor */
  401. btr_pcur_init(cursor);
  402. cursor->latch_mode = latch_mode;
  403. cursor->search_mode = mode;
  404. /* Search with the tree cursor */
  405. btr_cursor = btr_pcur_get_btr_cur(cursor);
  406. btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
  407. btr_cursor, 0, mtr);
  408. cursor->pos_state = BTR_PCUR_IS_POSITIONED;
  409. cursor->trx_if_known = NULL;
  410. }
  411. /******************************************************************
  412. Opens an persistent cursor to an index tree without initializing the
  413. cursor. */
  414. UNIV_INLINE
  415. void
  416. btr_pcur_open_with_no_init(
  417. /*=======================*/
  418. dict_index_t* index, /* in: index */
  419. dtuple_t* tuple, /* in: tuple on which search done */
  420. ulint mode, /* in: PAGE_CUR_L, ...;
  421. NOTE that if the search is made using a unique
  422. prefix of a record, mode should be
  423. PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
  424. may end up on the previous page of the
  425. record! */
  426. ulint latch_mode,/* in: BTR_SEARCH_LEAF, ...;
  427. NOTE that if has_search_latch != 0 then
  428. we maybe do not acquire a latch on the cursor
  429. page, but assume that the caller uses his
  430. btr search latch to protect the record! */
  431. btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
  432. ulint has_search_latch,/* in: latch mode the caller
  433. currently has on btr_search_latch:
  434. RW_S_LATCH, or 0 */
  435. mtr_t* mtr) /* in: mtr */
  436. {
  437. btr_cur_t* btr_cursor;
  438. cursor->latch_mode = latch_mode;
  439. cursor->search_mode = mode;
  440. /* Search with the tree cursor */
  441. btr_cursor = btr_pcur_get_btr_cur(cursor);
  442. btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
  443. btr_cursor, has_search_latch, mtr);
  444. cursor->pos_state = BTR_PCUR_IS_POSITIONED;
  445. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  446. cursor->trx_if_known = NULL;
  447. }
  448. /*********************************************************************
  449. Opens a persistent cursor at either end of an index. */
  450. UNIV_INLINE
  451. void
  452. btr_pcur_open_at_index_side(
  453. /*========================*/
  454. ibool from_left, /* in: TRUE if open to the low end,
  455. FALSE if to the high end */
  456. dict_index_t* index, /* in: index */
  457. ulint latch_mode, /* in: latch mode */
  458. btr_pcur_t* pcur, /* in: cursor */
  459. ibool do_init, /* in: TRUE if should be initialized */
  460. mtr_t* mtr) /* in: mtr */
  461. {
  462. pcur->latch_mode = latch_mode;
  463. if (from_left) {
  464. pcur->search_mode = PAGE_CUR_G;
  465. } else {
  466. pcur->search_mode = PAGE_CUR_L;
  467. }
  468. if (do_init) {
  469. btr_pcur_init(pcur);
  470. }
  471. btr_cur_open_at_index_side(from_left, index, latch_mode,
  472. btr_pcur_get_btr_cur(pcur), mtr);
  473. pcur->pos_state = BTR_PCUR_IS_POSITIONED;
  474. pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
  475. pcur->trx_if_known = NULL;
  476. }
  477. /**************************************************************************
  478. Positions a cursor at a randomly chosen position within a B-tree. */
  479. UNIV_INLINE
  480. void
  481. btr_pcur_open_at_rnd_pos(
  482. /*=====================*/
  483. dict_index_t* index, /* in: index */
  484. ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
  485. btr_pcur_t* cursor, /* in/out: B-tree pcur */
  486. mtr_t* mtr) /* in: mtr */
  487. {
  488. /* Initialize the cursor */
  489. cursor->latch_mode = latch_mode;
  490. cursor->search_mode = PAGE_CUR_G;
  491. btr_pcur_init(cursor);
  492. btr_cur_open_at_rnd_pos(index, latch_mode,
  493. btr_pcur_get_btr_cur(cursor), mtr);
  494. cursor->pos_state = BTR_PCUR_IS_POSITIONED;
  495. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  496. cursor->trx_if_known = NULL;
  497. }
  498. /******************************************************************
  499. Frees the possible memory heap of a persistent cursor and sets the latch
  500. mode of the persistent cursor to BTR_NO_LATCHES. */
  501. UNIV_INLINE
  502. void
  503. btr_pcur_close(
  504. /*===========*/
  505. btr_pcur_t* cursor) /* in: persistent cursor */
  506. {
  507. if (cursor->old_rec_buf != NULL) {
  508. mem_free(cursor->old_rec_buf);
  509. cursor->old_rec = NULL;
  510. cursor->old_rec_buf = NULL;
  511. }
  512. cursor->btr_cur.page_cur.rec = NULL;
  513. cursor->old_rec = NULL;
  514. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  515. cursor->latch_mode = BTR_NO_LATCHES;
  516. cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
  517. cursor->trx_if_known = NULL;
  518. }