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

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. Database log
  3. (c) 1995 Innobase Oy
  4. Created 12/9/1995 Heikki Tuuri
  5. *******************************************************/
  6. #include "os0file.h"
  7. #include "mach0data.h"
  8. #include "mtr0mtr.h"
  9. /**********************************************************
  10. Checks by parsing that the catenated log segment for a single mtr is
  11. consistent. */
  12. ibool
  13. log_check_log_recs(
  14. /*===============*/
  15. byte* buf, /* in: pointer to the start of the log segment
  16. in the log_sys->buf log buffer */
  17. ulint len, /* in: segment length in bytes */
  18. dulint buf_start_lsn); /* in: buffer start lsn */
  19. /****************************************************************
  20. Gets a log block flush bit. */
  21. UNIV_INLINE
  22. ibool
  23. log_block_get_flush_bit(
  24. /*====================*/
  25. /* out: TRUE if this block was the first
  26. to be written in a log flush */
  27. byte* log_block) /* in: log block */
  28. {
  29. if (LOG_BLOCK_FLUSH_BIT_MASK
  30. & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)) {
  31. return(TRUE);
  32. }
  33. return(FALSE);
  34. }
  35. /****************************************************************
  36. Sets the log block flush bit. */
  37. UNIV_INLINE
  38. void
  39. log_block_set_flush_bit(
  40. /*====================*/
  41. byte* log_block, /* in: log block */
  42. ibool val) /* in: value to set */
  43. {
  44. ulint field;
  45. field = mach_read_from_4(log_block + LOG_BLOCK_HDR_NO);
  46. if (val) {
  47. field = field | LOG_BLOCK_FLUSH_BIT_MASK;
  48. } else {
  49. field = field & ~LOG_BLOCK_FLUSH_BIT_MASK;
  50. }
  51. mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, field);
  52. }
  53. /****************************************************************
  54. Gets a log block number stored in the header. */
  55. UNIV_INLINE
  56. ulint
  57. log_block_get_hdr_no(
  58. /*=================*/
  59. /* out: log block number stored in the block
  60. header */
  61. byte* log_block) /* in: log block */
  62. {
  63. return(~LOG_BLOCK_FLUSH_BIT_MASK 
  64. & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO));
  65. }
  66. /****************************************************************
  67. Sets the log block number stored in the header; NOTE that this must be set
  68. before the flush bit! */
  69. UNIV_INLINE
  70. void
  71. log_block_set_hdr_no(
  72. /*=================*/
  73. byte* log_block, /* in: log block */
  74. ulint n) /* in: log block number: must be > 0 and
  75. < LOG_BLOCK_FLUSH_BIT_MASK */
  76. {
  77. ut_ad(n > 0);
  78. ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK);
  79. mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, n);
  80. }
  81. /****************************************************************
  82. Gets a log block data length. */
  83. UNIV_INLINE
  84. ulint
  85. log_block_get_data_len(
  86. /*===================*/
  87. /* out: log block data length measured as a
  88. byte offset from the block start */
  89. byte* log_block) /* in: log block */
  90. {
  91. return(mach_read_from_2(log_block + LOG_BLOCK_HDR_DATA_LEN));
  92. }
  93. /****************************************************************
  94. Sets the log block data length. */
  95. UNIV_INLINE
  96. void
  97. log_block_set_data_len(
  98. /*===================*/
  99. byte* log_block, /* in: log block */
  100. ulint len) /* in: data length */
  101. {
  102. mach_write_to_2(log_block + LOG_BLOCK_HDR_DATA_LEN, len);
  103. }
  104. /****************************************************************
  105. Gets a log block first mtr log record group offset. */
  106. UNIV_INLINE
  107. ulint
  108. log_block_get_first_rec_group(
  109. /*==========================*/
  110. /* out: first mtr log record group byte offset
  111. from the block start, 0 if none */
  112. byte* log_block) /* in: log block */
  113. {
  114. return(mach_read_from_2(log_block + LOG_BLOCK_FIRST_REC_GROUP));
  115. }
  116. /****************************************************************
  117. Sets the log block first mtr log record group offset. */
  118. UNIV_INLINE
  119. void
  120. log_block_set_first_rec_group(
  121. /*==========================*/
  122. byte* log_block, /* in: log block */
  123. ulint offset) /* in: offset, 0 if none */
  124. {
  125. mach_write_to_2(log_block + LOG_BLOCK_FIRST_REC_GROUP, offset);
  126. }
  127. /****************************************************************
  128. Gets a log block checkpoint number field (4 lowest bytes). */
  129. UNIV_INLINE
  130. ulint
  131. log_block_get_checkpoint_no(
  132. /*========================*/
  133. /* out: checkpoint no (4 lowest bytes) */
  134. byte* log_block) /* in: log block */
  135. {
  136. return(mach_read_from_4(log_block + LOG_BLOCK_CHECKPOINT_NO));
  137. }
  138. /****************************************************************
  139. Sets a log block checkpoint number field (4 lowest bytes). */
  140. UNIV_INLINE
  141. void
  142. log_block_set_checkpoint_no(
  143. /*========================*/
  144. byte* log_block, /* in: log block */
  145. dulint no) /* in: checkpoint no */
  146. {
  147. mach_write_to_4(log_block + LOG_BLOCK_CHECKPOINT_NO,
  148. ut_dulint_get_low(no));
  149. }
  150. /****************************************************************
  151. Converts a lsn to a log block number. */
  152. UNIV_INLINE
  153. ulint
  154. log_block_convert_lsn_to_no(
  155. /*========================*/
  156. /* out: log block number, it is > 0 and <= 1G */
  157. dulint lsn) /* in: lsn of a byte within the block */
  158. {
  159. ulint no;
  160. no = ut_dulint_get_low(lsn) / OS_FILE_LOG_BLOCK_SIZE;
  161. no += (ut_dulint_get_high(lsn) % OS_FILE_LOG_BLOCK_SIZE)
  162. * 2 * (0x80000000UL / OS_FILE_LOG_BLOCK_SIZE);
  163. no = no & 0x3FFFFFFFUL;
  164. return(no + 1);
  165. }
  166. /****************************************************************
  167. Calculates the checksum for a log block. */
  168. UNIV_INLINE
  169. ulint
  170. log_block_calc_checksum(
  171. /*====================*/
  172. /* out: checksum */
  173. byte* block) /* in: log block */
  174. {
  175. ulint sum;
  176. ulint sh;
  177. ulint i;
  178. sum = 1;
  179. sh = 0;
  180. for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
  181. sum = sum & 0x7FFFFFFFUL;
  182. sum += (((ulint)(*(block + i))) << sh) + (ulint)(*(block + i));
  183. sh++;
  184. if (sh > 24) {
  185. sh = 0;
  186. }
  187. }
  188. return(sum);
  189. }
  190. /****************************************************************
  191. Gets a log block checksum field value. */
  192. UNIV_INLINE
  193. ulint
  194. log_block_get_checksum(
  195. /*===================*/
  196. /* out: checksum */
  197. byte* log_block) /* in: log block */
  198. {
  199. return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE
  200. - LOG_BLOCK_CHECKSUM));
  201. }
  202. /****************************************************************
  203. Sets a log block checksum field value. */
  204. UNIV_INLINE
  205. void
  206. log_block_set_checksum(
  207. /*===================*/
  208. byte* log_block, /* in: log block */
  209. ulint checksum) /* in: checksum */
  210. {
  211. mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
  212. - LOG_BLOCK_CHECKSUM,
  213. checksum);
  214. }
  215. /****************************************************************
  216. Initializes a log block in the log buffer. */
  217. UNIV_INLINE
  218. void
  219. log_block_init(
  220. /*===========*/
  221. byte* log_block, /* in: pointer to the log buffer */
  222. dulint lsn) /* in: lsn within the log block */
  223. {
  224. ulint no;
  225. #ifdef UNIV_SYNC_DEBUG
  226. ut_ad(mutex_own(&(log_sys->mutex)));
  227. #endif /* UNIV_SYNC_DEBUG */
  228. no = log_block_convert_lsn_to_no(lsn);
  229. log_block_set_hdr_no(log_block, no);
  230. log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
  231. log_block_set_first_rec_group(log_block, 0);
  232. }
  233. /****************************************************************
  234. Initializes a log block in the log buffer in the old format, where there
  235. was no checksum yet. */
  236. UNIV_INLINE
  237. void
  238. log_block_init_in_old_format(
  239. /*=========================*/
  240. byte* log_block, /* in: pointer to the log buffer */
  241. dulint lsn) /* in: lsn within the log block */
  242. {
  243. ulint no;
  244. #ifdef UNIV_SYNC_DEBUG
  245. ut_ad(mutex_own(&(log_sys->mutex)));
  246. #endif /* UNIV_SYNC_DEBUG */
  247. no = log_block_convert_lsn_to_no(lsn);
  248. log_block_set_hdr_no(log_block, no);
  249. mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
  250. - LOG_BLOCK_CHECKSUM, no);
  251. log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
  252. log_block_set_first_rec_group(log_block, 0);
  253. }
  254. /****************************************************************
  255. Writes to the log the string given. The log must be released with
  256. log_release. */
  257. UNIV_INLINE
  258. dulint
  259. log_reserve_and_write_fast(
  260. /*=======================*/
  261. /* out: end lsn of the log record, ut_dulint_zero if
  262. did not succeed */
  263. byte* str, /* in: string */
  264. ulint len, /* in: string length */
  265. dulint* start_lsn,/* out: start lsn of the log record */
  266. ibool* success)/* out: TRUE if success */
  267. {
  268. log_t* log = log_sys;
  269. ulint data_len;
  270. dulint lsn;
  271. *success = TRUE;
  272. mutex_enter(&(log->mutex));
  273. data_len = len + log->buf_free % OS_FILE_LOG_BLOCK_SIZE;
  274. if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
  275.      /* The string does not fit within the current log block
  276.      or the log block would become full */
  277.      *success = FALSE;
  278. mutex_exit(&(log->mutex));
  279.      return(ut_dulint_zero);
  280. }
  281. *start_lsn = log->lsn;
  282. ut_memcpy(log->buf + log->buf_free, str, len);
  283. log_block_set_data_len(ut_align_down(log->buf + log->buf_free,
  284.   OS_FILE_LOG_BLOCK_SIZE),
  285. data_len);
  286. #ifdef UNIV_LOG_DEBUG
  287. log->old_buf_free = log->buf_free;
  288. log->old_lsn = log->lsn;
  289. #endif
  290. log->buf_free += len;
  291. ut_ad(log->buf_free <= log->buf_size);
  292. lsn = ut_dulint_add(log->lsn, len);
  293. log->lsn = lsn;
  294. #ifdef UNIV_LOG_DEBUG
  295. log_check_log_recs(log->buf + log->old_buf_free,
  296. log->buf_free - log->old_buf_free, log->old_lsn);
  297. #endif
  298. return(lsn);
  299. }
  300. /***************************************************************************
  301. Releases the log mutex. */
  302. UNIV_INLINE
  303. void
  304. log_release(void)
  305. /*=============*/
  306. {
  307. mutex_exit(&(log_sys->mutex));
  308. }
  309. /****************************************************************
  310. Gets the current lsn. */
  311. UNIV_INLINE
  312. dulint
  313. log_get_lsn(void)
  314. /*=============*/
  315. /* out: current lsn */
  316. {
  317. dulint lsn;
  318. mutex_enter(&(log_sys->mutex));
  319. lsn = log_sys->lsn;
  320. mutex_exit(&(log_sys->mutex));
  321. return(lsn);
  322. }
  323. /***************************************************************************
  324. Checks if there is need for a log buffer flush or a new checkpoint, and does
  325. this if yes. Any database operation should call this when it has modified
  326. more than about 4 pages. NOTE that this function may only be called when the
  327. OS thread owns no synchronization objects except the dictionary mutex. */
  328. UNIV_INLINE
  329. void
  330. log_free_check(void)
  331. /*================*/
  332. {
  333. /* ut_ad(sync_thread_levels_empty()); */
  334. if (log_sys->check_flush_or_checkpoint) {
  335. log_check_margins();
  336. }
  337. }