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

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 next user record in the tree. If no user
  242. records are left, the cursor ends up 'after last in tree'. */
  243. UNIV_INLINE
  244. ibool
  245. btr_pcur_move_to_next_user_rec(
  246. /*===========================*/
  247. /* out: TRUE if the cursor moved forward,
  248. ending on a user record */
  249. btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
  250. function may release the page latch */
  251. mtr_t* mtr) /* in: mtr */
  252. {
  253. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  254. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  255. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  256. loop:
  257. if (btr_pcur_is_after_last_on_page(cursor, mtr)) {
  258. if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
  259. return(FALSE);
  260. }
  261. btr_pcur_move_to_next_page(cursor, mtr);
  262. } else {
  263. btr_pcur_move_to_next_on_page(cursor, mtr);
  264. }
  265. if (btr_pcur_is_on_user_rec(cursor, mtr)) {
  266. return(TRUE);
  267. }
  268. goto loop;
  269. }
  270. /*************************************************************
  271. Moves the persistent cursor to the next record in the tree. If no records are
  272. left, the cursor stays 'after last in tree'. */
  273. UNIV_INLINE
  274. ibool
  275. btr_pcur_move_to_next(
  276. /*==================*/
  277. /* out: TRUE if the cursor was not after last
  278. in tree */
  279. btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
  280. function may release the page latch */
  281. mtr_t* mtr) /* in: mtr */
  282. {
  283. ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
  284. ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  285. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  286. if (btr_pcur_is_after_last_on_page(cursor, mtr)) {
  287. if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
  288. return(FALSE);
  289. }
  290. btr_pcur_move_to_next_page(cursor, mtr);
  291. return(TRUE);
  292. }
  293. btr_pcur_move_to_next_on_page(cursor, mtr);
  294. return(TRUE);
  295. }
  296. /******************************************************************
  297. Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
  298. that is, the cursor becomes detached. If there have been modifications
  299. to the page where pcur is positioned, this can be used instead of
  300. btr_pcur_release_leaf. Function btr_pcur_store_position should be used
  301. before calling this, if restoration of cursor is wanted later. */
  302. UNIV_INLINE
  303. void
  304. btr_pcur_commit(
  305. /*============*/
  306. btr_pcur_t* pcur) /* in: persistent cursor */
  307. {
  308. ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
  309. pcur->latch_mode = BTR_NO_LATCHES;
  310. mtr_commit(pcur->mtr);
  311. pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
  312. }
  313. /******************************************************************
  314. Differs from btr_pcur_commit in that we can specify the mtr to commit. */
  315. UNIV_INLINE
  316. void
  317. btr_pcur_commit_specify_mtr(
  318. /*========================*/
  319. btr_pcur_t* pcur, /* in: persistent cursor */
  320. mtr_t* mtr) /* in: mtr to commit */
  321. {
  322. ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
  323. pcur->latch_mode = BTR_NO_LATCHES;
  324. mtr_commit(mtr);
  325. pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
  326. }
  327. /******************************************************************
  328. Sets the pcur latch mode to BTR_NO_LATCHES. */
  329. UNIV_INLINE
  330. void
  331. btr_pcur_detach(
  332. /*============*/
  333. btr_pcur_t* pcur) /* in: persistent cursor */
  334. {
  335. ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
  336. pcur->latch_mode = BTR_NO_LATCHES;
  337. pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
  338. }
  339. /******************************************************************
  340. Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES. */
  341. UNIV_INLINE
  342. ibool
  343. btr_pcur_is_detached(
  344. /*=================*/
  345. /* out: TRUE if detached */
  346. btr_pcur_t* pcur) /* in: persistent cursor */
  347. {
  348. if (pcur->latch_mode == BTR_NO_LATCHES) {
  349. return(TRUE);
  350. }
  351. return(FALSE);
  352. }
  353. /******************************************************************
  354. Sets the old_rec_buf field to NULL. */
  355. UNIV_INLINE
  356. void
  357. btr_pcur_init(
  358. /*==========*/
  359. btr_pcur_t* pcur) /* in: persistent cursor */
  360. {
  361. pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
  362. pcur->old_rec_buf = NULL;
  363. pcur->old_rec = NULL;
  364. }
  365. /******************************************************************
  366. Initializes and opens a persistent cursor to an index tree. It should be
  367. closed with btr_pcur_close. */
  368. UNIV_INLINE
  369. void
  370. btr_pcur_open(
  371. /*==========*/
  372. dict_index_t* index, /* in: index */
  373. dtuple_t* tuple, /* in: tuple on which search done */
  374. ulint mode, /* in: PAGE_CUR_L, ...;
  375. NOTE that if the search is made using a unique
  376. prefix of a record, mode should be
  377. PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
  378. may end up on the previous page from the
  379. record! */
  380. ulint latch_mode,/* in: BTR_SEARCH_LEAF, ... */
  381. btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
  382. mtr_t* mtr) /* in: mtr */
  383. {
  384. btr_cur_t* btr_cursor;
  385. /* Initialize the cursor */
  386. btr_pcur_init(cursor);
  387. cursor->latch_mode = latch_mode;
  388. cursor->search_mode = mode;
  389. /* Search with the tree cursor */
  390. btr_cursor = btr_pcur_get_btr_cur(cursor);
  391. btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
  392. btr_cursor, 0, mtr);
  393. cursor->pos_state = BTR_PCUR_IS_POSITIONED;
  394. }
  395. /******************************************************************
  396. Opens an persistent cursor to an index tree without initializing the
  397. cursor. */
  398. UNIV_INLINE
  399. void
  400. btr_pcur_open_with_no_init(
  401. /*=======================*/
  402. dict_index_t* index, /* in: index */
  403. dtuple_t* tuple, /* in: tuple on which search done */
  404. ulint mode, /* in: PAGE_CUR_L, ...;
  405. NOTE that if the search is made using a unique
  406. prefix of a record, mode should be
  407. PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
  408. may end up on the previous page of the
  409. record! */
  410. ulint latch_mode,/* in: BTR_SEARCH_LEAF, ... */
  411. btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
  412. ulint has_search_latch,/* in: latch mode the caller
  413. currently has on btr_search_latch:
  414. RW_S_LATCH, or 0 */
  415. mtr_t* mtr) /* in: mtr */
  416. {
  417. btr_cur_t* btr_cursor;
  418. cursor->latch_mode = latch_mode;
  419. cursor->search_mode = mode;
  420. /* Search with the tree cursor */
  421. btr_cursor = btr_pcur_get_btr_cur(cursor);
  422. btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
  423. btr_cursor, has_search_latch, mtr);
  424. cursor->pos_state = BTR_PCUR_IS_POSITIONED;
  425. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  426. }
  427. /*********************************************************************
  428. Opens a persistent cursor at either end of an index. */
  429. UNIV_INLINE
  430. void
  431. btr_pcur_open_at_index_side(
  432. /*========================*/
  433. ibool from_left, /* in: TRUE if open to the low end,
  434. FALSE if to the high end */
  435. dict_index_t* index, /* in: index */
  436. ulint latch_mode, /* in: latch mode */
  437. btr_pcur_t* pcur, /* in: cursor */
  438. ibool do_init, /* in: TRUE if should be initialized */
  439. mtr_t* mtr) /* in: mtr */
  440. {
  441. pcur->latch_mode = latch_mode;
  442. if (from_left) {
  443. pcur->search_mode = PAGE_CUR_G;
  444. } else {
  445. pcur->search_mode = PAGE_CUR_L;
  446. }
  447. if (do_init) {
  448. btr_pcur_init(pcur);
  449. }
  450. btr_cur_open_at_index_side(from_left, index, latch_mode,
  451. btr_pcur_get_btr_cur(pcur), mtr);
  452. pcur->pos_state = BTR_PCUR_IS_POSITIONED;
  453. pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
  454. }
  455. /**************************************************************************
  456. Positions a cursor at a randomly chosen position within a B-tree. */
  457. UNIV_INLINE
  458. void
  459. btr_pcur_open_at_rnd_pos(
  460. /*=====================*/
  461. dict_index_t* index, /* in: index */
  462. ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
  463. btr_pcur_t* cursor, /* in/out: B-tree pcur */
  464. mtr_t* mtr) /* in: mtr */
  465. {
  466. /* Initialize the cursor */
  467. cursor->latch_mode = latch_mode;
  468. cursor->search_mode = PAGE_CUR_G;
  469. btr_pcur_init(cursor);
  470. btr_cur_open_at_rnd_pos(index, latch_mode,
  471. btr_pcur_get_btr_cur(cursor), mtr);
  472. cursor->pos_state = BTR_PCUR_IS_POSITIONED;
  473. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  474. }
  475. /******************************************************************
  476. Frees the possible memory heap of a persistent cursor and sets the latch
  477. mode of the persistent cursor to BTR_NO_LATCHES. */
  478. UNIV_INLINE
  479. void
  480. btr_pcur_close(
  481. /*===========*/
  482. btr_pcur_t* cursor) /* in: persistent cursor */
  483. {
  484. if (cursor->old_rec_buf != NULL) {
  485. mem_free(cursor->old_rec_buf);
  486. cursor->old_rec = NULL;
  487. cursor->old_rec_buf = NULL;
  488. }
  489. cursor->btr_cur.page_cur.rec = NULL;
  490. cursor->old_rec = NULL;
  491. cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
  492. cursor->latch_mode = BTR_NO_LATCHES;
  493. cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
  494. }