mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
365 lines
15 KiB
C
365 lines
15 KiB
C
/* Copyright (C) 2006 MySQL AB
|
|
Copyright (c) 2011, 2020, MariaDB Corporation Ab
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
|
|
|
|
/* Page cache variable structures */
|
|
|
|
#ifndef _ma_pagecache_h
|
|
#define _ma_pagecache_h
|
|
C_MODE_START
|
|
|
|
#include "ma_loghandler_lsn.h"
|
|
#include <m_string.h>
|
|
#include <hash.h>
|
|
|
|
/* Type of the page */
|
|
enum pagecache_page_type
|
|
{
|
|
/*
|
|
Used only for control page type changing during debugging. This define
|
|
should only be using when using DBUG.
|
|
*/
|
|
PAGECACHE_EMPTY_PAGE,
|
|
/* the page does not contain LSN */
|
|
PAGECACHE_PLAIN_PAGE,
|
|
/* the page contain LSN (maria tablespace page) */
|
|
PAGECACHE_LSN_PAGE,
|
|
/* Page type used when scanning file and we don't care about the type */
|
|
PAGECACHE_READ_UNKNOWN_PAGE
|
|
};
|
|
|
|
/*
|
|
This enum describe lock status changing. every type of page cache will
|
|
interpret WRITE/READ lock as it need.
|
|
*/
|
|
enum pagecache_page_lock
|
|
{
|
|
PAGECACHE_LOCK_LEFT_UNLOCKED, /* free -> free */
|
|
PAGECACHE_LOCK_LEFT_READLOCKED, /* read -> read */
|
|
PAGECACHE_LOCK_LEFT_WRITELOCKED, /* write -> write */
|
|
PAGECACHE_LOCK_READ, /* free -> read */
|
|
PAGECACHE_LOCK_WRITE, /* free -> write */
|
|
PAGECACHE_LOCK_READ_UNLOCK, /* read -> free */
|
|
PAGECACHE_LOCK_WRITE_UNLOCK, /* write -> free */
|
|
PAGECACHE_LOCK_WRITE_TO_READ /* write -> read */
|
|
};
|
|
/*
|
|
This enum describe pin status changing
|
|
*/
|
|
enum pagecache_page_pin
|
|
{
|
|
PAGECACHE_PIN_LEFT_PINNED, /* pinned -> pinned */
|
|
PAGECACHE_PIN_LEFT_UNPINNED, /* unpinned -> unpinned */
|
|
PAGECACHE_PIN, /* unpinned -> pinned */
|
|
PAGECACHE_UNPIN /* pinned -> unpinned */
|
|
};
|
|
/* How to write the page */
|
|
enum pagecache_write_mode
|
|
{
|
|
/* do not write immediately, i.e. it will be dirty page */
|
|
PAGECACHE_WRITE_DELAY,
|
|
/* page already is in the file. (key cache insert analogue) */
|
|
PAGECACHE_WRITE_DONE
|
|
};
|
|
|
|
/* page number for maria */
|
|
typedef ulonglong pgcache_page_no_t;
|
|
|
|
/* args for read/write hooks */
|
|
typedef struct st_pagecache_io_hook_args
|
|
{
|
|
uchar * page;
|
|
pgcache_page_no_t pageno;
|
|
uchar * data;
|
|
|
|
uchar *crypt_buf; /* when using encryption */
|
|
} PAGECACHE_IO_HOOK_ARGS;
|
|
|
|
struct st_pagecache;
|
|
|
|
/* Structure to store things from get_object */
|
|
|
|
typedef struct st_S3_BLOCK
|
|
{
|
|
uchar *str, *alloc_ptr;
|
|
size_t length;
|
|
} S3_BLOCK;
|
|
|
|
|
|
/* file descriptor for Maria */
|
|
typedef struct st_pagecache_file
|
|
{
|
|
/* Number of pages in the header which are not read with big blocks */
|
|
size_t head_blocks;
|
|
/* size of a big block for S3 or 0 */
|
|
size_t big_block_size;
|
|
/* File number */
|
|
File file;
|
|
|
|
/** Cannot be NULL */
|
|
my_bool (*pre_read_hook)(PAGECACHE_IO_HOOK_ARGS *args);
|
|
my_bool (*post_read_hook)(int error, PAGECACHE_IO_HOOK_ARGS *args);
|
|
|
|
/** Cannot be NULL */
|
|
my_bool (*pre_write_hook)(PAGECACHE_IO_HOOK_ARGS *args);
|
|
void (*post_write_hook)(int error, PAGECACHE_IO_HOOK_ARGS *args);
|
|
|
|
my_bool (*flush_log_callback)(PAGECACHE_IO_HOOK_ARGS *args);
|
|
|
|
/** Cannot be NULL */
|
|
uchar *callback_data;
|
|
} PAGECACHE_FILE;
|
|
|
|
/* declare structures that is used by st_pagecache */
|
|
|
|
struct st_pagecache_block_link;
|
|
typedef struct st_pagecache_block_link PAGECACHE_BLOCK_LINK;
|
|
struct st_pagecache_page;
|
|
typedef struct st_pagecache_page PAGECACHE_PAGE;
|
|
struct st_pagecache_hash_link;
|
|
typedef struct st_pagecache_hash_link PAGECACHE_HASH_LINK;
|
|
|
|
#include <wqueue.h>
|
|
|
|
/* Default size of hash for changed files */
|
|
#define MIN_PAGECACHE_CHANGED_BLOCKS_HASH_SIZE 512
|
|
|
|
#define PAGECACHE_PRIORITY_LOW 0
|
|
#define PAGECACHE_PRIORITY_DEFAULT 3
|
|
#define PAGECACHE_PRIORITY_HIGH 6
|
|
|
|
/*
|
|
The page cache structure
|
|
It also contains read-only statistics parameters.
|
|
*/
|
|
|
|
typedef struct st_pagecache
|
|
{
|
|
size_t mem_size; /* specified size of the cache memory */
|
|
size_t min_warm_blocks; /* min number of warm blocks; */
|
|
size_t age_threshold; /* age threshold for hot blocks */
|
|
ulonglong time; /* total number of block link operations */
|
|
size_t hash_entries; /* max number of entries in the hash table */
|
|
size_t changed_blocks_hash_size;/* Number of hash buckets for file blocks */
|
|
ssize_t hash_links; /* max number of hash links */
|
|
ssize_t hash_links_used; /* number of hash links taken from free links pool */
|
|
ssize_t disk_blocks; /* max number of blocks in the cache */
|
|
size_t blocks_used; /* maximum number of concurrently used blocks */
|
|
size_t blocks_unused; /* number of currently unused blocks */
|
|
size_t blocks_changed; /* number of currently dirty blocks */
|
|
size_t warm_blocks; /* number of blocks in warm sub-chain */
|
|
size_t cnt_for_resize_op; /* counter to block resize operation */
|
|
size_t blocks_available; /* number of blocks available in the LRU chain */
|
|
ssize_t blocks; /* max number of blocks in the cache */
|
|
uint32 block_size; /* size of the page buffer of a cache block */
|
|
PAGECACHE_HASH_LINK **hash_root;/* arr. of entries into hash table buckets */
|
|
PAGECACHE_HASH_LINK *hash_link_root;/* memory for hash table links */
|
|
PAGECACHE_HASH_LINK *free_hash_list;/* list of free hash links */
|
|
PAGECACHE_BLOCK_LINK *free_block_list;/* list of free blocks */
|
|
PAGECACHE_BLOCK_LINK *block_root;/* memory for block links */
|
|
uchar *block_mem; /* memory for block buffers */
|
|
PAGECACHE_BLOCK_LINK *used_last;/* ptr to the last block of the LRU chain */
|
|
PAGECACHE_BLOCK_LINK *used_ins;/* ptr to the insertion block in LRU chain */
|
|
mysql_mutex_t cache_lock; /* to lock access to the cache structure */
|
|
WQUEUE resize_queue; /* threads waiting during resize operation */
|
|
WQUEUE waiting_for_hash_link;/* waiting for a free hash link */
|
|
WQUEUE waiting_for_block; /* requests waiting for a free block */
|
|
/* hash for dirty file bl.*/
|
|
PAGECACHE_BLOCK_LINK **changed_blocks;
|
|
/* hash for other file bl.*/
|
|
PAGECACHE_BLOCK_LINK **file_blocks;
|
|
|
|
/**
|
|
Function for reading file in big hunks from S3
|
|
Data will be filled with pointer and length to data read
|
|
start_page will be contain first page read.
|
|
*/
|
|
my_bool (*big_block_read)(struct st_pagecache *pagecache,
|
|
PAGECACHE_IO_HOOK_ARGS *args,
|
|
struct st_pagecache_file *file, S3_BLOCK *data);
|
|
void (*big_block_free)(S3_BLOCK *data);
|
|
|
|
|
|
/*
|
|
The following variables are and variables used to hold parameters for
|
|
initializing the key cache.
|
|
*/
|
|
|
|
ulonglong param_buff_size; /* size the memory allocated for the cache */
|
|
size_t param_block_size; /* size of the blocks in the key cache */
|
|
size_t param_division_limit; /* min. percentage of warm blocks */
|
|
size_t param_age_threshold; /* determines when hot block is downgraded */
|
|
|
|
/* Statistics variables. These are reset in reset_pagecache_counters(). */
|
|
size_t global_blocks_changed; /* number of currently dirty blocks */
|
|
ulonglong global_cache_w_requests;/* number of write requests (write hits) */
|
|
ulonglong global_cache_write; /* number of writes from cache to files */
|
|
ulonglong global_cache_r_requests;/* number of read requests (read hits) */
|
|
ulonglong global_cache_read; /* number of reads from files to cache */
|
|
|
|
uint shift; /* block size = 2 ^ shift */
|
|
myf readwrite_flags; /* Flags to pread/pwrite() */
|
|
myf org_readwrite_flags; /* Flags to pread/pwrite() at init */
|
|
my_bool inited;
|
|
my_bool resize_in_flush; /* true during flush of resize operation */
|
|
my_bool can_be_used; /* usage of cache for read/write is allowed */
|
|
my_bool in_init; /* Set to 1 in MySQL during init/resize */
|
|
my_bool extra_debug; /* set to 1 if one wants extra logging */
|
|
HASH files_in_flush; /**< files in flush_pagecache_blocks_int() */
|
|
} PAGECACHE;
|
|
|
|
/** @brief Return values for PAGECACHE_FLUSH_FILTER */
|
|
enum pagecache_flush_filter_result
|
|
{
|
|
FLUSH_FILTER_SKIP_TRY_NEXT= 0,/**< skip page and move on to next one */
|
|
FLUSH_FILTER_OK, /**< flush page and move on to next one */
|
|
FLUSH_FILTER_SKIP_ALL /**< skip page and all next ones */
|
|
};
|
|
/** @brief a filter function type for flush_pagecache_blocks_with_filter() */
|
|
typedef enum pagecache_flush_filter_result
|
|
(*PAGECACHE_FLUSH_FILTER)(enum pagecache_page_type type,
|
|
pgcache_page_no_t page,
|
|
LSN rec_lsn, void *arg);
|
|
|
|
/* The default key cache */
|
|
extern PAGECACHE dflt_pagecache_var, *dflt_pagecache;
|
|
|
|
extern size_t init_pagecache(PAGECACHE *pagecache, size_t use_mem,
|
|
uint division_limit, uint age_threshold,
|
|
uint block_size, uint changed_blocks_hash_size,
|
|
myf my_read_flags)__attribute__((visibility("default"))) ;
|
|
extern size_t resize_pagecache(PAGECACHE *pagecache,
|
|
size_t use_mem, uint division_limit,
|
|
uint age_threshold, uint changed_blocks_hash_size);
|
|
extern void change_pagecache_param(PAGECACHE *pagecache, uint division_limit,
|
|
uint age_threshold);
|
|
|
|
extern uchar *pagecache_read(PAGECACHE *pagecache,
|
|
PAGECACHE_FILE *file,
|
|
pgcache_page_no_t pageno,
|
|
uint level,
|
|
uchar *buff,
|
|
enum pagecache_page_type type,
|
|
enum pagecache_page_lock lock,
|
|
PAGECACHE_BLOCK_LINK **link);
|
|
|
|
#define pagecache_write(P,F,N,L,B,T,O,I,M,K,R) \
|
|
pagecache_write_part(P,F,N,L,B,T,O,I,M,K,R,0,(P)->block_size)
|
|
|
|
#define pagecache_inject(P,F,N,L,B,T,O,I,K,R) \
|
|
pagecache_write_part(P,F,N,L,B,T,O,I,PAGECACHE_WRITE_DONE, \
|
|
K,R,0,(P)->block_size)
|
|
|
|
extern my_bool pagecache_write_part(PAGECACHE *pagecache,
|
|
PAGECACHE_FILE *file,
|
|
pgcache_page_no_t pageno,
|
|
uint level,
|
|
uchar *buff,
|
|
enum pagecache_page_type type,
|
|
enum pagecache_page_lock lock,
|
|
enum pagecache_page_pin pin,
|
|
enum pagecache_write_mode write_mode,
|
|
PAGECACHE_BLOCK_LINK **link,
|
|
LSN first_REDO_LSN_for_page,
|
|
uint offset,
|
|
uint size);
|
|
extern void pagecache_unlock(PAGECACHE *pagecache,
|
|
PAGECACHE_FILE *file,
|
|
pgcache_page_no_t pageno,
|
|
enum pagecache_page_lock lock,
|
|
enum pagecache_page_pin pin,
|
|
LSN first_REDO_LSN_for_page,
|
|
LSN lsn, my_bool was_changed);
|
|
extern void pagecache_unlock_by_link(PAGECACHE *pagecache,
|
|
PAGECACHE_BLOCK_LINK *block,
|
|
enum pagecache_page_lock lock,
|
|
enum pagecache_page_pin pin,
|
|
LSN first_REDO_LSN_for_page,
|
|
LSN lsn, my_bool was_changed,
|
|
my_bool any);
|
|
extern void pagecache_unpin(PAGECACHE *pagecache,
|
|
PAGECACHE_FILE *file,
|
|
pgcache_page_no_t pageno,
|
|
LSN lsn);
|
|
extern void pagecache_unpin_by_link(PAGECACHE *pagecache,
|
|
PAGECACHE_BLOCK_LINK *link,
|
|
LSN lsn);
|
|
extern void pagecache_set_write_on_delete_by_link(PAGECACHE_BLOCK_LINK *block);
|
|
|
|
|
|
/* Results of flush operation (bit field in fact) */
|
|
|
|
/* The flush is done. */
|
|
#define PCFLUSH_OK 0
|
|
/* There was errors during the flush process. */
|
|
#define PCFLUSH_ERROR 1
|
|
/* Pinned blocks was met and skipped. */
|
|
#define PCFLUSH_PINNED 2
|
|
/* PCFLUSH_ERROR and PCFLUSH_PINNED. */
|
|
#define PCFLUSH_PINNED_AND_ERROR (PCFLUSH_ERROR|PCFLUSH_PINNED)
|
|
|
|
// initialize file with empty hooks
|
|
void pagecache_file_set_null_hooks(PAGECACHE_FILE*);
|
|
|
|
#define flush_pagecache_blocks(A,B,C) \
|
|
flush_pagecache_blocks_with_filter(A,B,C,NULL,NULL)
|
|
extern int flush_pagecache_blocks_with_filter(PAGECACHE *keycache,
|
|
PAGECACHE_FILE *file,
|
|
enum flush_type type,
|
|
PAGECACHE_FLUSH_FILTER filter,
|
|
void *filter_arg)__attribute__((visibility("default"))) ;
|
|
extern my_bool pagecache_delete(PAGECACHE *pagecache,
|
|
PAGECACHE_FILE *file,
|
|
pgcache_page_no_t pageno,
|
|
enum pagecache_page_lock lock,
|
|
my_bool flush);
|
|
extern my_bool pagecache_delete_by_link(PAGECACHE *pagecache,
|
|
PAGECACHE_BLOCK_LINK *link,
|
|
enum pagecache_page_lock lock,
|
|
my_bool flush);
|
|
extern my_bool pagecache_delete_pages(PAGECACHE *pagecache,
|
|
PAGECACHE_FILE *file,
|
|
pgcache_page_no_t pageno,
|
|
uint page_count,
|
|
enum pagecache_page_lock lock,
|
|
my_bool flush);
|
|
extern void end_pagecache(PAGECACHE *keycache, my_bool cleanup)__attribute__((visibility("default"))) ;
|
|
extern my_bool pagecache_collect_changed_blocks_with_lsn(PAGECACHE *pagecache,
|
|
LEX_STRING *str,
|
|
LSN *min_lsn);
|
|
extern int reset_pagecache_counters(const char *name, PAGECACHE *pagecache);
|
|
extern uchar *pagecache_block_link_to_buffer(PAGECACHE_BLOCK_LINK *block);
|
|
|
|
extern uint pagecache_pagelevel(PAGECACHE_BLOCK_LINK *block);
|
|
extern void pagecache_add_level_by_link(PAGECACHE_BLOCK_LINK *block,
|
|
uint level);
|
|
|
|
/* Functions to handle multiple key caches */
|
|
extern my_bool multi_pagecache_init(void);
|
|
extern void multi_pagecache_free(void);
|
|
extern PAGECACHE *multi_pagecache_search(uchar *key, uint length,
|
|
PAGECACHE *def);
|
|
extern my_bool multi_pagecache_set(const uchar *key, uint length,
|
|
PAGECACHE *pagecache);
|
|
extern void multi_pagecache_change(PAGECACHE *old_data,
|
|
PAGECACHE *new_data);
|
|
#ifndef DBUG_OFF
|
|
void pagecache_file_no_dirty_page(PAGECACHE *pagecache, PAGECACHE_FILE *file);
|
|
#else
|
|
#define pagecache_file_no_dirty_page(A,B) {}
|
|
#endif
|
|
|
|
C_MODE_END
|
|
#endif /* _keycache_h */
|