===== File: extra/mariabackup/aria_backup_client.cc ===== 989 : 178 : logs.find_logs_after_last(target_dir); 990 : 178 : last_logno= logs.last(); // Update last_logno if extra logs were found 991 : : 992 : 178 : + if (multi_init_pagecache(&maria_pagecaches, 1, 1024L*1024L, 0, 0, 993 : : + static_cast(maria_block_size), 0, MY_WME)) 994 : 0 : die("Got error in Aria init_pagecache() (errno: %d)", errno); 995 : : 996 : 178 : if (init_pagecache(maria_log_pagecache, 1024L*1024L, ===== File: include/my_global.h ===== 689 : : /* Typical record cache */ 690 : : #define RECORD_CACHE_SIZE (uint) (128*1024) 691 : : /* Typical key cache */ 692 : : +#define KEY_CACHE_SIZE (ulong) (128L*1024L*1024L) 693 : : /* Default size of a key cache block */ 694 : : #define KEY_CACHE_BLOCK_SIZE (uint) 1024 695 : : + /* Min resonable key cache size, only for testing */ 696 : : +#define MIN_KEY_CACHE_SIZE 8192*16L 697 : : 698 : : /* Some things that this system doesn't have */ 699 : : ===== File: mysys/mf_keycache.c ===== 981 : : 982 : 5421 : DBUG_PRINT("status", ("used: %lu changed: %lu w_requests: %lu " 983 : : "writes: %lu r_requests: %lu reads: %lu", 984 : : + (ulong) keycache->blocks_used, 985 : : + (ulong) keycache->global_blocks_changed, 986 : : (ulong) keycache->global_cache_w_requests, 987 : : (ulong) keycache->global_cache_write, 988 : : (ulong) keycache->global_cache_r_requests, 1601 : 0 : keycache->warm_blocks--; 1602 : 0 : block->temperature= BLOCK_HOT; 1603 : 0 : KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks: %lu", 1604 : : + (ulong) keycache->warm_blocks)); 1605 : : } 1606 : 38443443 : link_block(keycache, block, hot, (my_bool)at_end); 1607 : 38443443 : block->last_hit_time= keycache->keycache_time; 1633 : 40932 : block->temperature= BLOCK_WARM; 1634 : : } 1635 : 33300799 : KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks: %lu", 1636 : : + (ulong) keycache->warm_blocks)); 1637 : : } 1638 : : } 1639 : 38443453 : } 3912 : 7144511 : int last_errcnt= 0; 3913 : 7144511 : DBUG_ENTER("flush_key_blocks_int"); 3914 : 7144511 : DBUG_PRINT("enter",("file: %d blocks_used: %lu blocks_changed: %lu", 3915 : : + file, (ulong) keycache->blocks_used, 3916 : : + (ulong) keycache->blocks_changed)); 3917 : : 3918 : : #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) 3919 : : DBUG_EXECUTE("check_keycache", ===== File: storage/maria/aria_chk.c ===== 1224 : : */ 1225 : 1 : maria_lock_database(info, F_EXTRA_LCK); 1226 : 1 : datafile= info->dfile.file; 1227 : 1 : + if (multi_init_pagecache(&maria_pagecaches, 1, (size_t) param->use_buffers, 1228 : : + 0, 0, maria_block_size, 0, MY_WME)) 1229 : : { 1230 : 0 : _ma_check_print_error(param, "Can't initialize page cache with %lu memory", 1231 : 0 : (ulong) param->use_buffers); 1232 : 0 : error= 1; 1233 : 0 : goto end2; 1234 : : } 1235 : : + /* The pagecache is initialized. Update the table pagecaches pointers */ 1236 : 1 : + ma_change_pagecache(info); 1237 : : 1238 : 1 : if (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX | 1239 : : T_ZEROFILL)) 1474 : 0 : _ma_check_print_error(param, default_close_errmsg, my_errno, filename); 1475 : 0 : DBUG_RETURN(1); 1476 : : } 1477 : 1 : + multi_end_pagecache(&maria_pagecaches); 1478 : 1 : if (error == 0) 1479 : : { 1480 : 1 : if (param->out_flag & O_NEW_DATA) ===== File: storage/maria/aria_ftdump.c ===== 85 : 0 : usage(); 86 : : } 87 : : 88 : 0 : + multi_init_pagecache(&maria_pagecaches, 1, 89 : : + PAGE_BUFFER_INIT, 0, 0, 90 : : + MARIA_KEY_BLOCK_LENGTH, 0, MY_WME); 91 : : 92 : 0 : if (!(info=maria_open(argv[0], O_RDONLY, 93 : : HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER, 0))) ===== File: storage/maria/aria_pack.c ===== 613 : : else 614 : 1 : fn_format(org_name,isam_file->s->open_file_name.str, "",MARIA_NAME_DEXT, 2+4+16); 615 : : 616 : 1 : + if (multi_init_pagecache(&maria_pagecaches, 1, MARIA_MIN_PAGE_CACHE_SIZE, 617 : : + 0, 0, maria_block_size, 0, MY_WME)) 618 : : { 619 : 0 : fprintf(stderr, "Can't initialize page cache\n"); 620 : 0 : goto err; 621 : : } 622 : : + /* The pagecache is initialized. Update the table pagecaches pointers */ 623 : 2 : + for (i=0 ; i < mrg->count ; i++) 624 : 1 : + ma_change_pagecache(mrg->file[i]); 625 : : 626 : 1 : if (!test_only && result_table) 627 : 0 : { 870 : 0 : if (join_maria_file >= 0) 871 : 0 : my_close(join_maria_file,MYF(0)); 872 : 0 : mrg_close(mrg); 873 : 0 : + multi_end_pagecache(&maria_pagecaches); 874 : 0 : fprintf(stderr, "Aborted: %s is not compressed\n", org_name); 875 : 0 : DBUG_RETURN(-1); 876 : : } ===== File: storage/maria/aria_read_log.c ===== 114 : 0 : fprintf(stderr, "Can't find any log\n"); 115 : 0 : goto err; 116 : : } 117 : 0 : + if (multi_init_pagecache(&maria_pagecaches, 1, (size_t) opt_page_buffer_size, 118 : : + 0, 0, maria_block_size, 0, MY_WME)) 119 : : { 120 : 0 : fprintf(stderr, "Got error in init_pagecache() (errno: %d)\n", errno); 121 : 0 : goto err; ===== File: storage/maria/ha_maria.cc ===== 42 : : #include "key.h" 43 : : #include "log.h" 44 : : #include "sql_parse.h" 45 : : +#include "mysql/plugin.h" 46 : : #include "mysql/service_print_check_msg.h" 47 : : #include "debug.h" 48 : : 58 : : 59 : : #define THD_TRN (TRN*) thd_get_ha_data(thd, maria_hton) 60 : : 61 : : +uint pagecache_segments, pagecache_division_limit, pagecache_file_hash_size; 62 : : +ulong pagecache_age_threshold; 63 : : ulonglong pagecache_buffer_size; 64 : : const char *zerofill_error_msg= 65 : : "Table is probably from another system and must be zerofilled or repaired ('REPAIR TABLE table_name') to be usable on this system"; 116 : : TYPELIB maria_group_commit_typelib= CREATE_TYPELIB_FOR(maria_group_commit_names); 117 : : 118 : : /** Interval between background checkpoints in seconds */ 119 : : +static uint checkpoint_interval; 120 : : static void update_checkpoint_interval(MYSQL_THD thd, 121 : : struct st_mysql_sys_var *var, 122 : : void *var_ptr, const void *save); 127 : : struct st_mysql_sys_var *var, 128 : : void *var_ptr, const void *save); 129 : : /** After that many consecutive recovery failures, remove logs */ 130 : : +static uint force_start_after_recovery_failures; 131 : : static void update_log_file_size(MYSQL_THD thd, 132 : : struct st_mysql_sys_var *var, 133 : : void *var_ptr, const void *save); 134 : : 135 : : /* The 4096 is there because of MariaDB privilege tables */ 136 : : +static MYSQL_SYSVAR_UINT(block_size, maria_block_size, 137 : : PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, 138 : : "Block size to be used for Aria index pages", 0, 0, 139 : : MARIA_KEY_BLOCK_LENGTH, 4096, 140 : : MARIA_MAX_KEY_BLOCK_LENGTH, MARIA_MIN_KEY_BLOCK_LENGTH); 141 : : 142 : : +static MYSQL_SYSVAR_UINT(checkpoint_interval, checkpoint_interval, 143 : : + PLUGIN_VAR_RQCMDARG, 144 : : + "Interval between tries to do an automatic " 145 : : + "checkpoints. In seconds; 0 means " 146 : : + "'no automatic checkpoints' which makes sense only " 147 : : + "for testing", 148 : : + NULL, update_checkpoint_interval, 30, 0, UINT_MAX, 1); 149 : : + 150 : : +static MYSQL_SYSVAR_UINT(checkpoint_log_activity, 151 : : + maria_checkpoint_min_log_activity, 152 : : + PLUGIN_VAR_RQCMDARG, 153 : : + "Number of bytes that the transaction log has to grow " 154 : : + "between checkpoints before a new checkpoint is " 155 : : + "written to the log", 156 : : + NULL, NULL, 1024*1024, 0, UINT_MAX, 1); 157 : : + 158 : : +static MYSQL_SYSVAR_UINT(force_start_after_recovery_failures, 159 : : + force_start_after_recovery_failures, 160 : : /* 161 : : Read-only because setting it on the fly has no useful effect, 162 : : should be set on command-line. 228 : : "multiple writes) to as much as you can afford", 0, 0, 229 : : KEY_CACHE_SIZE, 8192*16L, ~(ulonglong) 0, 1); 230 : : 231 : : +static MYSQL_SYSVAR_UINT(pagecache_division_limit, pagecache_division_limit, 232 : : PLUGIN_VAR_RQCMDARG, 233 : : "The minimum percentage of warm blocks in key cache", 0, 0, 234 : : 100, 1, 100, 1); 235 : : 236 : : +static MYSQL_SYSVAR_UINT(pagecache_file_hash_size, pagecache_file_hash_size, 237 : : PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, 238 : : "Number of hash buckets for open and changed files. If you have a lot of Aria " 239 : : "files open you should increase this for faster flush of changes. A good " 244 : : "Specifies how corrupted tables should be automatically repaired", 245 : : NULL, NULL, HA_RECOVER_BACKUP|HA_RECOVER_QUICK, &maria_recover_typelib); 246 : : 247 : : +static MYSQL_THDVAR_UINT(repair_threads, PLUGIN_VAR_RQCMDARG, 248 : : "Number of threads to use when repairing Aria tables. The value of 1 " 249 : : "disables parallel repair", 250 : : 0, 0, 1, 1, 128, 1); 264 : : "creation", NULL, NULL, TRANSLOG_SYNC_DIR_NEWFILE, 265 : : &maria_sync_log_dir_typelib); 266 : : 267 : : +static MYSQL_SYSVAR_UINT(pagecache_segments, pagecache_segments, 268 : : + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, 269 : : + "The number of segments in the page_cache. " 270 : : + "Each file is put in their own segments of size " 271 : : + "pagecache_buffer_size / segments. " 272 : : + "Having many segments improves parallel performance", 273 : : + 0, 0, 1, 1, 128, 1); 274 : : + 275 : : #ifdef USE_ARIA_FOR_TMP_TABLES 276 : : #define USE_ARIA_FOR_TMP_TABLES_VAL 1 277 : : #else 3940 : 13417 : res= res || 3941 : 6708 : ((force_start_after_recovery_failures != 0 && !aria_readonly) && 3942 : 0 : mark_recovery_start(log_dir)) || 3943 : 6708 : + multi_init_pagecache(&maria_pagecaches, pagecache_segments, 3944 : : + (size_t) pagecache_buffer_size, 3945 : : + pagecache_division_limit, 3946 : : + pagecache_age_threshold, maria_block_size, 3947 : 6708 : + pagecache_file_hash_size, 0) || 3948 : 6708 : !init_pagecache(maria_log_pagecache, 3949 : : TRANSLOG_PAGECACHE_SIZE, 0, 0, 3950 : 6708 : TRANSLOG_PAGE_SIZE, 0, 0) || 3961 : 6708 : ma_checkpoint_init(checkpoint_interval); 3962 : 6709 : maria_multi_threaded= maria_in_ha_maria= TRUE; 3963 : 6709 : maria_create_trn_hook= maria_create_trn_for_mysql; 3964 : 6709 : maria_assert_if_crashed_table= debug_assert_if_crashed_table; 3965 : : 3966 : 6709 : if (res) 4066 : : MYSQL_SYSVAR(pagecache_buffer_size), 4067 : : MYSQL_SYSVAR(pagecache_division_limit), 4068 : : MYSQL_SYSVAR(pagecache_file_hash_size), 4069 : : + MYSQL_SYSVAR(pagecache_segments), 4070 : : MYSQL_SYSVAR(recover_options), 4071 : : MYSQL_SYSVAR(repair_threads), 4072 : : MYSQL_SYSVAR(sort_buffer_size), 4087 : : void *var_ptr, const void *save) 4088 : : { 4089 : 59 : ma_checkpoint_end(); 4090 : 31 : + ma_checkpoint_init(*(uint *)var_ptr= *(uint*)save); 4091 : 31 : } 4092 : : 4093 : : 4192 : : 4193 : : 4194 : : static SHOW_VAR status_variables[]= { 4195 : : + {"blocks_not_flushed", (char*) &pagecache_stats.global_blocks_changed, SHOW_LONG}, 4196 : : + {"blocks_unused", (char*) &pagecache_stats.blocks_unused, SHOW_LONG}, 4197 : : + {"blocks_used", (char*) &pagecache_stats.blocks_used, SHOW_LONG}, 4198 : : + {"read_requests", (char*) &pagecache_stats.global_cache_r_requests, SHOW_LONGLONG}, 4199 : : + {"reads", (char*) &pagecache_stats.global_cache_read, SHOW_LONGLONG}, 4200 : : + {"write_requests", (char*) &pagecache_stats.global_cache_w_requests, SHOW_LONGLONG}, 4201 : : + {"writes", (char*) &pagecache_stats.global_cache_write, SHOW_LONGLONG}, 4202 : : + {NullS, NullS, SHOW_LONG} 4203 : : +}; 4204 : : + 4205 : : + 4206 : 33069 : +static int pagecache_stats_func(THD *thd, SHOW_VAR *var, void *buff, 4207 : : + system_status_var *, enum_var_type scope) 4208 : : +{ 4209 : 33069 : + multi_update_pagecache_stats(); 4210 : 33069 : + var->type= SHOW_ARRAY; 4211 : 33069 : + var->value= status_variables; 4212 : 33069 : + return 0; 4213 : : +} 4214 : : + 4215 : : +static SHOW_VAR dynamic_status_variables[]= 4216 : : +{ 4217 : : + /* Accessing pagecache causes multi_update_pagecache_stats() to be called */ 4218 : : + {"pagecache", (char*) &pagecache_stats_func, SHOW_FUNC}, 4219 : : + {"transaction_log_syncs", (char*) &translog_syncs, SHOW_LONGLONG}, 4220 : : {NullS, NullS, SHOW_LONG} 4221 : : }; 4222 : : 4405 : : PLUGIN_LICENSE_GPL, 4406 : : ha_maria_init, /* Plugin Init */ 4407 : : NULL, /* Plugin Deinit */ 4408 : : + 0x0106, /* 1.6 */ 4409 : : + dynamic_status_variables, /* status variables */ 4410 : : system_variables, /* system variables */ 4411 : : + "1.6", /* string version */ 4412 : : MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ 4413 : : } 4414 : : maria_declare_plugin_end; ===== File: storage/maria/ha_s3.cc ===== 682 : : Table is in S3. We have to modify the pagecache callbacks for the 683 : : data file, index file and for bitmap handling. 684 : : */ 685 : 255 : + file->s->pagecache= file->s->kfile.pagecache= file->dfile.pagecache= 686 : : + &s3_pagecache; 687 : 255 : file->dfile.big_block_size= file->s->kfile.big_block_size= 688 : 255 : file->s->bitmap.file.big_block_size= file->s->base.s3_block_size; 689 : 255 : file->s->kfile.head_blocks= file->s->base.keystart / file->s->block_size; ===== File: storage/maria/ma_bitmap.c ===== 247 : 476436 : bitmap->share= share; 248 : 476436 : bitmap->block_size= share->block_size; 249 : 476436 : bitmap->file.file= file; 250 : 476436 : + bitmap->file.pagecache= share->kfile.pagecache; 251 : 476436 : _ma_bitmap_set_pagecache_callbacks(&bitmap->file, share); 252 : : 253 : : /* Size needs to be aligned on 6 */ 550 : : be different. 551 : : There should be no pinned pages as bitmap->non_flushable==0. 552 : : */ 553 : 5616 : + if (flush_pagecache_blocks_with_filter(bitmap->file.pagecache, 554 : : &bitmap->file, FLUSH_KEEP, 555 : : filter_flush_bitmap_pages, 556 : 2808 : &bitmap->pages_covered) & 1080 : : } 1081 : : else 1082 : : { 1083 : 21592 : + res= pagecache_read(bitmap->file.pagecache, 1084 : : &bitmap->file, page, 0, 1085 : : bitmap->map, PAGECACHE_PLAIN_PAGE, 1086 : 21592 : PAGECACHE_LOCK_LEFT_UNLOCKED, 0) == NULL; 2870 : : { 2871 : 12877 : if (page == 0 && page_count == 0) 2872 : 238 : continue; /* Not used extent */ 2873 : 12639 : + if (pagecache_delete_pages(info->dfile.pagecache, &info->dfile, page, 2874 : : page_count, PAGECACHE_LOCK_WRITE, 1)) 2875 : 0 : DBUG_RETURN(1); 2876 : 12639 : mysql_mutex_lock(&bitmap->bitmap_lock); 3209 : : filesystem may fill gaps with zeroes physically which is a waste of 3210 : : time. 3211 : : */ 3212 : 0 : + if (pagecache_write(bitmap->file.pagecache, 3213 : : &bitmap->file, i, 0, 3214 : : zeroes, PAGECACHE_PLAIN_PAGE, 3215 : : PAGECACHE_LOCK_LEFT_UNLOCKED, ===== File: storage/maria/ma_blockrec.c ===== 448 : 471202 : int res= _ma_bitmap_end(share); 449 : 471202 : if (share->bitmap.file.file >= 0) 450 : : { 451 : 942288 : + if (share->pagecache && 452 : 471087 : + flush_pagecache_blocks(share->pagecache, &share->bitmap.file, 453 : : + share->deleting ? 454 : : + FLUSH_IGNORE_CHANGED : FLUSH_RELEASE)) 455 : 0 : res= 1; 456 : : /* 457 : : File must be synced as it is going out of the maria_open_list and so 7619 : 0 : (uint)buff[DIR_COUNT_OFFSET], 7620 : 0 : (uint)buff[DIR_FREE_OFFSET], 7621 : 0 : (uint) uint2korr(buff + EMPTY_SPACE_OFFSET)); 7622 : 0 : + printf("Start of directory: %u\n", 7623 : 0 : maria_block_size - PAGE_SUFFIX_SIZE - 7624 : 0 : (uint) buff[DIR_COUNT_OFFSET] * DIR_ENTRY_SIZE); 7625 : 0 : _ma_print_directory(share, stdout, buff, maria_block_size); ===== File: storage/maria/ma_checkpoint.c ===== 154 : : { 155 : 5662 : uint i, error= 0; 156 : 5662 : int error_errno= 0; 157 : : + uint dirty_pages; 158 : : /** @brief checkpoint_start_log_horizon will be stored there */ 159 : 5662 : const char *error_place= 0; 160 : : + LEX_STRING *record_pieces; /**< only malloc-ed pieces */ 161 : : + LEX_CUSTRING *log_array; 162 : : LSN min_page_rec_lsn, min_trn_rec_lsn, min_first_undo_lsn; 163 : : TRANSLOG_ADDRESS checkpoint_start_log_horizon; 164 : : char checkpoint_start_log_horizon_char[LSN_STORE_SIZE]; 165 : 5662 : + uint record_pieces_count= 3+maria_pagecaches.segments; 166 : 5662 : DBUG_ENTER("really_execute_checkpoint"); 167 : 5662 : DBUG_PRINT("enter", ("level: %d", checkpoint_in_progress)); 168 : : + 169 : 5662 : + record_pieces= my_alloca(sizeof(*record_pieces) * record_pieces_count + 170 : : + sizeof(*log_array) * 171 : : + (TRANSLOG_INTERNAL_PARTS + 5 + 172 : : + maria_pagecaches.segments)); 173 : 5662 : + if (!record_pieces) 174 : : + { 175 : 0 : + error_place= "allocating_memory"; 176 : 0 : + goto err; 177 : : + } 178 : 5662 : + log_array= (LEX_CUSTRING*) (record_pieces + record_pieces_count); 179 : 5662 : + bzero(record_pieces, sizeof(*record_pieces) * record_pieces_count); 180 : : 181 : : /* 182 : : STEP 1: record current end-of-log position using log's lock. It is 229 : : and thus we will have less work at Recovery. 230 : : */ 231 : : /* Using default pagecache for now */ 232 : 5662 : + if (unlikely(multi_pagecache_collect_changed_blocks_with_lsn(&maria_pagecaches, 233 : : + record_pieces+3, 234 : : + &min_page_rec_lsn, 235 : : + &dirty_pages))) 236 : : { 237 : 0 : error_place= "collect_pages"; 238 : 0 : goto err; 243 : : { 244 : : LSN lsn; 245 : : translog_size_t total_rec_length; 246 : : + uchar dirty_pages_buff[8]; 247 : : + LEX_CUSTRING *log_pos; 248 : : + 249 : : /* 250 : : the log handler is allowed to modify "str" and "length" (but not "*str") 251 : : of its argument, so we must not pass it record_pieces directly, 252 : : otherwise we would later not know what memory pieces to my_free(). 253 : : */ 254 : 5662 : log_array[TRANSLOG_INTERNAL_PARTS + 0].str= 255 : : (uchar*) checkpoint_start_log_horizon_char; 256 : 5662 : log_array[TRANSLOG_INTERNAL_PARTS + 0].length= total_rec_length= 257 : : sizeof(checkpoint_start_log_horizon_char); 258 : : + 259 : 5662 : + log_pos= log_array+ TRANSLOG_INTERNAL_PARTS + 1; 260 : 22648 : + for (i= 0; i < 3 ; i++) 261 : : { 262 : 16986 : + (*log_pos).str= (uchar*)record_pieces[i].str; 263 : 16986 : + (*log_pos).length= record_pieces[i].length; 264 : 16986 : + log_pos++; 265 : 16986 : total_rec_length+= (translog_size_t) record_pieces[i].length; 266 : : } 267 : : + 268 : 5662 : + int8store(dirty_pages_buff, (longlong) dirty_pages); 269 : 5662 : + (*log_pos).str= dirty_pages_buff; 270 : 5662 : + (*log_pos).length= 8; 271 : 5662 : + log_pos++; 272 : 5662 : + total_rec_length+= 8; 273 : : + 274 : : + /* Copy the information about the dirty pages in the page caches */ 275 : 11344 : + for (i= 0; i < maria_pagecaches.segments; i++) 276 : : + { 277 : 5682 : + if (record_pieces[3+i].length) 278 : : + { 279 : 28 : + (*log_pos).str= (uchar*) record_pieces[3+i].str; 280 : 28 : + (*log_pos).length= record_pieces[3+i].length; 281 : 28 : + log_pos++; 282 : 28 : + total_rec_length+= (translog_size_t) record_pieces[3+i].length; 283 : : + } 284 : : + } 285 : 5662 : if (unlikely(translog_write_record(&lsn, LOGREC_CHECKPOINT, 286 : : &dummy_transaction_object, NULL, 287 : : total_rec_length, 288 : : + (uint) (log_pos - log_array), 289 : : log_array, NULL, NULL) || 290 : : translog_flush(lsn))) 291 : : { 315 : : written the checkpoint record and control file. 316 : : */ 317 : : /* checkpoint succeeded */ 318 : 5662 : + pages_to_flush_before_next_checkpoint= dirty_pages; 319 : 5662 : DBUG_PRINT("checkpoint",("%u pages to flush before next checkpoint", 320 : : pages_to_flush_before_next_checkpoint)); 321 : : 346 : 0 : pages_to_flush_before_next_checkpoint= 0; 347 : : 348 : 5662 : end: 349 : 5662 : + if (record_pieces) 350 : : + { 351 : 28330 : + for (i= 0; i < record_pieces_count; i++) 352 : 22668 : + my_free(record_pieces[i].str); 353 : : + } 354 : : + my_afree(record_pieces); 355 : 5662 : mysql_mutex_lock(&LOCK_checkpoint); 356 : 5662 : checkpoint_in_progress= CHECKPOINT_NONE; 357 : 5662 : checkpoints_total++; 594 : : 595 : : static ulong maria_checkpoint_min_cache_activity= 10*1024*1024; 596 : : /* Set in ha_maria.cc */ 597 : : +uint maria_checkpoint_min_log_activity= 1*1024*1024; 598 : : 599 : 6733 : pthread_handler_t ma_checkpoint_background(void *arg) 600 : : { 610 : : TRANSLOG_ADDRESS log_horizon_at_last_checkpoint= 611 : 6733 : translog_get_horizon(); 612 : : ulonglong pagecache_flushes_at_last_checkpoint= 613 : 6733 : + multi_global_cache_writes(&maria_pagecaches); 614 : 6733 : uint UNINIT_VAR(pages_bunch_size); 615 : : struct st_filter_param filter_param; 616 : 6733 : PAGECACHE_FILE *UNINIT_VAR(dfile); /**< data file currently being flushed */ 647 : : } 648 : : { 649 : 301 : TRANSLOG_ADDRESS horizon= translog_get_horizon(); 650 : 301 : + ulonglong writes= multi_global_cache_writes(&maria_pagecaches); 651 : : 652 : : /* 653 : : With background flushing evenly distributed over the time 665 : : */ 666 : 301 : if ((ulonglong) (horizon - log_horizon_at_last_checkpoint) <= 667 : 275 : maria_checkpoint_min_log_activity && 668 : 275 : + ((ulonglong) (writes - pagecache_flushes_at_last_checkpoint) * 669 : 275 : + maria_pagecaches.caches->block_size) <= 670 : : maria_checkpoint_min_cache_activity) 671 : : { 672 : : /* 683 : : below is possibly greater than last_checkpoint_lsn. 684 : : */ 685 : 55 : log_horizon_at_last_checkpoint= translog_get_horizon(); 686 : 55 : + pagecache_flushes_at_last_checkpoint= writes; 687 : : /* 688 : : If the checkpoint above succeeded it has set d|kfiles and 689 : : d|kfiles_end. If is has failed, it has set 724 : : only the OS file descriptor. 725 : : */ 726 : : int res= 727 : 15 : + flush_pagecache_blocks_with_filter(dfile->pagecache, 728 : : dfile, FLUSH_KEEP_LAZY, 729 : : filter_flush_file_evenly, 730 : : &filter_param); 744 : 66 : while (kfile != kfiles_end) 745 : : { 746 : : int res= 747 : 13 : + flush_pagecache_blocks_with_filter(kfile->pagecache, 748 : : kfile, FLUSH_KEEP_LAZY, 749 : : filter_flush_file_evenly, 750 : : &filter_param); 1022 : : Tables in a normal state have their two file descriptors open. 1023 : : In some rare cases like REPAIR, some descriptor may be closed or even 1024 : : -1. If that happened, the _ma_state_info_write() may fail. This is 1025 : : + prevented by enclosing all places which close/change kfile.file with 1026 : : intern_lock. 1027 : : */ 1028 : 1362 : kfile= share->kfile; 1143 : : /** @todo all write failures should mark table corrupted */ 1144 : 0 : ma_message_no_user(0, "checkpoint bitmap page flush failed"); 1145 : : } 1146 : : } 1147 : : /* 1148 : : Clean up any unused states. 1227 : : { 1228 : 170 : if (filter != NULL) 1229 : : { 1230 : 169 : + if ((flush_pagecache_blocks_with_filter(dfile.pagecache, 1231 : : &dfile, FLUSH_KEEP_LAZY, 1232 : 169 : filter, &filter_param) & 1233 : : PCFLUSH_ERROR)) 1234 : 0 : ma_message_no_user(0, "checkpoint data page flush failed"); 1235 : 169 : + if ((flush_pagecache_blocks_with_filter(kfile.pagecache, 1236 : : &kfile, FLUSH_KEEP_LAZY, 1237 : 169 : filter, &filter_param) & 1238 : : PCFLUSH_ERROR)) ===== File: storage/maria/ma_close.c ===== 42 : 474428 : DBUG_ASSERT(info->key_del_used == 0); 43 : : /* Check that file is not part of any uncommitted transactions */ 44 : 474428 : DBUG_ASSERT(info->trn == 0 || info->trn == &dummy_transaction_object); 45 : 474428 : + DBUG_ASSERT(info->dfile.pagecache == info->s->kfile.pagecache); 46 : : 47 : : + /* pagecache can be 0 if we come here from maria_recreate_table */ 48 : 474428 : + if (share->reopen == 1 && share->pagecache) 49 : : { 50 : : /* 51 : : If we are going to close the file, flush page cache without 125 : : Extra flush, just in case someone opened and closed the file 126 : : since the start of the function (very unlikely) 127 : : */ 128 : 946056 : + if (share->pagecache && 129 : 472971 : + flush_pagecache_blocks(share->pagecache, &share->kfile, 130 : : + share->deleting ? 131 : : + FLUSH_IGNORE_CHANGED : 132 : : + FLUSH_RELEASE)) 133 : 0 : error= my_errno; 134 : 473085 : unmap_file(info); 135 : 473085 : if (!internal_table && ===== File: storage/maria/ma_init.c ===== 108 : 5342 : if (translog_status == TRANSLOG_OK || translog_status == TRANSLOG_READONLY) 109 : 5224 : translog_destroy(); 110 : 5342 : end_pagecache(maria_log_pagecache, TRUE); 111 : 5342 : + multi_end_pagecache(&maria_pagecaches); 112 : 5342 : ma_control_file_end(); 113 : 5342 : mysql_mutex_destroy(&THR_LOCK_maria); 114 : 5342 : my_hash_free(&maria_stored_state); ===== File: storage/maria/ma_keycache.c ===== 46 : : # Error code 47 : : */ 48 : : 49 : : +#ifdef NOT_USED 50 : : int maria_assign_to_pagecache(MARIA_HA *info, 51 : : ulonglong key_map __attribute__((unused)), 52 : : PAGECACHE *pagecache) 113 : : mysql_mutex_unlock(&share->intern_lock); 114 : : DBUG_RETURN(error); 115 : : } 116 : : +#endif 117 : : 118 : : 119 : : /* 137 : : */ 138 : : 139 : : 140 : : +#ifdef NOT_USED 141 : : void maria_change_pagecache(PAGECACHE *old_pagecache, 142 : : PAGECACHE *new_pagecache) 143 : : { 165 : : mysql_mutex_unlock(&THR_LOCK_maria); 166 : : DBUG_VOID_RETURN; 167 : : } 168 : : +#endif ===== File: storage/maria/ma_open.c ===== 106 : 0 : goto err; 107 : : } 108 : 479663 : if (data_file >= 0) 109 : : + { 110 : 477775 : info.dfile.file= data_file; 111 : 477775 : + info.dfile.pagecache= share->pagecache; 112 : : + } 113 : 1888 : else if (_ma_open_datafile(&info, share)) 114 : 0 : goto err; 115 : 479663 : errpos= 5; 335 : 478796 : share= &share_buff; 336 : 478796 : bzero((uchar*) &share_buff,sizeof(share_buff)); 337 : 478796 : share_buff.state.key_root=key_root; 338 : : 339 : 478796 : if (!s3) 340 : : { 609 : : with different block sizes. 610 : : */ 611 : 478329 : if (share->base.block_size != maria_block_size && 612 : 115 : + maria_pagecaches.initialized) 613 : : { 614 : 0 : DBUG_PRINT("error", ("Wrong block size %u; Expected %u", 615 : : (uint) share->base.block_size, 847 : 478329 : share->base.pack_bytes + 848 : 478329 : MY_TEST(share->options & HA_OPTION_CHECKSUM)); 849 : 478329 : share->kfile.file= kfile; 850 : : + /* Pagecaches are not initialize when using aria_chk */ 851 : 478329 : + if (maria_pagecaches.initialized) 852 : 478213 : + share->pagecache= share->kfile.pagecache= 853 : 478213 : + multi_get_pagecache(&maria_pagecaches); 854 : : 855 : 478329 : if (open_flags & HA_OPEN_COPY) 856 : : { 2060 : 479387 : info->dfile.file= share->bitmap.file.file= 2061 : 479387 : mysql_file_open(key_file_dfile, share->data_file_name.str, 2062 : : share->mode | O_SHARE | O_CLOEXEC, flags); 2063 : : + /* Note that share->pagecache may be 0 here if run from aria_chk */ 2064 : 479387 : + info->dfile.pagecache= share->bitmap.file.pagecache= share->pagecache; 2065 : 479387 : return info->dfile.file >= 0 ? 0 : 1; 2066 : : } 2067 : : 2077 : : share->unique_file_name.str, 2078 : : share->mode | O_SHARE | O_NOFOLLOW | O_CLOEXEC, 2079 : : MYF(MY_WME | MY_NOSYMLINKS)); 2080 : : + /* 2081 : : + share->kfile.pagecache is updated in the caller if needed. 2082 : : + This is needed as we don't want to change pagecache in ma_sort_index() 2083 : : + as we want to check pagecache concistency in ma_close(). 2084 : : + */ 2085 : 641 : mysql_mutex_unlock(&share->intern_lock); 2086 : 641 : return (share->kfile.file < 0); 2087 : : } 2088 : : 2089 : : 2090 : : +/* 2091 : : + Update pagecaches for a table. Used by aria_check() which creates 2092 : : + the pagecache after the table has been opened. 2093 : : +*/ 2094 : : + 2095 : 2 : +void ma_change_pagecache(MARIA_HA *info) 2096 : : +{ 2097 : 2 : + MARIA_SHARE *share= info->s; 2098 : 2 : + DBUG_ASSERT(share->pagecache == 0); 2099 : 2 : + share->pagecache= share->bitmap.file.pagecache= share->kfile.pagecache= 2100 : 2 : + info->dfile.pagecache= multi_get_pagecache(&maria_pagecaches); 2101 : 2 : +} 2102 : : + 2103 : : + 2104 : : /* 2105 : : Disable all indexes. 2106 : : ===== File: storage/maria/ma_pagecache.c ===== 89 : : #define PAGECACHE_DEBUG_LOG "my_pagecache_debug.log" 90 : : #define _VARARGS(X) X 91 : : 92 : : +/* For debugging of pagecache */ 93 : : +#ifdef EXTRA_DEBUG_BITMAP 94 : : +static my_bool pagecache_extra_debug= 1; 95 : : +#endif 96 : : + 97 : : /* 98 : : In key cache we have external raw locking here we use 99 : : SERIALIZED_READ_FROM_CACHE to avoid problem of reading 659 : : debug either of the above issues. 660 : : */ 661 : : 662 : : + if (pagecache_extra_debug) 663 : : { 664 : : char buff[80]; 665 : : uint len= my_sprintf(buff, 800 : 13830 : pagecache->disk_blocks= -1; 801 : 13830 : if (! pagecache->inited) 802 : : { 803 : 13830 : + my_hash_clear(&pagecache->files_in_flush); 804 : 13830 : if (mysql_mutex_init(key_PAGECACHE_cache_lock, 805 : 13830 : &pagecache->cache_lock, MY_MUTEX_INIT_FAST) || 806 : 13830 : my_hash_init(PSI_INSTRUMENT_ME, &pagecache->files_in_flush, 944 : 0 : my_free(pagecache->block_root); 945 : 0 : pagecache->block_root= NULL; 946 : : } 947 : 0 : + my_hash_free(&pagecache->files_in_flush); 948 : 0 : my_errno= error; 949 : 0 : pagecache->can_be_used= 0; 950 : 0 : DBUG_RETURN(0); 5240 : 9336073 : DBUG_ENTER("flush_pagecache_blocks_with_filter"); 5241 : 9336066 : DBUG_PRINT("enter", ("pagecache: %p fd: %di", pagecache, file->file)); 5242 : : 5243 : 9336076 : pagecache_pthread_mutex_lock(&pagecache->cache_lock); 5244 : 9336077 : inc_counter_for_resize_op(pagecache); 5245 : 9336077 : res= flush_pagecache_blocks_int(pagecache, file, type, filter, filter_arg); 5295 : : are not interesting for a checkpoint record. 5296 : : The caller has the intention of doing checkpoints. 5297 : : 5298 : : + @param pagecache pointer to the page cache 5299 : : + @param[out] str pointer to where the allocated buffer, and 5300 : : + its size, will be put 5301 : : + @param[in|out] min_rec_lsn pointer to where the minimum rec_lsn of all 5302 : : + relevant dirty pages will be put. 5303 : : + Note the original value is used as current 5304 : : + min value! 5305 : : + @param list_size Number of dirty_pages 5306 : : @return Operation status 5307 : : @retval 0 OK 5308 : : @retval 1 Error 5310 : : 5311 : 5682 : my_bool pagecache_collect_changed_blocks_with_lsn(PAGECACHE *pagecache, 5312 : : LEX_STRING *str, 5313 : : + LSN *min_rec_lsn, 5314 : : + uint *dirty_pages) 5315 : : { 5316 : 5682 : my_bool error= 0; 5317 : 5682 : + uint stored_list_size= 0; 5318 : : uint file_hash; 5319 : 5682 : + LSN minimum_rec_lsn= *min_rec_lsn; 5320 : : char *ptr; 5321 : 5682 : + DBUG_ENTER("pagecache_collect_changed_blocks_with_lsn"); 5322 : : 5323 : 5682 : + DBUG_ASSERT(!str->str); 5324 : : /* 5325 : : We lock the entire cache but will be quick, just reading/writing a few MBs 5326 : : of memory at most. 5388 : : } 5389 : : 5390 : : compile_time_assert(sizeof(pagecache->blocks) <= 8); 5391 : 5682 : if (stored_list_size == 0) 5392 : 5654 : goto end; 5393 : : + 5394 : 28 : + str->length= ((2 + /* table id */ 5395 : : + 1 + /* data or index file */ 5396 : : + 5 + /* pageno */ 5397 : : + LSN_STORE_SIZE /* rec_lsn */ 5398 : 28 : + ) * stored_list_size); 5399 : 28 : + if (!(str->str= my_malloc(PSI_INSTRUMENT_ME, str->length, MYF(MY_WME)))) 5400 : 0 : + goto err; 5401 : 28 : + ptr= str->str; 5402 : 28 : + DBUG_PRINT("info", ("found %u dirty pages", stored_list_size)); 5403 : 14364 : for (file_hash= 0; file_hash < pagecache->changed_blocks_hash_size; file_hash++) 5404 : : { 5405 : : PAGECACHE_BLOCK_LINK *block; 5433 : 28 : end: 5434 : 5682 : pagecache_pthread_mutex_unlock(&pagecache->cache_lock); 5435 : 5682 : *min_rec_lsn= minimum_rec_lsn; 5436 : 5682 : + *dirty_pages= stored_list_size; 5437 : 5682 : DBUG_RETURN(error); 5438 : : 5439 : 0 : err: 5440 : 0 : + stored_list_size= 0; 5441 : 0 : error= 1; 5442 : 0 : goto end; 5443 : : } ===== File: storage/maria/ma_pagecache.h ===== 97 : : size_t length; 98 : : } S3_BLOCK; 99 : : 100 : : /* file descriptor for Maria */ 101 : : typedef struct st_pagecache_file 102 : : { 119 : : 120 : : /** Cannot be NULL */ 121 : : uchar *callback_data; 122 : : + struct st_pagecache *pagecache; 123 : : } PAGECACHE_FILE; 124 : : 125 : : /* declare structures that is used by st_pagecache */ 216 : : my_bool resize_in_flush; /* true during flush of resize operation */ 217 : : my_bool can_be_used; /* usage of cache for read/write is allowed */ 218 : : my_bool in_init; /* Set to 1 in MySQL during init/resize */ 219 : : + my_bool multi; /* If part of segmented pagecache */ 220 : : HASH files_in_flush; /**< files in flush_pagecache_blocks_int() */ 221 : : } PAGECACHE; 222 : : 338 : : extern void end_pagecache(PAGECACHE *keycache, my_bool cleanup)__attribute__((visibility("default"))) ; 339 : : extern my_bool pagecache_collect_changed_blocks_with_lsn(PAGECACHE *pagecache, 340 : : LEX_STRING *str, 341 : : + LSN *min_lsn, 342 : : + uint *dirt_pages); 343 : : extern int reset_pagecache_counters(const char *name, PAGECACHE *pagecache); 344 : : extern uchar *pagecache_block_link_to_buffer(PAGECACHE_BLOCK_LINK *block); 345 : : 348 : : uint level); 349 : : 350 : : /* Functions to handle multiple key caches */ 351 : : + 352 : : +typedef struct st_pagecaches 353 : : +{ 354 : : + PAGECACHE *caches; 355 : : + ulonglong requests; 356 : : + uint segments; 357 : : + my_bool initialized; 358 : : +} PAGECACHES; 359 : : + 360 : : +my_bool multi_init_pagecache(PAGECACHES *pagecaches, ulong segments, 361 : : + size_t use_mem, uint division_limit, 362 : : + uint age_threshold, 363 : : + uint block_size, uint changed_blocks_hash_size, 364 : : + myf my_readwrite_flags); 365 : : +extern void multi_end_pagecache(PAGECACHES *pagecaches); 366 : : +extern my_bool 367 : : +multi_pagecache_collect_changed_blocks_with_lsn(PAGECACHES *pagecaches, 368 : : + LEX_STRING *str, 369 : : + LSN *min_rec_lsn, 370 : : + uint *dirty_pages); 371 : : + 372 : 478215 : +static inline PAGECACHE *multi_get_pagecache(PAGECACHES *pagecaches) 373 : : +{ 374 : 478215 : + return pagecaches->caches + (pagecaches->requests++ % pagecaches->segments); 375 : : +} 376 : : + 377 : : +/* Pagecache stats */ 378 : : + 379 : : +struct st_pagecache_stats 380 : : +{ 381 : : + size_t blocks_used; /* maximum number of concurrently used blocks */ 382 : : + size_t blocks_unused; /* number of currently unused blocks */ 383 : : + size_t blocks_changed; /* number of currently dirty blocks */ 384 : : + 385 : : + size_t global_blocks_changed; /* number of currently dirty blocks */ 386 : : + ulonglong global_cache_w_requests;/* number of write requests (write hits) */ 387 : : + ulonglong global_cache_write; /* number of writes from cache to files */ 388 : : + ulonglong global_cache_r_requests;/* number of read requests (read hits) */ 389 : : + ulonglong global_cache_read; /* number of reads from files to cache */ 390 : : +}; 391 : : + 392 : : +/* Stats will be updated when multi_update_pagecache_stats() is called */ 393 : : +extern struct st_pagecache_stats pagecache_stats; 394 : : +void multi_update_pagecache_stats(); 395 : : +ulonglong multi_global_cache_writes(PAGECACHES *pagecaches); 396 : : + 397 : : #ifndef DBUG_OFF 398 : : void pagecache_file_no_dirty_page(PAGECACHE *pagecache, PAGECACHE_FILE *file); 399 : : #else 400 : : #define pagecache_file_no_dirty_page(A,B) {} 401 : : #endif 402 : : 403 : : + 404 : : C_MODE_END 405 : : +#endif /* _ma_pagecache_h */ ===== File: storage/maria/ma_pagecaches.c ===== 1 : : +/* Copyright (C) MariaDB Corporation 2 : : 3 : : This program is free software; you can redistribute it and/or modify 4 : : it under the terms of the GNU General Public License as published by 14 : : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ 15 : : 16 : : /* 17 : : + Handling of multiple key caches in Aria 18 : : 19 : : + Each data and index pages for a table is put in the same cache, based on the 20 : : + filenumber of that index file. 21 : : */ 22 : : 23 : : #include "maria_def.h" 30 : : Functions to handle the pagecache objects 31 : : *****************************************************************************/ 32 : : 33 : : +/** 34 : : + Init 'segments' number of independent pagecaches 35 : : 36 : : + @return 0 ok 37 : : + @return 1 error 38 : : +*/ 39 : : 40 : 6888 : +my_bool multi_init_pagecache(PAGECACHES *pagecaches, ulong segments, 41 : : + size_t use_mem, uint division_limit, 42 : : + uint age_threshold, 43 : : + uint block_size, uint changed_blocks_hash_size, 44 : : + myf my_readwrite_flags) 45 : : { 46 : : + PAGECACHE *pagecache; 47 : 13776 : + DBUG_ENTER("init_pagecaches"); 48 : : + 49 : 6888 : + pagecaches->initialized= 0; 50 : 6888 : + if (!(pagecaches->caches= ((PAGECACHE*) 51 : 6888 : + my_malloc(PSI_INSTRUMENT_ME, 52 : : + sizeof(PAGECACHE) * segments, 53 : : + MYF(MY_FAE | MY_ZEROFILL))))) 54 : 0 : + DBUG_RETURN(1); 55 : : + 56 : 6888 : + pagecache= pagecaches->caches; 57 : 6888 : + pagecaches->segments= segments; 58 : 13792 : + for (ulong i= 0; i < segments ; i++, pagecache++) 59 : : + { 60 : 6904 : + if (init_pagecache(pagecache, 61 : 6904 : + MY_MAX(MIN_KEY_CACHE_SIZE, use_mem / segments), 62 : : + division_limit, age_threshold, 63 : : + block_size, changed_blocks_hash_size, 64 : : + my_readwrite_flags) == 0) 65 : 0 : + goto err; 66 : 6904 : + pagecache->multi= 1; /* Part of segemented cache */ 67 : : + } 68 : 6888 : + pagecaches->initialized= 1; 69 : 6888 : + DBUG_RETURN(0); 70 : : + 71 : 0 : +err: 72 : 0 : + while (pagecache-- != pagecaches->caches) 73 : 0 : + end_pagecache(pagecache, TRUE); 74 : 0 : + my_free(pagecaches->caches); 75 : 0 : + pagecaches->caches= 0; /* For easier debugging */ 76 : 0 : + DBUG_RETURN(1); 77 : : } 78 : : 79 : : 80 : 5343 : +void multi_end_pagecache(PAGECACHES *pagecaches) 81 : : { 82 : 10686 : + DBUG_ENTER("end_pagecaches"); 83 : : 84 : 5343 : + if (unlikely(!pagecaches->initialized)) 85 : 116 : + DBUG_VOID_RETURN; 86 : : + 87 : 10462 : + for (ulong i= 0; i < pagecaches->segments ; i++) 88 : 5235 : + end_pagecache(pagecaches->caches+i, TRUE); 89 : : + 90 : 5227 : + my_free(pagecaches->caches); 91 : 5227 : + pagecaches->caches= 0; 92 : 5227 : + pagecaches->initialized= 0; 93 : 5227 : + pagecaches->segments= 0; 94 : 5227 : + DBUG_VOID_RETURN; 95 : : +} 96 : : 97 : : 98 : : +/* 99 : : + Call pagecache_collect_changed_blocks_with_len() over all 100 : : + pagecaches 101 : : 102 : : + @param pagecaches The partitioned page cache 103 : : + @param str Buffers for changed blocks 104 : : + @param min_rec_lsn[out] Min rec lsn in pagecache 105 : : + @param dirty_pages[out] Total dirty pages found 106 : : */ 107 : : 108 : 5662 : +my_bool multi_pagecache_collect_changed_blocks_with_lsn(PAGECACHES *pagecaches, 109 : : + LEX_STRING *str, 110 : : + LSN *min_rec_lsn, 111 : : + uint *dirty_pages) 112 : : { 113 : 5662 : + uint pages= 0; 114 : 11324 : + DBUG_ENTER("multi_pagecache_collect_changed_blocks_with_lsn"); 115 : 5662 : + *min_rec_lsn= LSN_MAX; 116 : 11344 : + for (ulong i= 0; i < pagecaches->segments ; i++, str++) 117 : : + { 118 : : + uint tmp_dirty; 119 : 5682 : + if (unlikely(pagecache_collect_changed_blocks_with_lsn(pagecaches->caches+i, 120 : : + str, 121 : : + min_rec_lsn, 122 : : + &tmp_dirty))) 123 : : + { 124 : : + /* Free the collected checkpoint information */ 125 : : + do 126 : : + { 127 : 0 : + my_free(str->str); 128 : 0 : + str->str= 0; 129 : 0 : + str--; 130 : 0 : + } while (i-- > 0); 131 : 0 : + *dirty_pages= 0; 132 : 0 : + DBUG_RETURN(1); 133 : : + } 134 : 5682 : + pages+= tmp_dirty; 135 : : + } 136 : 5662 : + *dirty_pages= pages; 137 : 5662 : + DBUG_RETURN(0); 138 : : } 139 : : 140 : : 141 : : +struct st_pagecache_stats pagecache_stats; 142 : : + 143 : : /* 144 : : + Update the global pagecache status 145 : : + This function is called when accessing status variables 146 : : +*/ 147 : : 148 : 33069 : +void multi_update_pagecache_stats() 149 : : +{ 150 : : + struct st_pagecache_stats new; 151 : 33069 : + bzero(&new, sizeof(new)); 152 : 66146 : + for (uint i= 0 ; i < maria_pagecaches.segments ; i++) 153 : : + { 154 : 33077 : + PAGECACHE *pagecache= maria_pagecaches.caches + i; 155 : 33077 : + new.blocks_used+= pagecache->blocks_used; 156 : 33077 : + new.blocks_unused+= pagecache->blocks_unused; 157 : 33077 : + new.blocks_changed+= pagecache->blocks_changed; 158 : 33077 : + new.global_blocks_changed+= pagecache->global_blocks_changed; 159 : 33077 : + new.global_cache_w_requests+= pagecache->global_cache_w_requests; 160 : 33077 : + new.global_cache_write+= pagecache->global_cache_write; 161 : 33077 : + new.global_cache_r_requests+= pagecache->global_cache_r_requests; 162 : 33077 : + new.global_cache_read+= pagecache->global_cache_read; 163 : : + } 164 : 33069 : + pagecache_stats.blocks_used= new.blocks_used; 165 : 33069 : + pagecache_stats.blocks_unused= new.blocks_unused; 166 : 33069 : + pagecache_stats.blocks_changed= new.blocks_changed; 167 : 33069 : + pagecache_stats.global_blocks_changed= new.global_blocks_changed; 168 : 33069 : + pagecache_stats.global_cache_w_requests= new.global_cache_w_requests; 169 : 33069 : + pagecache_stats.global_cache_write= new.global_cache_write; 170 : 33069 : + pagecache_stats.global_cache_r_requests= new.global_cache_r_requests; 171 : 33069 : + pagecache_stats.global_cache_read= new.global_cache_read; 172 : 33069 : +}; 173 : : 174 : : 175 : : +/* 176 : : + Get the total writes to the pagecaches 177 : : */ 178 : : 179 : 7034 : +ulonglong multi_global_cache_writes(PAGECACHES *pagecaches) 180 : : { 181 : 7034 : + ulonglong count= 0; 182 : 14092 : + for (ulong i= 0; i < pagecaches->segments ; i++) 183 : 7058 : + count+= pagecaches->caches[i].global_cache_write; 184 : 7034 : + return count; 185 : : } 186 : : 187 : : 188 : : +/* 189 : : + Reset pagecache statistics 190 : : +*/ 191 : : + 192 : 0 : +void multi_reset_pagecache_counters(PAGECACHES *pagecaches) 193 : : { 194 : 0 : + for (ulong i= 0; i < pagecaches->segments ; i++) 195 : 0 : + reset_pagecache_counters(NullS, pagecaches->caches+i); 196 : 0 : + multi_update_pagecache_stats(); 197 : 0 : } ===== File: storage/maria/ma_recovery.c ===== 236 : 6885 : trace_file= NULL; /* no trace file for being fast */ 237 : : #endif 238 : 6885 : tprint(trace_file, "TRACE of the last Aria recovery from mysqld\n"); 239 : 6885 : + DBUG_ASSERT(maria_pagecaches.initialized); 240 : 6885 : res= maria_apply_log(LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, 0, MARIA_LOG_APPLY, 241 : : trace_file, TRUE, TRUE, &warnings_count); 242 : 6885 : if (!res) ===== File: storage/maria/ma_rt_test.c ===== 96 : 0 : get_options(argc, argv); 97 : : /* Maria requires that we always have a page cache */ 98 : 0 : if (maria_init() || 99 : 0 : + (multi_init_pagecache(&maria_pagecaches, 1, maria_block_size * 16, 0, 0, 100 : 0 : + maria_block_size, 0, MY_WME)) || 101 : 0 : ma_control_file_open_or_create() || 102 : 0 : (init_pagecache(maria_log_pagecache, 103 : : TRANSLOG_PAGECACHE_SIZE, 0, 0, ===== File: storage/maria/ma_static.c ===== 33 : : /* Unique number for this maria instance */ 34 : : uchar maria_uuid[MY_UUID_SIZE]; 35 : : uint maria_quick_table_bits=9; 36 : : +uint __attribute__((visibility("default"))) maria_block_size= MARIA_KEY_BLOCK_LENGTH; 37 : : my_bool maria_flush= 0, maria_single_user= 0; 38 : : my_bool maria_delay_key_write= 0, maria_page_checksums= 1; 39 : : my_bool maria_inited= FALSE; 55 : : my_off_t maria_max_temp_length= MAX_FILE_SIZE; 56 : : ulong maria_bulk_insert_tree_size=8192*1024; 57 : : ulong maria_data_pointer_size= 6; 58 : : +ulong maria_pagecache_segments; 59 : : 60 : : +PAGECACHES maria_pagecaches; 61 : : PAGECACHE maria_log_pagecache_var; 62 : : PAGECACHE *maria_log_pagecache= &maria_log_pagecache_var; 63 : : MY_TMPDIR *maria_tmpdir; /* Tempdir for redo */ ===== File: storage/maria/ma_test1.c ===== 79 : 0 : get_options(argc,argv); 80 : : /* Maria requires that we always have a page cache */ 81 : 0 : if (maria_init() || 82 : 0 : + (multi_init_pagecache(&maria_pagecaches, 1, maria_block_size * 16, 0, 0, 83 : 0 : + maria_block_size, 0, MY_WME)) || 84 : 0 : ma_control_file_open_or_create() || 85 : 0 : (init_pagecache(maria_log_pagecache, 86 : : TRANSLOG_PAGECACHE_SIZE, 0, 0, ===== File: storage/maria/ma_test2.c ===== 44 : : static my_bool opt_versioning= 0; 45 : : static uint use_blob= 0, update_count= 0; 46 : : static ulong pagecache_size=8192*32; 47 : : +static ulong pagecache_segments= 1; 48 : : static enum data_file_type record_type= DYNAMIC_RECORD; 49 : : 50 : : static uint keys=MARIA_KEYS,recant=1000; 89 : : 90 : : /* Maria requires that we always have a page cache */ 91 : 0 : if (maria_init() || 92 : 0 : + (multi_init_pagecache(&maria_pagecaches, pagecache_segments, 93 : : + pagecache_size, 0, 0, 94 : 0 : + maria_block_size, 0, MY_WME)) || 95 : 0 : ma_control_file_open_or_create() || 96 : 0 : (init_pagecache(maria_log_pagecache, 97 : : TRANSLOG_PAGECACHE_SIZE, 0, 0, 984 : 0 : goto err; 985 : : } 986 : 0 : file= 0; 987 : 0 : + multi_update_pagecache_stats(); 988 : 0 : maria_panic(HA_PANIC_CLOSE); /* Should close log */ 989 : 0 : if (!silent) 990 : : { 992 : 0 : printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete); 993 : 0 : if (rec_pointer_size) 994 : 0 : printf("Record pointer size: %d\n",rec_pointer_size); 995 : 0 : + printf("maria_block_size: %u\n", maria_block_size); 996 : 0 : if (write_cacheing) 997 : 0 : puts("Key cache resized"); 998 : 0 : if (write_cacheing) 1012 : : writes: %10lu\n\ 1013 : : r_requests: %10lu\n\ 1014 : : reads: %10lu\n", 1015 : 0 : + (ulong) pagecache_stats.blocks_used, 1016 : 0 : + (ulong) pagecache_stats.global_blocks_changed, 1017 : 0 : + (ulong) pagecache_stats.global_cache_w_requests, 1018 : 0 : + (ulong) pagecache_stats.global_cache_write, 1019 : 0 : + (ulong) pagecache_stats.global_cache_r_requests, 1020 : 0 : + (ulong) pagecache_stats.global_cache_read); 1021 : : } 1022 : 0 : maria_end(); 1023 : 0 : my_free(blob_buffer); 1130 : 0 : pack_type=0; /* Don't use DIFF_LENGTH */ 1131 : 0 : pack_seg=0; 1132 : 0 : break; 1133 : 0 : + case 'p': /* Segmented page cache */ 1134 : 0 : + pagecache_segments= atoi(++pos); 1135 : 0 : + pagecache_size*= pagecache_segments; 1136 : 0 : + break; 1137 : 0 : case 'R': /* Length of record pointer */ 1138 : 0 : rec_pointer_size=atoi(++pos); 1139 : 0 : if (rec_pointer_size > 7) ===== File: storage/maria/ma_test3.c ===== 177 : 0 : fprintf(stderr,"Can't open isam-file: %s\n",filename); 178 : 0 : exit(1); 179 : : } 180 : 0 : + multi_init_pagecache(&maria_pagecaches, 1, 65536L, 0, 0, 181 : : + MARIA_KEY_BLOCK_LENGTH, 0, MY_WME); 182 : : + 183 : 0 : printf("Process %d, pid: %ld\n",id,(long) getpid()); fflush(stdout); 184 : : 185 : 0 : for (error=i=0 ; i < tests && !error; i++) ===== File: storage/maria/ma_test_big.sh ===== 4 : : # finding bugs in blob handling 5 : : # 6 : : 7 : : +mkdir -p tmp 8 : : +cd tmp 9 : : set -e 10 : : a=15 11 : : while test $a -le 5000 12 : : do 13 : : echo $a 14 : : + rm -f aria_log* 15 : : + ../ma_test2 -s -L -K -W -P -M -T -c -b32768 -t4 -A1 -m$a > /dev/null 16 : : + ../aria_read_log -a -s >& /dev/null 17 : : + ../aria_chk -ess test2 18 : : + ../aria_read_log -a -s >& /dev/null 19 : : + ../aria_chk -ess test2 20 : : rm test2.MA? 21 : : + ../aria_read_log -a -s >& /dev/null 22 : : + ../aria_chk -ess test2 23 : : a=$((a+1)) 24 : : done 25 : : +cd .. 26 : : +rm -r tmp ===== File: storage/maria/maria_def.h ===== 184 : : 185 : : typedef struct s3_info S3_INFO; 186 : : 187 : : +extern uint maria_block_size, maria_checkpoint_frequency; 188 : : extern ulong maria_concurrent_insert; 189 : : extern my_bool maria_flush, maria_single_user, maria_page_checksums; 190 : : extern my_off_t maria_max_temp_length; 208 : : extern int maria_delete(MARIA_HA *file, const uchar *buff); 209 : : extern MARIA_HA *maria_open(const char *name, int mode, 210 : : uint wait_if_locked, S3_INFO *s3); 211 : : +extern void ma_change_pagecache(MARIA_HA *info); 212 : : extern int maria_panic(enum ha_panic_function function); 213 : : extern int maria_rfirst(MARIA_HA *file, uchar *buf, int inx); 214 : : extern int maria_rkey(MARIA_HA *file, uchar *buf, int inx, 355 : : typedef struct st_sort_key_blocks MA_SORT_KEY_BLOCKS; 356 : : typedef struct st_sort_ftbuf MA_SORT_FT_BUF; 357 : : 358 : : +extern PAGECACHES maria_pagecaches; 359 : : int maria_assign_to_pagecache(MARIA_HA *info, ulonglong key_map, 360 : : PAGECACHE *key_cache); 361 : : void maria_change_pagecache(PAGECACHE *old_key_cache, 1273 : : extern my_bool maria_inited, maria_in_ha_maria, maria_recovery_changed_data; 1274 : : extern my_bool maria_recovery_verbose, maria_checkpoint_disabled; 1275 : : extern my_bool maria_assert_if_crashed_table, aria_readonly; 1276 : : +extern uint maria_checkpoint_min_log_activity; 1277 : : extern HASH maria_stored_state; 1278 : : extern int (*maria_create_trn_hook)(MARIA_HA *); 1279 : : extern my_bool (*ma_killed)(MARIA_HA *); 1787 : 71711 : return ma_check_index_cond_real(info, keynr, record); 1788 : : } 1789 : : 1790 : : +extern void ma_update_pagecache_stats(); 1791 : : extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx); 1792 : : extern my_bool ma_killed_standalone(MARIA_HA *); 1793 : : ===== File: storage/maria/test_ma_backup.c ===== 45 : : 46 : : /* Maria requires that we always have a page cache */ 47 : 0 : if (maria_init() || 48 : 0 : + multi_init_pagecache(&maria_pagecaches, 1, 49 : 0 : + maria_block_size * 2000, 0, 0, 50 : 0 : + maria_block_size, 0, MY_WME) || 51 : 0 : ma_control_file_open_or_create() || 52 : 0 : (init_pagecache(maria_log_pagecache, 53 : : TRANSLOG_PAGECACHE_SIZE, 0, 0, Line coverage: 440/490 Branch coverage: 0/0