You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

640 lines
17 KiB

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