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

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. Database log
  3. (c) 1995-1997 Innobase Oy
  4. Created 12/9/1995 Heikki Tuuri
  5. *******************************************************/
  6. #include "log0log.h"
  7. #ifdef UNIV_NONINL
  8. #include "log0log.ic"
  9. #endif
  10. #include "mem0mem.h"
  11. #include "buf0buf.h"
  12. #include "buf0flu.h"
  13. #include "srv0srv.h"
  14. #include "log0recv.h"
  15. #include "fil0fil.h"
  16. #include "dict0boot.h"
  17. #include "srv0srv.h"
  18. #include "srv0start.h"
  19. #include "trx0sys.h"
  20. #include "trx0trx.h"
  21. /* Current free limit of space 0; protected by the log sys mutex; 0 means
  22. uninitialized */
  23. ulint log_fsp_current_free_limit = 0;
  24. /* Global log system variable */
  25. log_t* log_sys = NULL;
  26. ibool log_do_write = TRUE;
  27. ibool log_debug_writes = FALSE;
  28. /* These control how often we print warnings if the last checkpoint is too
  29. old */
  30. ibool log_has_printed_chkp_warning = FALSE;
  31. time_t log_last_warning_time;
  32. #ifdef UNIV_LOG_ARCHIVE
  33. /* Pointer to this variable is used as the i/o-message when we do i/o to an
  34. archive */
  35. byte log_archive_io;
  36. #endif /* UNIV_LOG_ARCHIVE */
  37. /* A margin for free space in the log buffer before a log entry is catenated */
  38. #define LOG_BUF_WRITE_MARGIN  (4 * OS_FILE_LOG_BLOCK_SIZE)
  39. /* Margins for free space in the log buffer after a log entry is catenated */
  40. #define LOG_BUF_FLUSH_RATIO 2
  41. #define LOG_BUF_FLUSH_MARGIN (LOG_BUF_WRITE_MARGIN + 4 * UNIV_PAGE_SIZE)
  42. /* Margin for the free space in the smallest log group, before a new query
  43. step which modifies the database, is started */
  44. #define LOG_CHECKPOINT_FREE_PER_THREAD (4 * UNIV_PAGE_SIZE)
  45. #define LOG_CHECKPOINT_EXTRA_FREE (8 * UNIV_PAGE_SIZE)
  46. /* This parameter controls asynchronous making of a new checkpoint; the value
  47. should be bigger than LOG_POOL_PREFLUSH_RATIO_SYNC */
  48. #define LOG_POOL_CHECKPOINT_RATIO_ASYNC 32
  49. /* This parameter controls synchronous preflushing of modified buffer pages */
  50. #define LOG_POOL_PREFLUSH_RATIO_SYNC 16
  51. /* The same ratio for asynchronous preflushing; this value should be less than
  52. the previous */
  53. #define LOG_POOL_PREFLUSH_RATIO_ASYNC 8
  54. /* Extra margin, in addition to one log file, used in archiving */
  55. #define LOG_ARCHIVE_EXTRA_MARGIN (4 * UNIV_PAGE_SIZE)
  56. /* This parameter controls asynchronous writing to the archive */
  57. #define LOG_ARCHIVE_RATIO_ASYNC 16
  58. /* Codes used in unlocking flush latches */
  59. #define LOG_UNLOCK_NONE_FLUSHED_LOCK 1
  60. #define LOG_UNLOCK_FLUSH_LOCK 2
  61. /* States of an archiving operation */
  62. #define LOG_ARCHIVE_READ 1
  63. #define LOG_ARCHIVE_WRITE 2
  64. /**********************************************************
  65. Completes a checkpoint write i/o to a log file. */
  66. static
  67. void
  68. log_io_complete_checkpoint(void);
  69. /*============================*/
  70. #ifdef UNIV_LOG_ARCHIVE
  71. /**********************************************************
  72. Completes an archiving i/o. */
  73. static
  74. void
  75. log_io_complete_archive(void);
  76. /*=========================*/
  77. #endif /* UNIV_LOG_ARCHIVE */
  78. /********************************************************************
  79. Sets the global variable log_fsp_current_free_limit. Also makes a checkpoint,
  80. so that we know that the limit has been written to a log checkpoint field
  81. on disk. */
  82. void
  83. log_fsp_current_free_limit_set_and_checkpoint(
  84. /*==========================================*/
  85. ulint limit) /* in: limit to set */
  86. {
  87. ibool success;
  88. mutex_enter(&(log_sys->mutex));
  89. log_fsp_current_free_limit = limit;
  90. mutex_exit(&(log_sys->mutex));
  91. /* Try to make a synchronous checkpoint */
  92. success = FALSE;
  93. while (!success) {
  94. success = log_checkpoint(TRUE, TRUE);
  95. }
  96. }
  97. /********************************************************************
  98. Returns the oldest modified block lsn in the pool, or log_sys->lsn if none
  99. exists. */
  100. static
  101. dulint
  102. log_buf_pool_get_oldest_modification(void)
  103. /*======================================*/
  104. {
  105. dulint lsn;
  106. #ifdef UNIV_SYNC_DEBUG
  107. ut_ad(mutex_own(&(log_sys->mutex)));
  108. #endif /* UNIV_SYNC_DEBUG */
  109. lsn = buf_pool_get_oldest_modification();
  110. if (ut_dulint_is_zero(lsn)) {
  111. lsn = log_sys->lsn;
  112. }
  113. return(lsn);
  114. }
  115. /****************************************************************
  116. Opens the log for log_write_low. The log must be closed with log_close and
  117. released with log_release. */
  118. dulint
  119. log_reserve_and_open(
  120. /*=================*/
  121. /* out: start lsn of the log record */
  122. ulint len) /* in: length of data to be catenated */
  123. {
  124. log_t* log = log_sys;
  125. ulint len_upper_limit;
  126. #ifdef UNIV_LOG_ARCHIVE
  127. ulint archived_lsn_age;
  128. ulint dummy;
  129. #endif /* UNIV_LOG_ARCHIVE */
  130. #ifdef UNIV_DEBUG
  131. ulint count = 0;
  132. #endif /* UNIV_DEBUG */
  133. ut_a(len < log->buf_size / 2);
  134. loop:
  135. mutex_enter(&(log->mutex));
  136. /* Calculate an upper limit for the space the string may take in the
  137. log buffer */
  138. len_upper_limit = LOG_BUF_WRITE_MARGIN + (5 * len) / 4;
  139. if (log->buf_free + len_upper_limit > log->buf_size) {
  140. mutex_exit(&(log->mutex));
  141. /* Not enough free space, do a syncronous flush of the log
  142. buffer */
  143. log_buffer_flush_to_disk();
  144. ut_ad(++count < 50);
  145. goto loop;
  146. }
  147. #ifdef UNIV_LOG_ARCHIVE
  148. if (log->archiving_state != LOG_ARCH_OFF) {
  149. archived_lsn_age = ut_dulint_minus(log->lsn,
  150. log->archived_lsn);
  151. if (archived_lsn_age + len_upper_limit
  152. > log->max_archived_lsn_age) {
  153. /* Not enough free archived space in log groups: do a
  154. synchronous archive write batch: */
  155. mutex_exit(&(log->mutex));
  156. ut_ad(len_upper_limit <= log->max_archived_lsn_age);
  157. log_archive_do(TRUE, &dummy);
  158. ut_ad(++count < 50);
  159. goto loop;
  160. }
  161. }
  162. #endif /* UNIV_LOG_ARCHIVE */
  163. #ifdef UNIV_LOG_DEBUG
  164. log->old_buf_free = log->buf_free;
  165. log->old_lsn = log->lsn;
  166. #endif
  167. return(log->lsn);
  168. }
  169. /****************************************************************
  170. Writes to the log the string given. It is assumed that the caller holds the
  171. log mutex. */
  172. void
  173. log_write_low(
  174. /*==========*/
  175. byte* str, /* in: string */
  176. ulint str_len) /* in: string length */
  177. {
  178. log_t* log = log_sys;
  179. ulint len;
  180. ulint data_len;
  181. byte* log_block;
  182. #ifdef UNIV_SYNC_DEBUG
  183. ut_ad(mutex_own(&(log->mutex)));
  184. #endif /* UNIV_SYNC_DEBUG */
  185. part_loop:
  186. /* Calculate a part length */
  187. data_len = (log->buf_free % OS_FILE_LOG_BLOCK_SIZE) + str_len;
  188. if (data_len <= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
  189.      /* The string fits within the current log block */
  190.     
  191.      len = str_len;
  192. } else {
  193. data_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE;
  194.      len = OS_FILE_LOG_BLOCK_SIZE
  195. - (log->buf_free % OS_FILE_LOG_BLOCK_SIZE)
  196.      - LOG_BLOCK_TRL_SIZE;
  197. }
  198. ut_memcpy(log->buf + log->buf_free, str, len);
  199. str_len -= len;
  200. str = str + len;
  201. log_block = ut_align_down(log->buf + log->buf_free,
  202. OS_FILE_LOG_BLOCK_SIZE);
  203. log_block_set_data_len(log_block, data_len);
  204. if (data_len == OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
  205. /* This block became full */
  206. log_block_set_data_len(log_block, OS_FILE_LOG_BLOCK_SIZE);
  207. log_block_set_checkpoint_no(log_block,
  208. log_sys->next_checkpoint_no);
  209. len += LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE;
  210. log->lsn = ut_dulint_add(log->lsn, len);
  211. /* Initialize the next block header */
  212. log_block_init(log_block + OS_FILE_LOG_BLOCK_SIZE, log->lsn);
  213. } else {
  214. log->lsn = ut_dulint_add(log->lsn, len);
  215. }
  216. log->buf_free += len;
  217. ut_ad(log->buf_free <= log->buf_size);
  218. if (str_len > 0) {
  219. goto part_loop;
  220. }
  221. }
  222. /****************************************************************
  223. Closes the log. */
  224. dulint
  225. log_close(void)
  226. /*===========*/
  227. /* out: lsn */
  228. {
  229. byte* log_block;
  230. ulint first_rec_group;
  231. dulint oldest_lsn;
  232. dulint lsn;
  233. log_t* log = log_sys;
  234. ulint checkpoint_age;
  235. #ifdef UNIV_SYNC_DEBUG
  236. ut_ad(mutex_own(&(log->mutex)));
  237. #endif /* UNIV_SYNC_DEBUG */
  238. lsn = log->lsn;
  239. log_block = ut_align_down(log->buf + log->buf_free,
  240. OS_FILE_LOG_BLOCK_SIZE);
  241. first_rec_group = log_block_get_first_rec_group(log_block);
  242. if (first_rec_group == 0) {
  243. /* We initialized a new log block which was not written
  244. full by the current mtr: the next mtr log record group
  245. will start within this block at the offset data_len */
  246. log_block_set_first_rec_group(log_block,
  247.   log_block_get_data_len(log_block));
  248. }
  249. if (log->buf_free > log->max_buf_free) {
  250. log->check_flush_or_checkpoint = TRUE;
  251. }
  252. checkpoint_age = ut_dulint_minus(lsn, log->last_checkpoint_lsn);
  253. if (checkpoint_age >= log->log_group_capacity) {
  254. /* TODO: split btr_store_big_rec_extern_fields() into small
  255. steps so that we can release all latches in the middle, and
  256. call log_free_check() to ensure we never write over log written
  257. after the latest checkpoint. In principle, we should split all
  258. big_rec operations, but other operations are smaller. */
  259. if (!log_has_printed_chkp_warning
  260.     || difftime(time(NULL), log_last_warning_time) > 15) {
  261.         log_has_printed_chkp_warning = TRUE;
  262. log_last_warning_time = time(NULL);
  263.         ut_print_timestamp(stderr);
  264. fprintf(stderr,
  265. "  InnoDB: ERROR: the age of the last checkpoint is %lu,n"
  266. "InnoDB: which exceeds the log group capacity %lu.n"
  267. "InnoDB: If you are using big BLOB or TEXT rows, you must set then"
  268. "InnoDB: combined size of log files at least 10 times bigger than then"
  269. "InnoDB: largest such row.n",
  270. (ulong) checkpoint_age,
  271. (ulong) log->log_group_capacity);
  272. }
  273. }
  274. if (checkpoint_age <= log->max_modified_age_async) {
  275. goto function_exit;
  276. }
  277. oldest_lsn = buf_pool_get_oldest_modification();
  278. if (ut_dulint_is_zero(oldest_lsn)
  279.     || (ut_dulint_minus(lsn, oldest_lsn)
  280. > log->max_modified_age_async)
  281.     || checkpoint_age > log->max_checkpoint_age_async) {
  282. log->check_flush_or_checkpoint = TRUE;
  283. }
  284. function_exit:
  285. #ifdef UNIV_LOG_DEBUG
  286. log_check_log_recs(log->buf + log->old_buf_free,
  287. log->buf_free - log->old_buf_free, log->old_lsn);
  288. #endif
  289. return(lsn);
  290. }
  291. #ifdef UNIV_LOG_ARCHIVE
  292. /**********************************************************
  293. Pads the current log block full with dummy log records. Used in producing
  294. consistent archived log files. */
  295. static
  296. void
  297. log_pad_current_log_block(void)
  298. /*===========================*/
  299. {
  300. byte b = MLOG_DUMMY_RECORD;
  301. ulint pad_length;
  302. ulint i;
  303. dulint lsn;
  304. /* We retrieve lsn only because otherwise gcc crashed on HP-UX */
  305. lsn = log_reserve_and_open(OS_FILE_LOG_BLOCK_SIZE);
  306. pad_length = OS_FILE_LOG_BLOCK_SIZE
  307. - (log_sys->buf_free % OS_FILE_LOG_BLOCK_SIZE)
  308. - LOG_BLOCK_TRL_SIZE;
  309. for (i = 0; i < pad_length; i++) {
  310. log_write_low(&b, 1);
  311. }
  312. lsn = log_sys->lsn;
  313. log_close();
  314. log_release();
  315. ut_a((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
  316. == LOG_BLOCK_HDR_SIZE);
  317. }
  318. #endif /* UNIV_LOG_ARCHIVE */
  319. /**********************************************************
  320. Calculates the data capacity of a log group, when the log file headers are not
  321. included. */
  322. ulint
  323. log_group_get_capacity(
  324. /*===================*/
  325. /* out: capacity in bytes */
  326. log_group_t* group) /* in: log group */
  327. {
  328. #ifdef UNIV_SYNC_DEBUG
  329. ut_ad(mutex_own(&(log_sys->mutex)));
  330. #endif /* UNIV_SYNC_DEBUG */
  331. return((group->file_size - LOG_FILE_HDR_SIZE) * group->n_files); 
  332. }
  333. /**********************************************************
  334. Calculates the offset within a log group, when the log file headers are not
  335. included. */
  336. UNIV_INLINE
  337. ulint
  338. log_group_calc_size_offset(
  339. /*=======================*/
  340. /* out: size offset (<= offset) */
  341. ulint offset, /* in: real offset within the log group */
  342. log_group_t* group) /* in: log group */
  343. {
  344. #ifdef UNIV_SYNC_DEBUG
  345. ut_ad(mutex_own(&(log_sys->mutex)));
  346. #endif /* UNIV_SYNC_DEBUG */
  347. return(offset - LOG_FILE_HDR_SIZE * (1 + offset / group->file_size));
  348. }
  349. /**********************************************************
  350. Calculates the offset within a log group, when the log file headers are
  351. included. */
  352. UNIV_INLINE
  353. ulint
  354. log_group_calc_real_offset(
  355. /*=======================*/
  356. /* out: real offset (>= offset) */
  357. ulint offset, /* in: size offset within the log group */
  358. log_group_t* group) /* in: log group */
  359. {
  360. #ifdef UNIV_SYNC_DEBUG
  361. ut_ad(mutex_own(&(log_sys->mutex)));
  362. #endif /* UNIV_SYNC_DEBUG */
  363. return(offset + LOG_FILE_HDR_SIZE
  364. * (1 + offset / (group->file_size - LOG_FILE_HDR_SIZE)));
  365. }
  366. /**********************************************************
  367. Calculates the offset of an lsn within a log group. */
  368. static
  369. ulint
  370. log_group_calc_lsn_offset(
  371. /*======================*/
  372. /* out: offset within the log group */
  373. dulint lsn, /* in: lsn, must be within 4 GB of
  374. group->lsn */
  375. log_group_t* group) /* in: log group */
  376. {
  377.         dulint         gr_lsn;
  378.         ib_longlong     gr_lsn_size_offset;
  379. ib_longlong difference;
  380. ib_longlong group_size;
  381. ib_longlong offset;
  382. #ifdef UNIV_SYNC_DEBUG
  383. ut_ad(mutex_own(&(log_sys->mutex)));
  384. #endif /* UNIV_SYNC_DEBUG */
  385. /* If total log file size is > 2 GB we can easily get overflows
  386. with 32-bit integers. Use 64-bit integers instead. */
  387. gr_lsn = group->lsn;
  388. gr_lsn_size_offset = (ib_longlong)
  389.                log_group_calc_size_offset(group->lsn_offset, group);
  390. group_size = (ib_longlong) log_group_get_capacity(group);
  391. if (ut_dulint_cmp(lsn, gr_lsn) >= 0) {
  392. difference = (ib_longlong) ut_dulint_minus(lsn, gr_lsn);
  393. } else {
  394. difference = (ib_longlong) ut_dulint_minus(gr_lsn, lsn);
  395. difference = difference % group_size;
  396. difference = group_size - difference;
  397. }
  398. offset = (gr_lsn_size_offset + difference) % group_size;
  399. ut_a(offset < (((ib_longlong) 1) << 32)); /* offset must be < 4 GB */
  400. /* fprintf(stderr,
  401. "Offset is %lu gr_lsn_offset is %lu difference is %lun",
  402.        (ulint)offset,(ulint)gr_lsn_size_offset, (ulint)difference);
  403. */
  404. return(log_group_calc_real_offset((ulint)offset, group));
  405. }
  406. /***********************************************************************
  407. Calculates where in log files we find a specified lsn. */
  408. ulint
  409. log_calc_where_lsn_is(
  410. /*==================*/
  411. /* out: log file number */
  412. ib_longlong* log_file_offset, /* out: offset in that file
  413. (including the header) */
  414. dulint first_header_lsn, /* in: first log file start
  415. lsn */
  416. dulint lsn, /* in: lsn whose position to
  417. determine */
  418. ulint n_log_files, /* in: total number of log
  419. files */
  420. ib_longlong log_file_size) /* in: log file size
  421. (including the header) */
  422. {
  423. ib_longlong ib_lsn;
  424. ib_longlong ib_first_header_lsn;
  425. ib_longlong capacity = log_file_size - LOG_FILE_HDR_SIZE;
  426. ulint file_no;
  427. ib_longlong add_this_many;
  428. ib_lsn = ut_conv_dulint_to_longlong(lsn);
  429. ib_first_header_lsn = ut_conv_dulint_to_longlong(first_header_lsn);
  430. if (ib_lsn < ib_first_header_lsn) {
  431. add_this_many = 1 + (ib_first_header_lsn - ib_lsn)
  432. / (capacity * (ib_longlong)n_log_files);
  433. ib_lsn += add_this_many
  434.           * capacity * (ib_longlong)n_log_files;
  435. }
  436. ut_a(ib_lsn >= ib_first_header_lsn);
  437. file_no = ((ulint)((ib_lsn - ib_first_header_lsn) / capacity))
  438.   % n_log_files;
  439. *log_file_offset = (ib_lsn - ib_first_header_lsn) % capacity;
  440. *log_file_offset = *log_file_offset + LOG_FILE_HDR_SIZE;
  441. return(file_no);
  442. }
  443. /************************************************************
  444. Sets the field values in group to correspond to a given lsn. For this function
  445. to work, the values must already be correctly initialized to correspond to
  446. some lsn, for instance, a checkpoint lsn. */
  447. void
  448. log_group_set_fields(
  449. /*=================*/
  450. log_group_t* group, /* in: group */
  451. dulint lsn) /* in: lsn for which the values should be
  452. set */
  453. {
  454. group->lsn_offset = log_group_calc_lsn_offset(lsn, group);
  455. group->lsn = lsn;
  456. }
  457. /*********************************************************************
  458. Calculates the recommended highest values for lsn - last_checkpoint_lsn,
  459. lsn - buf_get_oldest_modification(), and lsn - max_archive_lsn_age. */
  460. static
  461. ibool
  462. log_calc_max_ages(void)
  463. /*===================*/
  464. /* out: error value FALSE if the smallest log group is
  465. too small to accommodate the number of OS threads in
  466. the database server */
  467. {
  468. log_group_t* group;
  469. ulint margin;
  470. ulint free;
  471. ibool success = TRUE;
  472. ulint smallest_capacity;
  473. ulint archive_margin;
  474. ulint smallest_archive_margin;
  475. #ifdef UNIV_SYNC_DEBUG
  476. ut_ad(!mutex_own(&(log_sys->mutex)));
  477. #endif /* UNIV_SYNC_DEBUG */
  478. mutex_enter(&(log_sys->mutex));
  479. group = UT_LIST_GET_FIRST(log_sys->log_groups);
  480. ut_ad(group);
  481. smallest_capacity = ULINT_MAX;
  482. smallest_archive_margin = ULINT_MAX;
  483. while (group) {
  484. if (log_group_get_capacity(group) < smallest_capacity) {
  485. smallest_capacity = log_group_get_capacity(group);
  486. }
  487. archive_margin = log_group_get_capacity(group)
  488. - (group->file_size - LOG_FILE_HDR_SIZE)
  489. - LOG_ARCHIVE_EXTRA_MARGIN;
  490. if (archive_margin < smallest_archive_margin) {
  491. smallest_archive_margin = archive_margin;
  492. }
  493. group = UT_LIST_GET_NEXT(log_groups, group);
  494. }
  495. /* Add extra safety */
  496. smallest_capacity = smallest_capacity - smallest_capacity / 10;
  497. /* For each OS thread we must reserve so much free space in the
  498. smallest log group that it can accommodate the log entries produced
  499. by single query steps: running out of free log space is a serious
  500. system error which requires rebooting the database. */
  501. free = LOG_CHECKPOINT_FREE_PER_THREAD * (10 + srv_thread_concurrency)
  502. + LOG_CHECKPOINT_EXTRA_FREE;
  503. if (free >= smallest_capacity / 2) {
  504. success = FALSE;
  505. goto failure;
  506. } else {
  507. margin = smallest_capacity - free;
  508. }
  509. margin = ut_min(margin, log_sys->adm_checkpoint_interval);
  510. margin = margin - margin / 10; /* Add still some extra safety */
  511. log_sys->log_group_capacity = smallest_capacity;
  512. log_sys->max_modified_age_async = margin
  513. - margin / LOG_POOL_PREFLUSH_RATIO_ASYNC;
  514. log_sys->max_modified_age_sync = margin
  515. - margin / LOG_POOL_PREFLUSH_RATIO_SYNC;
  516. log_sys->max_checkpoint_age_async = margin - margin
  517. / LOG_POOL_CHECKPOINT_RATIO_ASYNC;
  518. log_sys->max_checkpoint_age = margin;
  519. #ifdef UNIV_LOG_ARCHIVE
  520. log_sys->max_archived_lsn_age = smallest_archive_margin;
  521. log_sys->max_archived_lsn_age_async = smallest_archive_margin
  522. - smallest_archive_margin /
  523.   LOG_ARCHIVE_RATIO_ASYNC;
  524. #endif /* UNIV_LOG_ARCHIVE */
  525. failure:
  526. mutex_exit(&(log_sys->mutex));
  527. if (!success) {
  528. fprintf(stderr,
  529. "InnoDB: Error: ib_logfiles are too small for innodb_thread_concurrency %lu.n"
  530. "InnoDB: The combined size of ib_logfiles should be bigger thann"
  531. "InnoDB: 200 kB * innodb_thread_concurrency.n"
  532. "InnoDB: To get mysqld to start up, set innodb_thread_concurrency in my.cnfn"
  533. "InnoDB: to a lower value, for example, to 8. After an ERROR-FREE shutdownn"
  534. "InnoDB: of mysqld you can adjust the size of ib_logfiles, as explained inn"
  535. "InnoDB: http://dev.mysql.com/doc/mysql/en/Adding_and_removing.htmln"
  536. "InnoDB: Cannot continue operation. Calling exit(1).n",
  537. (ulong)srv_thread_concurrency);
  538. exit(1);
  539. }
  540. return(success);
  541. }
  542. /**********************************************************
  543. Initializes the log. */
  544. void
  545. log_init(void)
  546. /*==========*/
  547. {
  548. byte* buf;
  549. log_sys = mem_alloc(sizeof(log_t));
  550. mutex_create(&(log_sys->mutex));
  551. mutex_set_level(&(log_sys->mutex), SYNC_LOG);
  552. mutex_enter(&(log_sys->mutex));
  553. /* Start the lsn from one log block from zero: this way every
  554. log record has a start lsn != zero, a fact which we will use */
  555. log_sys->lsn = LOG_START_LSN;
  556. ut_a(LOG_BUFFER_SIZE >= 16 * OS_FILE_LOG_BLOCK_SIZE);
  557. ut_a(LOG_BUFFER_SIZE >= 4 * UNIV_PAGE_SIZE);
  558. buf = ut_malloc(LOG_BUFFER_SIZE + OS_FILE_LOG_BLOCK_SIZE);
  559. log_sys->buf = ut_align(buf, OS_FILE_LOG_BLOCK_SIZE);
  560. log_sys->buf_size = LOG_BUFFER_SIZE;
  561. memset(log_sys->buf, '', LOG_BUFFER_SIZE);
  562. log_sys->max_buf_free = log_sys->buf_size / LOG_BUF_FLUSH_RATIO
  563. - LOG_BUF_FLUSH_MARGIN;
  564. log_sys->check_flush_or_checkpoint = TRUE;
  565. UT_LIST_INIT(log_sys->log_groups);
  566. log_sys->n_log_ios = 0;
  567. log_sys->n_log_ios_old = log_sys->n_log_ios;
  568. log_sys->last_printout_time = time(NULL);
  569. /*----------------------------*/
  570. log_sys->buf_next_to_write = 0;
  571. log_sys->write_lsn = ut_dulint_zero;
  572. log_sys->current_flush_lsn = ut_dulint_zero;
  573. log_sys->flushed_to_disk_lsn = ut_dulint_zero;
  574. log_sys->written_to_some_lsn = log_sys->lsn;
  575. log_sys->written_to_all_lsn = log_sys->lsn;
  576. log_sys->n_pending_writes = 0;
  577. log_sys->no_flush_event = os_event_create(NULL);
  578. os_event_set(log_sys->no_flush_event);
  579. log_sys->one_flushed_event = os_event_create(NULL);
  580. os_event_set(log_sys->one_flushed_event);
  581. /*----------------------------*/
  582. log_sys->adm_checkpoint_interval = ULINT_MAX;
  583. log_sys->next_checkpoint_no = ut_dulint_zero;
  584. log_sys->last_checkpoint_lsn = log_sys->lsn;
  585. log_sys->n_pending_checkpoint_writes = 0; 
  586. rw_lock_create(&(log_sys->checkpoint_lock));
  587. rw_lock_set_level(&(log_sys->checkpoint_lock), SYNC_NO_ORDER_CHECK);
  588. log_sys->checkpoint_buf = ut_align(
  589. mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE),
  590. OS_FILE_LOG_BLOCK_SIZE);
  591. memset(log_sys->checkpoint_buf, '', OS_FILE_LOG_BLOCK_SIZE);
  592. /*----------------------------*/
  593. #ifdef UNIV_LOG_ARCHIVE
  594. /* Under MySQL, log archiving is always off */
  595. log_sys->archiving_state = LOG_ARCH_OFF;
  596. log_sys->archived_lsn = log_sys->lsn;
  597. log_sys->next_archived_lsn = ut_dulint_zero;
  598. log_sys->n_pending_archive_ios = 0;
  599. rw_lock_create(&(log_sys->archive_lock));
  600. rw_lock_set_level(&(log_sys->archive_lock), SYNC_NO_ORDER_CHECK);
  601. log_sys->archive_buf = NULL;
  602. /* ut_align(
  603. ut_malloc(LOG_ARCHIVE_BUF_SIZE
  604.   + OS_FILE_LOG_BLOCK_SIZE),
  605. OS_FILE_LOG_BLOCK_SIZE); */
  606. log_sys->archive_buf_size = 0;
  607. /* memset(log_sys->archive_buf, '', LOG_ARCHIVE_BUF_SIZE); */
  608. log_sys->archiving_on = os_event_create(NULL);
  609. #endif /* UNIV_LOG_ARCHIVE */
  610. /*----------------------------*/
  611. log_block_init(log_sys->buf, log_sys->lsn);
  612. log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE);
  613. log_sys->buf_free = LOG_BLOCK_HDR_SIZE;
  614. log_sys->lsn = ut_dulint_add(LOG_START_LSN, LOG_BLOCK_HDR_SIZE);
  615. mutex_exit(&(log_sys->mutex));
  616. #ifdef UNIV_LOG_DEBUG
  617. recv_sys_create();
  618. recv_sys_init(FALSE, buf_pool_get_curr_size());
  619. recv_sys->parse_start_lsn = log_sys->lsn;
  620. recv_sys->scanned_lsn = log_sys->lsn;
  621. recv_sys->scanned_checkpoint_no = 0;
  622. recv_sys->recovered_lsn = log_sys->lsn;
  623. recv_sys->limit_lsn = ut_dulint_max;
  624. #endif
  625. }
  626. /**********************************************************************
  627. Inits a log group to the log system. */
  628. void
  629. log_group_init(
  630. /*===========*/
  631. ulint id, /* in: group id */
  632. ulint n_files, /* in: number of log files */
  633. ulint file_size, /* in: log file size in bytes */
  634. ulint space_id, /* in: space id of the file space
  635. which contains the log files of this
  636. group */
  637. ulint archive_space_id __attribute__((unused)))
  638. /* in: space id of the file space
  639. which contains some archived log
  640. files for this group; currently, only
  641. for the first log group this is
  642. used */
  643. {
  644. ulint i;
  645. log_group_t* group;
  646. group = mem_alloc(sizeof(log_group_t));
  647. group->id = id;
  648. group->n_files = n_files;
  649. group->file_size = file_size;
  650. group->space_id = space_id;
  651. group->state = LOG_GROUP_OK;
  652. group->lsn = LOG_START_LSN;
  653. group->lsn_offset = LOG_FILE_HDR_SIZE;
  654. group->n_pending_writes = 0;
  655. group->file_header_bufs = mem_alloc(sizeof(byte*) * n_files);
  656. #ifdef UNIV_LOG_ARCHIVE
  657. group->archive_file_header_bufs = mem_alloc(sizeof(byte*) * n_files);
  658. #endif /* UNIV_LOG_ARCHIVE */
  659. for (i = 0; i < n_files; i++) {
  660. *(group->file_header_bufs + i) = ut_align(
  661. mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE),
  662. OS_FILE_LOG_BLOCK_SIZE);
  663. memset(*(group->file_header_bufs + i), '',
  664. LOG_FILE_HDR_SIZE);
  665. #ifdef UNIV_LOG_ARCHIVE
  666. *(group->archive_file_header_bufs + i) = ut_align(
  667. mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE),
  668. OS_FILE_LOG_BLOCK_SIZE);
  669. memset(*(group->archive_file_header_bufs + i), '',
  670. LOG_FILE_HDR_SIZE);
  671. #endif /* UNIV_LOG_ARCHIVE */
  672. }
  673. #ifdef UNIV_LOG_ARCHIVE
  674. group->archive_space_id = archive_space_id;
  675. group->archived_file_no = 0;
  676. group->archived_offset = 0;
  677. #endif /* UNIV_LOG_ARCHIVE */
  678. group->checkpoint_buf = ut_align(
  679. mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE),
  680. OS_FILE_LOG_BLOCK_SIZE);
  681. memset(group->checkpoint_buf, '', OS_FILE_LOG_BLOCK_SIZE);
  682. UT_LIST_ADD_LAST(log_groups, log_sys->log_groups, group);
  683. ut_a(log_calc_max_ages());
  684. }
  685. /**********************************************************************
  686. Does the unlockings needed in flush i/o completion. */
  687. UNIV_INLINE
  688. void
  689. log_flush_do_unlocks(
  690. /*=================*/
  691. ulint code) /* in: any ORed combination of LOG_UNLOCK_FLUSH_LOCK
  692. and LOG_UNLOCK_NONE_FLUSHED_LOCK */
  693. {
  694. #ifdef UNIV_SYNC_DEBUG
  695. ut_ad(mutex_own(&(log_sys->mutex)));
  696. #endif /* UNIV_SYNC_DEBUG */
  697. /* NOTE that we must own the log mutex when doing the setting of the
  698. events: this is because transactions will wait for these events to
  699. be set, and at that moment the log flush they were waiting for must
  700. have ended. If the log mutex were not reserved here, the i/o-thread
  701. calling this function might be preempted for a while, and when it
  702. resumed execution, it might be that a new flush had been started, and
  703. this function would erroneously signal the NEW flush as completed.
  704. Thus, the changes in the state of these events are performed
  705. atomically in conjunction with the changes in the state of
  706. log_sys->n_pending_writes etc. */ 
  707. if (code & LOG_UNLOCK_NONE_FLUSHED_LOCK) {
  708. os_event_set(log_sys->one_flushed_event);
  709. }
  710. if (code & LOG_UNLOCK_FLUSH_LOCK) {
  711. os_event_set(log_sys->no_flush_event);
  712. }
  713. }
  714. /**********************************************************************
  715. Checks if a flush is completed for a log group and does the completion
  716. routine if yes. */
  717. UNIV_INLINE
  718. ulint
  719. log_group_check_flush_completion(
  720. /*=============================*/
  721. /* out: LOG_UNLOCK_NONE_FLUSHED_LOCK or 0 */
  722. log_group_t* group) /* in: log group */
  723. {
  724. #ifdef UNIV_SYNC_DEBUG
  725. ut_ad(mutex_own(&(log_sys->mutex)));
  726. #endif /* UNIV_SYNC_DEBUG */
  727. if (!log_sys->one_flushed && group->n_pending_writes == 0) {
  728. if (log_debug_writes) {
  729. fprintf(stderr,
  730. "Log flushed first to group %lun", (ulong) group->id);
  731. }
  732. log_sys->written_to_some_lsn = log_sys->write_lsn;
  733. log_sys->one_flushed = TRUE;
  734. return(LOG_UNLOCK_NONE_FLUSHED_LOCK);
  735. }
  736. if (log_debug_writes && (group->n_pending_writes == 0)) {
  737. fprintf(stderr, "Log flushed to group %lun", (ulong) group->id);
  738. }
  739. return(0);
  740. }
  741. /**********************************************************
  742. Checks if a flush is completed and does the completion routine if yes. */
  743. static
  744. ulint
  745. log_sys_check_flush_completion(void)
  746. /*================================*/
  747. /* out: LOG_UNLOCK_FLUSH_LOCK or 0 */
  748. {
  749. ulint move_start;
  750. ulint move_end;
  751. #ifdef UNIV_SYNC_DEBUG
  752. ut_ad(mutex_own(&(log_sys->mutex)));
  753. #endif /* UNIV_SYNC_DEBUG */
  754. if (log_sys->n_pending_writes == 0) {
  755. log_sys->written_to_all_lsn = log_sys->write_lsn;
  756. log_sys->buf_next_to_write = log_sys->write_end_offset;
  757. if (log_sys->write_end_offset > log_sys->max_buf_free / 2) {
  758. /* Move the log buffer content to the start of the
  759. buffer */
  760. move_start = ut_calc_align_down(
  761. log_sys->write_end_offset,
  762. OS_FILE_LOG_BLOCK_SIZE);
  763. move_end = ut_calc_align(log_sys->buf_free,
  764. OS_FILE_LOG_BLOCK_SIZE);
  765. ut_memmove(log_sys->buf, log_sys->buf + move_start,
  766. move_end - move_start);
  767. log_sys->buf_free -= move_start;
  768. log_sys->buf_next_to_write -= move_start;
  769. }
  770. return(LOG_UNLOCK_FLUSH_LOCK);
  771. }
  772. return(0);
  773. }
  774. /**********************************************************
  775. Completes an i/o to a log file. */
  776. void
  777. log_io_complete(
  778. /*============*/
  779. log_group_t* group) /* in: log group or a dummy pointer */
  780. {
  781. ulint unlock;
  782. #ifdef UNIV_LOG_ARCHIVE
  783. if ((byte*)group == &log_archive_io) {
  784. /* It was an archive write */
  785. log_io_complete_archive();
  786. return;
  787. }
  788. #endif /* UNIV_LOG_ARCHIVE */
  789. if ((ulint)group & 0x1UL) {
  790. /* It was a checkpoint write */
  791. group = (log_group_t*)((ulint)group - 1);
  792. if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC
  793.    && srv_unix_file_flush_method != SRV_UNIX_NOSYNC) {
  794.         fil_flush(group->space_id);
  795. }
  796. if (log_debug_writes) {
  797. fprintf(stderr,
  798. "Checkpoint info written to group %lun",
  799. group->id);
  800. }
  801. log_io_complete_checkpoint();
  802. return;
  803. }
  804. ut_error; /* We currently use synchronous writing of the
  805. logs and cannot end up here! */
  806. if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC
  807.     && srv_unix_file_flush_method != SRV_UNIX_NOSYNC
  808.     && srv_flush_log_at_trx_commit != 2) {
  809.         fil_flush(group->space_id);
  810. }
  811. mutex_enter(&(log_sys->mutex));
  812. ut_a(group->n_pending_writes > 0);
  813. ut_a(log_sys->n_pending_writes > 0);
  814. group->n_pending_writes--;
  815. log_sys->n_pending_writes--;
  816. unlock = log_group_check_flush_completion(group);
  817. unlock = unlock | log_sys_check_flush_completion();
  818. log_flush_do_unlocks(unlock);
  819. mutex_exit(&(log_sys->mutex));
  820. }
  821. /**********************************************************
  822. Writes a log file header to a log file space. */
  823. static
  824. void
  825. log_group_file_header_flush(
  826. /*========================*/
  827. log_group_t* group, /* in: log group */
  828. ulint nth_file, /* in: header to the nth file in the
  829. log file space */
  830. dulint start_lsn) /* in: log file data starts at this
  831. lsn */
  832. {
  833. byte* buf;
  834. ulint dest_offset;
  835. #ifdef UNIV_SYNC_DEBUG
  836. ut_ad(mutex_own(&(log_sys->mutex)));
  837. #endif /* UNIV_SYNC_DEBUG */
  838. ut_a(nth_file < group->n_files);
  839. buf = *(group->file_header_bufs + nth_file);
  840. mach_write_to_4(buf + LOG_GROUP_ID, group->id);
  841. mach_write_to_8(buf + LOG_FILE_START_LSN, start_lsn);
  842. /* Wipe over possible label of ibbackup --restore */
  843. memcpy(buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, "    ", 4);
  844. dest_offset = nth_file * group->file_size;
  845. if (log_debug_writes) {
  846. fprintf(stderr,
  847. "Writing log file header to group %lu file %lun",
  848. (ulong) group->id, (ulong) nth_file);
  849. }
  850. if (log_do_write) {
  851. log_sys->n_log_ios++;
  852. fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id,
  853. dest_offset / UNIV_PAGE_SIZE,
  854. dest_offset % UNIV_PAGE_SIZE,
  855. OS_FILE_LOG_BLOCK_SIZE,
  856. buf, group);
  857. }
  858. }
  859. /**********************************************************
  860. Stores a 4-byte checksum to the trailer checksum field of a log block
  861. before writing it to a log file. This checksum is used in recovery to
  862. check the consistency of a log block. */
  863. static
  864. void
  865. log_block_store_checksum(
  866. /*=====================*/
  867. byte* block) /* in/out: pointer to a log block */
  868. {
  869. log_block_set_checksum(block, log_block_calc_checksum(block));
  870. }
  871. /**********************************************************
  872. Writes a buffer to a log file group. */
  873. void
  874. log_group_write_buf(
  875. /*================*/
  876. log_group_t* group, /* in: log group */
  877. byte* buf, /* in: buffer */
  878. ulint len, /* in: buffer len; must be divisible
  879. by OS_FILE_LOG_BLOCK_SIZE */
  880. dulint start_lsn, /* in: start lsn of the buffer; must
  881. be divisible by
  882. OS_FILE_LOG_BLOCK_SIZE */
  883. ulint new_data_offset)/* in: start offset of new data in
  884. buf: this parameter is used to decide
  885. if we have to write a new log file
  886. header */
  887. {
  888. ulint write_len;
  889. ibool write_header;
  890. ulint next_offset;
  891. ulint i;
  892. #ifdef UNIV_SYNC_DEBUG
  893. ut_ad(mutex_own(&(log_sys->mutex)));
  894. #endif /* UNIV_SYNC_DEBUG */
  895. ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0);
  896. ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
  897. if (new_data_offset == 0) {
  898. write_header = TRUE;
  899. } else {
  900. write_header = FALSE;
  901. }
  902. loop:
  903. if (len == 0) {
  904. return;
  905. }
  906. next_offset = log_group_calc_lsn_offset(start_lsn, group);
  907. if ((next_offset % group->file_size == LOG_FILE_HDR_SIZE)
  908.     && write_header) {
  909. /* We start to write a new log file instance in the group */
  910. log_group_file_header_flush(group,
  911. next_offset / group->file_size, start_lsn);
  912. }
  913. if ((next_offset % group->file_size) + len > group->file_size) {
  914. write_len = group->file_size
  915. - (next_offset % group->file_size);
  916. } else {
  917. write_len = len;
  918. }
  919. if (log_debug_writes) {
  920. fprintf(stderr,
  921. "Writing log file segment to group %lu offset %lu len %lun"
  922. "start lsn %lu %lun"
  923. "First block n:o %lu last block n:o %lun",
  924. (ulong) group->id, (ulong) next_offset,
  925.         (ulong) write_len,
  926. (ulong) ut_dulint_get_high(start_lsn),
  927. (ulong) ut_dulint_get_low(start_lsn),
  928. (ulong) log_block_get_hdr_no(buf),
  929. (ulong) log_block_get_hdr_no(
  930. buf + write_len - OS_FILE_LOG_BLOCK_SIZE));
  931. ut_a(log_block_get_hdr_no(buf)
  932. == log_block_convert_lsn_to_no(start_lsn));
  933. for (i = 0; i < write_len / OS_FILE_LOG_BLOCK_SIZE; i++) {
  934. ut_a(log_block_get_hdr_no(buf) + i
  935. == log_block_get_hdr_no(buf
  936. + i * OS_FILE_LOG_BLOCK_SIZE));
  937. }
  938. }
  939. /* Calculate the checksums for each log block and write them to
  940. the trailer fields of the log blocks */
  941. for (i = 0; i < write_len / OS_FILE_LOG_BLOCK_SIZE; i++) {
  942. log_block_store_checksum(buf + i * OS_FILE_LOG_BLOCK_SIZE);
  943. }
  944. if (log_do_write) {
  945. log_sys->n_log_ios++;
  946. fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id,
  947. next_offset / UNIV_PAGE_SIZE,
  948. next_offset % UNIV_PAGE_SIZE, write_len, buf, group);
  949. }
  950. if (write_len < len) {
  951. start_lsn = ut_dulint_add(start_lsn, write_len);
  952. len -= write_len;
  953. buf += write_len;
  954. write_header = TRUE;
  955. goto loop;
  956. }
  957. }
  958. /**********************************************************
  959. This function is called, e.g., when a transaction wants to commit. It checks
  960. that the log has been written to the log file up to the last log entry written
  961. by the transaction. If there is a flush running, it waits and checks if the
  962. flush flushed enough. If not, starts a new flush. */
  963. void
  964. log_write_up_to(
  965. /*============*/
  966. dulint lsn, /* in: log sequence number up to which the log should
  967. be written, ut_dulint_max if not specified */
  968. ulint wait, /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
  969. or LOG_WAIT_ALL_GROUPS */
  970. ibool flush_to_disk)
  971. /* in: TRUE if we want the written log also to be
  972. flushed to disk */
  973. {
  974. log_group_t* group;
  975. ulint start_offset;
  976. ulint end_offset;
  977. ulint area_start;
  978. ulint area_end;
  979. ulint loop_count;
  980. ulint unlock;
  981. if (recv_no_ibuf_operations) {
  982. /* Recovery is running and no operations on the log files are
  983. allowed yet (the variable name .._no_ibuf_.. is misleading) */
  984. return;
  985. }
  986. loop_count = 0;
  987. loop:
  988. loop_count++;
  989. ut_ad(loop_count < 5);
  990. if (loop_count > 2) {
  991. /* fprintf(stderr, "Log loop count %lun", loop_count); */
  992. }
  993. mutex_enter(&(log_sys->mutex));
  994. if (flush_to_disk
  995.     && ut_dulint_cmp(log_sys->flushed_to_disk_lsn, lsn) >= 0) {
  996.     
  997. mutex_exit(&(log_sys->mutex));
  998. return;
  999. }
  1000. if (!flush_to_disk
  1001.     && (ut_dulint_cmp(log_sys->written_to_all_lsn, lsn) >= 0
  1002.      || (ut_dulint_cmp(log_sys->written_to_some_lsn, lsn) >= 0
  1003.          && wait != LOG_WAIT_ALL_GROUPS))) {
  1004. mutex_exit(&(log_sys->mutex));
  1005. return;
  1006. }
  1007. if (log_sys->n_pending_writes > 0) {
  1008. /* A write (+ possibly flush to disk) is running */
  1009. if (flush_to_disk
  1010.     && ut_dulint_cmp(log_sys->current_flush_lsn, lsn) >= 0) {
  1011. /* The write + flush will write enough: wait for it to
  1012. complete  */
  1013.     
  1014. goto do_waits;
  1015. }
  1016. if (!flush_to_disk
  1017.     && ut_dulint_cmp(log_sys->write_lsn, lsn) >= 0) {
  1018. /* The write will write enough: wait for it to
  1019. complete  */
  1020. goto do_waits;
  1021. }
  1022. mutex_exit(&(log_sys->mutex));
  1023. /* Wait for the write to complete and try to start a new
  1024. write */
  1025. os_event_wait(log_sys->no_flush_event);
  1026. goto loop;
  1027. }
  1028. if (!flush_to_disk
  1029. && log_sys->buf_free == log_sys->buf_next_to_write) {
  1030. /* Nothing to write and no flush to disk requested */
  1031. mutex_exit(&(log_sys->mutex));
  1032. return;
  1033. }
  1034. if (log_debug_writes) {
  1035. fprintf(stderr,
  1036. "Writing log from %lu %lu up to lsn %lu %lun",
  1037. (ulong) ut_dulint_get_high(log_sys->written_to_all_lsn),
  1038. (ulong) ut_dulint_get_low(log_sys->written_to_all_lsn),
  1039. (ulong) ut_dulint_get_high(log_sys->lsn),
  1040. (ulong) ut_dulint_get_low(log_sys->lsn));
  1041. }
  1042. log_sys->n_pending_writes++;
  1043. group = UT_LIST_GET_FIRST(log_sys->log_groups);
  1044. group->n_pending_writes++;  /* We assume here that we have only
  1045. one log group! */
  1046. os_event_reset(log_sys->no_flush_event);
  1047. os_event_reset(log_sys->one_flushed_event);
  1048. start_offset = log_sys->buf_next_to_write;
  1049. end_offset = log_sys->buf_free;
  1050. area_start = ut_calc_align_down(start_offset, OS_FILE_LOG_BLOCK_SIZE);
  1051. area_end = ut_calc_align(end_offset, OS_FILE_LOG_BLOCK_SIZE);
  1052. ut_ad(area_end - area_start > 0);
  1053. log_sys->write_lsn = log_sys->lsn;
  1054. if (flush_to_disk) {
  1055. log_sys->current_flush_lsn = log_sys->lsn;
  1056. }
  1057. log_sys->one_flushed = FALSE;
  1058. log_block_set_flush_bit(log_sys->buf + area_start, TRUE);
  1059. log_block_set_checkpoint_no(
  1060. log_sys->buf + area_end - OS_FILE_LOG_BLOCK_SIZE,
  1061. log_sys->next_checkpoint_no);
  1062. /* Copy the last, incompletely written, log block a log block length
  1063. up, so that when the flush operation writes from the log buffer, the
  1064. segment to write will not be changed by writers to the log */
  1065. ut_memcpy(log_sys->buf + area_end,
  1066. log_sys->buf + area_end - OS_FILE_LOG_BLOCK_SIZE,
  1067. OS_FILE_LOG_BLOCK_SIZE);
  1068. log_sys->buf_free += OS_FILE_LOG_BLOCK_SIZE;
  1069. log_sys->write_end_offset = log_sys->buf_free;
  1070. group = UT_LIST_GET_FIRST(log_sys->log_groups);
  1071. /* Do the write to the log files */
  1072. while (group) {
  1073. log_group_write_buf(group,
  1074. log_sys->buf + area_start,
  1075. area_end - area_start,
  1076. ut_dulint_align_down(log_sys->written_to_all_lsn,
  1077. OS_FILE_LOG_BLOCK_SIZE),
  1078. start_offset - area_start);
  1079. log_group_set_fields(group, log_sys->write_lsn);
  1080. group = UT_LIST_GET_NEXT(log_groups, group);
  1081. }
  1082. mutex_exit(&(log_sys->mutex));
  1083. if (srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) {
  1084. /* O_DSYNC means the OS did not buffer the log file at all:
  1085. so we have also flushed to disk what we have written */
  1086. log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
  1087. } else if (flush_to_disk) {
  1088. group = UT_LIST_GET_FIRST(log_sys->log_groups);
  1089.         fil_flush(group->space_id);
  1090. log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
  1091. }
  1092. mutex_enter(&(log_sys->mutex));
  1093. group = UT_LIST_GET_FIRST(log_sys->log_groups);
  1094. ut_a(group->n_pending_writes == 1);
  1095. ut_a(log_sys->n_pending_writes == 1);
  1096. group->n_pending_writes--;
  1097. log_sys->n_pending_writes--;
  1098. unlock = log_group_check_flush_completion(group);
  1099. unlock = unlock | log_sys_check_flush_completion();
  1100. log_flush_do_unlocks(unlock);
  1101. mutex_exit(&(log_sys->mutex));
  1102. return;
  1103. do_waits:
  1104. mutex_exit(&(log_sys->mutex));
  1105. if (wait == LOG_WAIT_ONE_GROUP) {
  1106. os_event_wait(log_sys->one_flushed_event);
  1107. } else if (wait == LOG_WAIT_ALL_GROUPS) {
  1108. os_event_wait(log_sys->no_flush_event);
  1109. } else {
  1110. ut_ad(wait == LOG_NO_WAIT);
  1111. }
  1112. }
  1113. /********************************************************************
  1114. Does a syncronous flush of the log buffer to disk. */
  1115. void
  1116. log_buffer_flush_to_disk(void)
  1117. /*==========================*/
  1118. {
  1119. dulint lsn;
  1120. mutex_enter(&(log_sys->mutex));
  1121. lsn = log_sys->lsn;
  1122. mutex_exit(&(log_sys->mutex));
  1123. log_write_up_to(lsn, LOG_WAIT_ALL_GROUPS, TRUE);
  1124. }
  1125. /********************************************************************
  1126. Tries to establish a big enough margin of free space in the log buffer, such
  1127. that a new log entry can be catenated without an immediate need for a flush. */
  1128. static
  1129. void
  1130. log_flush_margin(void)
  1131. /*==================*/
  1132. {
  1133. ibool do_flush = FALSE;
  1134. log_t* log = log_sys;
  1135. dulint lsn;
  1136. mutex_enter(&(log->mutex));
  1137. if (log->buf_free > log->max_buf_free) {
  1138. if (log->n_pending_writes > 0) {
  1139. /* A flush is running: hope that it will provide enough
  1140. free space */
  1141. } else {
  1142. do_flush = TRUE;
  1143. lsn = log->lsn;
  1144. }
  1145. }
  1146. mutex_exit(&(log->mutex));
  1147. if (do_flush) {
  1148. log_write_up_to(lsn, LOG_NO_WAIT, FALSE);
  1149. }
  1150. }
  1151. /********************************************************************
  1152. Advances the smallest lsn for which there are unflushed dirty blocks in the
  1153. buffer pool. NOTE: this function may only be called if the calling thread owns
  1154. no synchronization objects! */
  1155. ibool
  1156. log_preflush_pool_modified_pages(
  1157. /*=============================*/
  1158. /* out: FALSE if there was a flush batch of
  1159. the same type running, which means that we
  1160. could not start this flush batch */
  1161. dulint new_oldest, /* in: try to advance oldest_modified_lsn
  1162. at least to this lsn */
  1163. ibool sync) /* in: TRUE if synchronous operation is
  1164. desired */
  1165. {
  1166. ulint n_pages;
  1167. if (recv_recovery_on) {
  1168. /* If the recovery is running, we must first apply all
  1169. log records to their respective file pages to get the
  1170. right modify lsn values to these pages: otherwise, there
  1171. might be pages on disk which are not yet recovered to the
  1172. current lsn, and even after calling this function, we could
  1173. not know how up-to-date the disk version of the database is,
  1174. and we could not make a new checkpoint on the basis of the
  1175. info on the buffer pool only. */
  1176. recv_apply_hashed_log_recs(TRUE);
  1177. }
  1178. n_pages = buf_flush_batch(BUF_FLUSH_LIST, ULINT_MAX, new_oldest);
  1179. if (sync) {
  1180. buf_flush_wait_batch_end(BUF_FLUSH_LIST);
  1181. }
  1182. if (n_pages == ULINT_UNDEFINED) {
  1183. return(FALSE);
  1184. }
  1185. return(TRUE);
  1186. }
  1187. /**********************************************************
  1188. Completes a checkpoint. */
  1189. static
  1190. void
  1191. log_complete_checkpoint(void)
  1192. /*=========================*/
  1193. {
  1194. #ifdef UNIV_SYNC_DEBUG
  1195. ut_ad(mutex_own(&(log_sys->mutex)));
  1196. #endif /* UNIV_SYNC_DEBUG */
  1197. ut_ad(log_sys->n_pending_checkpoint_writes == 0);
  1198. log_sys->next_checkpoint_no
  1199. = ut_dulint_add(log_sys->next_checkpoint_no, 1);
  1200. log_sys->last_checkpoint_lsn = log_sys->next_checkpoint_lsn;
  1201. rw_lock_x_unlock_gen(&(log_sys->checkpoint_lock), LOG_CHECKPOINT);
  1202. }
  1203. /**********************************************************
  1204. Completes an asynchronous checkpoint info write i/o to a log file. */
  1205. static
  1206. void
  1207. log_io_complete_checkpoint(void)
  1208. /*============================*/
  1209. {
  1210. mutex_enter(&(log_sys->mutex));
  1211. ut_ad(log_sys->n_pending_checkpoint_writes > 0);
  1212. log_sys->n_pending_checkpoint_writes--;
  1213. if (log_sys->n_pending_checkpoint_writes == 0) {
  1214. log_complete_checkpoint();
  1215. }
  1216. mutex_exit(&(log_sys->mutex));
  1217. }
  1218. /***********************************************************************
  1219. Writes info to a checkpoint about a log group. */
  1220. static
  1221. void
  1222. log_checkpoint_set_nth_group_info(
  1223. /*==============================*/
  1224. byte* buf, /* in: buffer for checkpoint info */
  1225. ulint n, /* in: nth slot */
  1226. ulint file_no,/* in: archived file number */
  1227. ulint offset) /* in: archived file offset */
  1228. {
  1229. ut_ad(n < LOG_MAX_N_GROUPS);
  1230. mach_write_to_4(buf + LOG_CHECKPOINT_GROUP_ARRAY
  1231. + 8 * n + LOG_CHECKPOINT_ARCHIVED_FILE_NO, file_no);
  1232. mach_write_to_4(buf + LOG_CHECKPOINT_GROUP_ARRAY
  1233. + 8 * n + LOG_CHECKPOINT_ARCHIVED_OFFSET, offset);
  1234. }
  1235. /***********************************************************************
  1236. Gets info from a checkpoint about a log group. */
  1237. void
  1238. log_checkpoint_get_nth_group_info(
  1239. /*==============================*/
  1240. byte* buf, /* in: buffer containing checkpoint info */
  1241. ulint n, /* in: nth slot */
  1242. ulint* file_no,/* out: archived file number */
  1243. ulint* offset) /* out: archived file offset */
  1244. {
  1245. ut_ad(n < LOG_MAX_N_GROUPS);
  1246. *file_no = mach_read_from_4(buf + LOG_CHECKPOINT_GROUP_ARRAY
  1247. + 8 * n + LOG_CHECKPOINT_ARCHIVED_FILE_NO);
  1248. *offset = mach_read_from_4(buf + LOG_CHECKPOINT_GROUP_ARRAY
  1249. + 8 * n + LOG_CHECKPOINT_ARCHIVED_OFFSET);
  1250. }
  1251. /**********************************************************
  1252. Writes the checkpoint info to a log group header. */
  1253. static
  1254. void
  1255. log_group_checkpoint(
  1256. /*=================*/
  1257. log_group_t* group) /* in: log group */
  1258. {
  1259. log_group_t* group2;
  1260. #ifdef UNIV_LOG_ARCHIVE
  1261. dulint archived_lsn;
  1262. dulint next_archived_lsn;
  1263. #endif /* UNIV_LOG_ARCHIVE */
  1264. ulint write_offset;
  1265. ulint fold;
  1266. byte* buf;
  1267. ulint i;
  1268. #ifdef UNIV_SYNC_DEBUG
  1269. ut_ad(mutex_own(&(log_sys->mutex)));
  1270. #endif /* UNIV_SYNC_DEBUG */
  1271. ut_a(LOG_CHECKPOINT_SIZE <= OS_FILE_LOG_BLOCK_SIZE);
  1272. buf = group->checkpoint_buf;
  1273. mach_write_to_8(buf + LOG_CHECKPOINT_NO, log_sys->next_checkpoint_no);
  1274. mach_write_to_8(buf + LOG_CHECKPOINT_LSN,
  1275. log_sys->next_checkpoint_lsn);
  1276. mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET,
  1277. log_group_calc_lsn_offset(
  1278. log_sys->next_checkpoint_lsn, group));
  1279. mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, log_sys->buf_size);
  1280. #ifdef UNIV_LOG_ARCHIVE
  1281. if (log_sys->archiving_state == LOG_ARCH_OFF) {
  1282. archived_lsn = ut_dulint_max;
  1283. } else {
  1284. archived_lsn = log_sys->archived_lsn;
  1285. if (0 != ut_dulint_cmp(archived_lsn,
  1286. log_sys->next_archived_lsn)) {
  1287. next_archived_lsn = log_sys->next_archived_lsn;
  1288. /* For debugging only */
  1289. }
  1290. }
  1291. mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, archived_lsn);
  1292. #else /* UNIV_LOG_ARCHIVE */
  1293. mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, ut_dulint_max);
  1294. #endif /* UNIV_LOG_ARCHIVE */
  1295. for (i = 0; i < LOG_MAX_N_GROUPS; i++) {
  1296. log_checkpoint_set_nth_group_info(buf, i, 0, 0);
  1297. }
  1298. group2 = UT_LIST_GET_FIRST(log_sys->log_groups);
  1299. while (group2) {
  1300. log_checkpoint_set_nth_group_info(buf, group2->id,
  1301. #ifdef UNIV_LOG_ARCHIVE
  1302. group2->archived_file_no,
  1303. group2->archived_offset
  1304. #else /* UNIV_LOG_ARCHIVE */
  1305. 0, 0
  1306. #endif /* UNIV_LOG_ARCHIVE */
  1307. );
  1308. group2 = UT_LIST_GET_NEXT(log_groups, group2);
  1309. }
  1310. fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1);
  1311. mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_1, fold);
  1312. fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
  1313. LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
  1314. mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_2, fold);
  1315. /* Starting from InnoDB-3.23.50, we also write info on allocated
  1316. size in the tablespace */
  1317. mach_write_to_4(buf + LOG_CHECKPOINT_FSP_FREE_LIMIT,
  1318. log_fsp_current_free_limit);
  1319. mach_write_to_4(buf + LOG_CHECKPOINT_FSP_MAGIC_N,
  1320. LOG_CHECKPOINT_FSP_MAGIC_N_VAL);
  1321. /* We alternate the physical place of the checkpoint info in the first
  1322. log file */
  1323. if (ut_dulint_get_low(log_sys->next_checkpoint_no) % 2 == 0) {
  1324. write_offset = LOG_CHECKPOINT_1;
  1325. } else {
  1326. write_offset = LOG_CHECKPOINT_2;
  1327. }
  1328. if (log_do_write) {
  1329. if (log_sys->n_pending_checkpoint_writes == 0) {
  1330. rw_lock_x_lock_gen(&(log_sys->checkpoint_lock),
  1331. LOG_CHECKPOINT);
  1332. }
  1333. log_sys->n_pending_checkpoint_writes++;
  1334. log_sys->n_log_ios++;
  1335. /* We send as the last parameter the group machine address
  1336. added with 1, as we want to distinguish between a normal log
  1337. file write and a checkpoint field write */
  1338. fil_io(OS_FILE_WRITE | OS_FILE_LOG, FALSE, group->space_id,
  1339. write_offset / UNIV_PAGE_SIZE,
  1340. write_offset % UNIV_PAGE_SIZE,
  1341. OS_FILE_LOG_BLOCK_SIZE,
  1342. buf, ((byte*)group + 1));
  1343. ut_ad(((ulint)group & 0x1UL) == 0);
  1344. }
  1345. }
  1346. /**********************************************************
  1347. Writes info to a buffer of a log group when log files are created in
  1348. backup restoration. */
  1349. void
  1350. log_reset_first_header_and_checkpoint(
  1351. /*==================================*/
  1352. byte* hdr_buf,/* in: buffer which will be written to the start
  1353. of the first log file */
  1354. dulint start) /* in: lsn of the start of the first log file;
  1355. we pretend that there is a checkpoint at
  1356. start + LOG_BLOCK_HDR_SIZE */
  1357. {
  1358. ulint fold;
  1359. byte* buf;
  1360. dulint lsn;
  1361. mach_write_to_4(hdr_buf + LOG_GROUP_ID, 0);
  1362. mach_write_to_8(hdr_buf + LOG_FILE_START_LSN, start);
  1363. lsn = ut_dulint_add(start, LOG_BLOCK_HDR_SIZE);
  1364. /* Write the label of ibbackup --restore */
  1365. strcpy((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
  1366. "ibbackup ");
  1367. ut_sprintf_timestamp(
  1368. (char*) hdr_buf + (LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
  1369. + (sizeof "ibbackup ") - 1));
  1370. buf = hdr_buf + LOG_CHECKPOINT_1;
  1371. mach_write_to_8(buf + LOG_CHECKPOINT_NO, ut_dulint_zero);
  1372. mach_write_to_8(buf + LOG_CHECKPOINT_LSN, lsn);
  1373. mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET,
  1374. LOG_FILE_HDR_SIZE + LOG_BLOCK_HDR_SIZE);
  1375. mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, 2 * 1024 * 1024);
  1376. mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, ut_dulint_max);
  1377. fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1);
  1378. mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_1, fold);
  1379. fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
  1380. LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
  1381. mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_2, fold);
  1382. /* Starting from InnoDB-3.23.50, we should also write info on
  1383. allocated size in the tablespace, but unfortunately we do not
  1384. know it here */
  1385. }
  1386. /**********************************************************
  1387. Reads a checkpoint info from a log group header to log_sys->checkpoint_buf. */
  1388. void
  1389. log_group_read_checkpoint_info(
  1390. /*===========================*/
  1391. log_group_t* group, /* in: log group */
  1392. ulint field) /* in: LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2 */
  1393. {
  1394. #ifdef UNIV_SYNC_DEBUG
  1395. ut_ad(mutex_own(&(log_sys->mutex)));
  1396. #endif /* UNIV_SYNC_DEBUG */
  1397. log_sys->n_log_ios++;
  1398. fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, group->space_id,
  1399. field / UNIV_PAGE_SIZE, field % UNIV_PAGE_SIZE,
  1400. OS_FILE_LOG_BLOCK_SIZE, log_sys->checkpoint_buf, NULL);
  1401. }
  1402. /**********************************************************
  1403. Writes checkpoint info to groups. */
  1404. void
  1405. log_groups_write_checkpoint_info(void)
  1406. /*==================================*/
  1407. {
  1408. log_group_t* group;
  1409. #ifdef UNIV_SYNC_DEBUG
  1410. ut_ad(mutex_own(&(log_sys->mutex)));
  1411. #endif /* UNIV_SYNC_DEBUG */
  1412. group = UT_LIST_GET_FIRST(log_sys->log_groups);
  1413. while (group) {
  1414. log_group_checkpoint(group);
  1415. group = UT_LIST_GET_NEXT(log_groups, group);
  1416. }
  1417. }
  1418. /**********************************************************
  1419. Makes a checkpoint. Note that this function does not flush dirty
  1420. blocks from the buffer pool: it only checks what is lsn of the oldest
  1421. modification in the pool, and writes information about the lsn in
  1422. log files. Use log_make_checkpoint_at to flush also the pool. */
  1423. ibool
  1424. log_checkpoint(
  1425. /*===========*/
  1426. /* out: TRUE if success, FALSE if a checkpoint
  1427. write was already running */
  1428. ibool sync, /* in: TRUE if synchronous operation is
  1429. desired */
  1430. ibool write_always) /* in: the function normally checks if the
  1431. the new checkpoint would have a greater
  1432. lsn than the previous one: if not, then no
  1433. physical write is done; by setting this
  1434. parameter TRUE, a physical write will always be
  1435. made to log files */
  1436. {
  1437. dulint oldest_lsn;
  1438. if (recv_recovery_is_on()) {
  1439. recv_apply_hashed_log_recs(TRUE);
  1440. }
  1441. if (srv_unix_file_flush_method != SRV_UNIX_NOSYNC) {
  1442.         fil_flush_file_spaces(FIL_TABLESPACE);
  1443. }
  1444. mutex_enter(&(log_sys->mutex));
  1445. oldest_lsn = log_buf_pool_get_oldest_modification();
  1446. mutex_exit(&(log_sys->mutex));
  1447. /* Because log also contains headers and dummy log records,
  1448. if the buffer pool contains no dirty buffers, oldest_lsn
  1449. gets the value log_sys->lsn from the previous function,
  1450. and we must make sure that the log is flushed up to that
  1451. lsn. If there are dirty buffers in the buffer pool, then our
  1452. write-ahead-logging algorithm ensures that the log has been flushed
  1453. up to oldest_lsn. */
  1454. log_write_up_to(oldest_lsn, LOG_WAIT_ALL_GROUPS, TRUE);
  1455. mutex_enter(&(log_sys->mutex));
  1456. if (!write_always && ut_dulint_cmp(
  1457. log_sys->last_checkpoint_lsn, oldest_lsn) >= 0) {
  1458. mutex_exit(&(log_sys->mutex));
  1459. return(TRUE);
  1460. }
  1461. ut_ad(ut_dulint_cmp(log_sys->written_to_all_lsn, oldest_lsn) >= 0);
  1462. if (log_sys->n_pending_checkpoint_writes > 0) {
  1463. /* A checkpoint write is running */
  1464. mutex_exit(&(log_sys->mutex));
  1465. if (sync) {
  1466. /* Wait for the checkpoint write to complete */
  1467. rw_lock_s_lock(&(log_sys->checkpoint_lock));
  1468. rw_lock_s_unlock(&(log_sys->checkpoint_lock));
  1469. }
  1470. return(FALSE);
  1471. }
  1472. log_sys->next_checkpoint_lsn = oldest_lsn;
  1473. if (log_debug_writes) {
  1474. fprintf(stderr, "Making checkpoint no %lu at lsn %lu %lun",
  1475. (ulong) ut_dulint_get_low(log_sys->next_checkpoint_no),
  1476. (ulong) ut_dulint_get_high(oldest_lsn),
  1477. (ulong) ut_dulint_get_low(oldest_lsn));
  1478. }
  1479. log_groups_write_checkpoint_info();
  1480. mutex_exit(&(log_sys->mutex));
  1481. if (sync) {
  1482. /* Wait for the checkpoint write to complete */
  1483. rw_lock_s_lock(&(log_sys->checkpoint_lock));
  1484. rw_lock_s_unlock(&(log_sys->checkpoint_lock));
  1485. }
  1486. return(TRUE);
  1487. }
  1488. /********************************************************************
  1489. Makes a checkpoint at a given lsn or later. */
  1490. void
  1491. log_make_checkpoint_at(
  1492. /*===================*/
  1493. dulint lsn, /* in: make a checkpoint at this or a later
  1494. lsn, if ut_dulint_max, makes a checkpoint at
  1495. the latest lsn */
  1496. ibool write_always) /* in: the function normally checks if the
  1497. the new checkpoint would have a greater
  1498. lsn than the previous one: if not, then no
  1499. physical write is done; by setting this
  1500. parameter TRUE, a physical write will always be
  1501. made to log files */
  1502. {
  1503. ibool success;
  1504. /* Preflush pages synchronously */
  1505. success = FALSE;
  1506. while (!success) {
  1507. success = log_preflush_pool_modified_pages(lsn, TRUE);
  1508. }
  1509. success = FALSE;
  1510. while (!success) {
  1511. success = log_checkpoint(TRUE, write_always);
  1512. }
  1513. }
  1514. /********************************************************************
  1515. Tries to establish a big enough margin of free space in the log groups, such
  1516. that a new log entry can be catenated without an immediate need for a
  1517. checkpoint. NOTE: this function may only be called if the calling thread
  1518. owns no synchronization objects! */
  1519. static
  1520. void
  1521. log_checkpoint_margin(void)
  1522. /*=======================*/
  1523. {
  1524. log_t* log = log_sys;
  1525. ulint age;
  1526. ulint checkpoint_age;
  1527. ulint advance;
  1528. dulint oldest_lsn;
  1529. dulint new_oldest;
  1530. ibool do_preflush;
  1531. ibool sync;
  1532. ibool checkpoint_sync;
  1533. ibool do_checkpoint;
  1534. ibool success;
  1535. loop:
  1536. sync = FALSE;
  1537. checkpoint_sync = FALSE;
  1538. do_preflush = FALSE;
  1539. do_checkpoint = FALSE;
  1540. mutex_enter(&(log->mutex));
  1541. if (log->check_flush_or_checkpoint == FALSE) {
  1542. mutex_exit(&(log->mutex));
  1543. return;
  1544. }
  1545. oldest_lsn = log_buf_pool_get_oldest_modification();
  1546. age = ut_dulint_minus(log->lsn, oldest_lsn);
  1547. if (age > log->max_modified_age_sync) {
  1548. /* A flush is urgent: we have to do a synchronous preflush */
  1549. sync = TRUE;
  1550. advance = 2 * (age - log->max_modified_age_sync);
  1551. new_oldest = ut_dulint_add(oldest_lsn, advance);
  1552. do_preflush = TRUE;
  1553. } else if (age > log->max_modified_age_async) {
  1554. /* A flush is not urgent: we do an asynchronous preflush */
  1555. advance = age - log->max_modified_age_async;
  1556. new_oldest = ut_dulint_add(oldest_lsn, advance);
  1557. do_preflush = TRUE;
  1558. }
  1559. checkpoint_age = ut_dulint_minus(log->lsn, log->last_checkpoint_lsn);
  1560. if (checkpoint_age > log->max_checkpoint_age) {
  1561. /* A checkpoint is urgent: we do it synchronously */
  1562. checkpoint_sync = TRUE;
  1563. do_checkpoint = TRUE;
  1564. } else if (checkpoint_age > log->max_checkpoint_age_async) {
  1565. /* A checkpoint is not urgent: do it asynchronously */
  1566. do_checkpoint = TRUE;
  1567. log->check_flush_or_checkpoint = FALSE;
  1568. } else {
  1569. log->check_flush_or_checkpoint = FALSE;
  1570. }
  1571. mutex_exit(&(log->mutex));
  1572. if (do_preflush) {
  1573. success = log_preflush_pool_modified_pages(new_oldest, sync);
  1574. /* If the flush succeeded, this thread has done its part
  1575. and can proceed. If it did not succeed, there was another
  1576. thread doing a flush at the same time. If sync was FALSE,
  1577. the flush was not urgent, and we let this thread proceed.
  1578. Otherwise, we let it start from the beginning again. */
  1579. if (sync && !success) {
  1580. mutex_enter(&(log->mutex));
  1581. log->check_flush_or_checkpoint = TRUE;
  1582. mutex_exit(&(log->mutex));
  1583. goto loop;
  1584. }
  1585. }
  1586. if (do_checkpoint) {
  1587. log_checkpoint(checkpoint_sync, FALSE);
  1588. if (checkpoint_sync) {
  1589. goto loop;
  1590. }
  1591. }
  1592. }
  1593. /**********************************************************
  1594. Reads a specified log segment to a buffer. */
  1595. void
  1596. log_group_read_log_seg(
  1597. /*===================*/
  1598. ulint type, /* in: LOG_ARCHIVE or LOG_RECOVER */
  1599. byte* buf, /* in: buffer where to read */
  1600. log_group_t* group, /* in: log group */
  1601. dulint start_lsn, /* in: read area start */
  1602. dulint end_lsn) /* in: read area end */
  1603. {
  1604. ulint len;
  1605. ulint source_offset;
  1606. ibool sync;
  1607. #ifdef UNIV_SYNC_DEBUG
  1608. ut_ad(mutex_own(&(log_sys->mutex)));
  1609. #endif /* UNIV_SYNC_DEBUG */
  1610. sync = FALSE;
  1611. if (type == LOG_RECOVER) {
  1612. sync = TRUE;
  1613. }
  1614. loop:
  1615. source_offset = log_group_calc_lsn_offset(start_lsn, group);
  1616. len = ut_dulint_minus(end_lsn, start_lsn);
  1617. ut_ad(len != 0);
  1618. if ((source_offset % group->file_size) + len > group->file_size) {
  1619. len = group->file_size - (source_offset % group->file_size);
  1620. }
  1621. #ifdef UNIV_LOG_ARCHIVE
  1622. if (type == LOG_ARCHIVE) {
  1623. log_sys->n_pending_archive_ios++;
  1624. }
  1625. #endif /* UNIV_LOG_ARCHIVE */
  1626. log_sys->n_log_ios++;
  1627. fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id,
  1628. source_offset / UNIV_PAGE_SIZE, source_offset % UNIV_PAGE_SIZE,
  1629. len, buf, NULL);
  1630. start_lsn = ut_dulint_add(start_lsn, len);
  1631. buf += len;
  1632. if (ut_dulint_cmp(start_lsn, end_lsn) != 0) {
  1633. goto loop;
  1634. }
  1635. }
  1636. #ifdef UNIV_LOG_ARCHIVE
  1637. /**********************************************************
  1638. Generates an archived log file name. */
  1639. void
  1640. log_archived_file_name_gen(
  1641. /*=======================*/
  1642. char* buf, /* in: buffer where to write */
  1643. ulint id __attribute__((unused)),
  1644. /* in: group id;
  1645. currently we only archive the first group */
  1646. ulint file_no)/* in: file number */
  1647. {
  1648. sprintf(buf, "%sib_arch_log_%010lu", srv_arch_dir, (ulong) file_no);
  1649. }
  1650. /**********************************************************
  1651. Writes a log file header to a log file space. */
  1652. static
  1653. void
  1654. log_group_archive_file_header_write(
  1655. /*================================*/
  1656. log_group_t* group, /* in: log group */
  1657. ulint nth_file, /* in: header to the nth file in the
  1658. archive log file space */
  1659. ulint file_no, /* in: archived file number */
  1660. dulint start_lsn) /* in: log file data starts at this
  1661. lsn */
  1662. {
  1663. byte* buf;
  1664. ulint dest_offset;
  1665. #ifdef UNIV_SYNC_DEBUG
  1666. ut_ad(mutex_own(&(log_sys->mutex)));
  1667. #endif /* UNIV_SYNC_DEBUG */
  1668. ut_a(nth_file < group->n_files);
  1669. buf = *(group->archive_file_header_bufs + nth_file);
  1670. mach_write_to_4(buf + LOG_GROUP_ID, group->id);
  1671. mach_write_to_8(buf + LOG_FILE_START_LSN, start_lsn);
  1672. mach_write_to_4(buf + LOG_FILE_NO, file_no);
  1673. mach_write_to_4(buf + LOG_FILE_ARCH_COMPLETED, FALSE);
  1674. dest_offset = nth_file * group->file_size;
  1675. log_sys->n_log_ios++;
  1676. fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->archive_space_id,
  1677. dest_offset / UNIV_PAGE_SIZE,
  1678. dest_offset % UNIV_PAGE_SIZE,
  1679. 2 * OS_FILE_LOG_BLOCK_SIZE,
  1680. buf, &log_archive_io);
  1681. }
  1682. /**********************************************************
  1683. Writes a log file header to a completed archived log file. */
  1684. static
  1685. void
  1686. log_group_archive_completed_header_write(
  1687. /*=====================================*/
  1688. log_group_t* group, /* in: log group */
  1689. ulint nth_file, /* in: header to the nth file in the
  1690. archive log file space */
  1691. dulint end_lsn) /* in: end lsn of the file */
  1692. {
  1693. byte* buf;
  1694. ulint dest_offset;
  1695. #ifdef UNIV_SYNC_DEBUG
  1696. ut_ad(mutex_own(&(log_sys->mutex)));
  1697. #endif /* UNIV_SYNC_DEBUG */
  1698. ut_a(nth_file < group->n_files);
  1699. buf = *(group->archive_file_header_bufs + nth_file);
  1700. mach_write_to_4(buf + LOG_FILE_ARCH_COMPLETED, TRUE);
  1701. mach_write_to_8(buf + LOG_FILE_END_LSN, end_lsn);
  1702. dest_offset = nth_file * group->file_size + LOG_FILE_ARCH_COMPLETED;
  1703. log_sys->n_log_ios++;
  1704. fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->archive_space_id,
  1705. dest_offset / UNIV_PAGE_SIZE,
  1706. dest_offset % UNIV_PAGE_SIZE,
  1707. OS_FILE_LOG_BLOCK_SIZE,
  1708. buf + LOG_FILE_ARCH_COMPLETED,
  1709. &log_archive_io);
  1710. }
  1711. /**********************************************************
  1712. Does the archive writes for a single log group. */
  1713. static
  1714. void
  1715. log_group_archive(
  1716. /*==============*/
  1717. log_group_t* group) /* in: log group */
  1718. {
  1719. os_file_t file_handle;
  1720. dulint start_lsn;
  1721. dulint end_lsn;
  1722. char name[1024];
  1723. byte* buf;
  1724. ulint len;
  1725. ibool ret;
  1726. ulint next_offset;
  1727. ulint n_files;
  1728. ulint open_mode;
  1729. #ifdef UNIV_SYNC_DEBUG
  1730. ut_ad(mutex_own(&(log_sys->mutex)));
  1731. #endif /* UNIV_SYNC_DEBUG */
  1732. start_lsn = log_sys->archived_lsn;
  1733. ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
  1734. end_lsn = log_sys->next_archived_lsn;
  1735. ut_a(ut_dulint_get_low(end_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
  1736. buf = log_sys->archive_buf;
  1737. n_files = 0;
  1738. next_offset = group->archived_offset;
  1739. loop:
  1740. if ((next_offset % group->file_size == 0)
  1741.     || (fil_space_get_size(group->archive_space_id) == 0)) {
  1742. /* Add the file to the archive file space; create or open the
  1743. file */
  1744. if (next_offset % group->file_size == 0) {
  1745. open_mode = OS_FILE_CREATE;
  1746. } else {
  1747. open_mode = OS_FILE_OPEN;
  1748. }
  1749. log_archived_file_name_gen(name, group->id,
  1750. group->archived_file_no + n_files);
  1751. file_handle = os_file_create(name, open_mode, OS_FILE_AIO,
  1752. OS_DATA_FILE, &ret);
  1753. if (!ret && (open_mode == OS_FILE_CREATE)) {
  1754. file_handle = os_file_create(name, OS_FILE_OPEN,
  1755. OS_FILE_AIO, OS_DATA_FILE, &ret);
  1756. }
  1757. if (!ret) {
  1758. fprintf(stderr,
  1759. "InnoDB: Cannot create or open archive log file %s.n"
  1760. "InnoDB: Cannot continue operation.n"
  1761. "InnoDB: Check that the log archive directory exists,n"
  1762. "InnoDB: you have access rights to it, andn"
  1763. "InnoDB: there is space available.n", name);
  1764. exit(1);
  1765. }
  1766. if (log_debug_writes) {
  1767. fprintf(stderr, "Created archive file %sn", name);
  1768. }
  1769. ret = os_file_close(file_handle);
  1770. ut_a(ret);
  1771. /* Add the archive file as a node to the space */
  1772. fil_node_create(name, group->file_size / UNIV_PAGE_SIZE,
  1773. group->archive_space_id, FALSE);
  1774. if (next_offset % group->file_size == 0) {
  1775. log_group_archive_file_header_write(group, n_files,
  1776. group->archived_file_no + n_files,
  1777. start_lsn);
  1778. next_offset += LOG_FILE_HDR_SIZE;
  1779. }
  1780. }
  1781. len = ut_dulint_minus(end_lsn, start_lsn);
  1782. if (group->file_size < (next_offset % group->file_size) + len) {
  1783. len = group->file_size - (next_offset % group->file_size);
  1784. }
  1785. if (log_debug_writes) {
  1786. fprintf(stderr,
  1787. "Archiving starting at lsn %lu %lu, len %lu to group %lun",
  1788. (ulong) ut_dulint_get_high(start_lsn),
  1789. (ulong) ut_dulint_get_low(start_lsn),
  1790. (ulong) len, (ulong) group->id);
  1791. }
  1792. log_sys->n_pending_archive_ios++;
  1793. log_sys->n_log_ios++;
  1794. fil_io(OS_FILE_WRITE | OS_FILE_LOG, FALSE, group->archive_space_id,
  1795. next_offset / UNIV_PAGE_SIZE, next_offset % UNIV_PAGE_SIZE,
  1796. ut_calc_align(len, OS_FILE_LOG_BLOCK_SIZE), buf,
  1797. &log_archive_io);
  1798. start_lsn = ut_dulint_add(start_lsn, len);
  1799. next_offset += len;
  1800. buf += len;
  1801. if (next_offset % group->file_size == 0) {
  1802. n_files++;
  1803. }
  1804. if (ut_dulint_cmp(end_lsn, start_lsn) != 0) {
  1805. goto loop;
  1806. }
  1807. group->next_archived_file_no = group->archived_file_no + n_files;
  1808. group->next_archived_offset = next_offset % group->file_size;
  1809. ut_a(group->next_archived_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
  1810. }
  1811. /*********************************************************
  1812. (Writes to the archive of each log group.) Currently, only the first
  1813. group is archived. */
  1814. static
  1815. void
  1816. log_archive_groups(void)
  1817. /*====================*/
  1818. {
  1819. log_group_t* group;
  1820. #ifdef UNIV_SYNC_DEBUG
  1821. ut_ad(mutex_own(&(log_sys->mutex)));
  1822. #endif /* UNIV_SYNC_DEBUG */
  1823. group = UT_LIST_GET_FIRST(log_sys->log_groups);
  1824. log_group_archive(group);
  1825. }
  1826. /*********************************************************
  1827. Completes the archiving write phase for (each log group), currently,
  1828. the first log group. */
  1829. static
  1830. void
  1831. log_archive_write_complete_groups(void)
  1832. /*===================================*/
  1833. {
  1834. log_group_t* group;
  1835. ulint end_offset;
  1836. ulint trunc_files;
  1837. ulint n_files;
  1838. dulint start_lsn;
  1839. dulint end_lsn;
  1840. ulint i;
  1841. #ifdef UNIV_SYNC_DEBUG
  1842. ut_ad(mutex_own(&(log_sys->mutex)));
  1843. #endif /* UNIV_SYNC_DEBUG */
  1844. group = UT_LIST_GET_FIRST(log_sys->log_groups);
  1845. group->archived_file_no = group->next_archived_file_no;
  1846. group->archived_offset = group->next_archived_offset;
  1847. /* Truncate from the archive file space all but the last
  1848. file, or if it has been written full, all files */
  1849. n_files = (UNIV_PAGE_SIZE
  1850.     * fil_space_get_size(group->archive_space_id))
  1851.      / group->file_size;
  1852. ut_ad(n_files > 0);
  1853. end_offset = group->archived_offset;
  1854. if (end_offset % group->file_size == 0) {
  1855. trunc_files = n_files;
  1856. } else {
  1857. trunc_files = n_files - 1;
  1858. }
  1859. if (log_debug_writes && trunc_files) {
  1860. fprintf(stderr,
  1861. "Complete file(s) archived to group %lun",
  1862.   (ulong) group->id);
  1863. }
  1864. /* Calculate the archive file space start lsn */
  1865. start_lsn = ut_dulint_subtract(log_sys->next_archived_lsn,
  1866. end_offset - LOG_FILE_HDR_SIZE
  1867. + trunc_files
  1868.   * (group->file_size - LOG_FILE_HDR_SIZE));
  1869. end_lsn = start_lsn;
  1870. for (i = 0; i < trunc_files; i++) {
  1871. end_lsn = ut_dulint_add(end_lsn,
  1872. group->file_size - LOG_FILE_HDR_SIZE);
  1873. /* Write a notice to the headers of archived log
  1874. files that the file write has been completed */
  1875. log_group_archive_completed_header_write(group, i, end_lsn);
  1876. }
  1877. fil_space_truncate_start(group->archive_space_id,
  1878. trunc_files * group->file_size);
  1879. if (log_debug_writes) {
  1880. fputs("Archiving writes completedn", stderr);
  1881. }
  1882. }
  1883. /**********************************************************
  1884. Completes an archiving i/o. */
  1885. static
  1886. void
  1887. log_archive_check_completion_low(void)
  1888. /*==================================*/
  1889. {
  1890. #ifdef UNIV_SYNC_DEBUG
  1891. ut_ad(mutex_own(&(log_sys->mutex)));
  1892. #endif /* UNIV_SYNC_DEBUG */
  1893. if (log_sys->n_pending_archive_ios == 0
  1894. && log_sys->archiving_phase == LOG_ARCHIVE_READ) {
  1895. if (log_debug_writes) {
  1896. fputs("Archiving read completedn", stderr);
  1897. }
  1898.      /* Archive buffer has now been read in: start archive writes */
  1899. log_sys->archiving_phase = LOG_ARCHIVE_WRITE;
  1900. log_archive_groups();
  1901. }
  1902. if (log_sys->n_pending_archive_ios == 0
  1903. && log_sys->archiving_phase == LOG_ARCHIVE_WRITE) {
  1904.       log_archive_write_complete_groups();
  1905. log_sys->archived_lsn = log_sys->next_archived_lsn;
  1906. rw_lock_x_unlock_gen(&(log_sys->archive_lock), LOG_ARCHIVE);
  1907. }
  1908. }
  1909. /**********************************************************
  1910. Completes an archiving i/o. */
  1911. static
  1912. void
  1913. log_io_complete_archive(void)
  1914. /*=========================*/
  1915. {
  1916. log_group_t* group;
  1917. mutex_enter(&(log_sys->mutex));
  1918. group = UT_LIST_GET_FIRST(log_sys->log_groups);
  1919. mutex_exit(&(log_sys->mutex));
  1920. fil_flush(group->archive_space_id);
  1921. mutex_enter(&(log_sys->mutex));
  1922. ut_ad(log_sys->n_pending_archive_ios > 0);
  1923. log_sys->n_pending_archive_ios--;
  1924. log_archive_check_completion_low();
  1925. mutex_exit(&(log_sys->mutex));
  1926. }
  1927. /************************************************************************
  1928. Starts an archiving operation. */
  1929. ibool
  1930. log_archive_do(
  1931. /*===========*/
  1932. /* out: TRUE if succeed, FALSE if an archiving
  1933. operation was already running */
  1934. ibool sync, /* in: TRUE if synchronous operation is desired */
  1935. ulint* n_bytes)/* out: archive log buffer size, 0 if nothing to
  1936. archive */
  1937. {
  1938. ibool calc_new_limit;
  1939. dulint start_lsn;
  1940. dulint limit_lsn;
  1941. calc_new_limit = TRUE;
  1942. loop:
  1943. mutex_enter(&(log_sys->mutex));
  1944. if (log_sys->archiving_state == LOG_ARCH_OFF) {
  1945. mutex_exit(&(log_sys->mutex));
  1946. *n_bytes = 0;
  1947. return(TRUE);
  1948. } else if (log_sys->archiving_state == LOG_ARCH_STOPPED
  1949.            || log_sys->archiving_state == LOG_ARCH_STOPPING2) {
  1950. mutex_exit(&(log_sys->mutex));
  1951. os_event_wait(log_sys->archiving_on);
  1952. mutex_enter(&(log_sys->mutex));
  1953. goto loop;
  1954. }
  1955. start_lsn = log_sys->archived_lsn;
  1956. if (calc_new_limit) {
  1957.         ut_a(log_sys->archive_buf_size % OS_FILE_LOG_BLOCK_SIZE == 0);
  1958. limit_lsn = ut_dulint_add(start_lsn,
  1959. log_sys->archive_buf_size);
  1960. *n_bytes = log_sys->archive_buf_size;
  1961. if (ut_dulint_cmp(limit_lsn, log_sys->lsn) >= 0) {
  1962. limit_lsn = ut_dulint_align_down(log_sys->lsn,
  1963. OS_FILE_LOG_BLOCK_SIZE);
  1964. }
  1965. }
  1966. if (ut_dulint_cmp(log_sys->archived_lsn, limit_lsn) >= 0) {
  1967. mutex_exit(&(log_sys->mutex));
  1968. *n_bytes = 0;
  1969. return(TRUE);
  1970. }
  1971. if (ut_dulint_cmp(log_sys->written_to_all_lsn, limit_lsn) < 0) {
  1972. mutex_exit(&(log_sys->mutex));
  1973. log_write_up_to(limit_lsn, LOG_WAIT_ALL_GROUPS, TRUE);
  1974. calc_new_limit = FALSE;
  1975. goto loop;
  1976. }
  1977. if (log_sys->n_pending_archive_ios > 0) {
  1978. /* An archiving operation is running */
  1979. mutex_exit(&(log_sys->mutex));
  1980. if (sync) {
  1981. rw_lock_s_lock(&(log_sys->archive_lock));
  1982. rw_lock_s_unlock(&(log_sys->archive_lock));
  1983. }
  1984. *n_bytes = log_sys->archive_buf_size;
  1985. return(FALSE);
  1986. }
  1987. rw_lock_x_lock_gen(&(log_sys->archive_lock), LOG_ARCHIVE);
  1988. log_sys->archiving_phase = LOG_ARCHIVE_READ;
  1989. log_sys->next_archived_lsn = limit_lsn;
  1990. if (log_debug_writes) {
  1991. fprintf(stderr,
  1992. "Archiving from lsn %lu %lu to lsn %lu %lun",
  1993. (ulong) ut_dulint_get_high(log_sys->archived_lsn),
  1994. (ulong) ut_dulint_get_low(log_sys->archived_lsn),
  1995. (ulong) ut_dulint_get_high(limit_lsn),
  1996. (ulong) ut_dulint_get_low(limit_lsn));
  1997. }
  1998. /* Read the log segment to the archive buffer */
  1999. log_group_read_log_seg(LOG_ARCHIVE, log_sys->archive_buf,
  2000. UT_LIST_GET_FIRST(log_sys->log_groups),
  2001. start_lsn, limit_lsn);
  2002. mutex_exit(&(log_sys->mutex));
  2003. if (sync) {
  2004. rw_lock_s_lock(&(log_sys->archive_lock));
  2005. rw_lock_s_unlock(&(log_sys->archive_lock));
  2006. }
  2007. *n_bytes = log_sys->archive_buf_size;
  2008. return(TRUE);
  2009. }
  2010. /********************************************************************
  2011. Writes the log contents to the archive at least up to the lsn when this
  2012. function was called. */
  2013. static
  2014. void
  2015. log_archive_all(void)
  2016. /*=================*/
  2017. {
  2018. dulint present_lsn;
  2019. ulint dummy;
  2020. mutex_enter(&(log_sys->mutex));
  2021. if (log_sys->archiving_state == LOG_ARCH_OFF) {
  2022. mutex_exit(&(log_sys->mutex));
  2023. return;
  2024. }
  2025. present_lsn = log_sys->lsn;
  2026. mutex_exit(&(log_sys->mutex));
  2027. log_pad_current_log_block();
  2028. for (;;) {
  2029. mutex_enter(&(log_sys->mutex));
  2030. if (ut_dulint_cmp(present_lsn, log_sys->archived_lsn) <= 0) {
  2031. mutex_exit(&(log_sys->mutex));
  2032. return;
  2033. }
  2034. mutex_exit(&(log_sys->mutex));
  2035. log_archive_do(TRUE, &dummy);
  2036. }
  2037. }
  2038. /*********************************************************
  2039. Closes the possible open archive log file (for each group) the first group,
  2040. and if it was open, increments the group file count by 2, if desired. */
  2041. static
  2042. void
  2043. log_archive_close_groups(
  2044. /*=====================*/
  2045. ibool increment_file_count) /* in: TRUE if we want to increment
  2046. the file count */
  2047. {
  2048. log_group_t* group;
  2049. ulint trunc_len;
  2050. #ifdef UNIV_SYNC_DEBUG
  2051. ut_ad(mutex_own(&(log_sys->mutex)));
  2052. #endif /* UNIV_SYNC_DEBUG */
  2053. if (log_sys->archiving_state == LOG_ARCH_OFF) {
  2054. return;
  2055. }
  2056. group = UT_LIST_GET_FIRST(log_sys->log_groups);
  2057. trunc_len = UNIV_PAGE_SIZE
  2058.     * fil_space_get_size(group->archive_space_id);
  2059. if (trunc_len > 0) {
  2060. ut_a(trunc_len == group->file_size);
  2061.     
  2062. /* Write a notice to the headers of archived log
  2063. files that the file write has been completed */
  2064. log_group_archive_completed_header_write(group,
  2065. 0, log_sys->archived_lsn);
  2066. fil_space_truncate_start(group->archive_space_id,
  2067. trunc_len);
  2068. if (increment_file_count) {
  2069. group->archived_offset = 0;
  2070. group->archived_file_no += 2;
  2071. }
  2072. if (log_debug_writes) {
  2073. fprintf(stderr,
  2074. "Incrementing arch file no to %lu in log group %lun",
  2075. (ulong) group->archived_file_no + 2,
  2076.         (ulong) group->id);
  2077. }
  2078. }
  2079. }
  2080. /********************************************************************
  2081. Writes the log contents to the archive up to the lsn when this function was
  2082. called, and stops the archiving. When archiving is started again, the archived
  2083. log file numbers start from 2 higher, so that the archiving will not write
  2084. again to the archived log files which exist when this function returns. */
  2085. ulint
  2086. log_archive_stop(void)
  2087. /*==================*/
  2088. /* out: DB_SUCCESS or DB_ERROR */
  2089. {
  2090. ibool success;
  2091. mutex_enter(&(log_sys->mutex));
  2092. if (log_sys->archiving_state != LOG_ARCH_ON) {
  2093. mutex_exit(&(log_sys->mutex));
  2094. return(DB_ERROR);
  2095. }
  2096. log_sys->archiving_state = LOG_ARCH_STOPPING;
  2097. mutex_exit(&(log_sys->mutex));
  2098. log_archive_all();
  2099. mutex_enter(&(log_sys->mutex));
  2100. log_sys->archiving_state = LOG_ARCH_STOPPING2;
  2101. os_event_reset(log_sys->archiving_on);
  2102. mutex_exit(&(log_sys->mutex));
  2103. /* Wait for a possible archiving operation to end */
  2104. rw_lock_s_lock(&(log_sys->archive_lock));
  2105. rw_lock_s_unlock(&(log_sys->archive_lock));
  2106. mutex_enter(&(log_sys->mutex));
  2107. /* Close all archived log files, incrementing the file count by 2,
  2108. if appropriate */
  2109. log_archive_close_groups(TRUE);
  2110. mutex_exit(&(log_sys->mutex));
  2111. /* Make a checkpoint, so that if recovery is needed, the file numbers
  2112. of new archived log files will start from the right value */
  2113. success = FALSE;
  2114. while (!success) {
  2115. success = log_checkpoint(TRUE, TRUE);
  2116. }
  2117. mutex_enter(&(log_sys->mutex));
  2118. log_sys->archiving_state = LOG_ARCH_STOPPED;
  2119. mutex_exit(&(log_sys->mutex));
  2120. return(DB_SUCCESS);
  2121. }
  2122. /********************************************************************
  2123. Starts again archiving which has been stopped. */
  2124. ulint
  2125. log_archive_start(void)
  2126. /*===================*/
  2127. /* out: DB_SUCCESS or DB_ERROR */
  2128. {
  2129. mutex_enter(&(log_sys->mutex));
  2130. if (log_sys->archiving_state != LOG_ARCH_STOPPED) {
  2131. mutex_exit(&(log_sys->mutex));
  2132. return(DB_ERROR);
  2133. }
  2134. log_sys->archiving_state = LOG_ARCH_ON;
  2135. os_event_set(log_sys->archiving_on);
  2136. mutex_exit(&(log_sys->mutex));
  2137. return(DB_SUCCESS);
  2138. }
  2139. /********************************************************************
  2140. Stop archiving the log so that a gap may occur in the archived log files. */
  2141. ulint
  2142. log_archive_noarchivelog(void)
  2143. /*==========================*/
  2144. /* out: DB_SUCCESS or DB_ERROR */
  2145. {
  2146. loop:
  2147. mutex_enter(&(log_sys->mutex));
  2148. if (log_sys->archiving_state == LOG_ARCH_STOPPED
  2149.     || log_sys->archiving_state == LOG_ARCH_OFF) {
  2150. log_sys->archiving_state = LOG_ARCH_OFF;
  2151. os_event_set(log_sys->archiving_on);
  2152. mutex_exit(&(log_sys->mutex));
  2153. return(DB_SUCCESS);
  2154. }
  2155. mutex_exit(&(log_sys->mutex));
  2156. log_archive_stop();
  2157. os_thread_sleep(500000);
  2158. goto loop;
  2159. }
  2160. /********************************************************************
  2161. Start archiving the log so that a gap may occur in the archived log files. */
  2162. ulint
  2163. log_archive_archivelog(void)
  2164. /*========================*/
  2165. /* out: DB_SUCCESS or DB_ERROR */
  2166. {
  2167. mutex_enter(&(log_sys->mutex));
  2168. if (log_sys->archiving_state == LOG_ARCH_OFF) {
  2169. log_sys->archiving_state = LOG_ARCH_ON;
  2170. log_sys->archived_lsn = ut_dulint_align_down(log_sys->lsn,
  2171. OS_FILE_LOG_BLOCK_SIZE);
  2172. mutex_exit(&(log_sys->mutex));
  2173. return(DB_SUCCESS);
  2174. }
  2175. mutex_exit(&(log_sys->mutex));
  2176. return(DB_ERROR);
  2177. }
  2178. /********************************************************************
  2179. Tries to establish a big enough margin of free space in the log groups, such
  2180. that a new log entry can be catenated without an immediate need for
  2181. archiving. */
  2182. static
  2183. void
  2184. log_archive_margin(void)
  2185. /*====================*/
  2186. {
  2187. log_t* log = log_sys;
  2188. ulint age;
  2189. ibool sync;
  2190. ulint dummy;
  2191. loop:
  2192. mutex_enter(&(log->mutex));
  2193. if (log->archiving_state == LOG_ARCH_OFF) {
  2194. mutex_exit(&(log->mutex));
  2195. return;
  2196. }
  2197. age = ut_dulint_minus(log->lsn, log->archived_lsn);
  2198. if (age > log->max_archived_lsn_age) {
  2199. /* An archiving is urgent: we have to do synchronous i/o */
  2200. sync = TRUE;
  2201. } else if (age > log->max_archived_lsn_age_async) {
  2202. /* An archiving is not urgent: we do asynchronous i/o */
  2203. sync = FALSE;
  2204. } else {
  2205. /* No archiving required yet */
  2206. mutex_exit(&(log->mutex));
  2207. return;
  2208. }
  2209. mutex_exit(&(log->mutex));
  2210. log_archive_do(sync, &dummy);
  2211. if (sync == TRUE) {
  2212. /* Check again that enough was written to the archive */
  2213. goto loop;
  2214. }
  2215. }
  2216. #endif /* UNIV_LOG_ARCHIVE */
  2217. /************************************************************************
  2218. Checks that there is enough free space in the log to start a new query step.
  2219. Flushes the log buffer or makes a new checkpoint if necessary. NOTE: this
  2220. function may only be called if the calling thread owns no synchronization
  2221. objects! */
  2222. void
  2223. log_check_margins(void)
  2224. /*===================*/
  2225. {
  2226. loop:
  2227. log_flush_margin();
  2228. log_checkpoint_margin();
  2229. #ifdef UNIV_LOG_ARCHIVE
  2230. log_archive_margin();
  2231. #endif /* UNIV_LOG_ARCHIVE */
  2232. mutex_enter(&(log_sys->mutex));
  2233. if (log_sys->check_flush_or_checkpoint) {
  2234. mutex_exit(&(log_sys->mutex));
  2235. goto loop;
  2236. }
  2237. mutex_exit(&(log_sys->mutex));
  2238. }
  2239. /********************************************************************
  2240. Makes a checkpoint at the latest lsn and writes it to first page of each
  2241. data file in the database, so that we know that the file spaces contain
  2242. all modifications up to that lsn. This can only be called at database
  2243. shutdown. This function also writes all log in log files to the log archive. */
  2244. void
  2245. logs_empty_and_mark_files_at_shutdown(void)
  2246. /*=======================================*/
  2247. {
  2248. dulint lsn;
  2249. ulint arch_log_no;
  2250. if (srv_print_verbose_log) {
  2251.         ut_print_timestamp(stderr);
  2252.         fprintf(stderr, "  InnoDB: Starting shutdown...n");
  2253. }
  2254. /* Wait until the master thread and all other operations are idle: our
  2255. algorithm only works if the server is idle at shutdown */
  2256. srv_shutdown_state = SRV_SHUTDOWN_CLEANUP;
  2257. loop:
  2258. os_thread_sleep(100000);
  2259. mutex_enter(&kernel_mutex);
  2260. /* Check that there are no longer transactions */
  2261. if (trx_n_mysql_transactions > 0
  2262. || UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
  2263. mutex_exit(&kernel_mutex);
  2264. goto loop;
  2265. }
  2266. /* Check that the master thread is suspended */
  2267. if (srv_n_threads_active[SRV_MASTER] != 0) {
  2268. mutex_exit(&kernel_mutex);
  2269. goto loop;
  2270. }
  2271. mutex_exit(&kernel_mutex);
  2272. mutex_enter(&(log_sys->mutex));
  2273. if (
  2274. #ifdef UNIV_LOG_ARCHIVE
  2275. log_sys->n_pending_archive_ios ||
  2276. #endif /* UNIV_LOG_ARCHIVE */
  2277. log_sys->n_pending_checkpoint_writes ||
  2278. log_sys->n_pending_writes) {
  2279. mutex_exit(&(log_sys->mutex));
  2280. goto loop;
  2281. }
  2282. mutex_exit(&(log_sys->mutex));
  2283. if (!buf_pool_check_no_pending_io()) {
  2284. goto loop;
  2285. }
  2286. #ifdef UNIV_LOG_ARCHIVE
  2287. log_archive_all();
  2288. #endif /* UNIV_LOG_ARCHIVE */
  2289. if (!srv_very_fast_shutdown) {
  2290. /* In a 'very fast' shutdown we do not flush the buffer pool:
  2291. it is essentially a 'crash' of the InnoDB server. */
  2292. log_make_checkpoint_at(ut_dulint_max, TRUE);
  2293. } else {
  2294. /* Make sure that the log is all flushed to disk, so that
  2295. we can recover all committed transactions in a crash
  2296. recovery */
  2297. log_buffer_flush_to_disk();
  2298. }
  2299. mutex_enter(&(log_sys->mutex));
  2300. lsn = log_sys->lsn;
  2301. if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0
  2302.     && !srv_very_fast_shutdown)
  2303. #ifdef UNIV_LOG_ARCHIVE
  2304.    || (srv_log_archive_on
  2305.        && ut_dulint_cmp(lsn,
  2306.     ut_dulint_add(log_sys->archived_lsn, LOG_BLOCK_HDR_SIZE))
  2307.    != 0)
  2308. #endif /* UNIV_LOG_ARCHIVE */
  2309. ) {
  2310.      mutex_exit(&(log_sys->mutex));
  2311.      goto loop;
  2312. }    
  2313. arch_log_no = 0;
  2314. #ifdef UNIV_LOG_ARCHIVE
  2315. UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no;
  2316. if (0 == UT_LIST_GET_FIRST(log_sys->log_groups)->archived_offset) {
  2317. arch_log_no--;
  2318. }
  2319. log_archive_close_groups(TRUE);
  2320. #endif /* UNIV_LOG_ARCHIVE */
  2321. mutex_exit(&(log_sys->mutex));
  2322. mutex_enter(&kernel_mutex);
  2323. /* Check that the master thread has stayed suspended */
  2324. if (srv_n_threads_active[SRV_MASTER] != 0) {
  2325. fprintf(stderr,
  2326. "InnoDB: Warning: the master thread woke up during shutdownn");
  2327. mutex_exit(&kernel_mutex);
  2328. goto loop;
  2329. }
  2330. mutex_exit(&kernel_mutex);
  2331. fil_flush_file_spaces(FIL_TABLESPACE);
  2332. fil_flush_file_spaces(FIL_LOG);
  2333. /* The call fil_write_flushed_lsn_to_data_files() will pass the buffer
  2334. pool: therefore it is essential that the buffer pool has been
  2335. completely flushed to disk! (We do not call fil_write... if the
  2336. 'very fast' shutdown is enabled.) */
  2337. if (!srv_very_fast_shutdown && !buf_all_freed()) {
  2338. goto loop;
  2339. }
  2340. /* The lock timeout thread should now have exited */
  2341. if (srv_lock_timeout_and_monitor_active) {
  2342. goto loop;
  2343. }
  2344. /* We now let also the InnoDB error monitor thread to exit */
  2345. srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
  2346. if (srv_error_monitor_active) {
  2347. goto loop;
  2348. }
  2349. /* Make some checks that the server really is quiet */
  2350. ut_a(srv_n_threads_active[SRV_MASTER] == 0);
  2351. ut_a(srv_very_fast_shutdown || buf_all_freed());
  2352. ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
  2353. if (ut_dulint_cmp(lsn, srv_start_lsn) < 0) {
  2354. fprintf(stderr,
  2355. "InnoDB: Error: log sequence number at shutdown %lu %lun"
  2356. "InnoDB: is lower than at startup %lu %lu!n",
  2357.   (ulong) ut_dulint_get_high(lsn),
  2358.   (ulong) ut_dulint_get_low(lsn),
  2359.   (ulong) ut_dulint_get_high(srv_start_lsn),
  2360.   (ulong) ut_dulint_get_low(srv_start_lsn));
  2361. }
  2362. srv_shutdown_lsn = lsn;
  2363. if (!srv_very_fast_shutdown) {
  2364. /* In a 'very fast' shutdown we do not flush the buffer pool:
  2365. it is essentially a 'crash' of the InnoDB server. Then we must
  2366. not write the lsn stamps to the data files, since at a
  2367. startup InnoDB deduces from the stamps if the previous
  2368. shutdown was clean. */
  2369. fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
  2370. }
  2371. fil_flush_file_spaces(FIL_TABLESPACE);
  2372. fil_close_all_files();
  2373. /* Make some checks that the server really is quiet */
  2374. ut_a(srv_n_threads_active[SRV_MASTER] == 0);
  2375. ut_a(srv_very_fast_shutdown || buf_all_freed());
  2376. ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
  2377. }
  2378. /**********************************************************
  2379. Checks by parsing that the catenated log segment for a single mtr is
  2380. consistent. */
  2381. ibool
  2382. log_check_log_recs(
  2383. /*===============*/
  2384. byte* buf, /* in: pointer to the start of the log segment
  2385. in the log_sys->buf log buffer */
  2386. ulint len, /* in: segment length in bytes */
  2387. dulint buf_start_lsn) /* in: buffer start lsn */
  2388. {
  2389. dulint contiguous_lsn;
  2390. dulint scanned_lsn;
  2391. byte* start;
  2392. byte* end;
  2393. byte* buf1;
  2394. byte* scan_buf;
  2395. #ifdef UNIV_SYNC_DEBUG
  2396. ut_ad(mutex_own(&(log_sys->mutex)));
  2397. #endif /* UNIV_SYNC_DEBUG */
  2398. if (len == 0) {
  2399. return(TRUE);
  2400. }
  2401. start = ut_align_down(buf, OS_FILE_LOG_BLOCK_SIZE);
  2402. end = ut_align(buf + len, OS_FILE_LOG_BLOCK_SIZE);
  2403. buf1 = mem_alloc((end - start) + OS_FILE_LOG_BLOCK_SIZE);
  2404. scan_buf = ut_align(buf1, OS_FILE_LOG_BLOCK_SIZE);
  2405. ut_memcpy(scan_buf, start, end - start);
  2406. recv_scan_log_recs(TRUE,
  2407. (buf_pool->n_frames -
  2408. recv_n_pool_free_frames) * UNIV_PAGE_SIZE,
  2409. FALSE, scan_buf, end - start,
  2410. ut_dulint_align_down(buf_start_lsn,
  2411. OS_FILE_LOG_BLOCK_SIZE),
  2412. &contiguous_lsn, &scanned_lsn);
  2413. ut_a(ut_dulint_cmp(scanned_lsn, ut_dulint_add(buf_start_lsn, len))
  2414. == 0);
  2415. ut_a(ut_dulint_cmp(recv_sys->recovered_lsn, scanned_lsn) == 0);
  2416. mem_free(buf1);
  2417. return(TRUE);
  2418. }
  2419. /**********************************************************
  2420. Peeks the current lsn. */
  2421. ibool
  2422. log_peek_lsn(
  2423. /*=========*/
  2424. /* out: TRUE if success, FALSE if could not get the
  2425. log system mutex */
  2426. dulint* lsn) /* out: if returns TRUE, current lsn is here */
  2427. {
  2428. if (0 == mutex_enter_nowait(&(log_sys->mutex), __FILE__, __LINE__)) {
  2429.         *lsn = log_sys->lsn;
  2430. mutex_exit(&(log_sys->mutex));
  2431. return(TRUE);
  2432. }
  2433. return(FALSE);
  2434. }
  2435. /**********************************************************
  2436. Prints info of the log. */
  2437. void
  2438. log_print(
  2439. /*======*/
  2440. FILE* file) /* in: file where to print */
  2441. {
  2442. double time_elapsed;
  2443. time_t current_time;
  2444. mutex_enter(&(log_sys->mutex));
  2445. fprintf(file,
  2446. "Log sequence number %lu %lun"
  2447.        "Log flushed up to   %lu %lun"
  2448.        "Last checkpoint at  %lu %lun",
  2449. (ulong) ut_dulint_get_high(log_sys->lsn),
  2450. (ulong) ut_dulint_get_low(log_sys->lsn),
  2451. (ulong) ut_dulint_get_high(log_sys->flushed_to_disk_lsn),
  2452. (ulong) ut_dulint_get_low(log_sys->flushed_to_disk_lsn),
  2453. (ulong) ut_dulint_get_high(log_sys->last_checkpoint_lsn),
  2454. (ulong) ut_dulint_get_low(log_sys->last_checkpoint_lsn));
  2455. current_time = time(NULL);
  2456. time_elapsed = 0.001 + difftime(current_time,
  2457. log_sys->last_printout_time);
  2458. fprintf(file,
  2459. "%lu pending log writes, %lu pending chkp writesn"
  2460. "%lu log i/o's done, %.2f log i/o's/secondn",
  2461. (ulong) log_sys->n_pending_writes,
  2462. (ulong) log_sys->n_pending_checkpoint_writes,
  2463. (ulong) log_sys->n_log_ios,
  2464. ((log_sys->n_log_ios - log_sys->n_log_ios_old) / time_elapsed));
  2465. log_sys->n_log_ios_old = log_sys->n_log_ios;
  2466. log_sys->last_printout_time = current_time;
  2467. mutex_exit(&(log_sys->mutex));
  2468. }
  2469. /**************************************************************************
  2470. Refreshes the statistics used to print per-second averages. */
  2471. void
  2472. log_refresh_stats(void)
  2473. /*===================*/
  2474. {
  2475. log_sys->n_log_ios_old = log_sys->n_log_ios;
  2476. log_sys->last_printout_time = time(NULL);
  2477. }