mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
postreview changes for page cache and pre review commit for loghandler
storage/maria/unittest/test_file.c: Rename: unittest/mysys/test_file.c -> storage/maria/unittest/test_file.c storage/maria/unittest/test_file.h: Rename: unittest/mysys/test_file.h -> storage/maria/unittest/test_file.h include/pagecache.h: A waiting queue mechanism moved to separate file wqueue.* Pointer name changed for compatibility mysys/Makefile.am: A waiting queue mechanism moved to separate file wqueue.* mysys/mf_keycache.c: fixed unsigned comparison mysys/mf_pagecache.c: A waiting queue mechanism moved to separate file wqueue.* Fixed bug in unregistering block during write storage/maria/Makefile.am: The loghandler files added storage/maria/ma_control_file.h: Now we have loghandler and can compile control file storage/maria/maria_def.h: Including files need for compilation of maria storage/maria/unittest/Makefile.am: unit tests of loghandler storage/maria/unittest/ma_control_file-t.c: Used maria def storage/maria/unittest/mf_pagecache_consist.c: fixed memory overrun storage/maria/unittest/mf_pagecache_single.c: fixed used uninitialized memory unittest/mysys/Makefile.am: unittests of pagecache moved to maria becase pagecache need loghandler include/wqueue.h: New BitKeeper file ``include/wqueue.h'' mysys/wqueue.c: New BitKeeper file ``mysys/wqueue.c'' storage/maria/ma_loghandler.c: New BitKeeper file ``storage/maria/ma_loghandler.c'' storage/maria/ma_loghandler.h: New BitKeeper file ``storage/maria/ma_loghandler.h'' storage/maria/ma_loghandler_lsn.h: New BitKeeper file ``storage/maria/ma_loghandler_lsn.h'' storage/maria/unittest/ma_test_loghandler-t.c: New BitKeeper file ``storage/maria/unittest/ma_test_loghandler-t.c'' storage/maria/unittest/ma_test_loghandler_multigroup-t.c: New BitKeeper file ``storage/maria/unittest/ma_test_loghandler_multigroup-t.c'' storage/maria/unittest/ma_test_loghandler_multithread-t.c: New BitKeeper file ``storage/maria/unittest/ma_test_loghandler_multithread-t.c'' storage/maria/unittest/ma_test_loghandler_pagecache-t.c: New BitKeeper file ``storage/maria/unittest/ma_test_loghandler_pagecache-t.c''
This commit is contained in:
@ -20,11 +20,13 @@
|
|||||||
#define _pagecache_h
|
#define _pagecache_h
|
||||||
C_MODE_START
|
C_MODE_START
|
||||||
|
|
||||||
|
#include "../storage/maria/ma_loghandler_lsn.h"
|
||||||
|
|
||||||
/* Type of the page */
|
/* Type of the page */
|
||||||
enum pagecache_page_type
|
enum pagecache_page_type
|
||||||
{
|
{
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
/* used only for control page type chenging during debugging */
|
/* used only for control page type changing during debugging */
|
||||||
PAGECACHE_EMPTY_PAGE,
|
PAGECACHE_EMPTY_PAGE,
|
||||||
#endif
|
#endif
|
||||||
/* the page does not contain LSN */
|
/* the page does not contain LSN */
|
||||||
@ -34,7 +36,7 @@ enum pagecache_page_type
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This enum describe lock status changing. every typr of page cache will
|
This enum describe lock status changing. every type of page cache will
|
||||||
interpret WRITE/READ lock as it need.
|
interpret WRITE/READ lock as it need.
|
||||||
*/
|
*/
|
||||||
enum pagecache_page_lock
|
enum pagecache_page_lock
|
||||||
@ -71,9 +73,7 @@ enum pagecache_write_mode
|
|||||||
|
|
||||||
typedef void *PAGECACHE_PAGE_LINK;
|
typedef void *PAGECACHE_PAGE_LINK;
|
||||||
|
|
||||||
/* TODO: move to loghandler emulator */
|
typedef void *LSN_PTR;
|
||||||
typedef void LOG_HANDLER;
|
|
||||||
typedef void *LSN;
|
|
||||||
|
|
||||||
/* file descriptor for Maria */
|
/* file descriptor for Maria */
|
||||||
typedef struct st_pagecache_file
|
typedef struct st_pagecache_file
|
||||||
@ -82,7 +82,7 @@ typedef struct st_pagecache_file
|
|||||||
} PAGECACHE_FILE;
|
} PAGECACHE_FILE;
|
||||||
|
|
||||||
/* page number for maria */
|
/* page number for maria */
|
||||||
typedef uint32 maria_page_no_t;
|
typedef uint32 pgcache_page_no_t;
|
||||||
|
|
||||||
/* declare structures that is used by st_pagecache */
|
/* declare structures that is used by st_pagecache */
|
||||||
|
|
||||||
@ -93,11 +93,9 @@ typedef struct st_pagecache_page PAGECACHE_PAGE;
|
|||||||
struct st_pagecache_hash_link;
|
struct st_pagecache_hash_link;
|
||||||
typedef struct st_pagecache_hash_link PAGECACHE_HASH_LINK;
|
typedef struct st_pagecache_hash_link PAGECACHE_HASH_LINK;
|
||||||
|
|
||||||
/* info about requests in a waiting queue */
|
#include <wqueue.h>
|
||||||
typedef struct st_pagecache_wqueue
|
|
||||||
{
|
typedef my_bool (*pagecache_disk_read_validator)(byte *page, gptr data);
|
||||||
struct st_my_thread_var *last_thread; /* circular list of waiting threads */
|
|
||||||
} PAGECACHE_WQUEUE;
|
|
||||||
|
|
||||||
#define PAGECACHE_CHANGED_BLOCKS_HASH 128 /* must be power of 2 */
|
#define PAGECACHE_CHANGED_BLOCKS_HASH 128 /* must be power of 2 */
|
||||||
|
|
||||||
@ -136,16 +134,14 @@ typedef struct st_pagecache
|
|||||||
PAGECACHE_BLOCK_LINK *used_last;/* ptr to the last block of the LRU chain */
|
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 */
|
PAGECACHE_BLOCK_LINK *used_ins;/* ptr to the insertion block in LRU chain */
|
||||||
pthread_mutex_t cache_lock; /* to lock access to the cache structure */
|
pthread_mutex_t cache_lock; /* to lock access to the cache structure */
|
||||||
PAGECACHE_WQUEUE resize_queue; /* threads waiting during resize operation */
|
WQUEUE resize_queue; /* threads waiting during resize operation */
|
||||||
PAGECACHE_WQUEUE waiting_for_hash_link;/* waiting for a free hash link */
|
WQUEUE waiting_for_hash_link;/* waiting for a free hash link */
|
||||||
PAGECACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */
|
WQUEUE waiting_for_block; /* requests waiting for a free block */
|
||||||
/* hash for dirty file bl.*/
|
/* hash for dirty file bl.*/
|
||||||
PAGECACHE_BLOCK_LINK *changed_blocks[PAGECACHE_CHANGED_BLOCKS_HASH];
|
PAGECACHE_BLOCK_LINK *changed_blocks[PAGECACHE_CHANGED_BLOCKS_HASH];
|
||||||
/* hash for other file bl.*/
|
/* hash for other file bl.*/
|
||||||
PAGECACHE_BLOCK_LINK *file_blocks[PAGECACHE_CHANGED_BLOCKS_HASH];
|
PAGECACHE_BLOCK_LINK *file_blocks[PAGECACHE_CHANGED_BLOCKS_HASH];
|
||||||
|
|
||||||
LOG_HANDLER *loghandler; /* loghandler structure */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following variables are and variables used to hold parameters for
|
The following variables are and variables used to hold parameters for
|
||||||
initializing the key cache.
|
initializing the key cache.
|
||||||
@ -169,24 +165,29 @@ typedef struct st_pagecache
|
|||||||
|
|
||||||
extern int init_pagecache(PAGECACHE *pagecache, my_size_t use_mem,
|
extern int init_pagecache(PAGECACHE *pagecache, my_size_t use_mem,
|
||||||
uint division_limit, uint age_threshold,
|
uint division_limit, uint age_threshold,
|
||||||
uint block_size,
|
uint block_size);
|
||||||
LOG_HANDLER *loghandler);
|
|
||||||
extern int resize_pagecache(PAGECACHE *pagecache,
|
extern int resize_pagecache(PAGECACHE *pagecache,
|
||||||
my_size_t use_mem, uint division_limit,
|
my_size_t use_mem, uint division_limit,
|
||||||
uint age_threshold);
|
uint age_threshold);
|
||||||
extern void change_pagecache_param(PAGECACHE *pagecache, uint division_limit,
|
extern void change_pagecache_param(PAGECACHE *pagecache, uint division_limit,
|
||||||
uint age_threshold);
|
uint age_threshold);
|
||||||
extern byte *pagecache_read(PAGECACHE *pagecache,
|
|
||||||
PAGECACHE_FILE *file,
|
#define pagecache_read(P,F,N,L,B,T,K,I) \
|
||||||
maria_page_no_t pageno,
|
pagecache_valid_read(P,F,N,L,B,T,K,I,0,0)
|
||||||
uint level,
|
|
||||||
byte *buff,
|
extern byte *pagecache_valid_read(PAGECACHE *pagecache,
|
||||||
enum pagecache_page_type type,
|
PAGECACHE_FILE *file,
|
||||||
enum pagecache_page_lock lock,
|
pgcache_page_no_t pageno,
|
||||||
PAGECACHE_PAGE_LINK *link);
|
uint level,
|
||||||
|
byte *buff,
|
||||||
|
enum pagecache_page_type type,
|
||||||
|
enum pagecache_page_lock lock,
|
||||||
|
PAGECACHE_PAGE_LINK *link,
|
||||||
|
pagecache_disk_read_validator validator,
|
||||||
|
gptr validator_data);
|
||||||
extern my_bool pagecache_write(PAGECACHE *pagecache,
|
extern my_bool pagecache_write(PAGECACHE *pagecache,
|
||||||
PAGECACHE_FILE *file,
|
PAGECACHE_FILE *file,
|
||||||
maria_page_no_t pageno,
|
pgcache_page_no_t pageno,
|
||||||
uint level,
|
uint level,
|
||||||
byte *buff,
|
byte *buff,
|
||||||
enum pagecache_page_type type,
|
enum pagecache_page_type type,
|
||||||
@ -196,20 +197,20 @@ extern my_bool pagecache_write(PAGECACHE *pagecache,
|
|||||||
PAGECACHE_PAGE_LINK *link);
|
PAGECACHE_PAGE_LINK *link);
|
||||||
extern void pagecache_unlock_page(PAGECACHE *pagecache,
|
extern void pagecache_unlock_page(PAGECACHE *pagecache,
|
||||||
PAGECACHE_FILE *file,
|
PAGECACHE_FILE *file,
|
||||||
maria_page_no_t pageno,
|
pgcache_page_no_t pageno,
|
||||||
enum pagecache_page_lock lock,
|
enum pagecache_page_lock lock,
|
||||||
enum pagecache_page_pin pin,
|
enum pagecache_page_pin pin,
|
||||||
my_bool stamp_this_page,
|
my_bool stamp_this_page,
|
||||||
LSN first_REDO_LSN_for_page);
|
LSN_PTR first_REDO_LSN_for_page);
|
||||||
extern void pagecache_unlock(PAGECACHE *pagecache,
|
extern void pagecache_unlock(PAGECACHE *pagecache,
|
||||||
PAGECACHE_PAGE_LINK *link,
|
PAGECACHE_PAGE_LINK *link,
|
||||||
enum pagecache_page_lock lock,
|
enum pagecache_page_lock lock,
|
||||||
enum pagecache_page_pin pin,
|
enum pagecache_page_pin pin,
|
||||||
my_bool stamp_this_page,
|
my_bool stamp_this_page,
|
||||||
LSN first_REDO_LSN_for_page);
|
LSN_PTR first_REDO_LSN_for_page);
|
||||||
extern void pagecache_unpin_page(PAGECACHE *pagecache,
|
extern void pagecache_unpin_page(PAGECACHE *pagecache,
|
||||||
PAGECACHE_FILE *file,
|
PAGECACHE_FILE *file,
|
||||||
maria_page_no_t pageno);
|
pgcache_page_no_t pageno);
|
||||||
extern void pagecache_unpin(PAGECACHE *pagecache,
|
extern void pagecache_unpin(PAGECACHE *pagecache,
|
||||||
PAGECACHE_PAGE_LINK *link);
|
PAGECACHE_PAGE_LINK *link);
|
||||||
extern int flush_pagecache_blocks(PAGECACHE *keycache,
|
extern int flush_pagecache_blocks(PAGECACHE *keycache,
|
||||||
@ -217,7 +218,7 @@ extern int flush_pagecache_blocks(PAGECACHE *keycache,
|
|||||||
enum flush_type type);
|
enum flush_type type);
|
||||||
extern my_bool pagecache_delete_page(PAGECACHE *pagecache,
|
extern my_bool pagecache_delete_page(PAGECACHE *pagecache,
|
||||||
PAGECACHE_FILE *file,
|
PAGECACHE_FILE *file,
|
||||||
maria_page_no_t pageno,
|
pgcache_page_no_t pageno,
|
||||||
enum pagecache_page_lock lock,
|
enum pagecache_page_lock lock,
|
||||||
my_bool flush);
|
my_bool flush);
|
||||||
extern void end_pagecache(PAGECACHE *keycache, my_bool cleanup);
|
extern void end_pagecache(PAGECACHE *keycache, my_bool cleanup);
|
||||||
|
26
include/wqueue.h
Normal file
26
include/wqueue.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
#ifndef _wqueue_h
|
||||||
|
#define _wqueue_h
|
||||||
|
|
||||||
|
#include <my_global.h>
|
||||||
|
#include <my_pthread.h>
|
||||||
|
|
||||||
|
/* info about requests in a waiting queue */
|
||||||
|
typedef struct st_pagecache_wqueue
|
||||||
|
{
|
||||||
|
struct st_my_thread_var *last_thread; /* circular list of waiting
|
||||||
|
threads */
|
||||||
|
} WQUEUE;
|
||||||
|
|
||||||
|
#ifdef THREAD
|
||||||
|
void wqueue_link_into_queue(WQUEUE *wqueue, struct st_my_thread_var *thread);
|
||||||
|
void wqueue_unlink_from_queue(WQUEUE *wqueue, struct st_my_thread_var *thread);
|
||||||
|
void wqueue_add_to_queue(WQUEUE *wqueue, struct st_my_thread_var *thread);
|
||||||
|
void wqueue_add_and_wait(WQUEUE *wqueue,
|
||||||
|
struct st_my_thread_var *thread,
|
||||||
|
pthread_mutex_t *lock);
|
||||||
|
void wqueue_release_queue(WQUEUE *wqueue);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -56,7 +56,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
|
|||||||
my_handler.c my_netware.c my_largepage.c \
|
my_handler.c my_netware.c my_largepage.c \
|
||||||
my_memmem.c \
|
my_memmem.c \
|
||||||
my_windac.c my_access.c base64.c my_libwrap.c \
|
my_windac.c my_access.c base64.c my_libwrap.c \
|
||||||
mf_pagecache.c
|
mf_pagecache.c wqueue.c
|
||||||
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
|
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
|
||||||
thr_mutex.c thr_rwlock.c \
|
thr_mutex.c thr_rwlock.c \
|
||||||
CMakeLists.txt mf_soundex.c \
|
CMakeLists.txt mf_soundex.c \
|
||||||
|
@ -1008,12 +1008,12 @@ static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block)
|
|||||||
|
|
||||||
KEYCACHE_THREAD_TRACE("unlink_block");
|
KEYCACHE_THREAD_TRACE("unlink_block");
|
||||||
#if defined(KEYCACHE_DEBUG)
|
#if defined(KEYCACHE_DEBUG)
|
||||||
|
KEYCACHE_DBUG_ASSERT(keycache->blocks_available != 0);
|
||||||
keycache->blocks_available--;
|
keycache->blocks_available--;
|
||||||
KEYCACHE_DBUG_PRINT("unlink_block",
|
KEYCACHE_DBUG_PRINT("unlink_block",
|
||||||
("unlinked block %u status=%x #requests=%u #available=%u",
|
("unlinked block %u status=%x #requests=%u #available=%u",
|
||||||
BLOCK_NUMBER(block), block->status,
|
BLOCK_NUMBER(block), block->status,
|
||||||
block->requests, keycache->blocks_available));
|
block->requests, keycache->blocks_available));
|
||||||
KEYCACHE_DBUG_ASSERT(keycache->blocks_available >= 0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
167
mysys/wqueue.c
Normal file
167
mysys/wqueue.c
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
|
||||||
|
#include <wqueue.h>
|
||||||
|
|
||||||
|
#define STRUCT_PTR(TYPE, MEMBER, a) \
|
||||||
|
(TYPE *) ((char *) (a) - offsetof(TYPE, MEMBER))
|
||||||
|
/*
|
||||||
|
Link a thread into double-linked queue of waiting threads.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
wqueue_link_into_queue()
|
||||||
|
wqueue pointer to the queue structure
|
||||||
|
thread pointer to the thread to be added to the queue
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
none
|
||||||
|
|
||||||
|
NOTES.
|
||||||
|
Queue is represented by a circular list of the thread structures
|
||||||
|
The list is double-linked of the type (**prev,*next), accessed by
|
||||||
|
a pointer to the last element.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void wqueue_link_into_queue(WQUEUE *wqueue, struct st_my_thread_var *thread)
|
||||||
|
{
|
||||||
|
struct st_my_thread_var *last;
|
||||||
|
if (!(last= wqueue->last_thread))
|
||||||
|
{
|
||||||
|
/* Queue is empty */
|
||||||
|
thread->next= thread;
|
||||||
|
thread->prev= &thread->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread->prev= last->next->prev;
|
||||||
|
last->next->prev= &thread->next;
|
||||||
|
thread->next= last->next;
|
||||||
|
last->next= thread;
|
||||||
|
}
|
||||||
|
wqueue->last_thread= thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add a thread to single-linked queue of waiting threads
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
wqueue_add_to_queue()
|
||||||
|
wqueue pointer to the queue structure
|
||||||
|
thread pointer to the thread to be added to the queue
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
none
|
||||||
|
|
||||||
|
NOTES.
|
||||||
|
Queue is represented by a circular list of the thread structures
|
||||||
|
The list is single-linked of the type (*next), accessed by a pointer
|
||||||
|
to the last element.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void wqueue_add_to_queue(WQUEUE *wqueue, struct st_my_thread_var *thread)
|
||||||
|
{
|
||||||
|
struct st_my_thread_var *last;
|
||||||
|
if (!(last= wqueue->last_thread))
|
||||||
|
thread->next= thread;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread->next= last->next;
|
||||||
|
last->next= thread;
|
||||||
|
}
|
||||||
|
wqueue->last_thread= thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Unlink a thread from double-linked queue of waiting threads
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
wqueue_unlink_from_queue()
|
||||||
|
wqueue pointer to the queue structure
|
||||||
|
thread pointer to the thread to be removed from the queue
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
none
|
||||||
|
|
||||||
|
NOTES.
|
||||||
|
See NOTES for link_into_queue
|
||||||
|
*/
|
||||||
|
|
||||||
|
void wqueue_unlink_from_queue(WQUEUE *wqueue, struct st_my_thread_var *thread)
|
||||||
|
{
|
||||||
|
if (thread->next == thread)
|
||||||
|
/* The queue contains only one member */
|
||||||
|
wqueue->last_thread= NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread->next->prev= thread->prev;
|
||||||
|
*thread->prev= thread->next;
|
||||||
|
if (wqueue->last_thread == thread)
|
||||||
|
wqueue->last_thread= STRUCT_PTR(struct st_my_thread_var, next,
|
||||||
|
thread->prev);
|
||||||
|
}
|
||||||
|
thread->next= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove all threads from queue signaling them to proceed
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
wqueue_realease_queue()
|
||||||
|
wqueue pointer to the queue structure
|
||||||
|
thread pointer to the thread to be added to the queue
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
none
|
||||||
|
|
||||||
|
NOTES.
|
||||||
|
See notes for add_to_queue
|
||||||
|
When removed from the queue each thread is signaled via condition
|
||||||
|
variable thread->suspend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void wqueue_release_queue(WQUEUE *wqueue)
|
||||||
|
{
|
||||||
|
struct st_my_thread_var *last= wqueue->last_thread;
|
||||||
|
struct st_my_thread_var *next= last->next;
|
||||||
|
struct st_my_thread_var *thread;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
thread= next;
|
||||||
|
pthread_cond_signal(&thread->suspend);
|
||||||
|
next= thread->next;
|
||||||
|
thread->next= NULL;
|
||||||
|
}
|
||||||
|
while (thread != last);
|
||||||
|
wqueue->last_thread= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add thread and wait
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
wqueue_add_and_wait()
|
||||||
|
wqueue queue to add to
|
||||||
|
thread thread which is waiting
|
||||||
|
lock mutex need for the operation
|
||||||
|
*/
|
||||||
|
|
||||||
|
void wqueue_add_and_wait(WQUEUE *wqueue,
|
||||||
|
struct st_my_thread_var *thread, pthread_mutex_t *lock)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("wqueue_add_and_wait");
|
||||||
|
DBUG_PRINT("enter", ("thread ox%lxcond 0x%lx, mutex 0x%lx",
|
||||||
|
(ulong) thread, (ulong) &thread->suspend, (ulong) lock));
|
||||||
|
wqueue_add_to_queue(wqueue, thread);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info", ("wait... cond 0x%lx, mutex 0x%lx",
|
||||||
|
(ulong) &thread->suspend, (ulong) lock));
|
||||||
|
pthread_cond_wait(&thread->suspend, lock);
|
||||||
|
DBUG_PRINT("info", ("wait done cond 0x%lx, mutex 0x%lx, next 0x%lx",
|
||||||
|
(ulong) &thread->suspend, (ulong) lock,
|
||||||
|
(ulong) thread->next));
|
||||||
|
}
|
||||||
|
while (thread->next);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
@ -110,7 +110,7 @@ libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
|
|||||||
ma_ft_nlq_search.c ft_maria.c ma_sort.c \
|
ma_ft_nlq_search.c ft_maria.c ma_sort.c \
|
||||||
ha_maria.cc trnman.c lockman.c tablockman.c \
|
ha_maria.cc trnman.c lockman.c tablockman.c \
|
||||||
ma_rt_index.c ma_rt_key.c ma_rt_mbr.c ma_rt_split.c \
|
ma_rt_index.c ma_rt_key.c ma_rt_mbr.c ma_rt_split.c \
|
||||||
ma_sp_key.c ma_control_file.c
|
ma_sp_key.c ma_control_file.c ma_loghandler.c
|
||||||
CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA?
|
CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA?
|
||||||
|
|
||||||
SUFFIXES = .sh
|
SUFFIXES = .sh
|
||||||
|
@ -17,28 +17,10 @@
|
|||||||
/*
|
/*
|
||||||
WL#3234 Maria control file
|
WL#3234 Maria control file
|
||||||
First version written by Guilhem Bichot on 2006-04-27.
|
First version written by Guilhem Bichot on 2006-04-27.
|
||||||
Does not compile yet.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _control_file_h
|
#ifndef _ma_control_file_h
|
||||||
#define _control_file_h
|
#define _ma_control_file_h
|
||||||
|
|
||||||
/*
|
|
||||||
Not everybody needs to call the control file that's why control_file.h is
|
|
||||||
not in maria_def.h. However, policy or habit may want to change this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef REMOVE_WHEN_SANJA_PUSHES_LOG_HANDLER
|
|
||||||
/*
|
|
||||||
this is to get the control file to compile, until Sanja pushes the log
|
|
||||||
handler which will supersede those definitions.
|
|
||||||
*/
|
|
||||||
typedef struct st_lsn {
|
|
||||||
uint32 file_no;
|
|
||||||
uint32 rec_offset;
|
|
||||||
} LSN;
|
|
||||||
#define maria_data_root "."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CONTROL_FILE_BASE_NAME "maria_control"
|
#define CONTROL_FILE_BASE_NAME "maria_control"
|
||||||
/*
|
/*
|
||||||
|
5417
storage/maria/ma_loghandler.c
Normal file
5417
storage/maria/ma_loghandler.c
Normal file
File diff suppressed because it is too large
Load Diff
314
storage/maria/ma_loghandler.h
Normal file
314
storage/maria/ma_loghandler.h
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
|
||||||
|
#ifndef _ma_loghandler_h
|
||||||
|
#define _ma_loghandler_h
|
||||||
|
|
||||||
|
/* Transaction log flags */
|
||||||
|
#define TRANSLOG_PAGE_CRC 1
|
||||||
|
#define TRANSLOG_SECTOR_PROTECTION (1<<1)
|
||||||
|
#define TRANSLOG_RECORD_CRC (1<<2)
|
||||||
|
|
||||||
|
/* page size in transaction log */
|
||||||
|
#define TRANSLOG_PAGE_SIZE (8*1024)
|
||||||
|
|
||||||
|
#include "ma_loghandler_lsn.h"
|
||||||
|
|
||||||
|
/* short transaction ID type */
|
||||||
|
typedef uint16 SHORT_TRANSACTION_ID;
|
||||||
|
|
||||||
|
/* types of records in the transaction log */
|
||||||
|
enum translog_record_type
|
||||||
|
{
|
||||||
|
LOGREC_RESERVED_FOR_CHUNKS23= 0,
|
||||||
|
LOGREC_REDO_INSERT_ROW_HEAD= 1,
|
||||||
|
LOGREC_REDO_INSERT_ROW_TAIL= 2,
|
||||||
|
LOGREC_REDO_INSERT_ROW_BLOB= 3,
|
||||||
|
LOGREC_REDO_INSERT_ROW_BLOBS= 4,
|
||||||
|
LOGREC_REDO_PURGE_ROW= 5,
|
||||||
|
eLOGREC_REDO_PURGE_BLOCKS= 6,
|
||||||
|
LOGREC_REDO_DELETE_ROW= 7,
|
||||||
|
LOGREC_REDO_UPDATE_ROW_HEAD= 8,
|
||||||
|
LOGREC_REDO_INDEX= 9,
|
||||||
|
LOGREC_REDO_UNDELETE_ROW= 10,
|
||||||
|
LOGREC_CLR_END= 11,
|
||||||
|
LOGREC_PURGE_END= 12,
|
||||||
|
LOGREC_UNDO_ROW_INSERT= 13,
|
||||||
|
LOGREC_UNDO_ROW_DELETE= 14,
|
||||||
|
LOGREC_UNDO_ROW_UPDATE= 15,
|
||||||
|
LOGREC_UNDO_KEY_INSERT= 16,
|
||||||
|
LOGREC_UNDO_KEY_DELETE= 17,
|
||||||
|
LOGREC_PREPARE= 18,
|
||||||
|
LOGREC_PREPARE_WITH_UNDO_PURGE= 19,
|
||||||
|
LOGREC_COMMIT= 20,
|
||||||
|
LOGREC_COMMIT_WITH_UNDO_PURGE= 21,
|
||||||
|
LOGREC_CHECKPOINT_PAGE= 22,
|
||||||
|
LOGREC_CHECKPOINT_TRAN= 23,
|
||||||
|
LOGREC_CHECKPOINT_TABL= 24,
|
||||||
|
LOGREC_REDO_CREATE_TABLE= 25,
|
||||||
|
LOGREC_REDO_RENAME_TABLE= 26,
|
||||||
|
LOGREC_REDO_DROP_TABLE= 27,
|
||||||
|
LOGREC_REDO_TRUNCATE_TABLE= 28,
|
||||||
|
LOGREC_FILE_ID= 29,
|
||||||
|
LOGREC_LONG_TRANSACTION_ID= 30,
|
||||||
|
LOGREC_RESERVED_FUTURE_EXTENSION= 63
|
||||||
|
};
|
||||||
|
#define LOGREC_NUMBER_OF_TYPES 64
|
||||||
|
|
||||||
|
typedef uint32 translog_size_t;
|
||||||
|
|
||||||
|
#define TRANSLOG_RECORD_HEADER_MAX_SIZE 1024
|
||||||
|
|
||||||
|
typedef struct st_translog_group_descriptor
|
||||||
|
{
|
||||||
|
TRANSLOG_ADDRESS addr;
|
||||||
|
uint8 num;
|
||||||
|
} TRANSLOG_GROUP;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct st_translog_header_buffer
|
||||||
|
{
|
||||||
|
/* LSN of the read record */
|
||||||
|
LSN lsn;
|
||||||
|
/* type of the read record */
|
||||||
|
enum translog_record_type type;
|
||||||
|
/* short transaction ID or 0 if it has no sense for the record */
|
||||||
|
SHORT_TRANSACTION_ID short_trid;
|
||||||
|
/*
|
||||||
|
The Record length in buffer (including read header, but excluding
|
||||||
|
hidden part of record (type, short TrID, length)
|
||||||
|
*/
|
||||||
|
translog_size_t record_length;
|
||||||
|
/*
|
||||||
|
Real compressed LSN(s) size economy (<number of LSN(s)>*7 - <real_size>)
|
||||||
|
*/
|
||||||
|
uint16 compressed_LSN_economy;
|
||||||
|
/*
|
||||||
|
Buffer for write decoded header of the record (depend on the record
|
||||||
|
type)
|
||||||
|
*/
|
||||||
|
uchar header[TRANSLOG_RECORD_HEADER_MAX_SIZE];
|
||||||
|
/* non read body data offset on the page */
|
||||||
|
uint16 non_header_data_start_offset;
|
||||||
|
/* non read body data length in this first chunk */
|
||||||
|
uint16 non_header_data_len;
|
||||||
|
/* number of groups listed in */
|
||||||
|
uint groups_no;
|
||||||
|
/* array of groups descriptors, can be used only if groups_no > 0 */
|
||||||
|
TRANSLOG_GROUP *groups;
|
||||||
|
/* in multi-group number of chunk0 pages (valid only if groups_no > 0) */
|
||||||
|
uint chunk0_pages;
|
||||||
|
/* chunk 0 data address (valid only if groups_no > 0) */
|
||||||
|
TRANSLOG_ADDRESS chunk0_data_addr;
|
||||||
|
/* chunk 0 data size (valid only if groups_no > 0) */
|
||||||
|
uint16 chunk0_data_len;
|
||||||
|
} TRANSLOG_HEADER_BUFFER;
|
||||||
|
|
||||||
|
|
||||||
|
struct st_translog_scanner_data
|
||||||
|
{
|
||||||
|
uchar buffer[TRANSLOG_PAGE_SIZE]; /* buffer for page content */
|
||||||
|
TRANSLOG_ADDRESS page_addr; /* current page address */
|
||||||
|
TRANSLOG_ADDRESS horizon; /* end of the log which we saw
|
||||||
|
last time */
|
||||||
|
TRANSLOG_ADDRESS last_file_page; /* Last page on in this file */
|
||||||
|
uchar *page; /* page content pointer */
|
||||||
|
translog_size_t page_offset; /* offset of the chunk in the
|
||||||
|
page */
|
||||||
|
my_bool fixed_horizon; /* set horizon only once at
|
||||||
|
init */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct st_translog_reader_data
|
||||||
|
{
|
||||||
|
TRANSLOG_HEADER_BUFFER header; /* Header */
|
||||||
|
struct st_translog_scanner_data scanner; /* chunks scanner */
|
||||||
|
translog_size_t body_offset; /* current chunk body offset */
|
||||||
|
translog_size_t current_offset; /* data offset from the record
|
||||||
|
beginning */
|
||||||
|
uint16 read_header; /* number of bytes read in
|
||||||
|
header */
|
||||||
|
uint16 chunk_size; /* current chunk size */
|
||||||
|
uint current_group; /* current group */
|
||||||
|
uint current_chunk; /* current chunk in the group */
|
||||||
|
my_bool eor; /* end of the record */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initialize transaction log
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
translog_init()
|
||||||
|
directory Directory where log files are put
|
||||||
|
log_file_max_size max size of one log size (for new logs creation)
|
||||||
|
server_version version of MySQL servger (MYSQL_VERSION_ID)
|
||||||
|
server_id server ID (replication & Co)
|
||||||
|
pagecache Page cache for the log reads
|
||||||
|
flags flags (TRANSLOG_PAGE_CRC, TRANSLOG_SECTOR_PROTECTION
|
||||||
|
TRANSLOG_RECORD_CRC)
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
1 - Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool translog_init(const char *directory, uint32 log_file_max_size,
|
||||||
|
uint32 server_version,
|
||||||
|
uint32 server_id, PAGECACHE *pagecache, uint flags);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Write the log record
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
translog_write_record()
|
||||||
|
lsn LSN of the record will be writen here
|
||||||
|
type the log record type
|
||||||
|
short_trid Sort transaction ID or 0 if it has no sense
|
||||||
|
tcb Transaction control block pointer for hooks by
|
||||||
|
record log type
|
||||||
|
partN_length length of Ns part of the log
|
||||||
|
partN_buffer pointer on Ns part buffer
|
||||||
|
0 sign of the end of parts
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
1 - Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool translog_write_record(LSN *lsn,
|
||||||
|
enum translog_record_type type,
|
||||||
|
SHORT_TRANSACTION_ID short_trid,
|
||||||
|
void *tcb,
|
||||||
|
translog_size_t part1_length,
|
||||||
|
uchar *part1_buff, ...);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Free log handler resources
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
translog_destroy()
|
||||||
|
*/
|
||||||
|
|
||||||
|
void translog_destroy();
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read record header and some fixed part of a record (the part depend on
|
||||||
|
record type).
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
translog_read_record_header()
|
||||||
|
lsn log record serial number (address of the record)
|
||||||
|
buff log record header buffer
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
- lsn can point to TRANSLOG_HEADER_BUFFER::lsn and it will be processed
|
||||||
|
correctly.
|
||||||
|
- Some type of record can be read completely by this call
|
||||||
|
- "Decoded" header stored in TRANSLOG_HEADER_BUFFER::header (relative
|
||||||
|
LSN can be translated to absolute one), some fields can be added
|
||||||
|
(like actual header length in the record if the header has variable
|
||||||
|
length)
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - error
|
||||||
|
number of bytes in TRANSLOG_HEADER_BUFFER::header where stored decoded
|
||||||
|
part of the header
|
||||||
|
*/
|
||||||
|
|
||||||
|
translog_size_t translog_read_record_header(LSN *lsn,
|
||||||
|
TRANSLOG_HEADER_BUFFER *buff);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Free resources used by TRANSLOG_HEADER_BUFFER
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
translog_free_record_header();
|
||||||
|
*/
|
||||||
|
|
||||||
|
void translog_free_record_header(TRANSLOG_HEADER_BUFFER *buff);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read a part of the record.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
translog_read_record_header()
|
||||||
|
lsn log record serial number (address of the record)
|
||||||
|
offset from the beginning of the record beginning (read
|
||||||
|
by translog_read_record_header).
|
||||||
|
length length of record part which have to be read.
|
||||||
|
buffer buffer where to read the record part (have to be at
|
||||||
|
least 'length' bytes length)
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - error (or read out of the record)
|
||||||
|
length of data actually read
|
||||||
|
*/
|
||||||
|
|
||||||
|
translog_size_t translog_read_record(LSN *lsn,
|
||||||
|
translog_size_t offset,
|
||||||
|
translog_size_t length,
|
||||||
|
uchar *buffer,
|
||||||
|
struct st_translog_reader_data *data);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Flush the log up to given LSN (included)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
translog_flush()
|
||||||
|
lsn log record serial number up to which (inclusive)
|
||||||
|
the log have to be flushed
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
1 - Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool translog_flush(LSN *lsn);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read record header and some fixed part of the next record (the part
|
||||||
|
depend on record type).
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
translog_read_next_record_header()
|
||||||
|
lsn log record serial number (address of the record)
|
||||||
|
previous to the record which will be read
|
||||||
|
If LSN present scanner will be initialized from it,
|
||||||
|
do not use LSN after initialization for fast scanning.
|
||||||
|
buff log record header buffer
|
||||||
|
fixed_horizon true if it is OK do not read records which was written
|
||||||
|
after scaning begining
|
||||||
|
scanner data for scaning if lsn is NULL scanner data
|
||||||
|
will be used for continue scaning.
|
||||||
|
scanner can be NULL.
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
- lsn can point to TRANSLOG_HEADER_BUFFER::lsn and it will be processed
|
||||||
|
correctly (lsn in buffer will be replaced by next record, but initial
|
||||||
|
lsn will be read correctly).
|
||||||
|
- it is like translog_read_record_header, but read next record, so see
|
||||||
|
its NOTES.
|
||||||
|
- in case of end of the log buff->lsn will be set to
|
||||||
|
(CONTROL_FILE_IMPOSSIBLE_LOGNO, 0)
|
||||||
|
RETURN
|
||||||
|
0 - error
|
||||||
|
TRANSLOG_RECORD_HEADER_MAX_SIZE + 1 - End of the log
|
||||||
|
number of bytes in TRANSLOG_HEADER_BUFFER::header where stored decoded
|
||||||
|
part of the header
|
||||||
|
*/
|
||||||
|
|
||||||
|
translog_size_t translog_read_next_record_header(LSN *lsn,
|
||||||
|
TRANSLOG_HEADER_BUFFER *buff,
|
||||||
|
my_bool fixed_horizon,
|
||||||
|
struct
|
||||||
|
st_translog_scanner_data
|
||||||
|
*scanner);
|
||||||
|
|
||||||
|
#endif
|
39
storage/maria/ma_loghandler_lsn.h
Normal file
39
storage/maria/ma_loghandler_lsn.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef _ma_loghandler_lsn_h
|
||||||
|
#define _ma_loghandler_lsn_h
|
||||||
|
|
||||||
|
/* Transaction log record address (file_no is int24 on the disk) */
|
||||||
|
typedef struct st_translog_address
|
||||||
|
{
|
||||||
|
uint32 file_no;
|
||||||
|
uint32 rec_offset;
|
||||||
|
} TRANSLOG_ADDRESS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compare addresses
|
||||||
|
A1 > A2 -> result > 0
|
||||||
|
A1 == A2 -> 0
|
||||||
|
A1 < A2 -> result < 0
|
||||||
|
*/
|
||||||
|
#define cmp_translog_addr(A1,A2) \
|
||||||
|
((A1).file_no == (A2).file_no ? \
|
||||||
|
((int64)(A1).rec_offset) - (int64)(A2).rec_offset : \
|
||||||
|
((int64)(A1).file_no - (int64)(A2).file_no))
|
||||||
|
|
||||||
|
/* LSN type (address of certain log record chank */
|
||||||
|
typedef TRANSLOG_ADDRESS LSN;
|
||||||
|
|
||||||
|
/* Puts LSN into buffer (dst) */
|
||||||
|
#define lsn7store(dst, lsn) \
|
||||||
|
do { \
|
||||||
|
int3store((dst), (lsn)->file_no); \
|
||||||
|
int4store((dst) + 3, (lsn)->rec_offset); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Unpacks LSN from the buffer (P) */
|
||||||
|
#define lsn7korr(lsn, P) \
|
||||||
|
do { \
|
||||||
|
(lsn)->file_no= uint3korr(P); \
|
||||||
|
(lsn)->rec_offset= uint4korr((P) + 3); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif
|
@ -26,6 +26,10 @@
|
|||||||
#include <my_no_pthread.h>
|
#include <my_no_pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <pagecache.h>
|
||||||
|
#include "ma_loghandler.h"
|
||||||
|
#include "ma_control_file.h"
|
||||||
|
|
||||||
/* undef map from my_nosys; We need test-if-disk full */
|
/* undef map from my_nosys; We need test-if-disk full */
|
||||||
#undef my_write
|
#undef my_write
|
||||||
|
|
||||||
@ -438,6 +442,7 @@ extern LIST *maria_open_list;
|
|||||||
extern uchar NEAR maria_file_magic[], NEAR maria_pack_file_magic[];
|
extern uchar NEAR maria_file_magic[], NEAR maria_pack_file_magic[];
|
||||||
extern uint NEAR maria_read_vec[], NEAR maria_readnext_vec[];
|
extern uint NEAR maria_read_vec[], NEAR maria_readnext_vec[];
|
||||||
extern uint maria_quick_table_bits;
|
extern uint maria_quick_table_bits;
|
||||||
|
extern const char *maria_data_root;
|
||||||
extern my_bool maria_inited;
|
extern my_bool maria_inited;
|
||||||
|
|
||||||
/* This is used by _ma_calc_xxx_key_length och _ma_store_key */
|
/* This is used by _ma_calc_xxx_key_length och _ma_store_key */
|
||||||
|
@ -14,8 +14,10 @@
|
|||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
AM_CPPFLAGS = @ZLIB_INCLUDES@ -I$(top_builddir)/include
|
AM_CPPFLAGS = @ZLIB_INCLUDES@ -I$(top_builddir)/include \
|
||||||
AM_CPPFLAGS += -I$(top_srcdir)/include -I$(top_srcdir)/unittest/mytap
|
-I$(top_srcdir)/include -I$(top_srcdir)/unittest/mytap
|
||||||
|
INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \
|
||||||
|
-I$(top_srcdir)/include -I$(top_srcdir)/unittest/mytap
|
||||||
|
|
||||||
# Only reason to link with libmyisam.a here is that it's where some fulltext
|
# Only reason to link with libmyisam.a here is that it's where some fulltext
|
||||||
# pieces are (but soon we'll remove fulltext dependencies from Maria).
|
# pieces are (but soon we'll remove fulltext dependencies from Maria).
|
||||||
@ -24,6 +26,54 @@ LDADD= $(top_builddir)/unittest/mytap/libmytap.a \
|
|||||||
$(top_builddir)/storage/myisam/libmyisam.a \
|
$(top_builddir)/storage/myisam/libmyisam.a \
|
||||||
$(top_builddir)/mysys/libmysys.a \
|
$(top_builddir)/mysys/libmysys.a \
|
||||||
$(top_builddir)/dbug/libdbug.a \
|
$(top_builddir)/dbug/libdbug.a \
|
||||||
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
|
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@ \
|
||||||
noinst_PROGRAMS = ma_control_file-t trnman-t lockman-t lockman1-t lockman2-t
|
$(top_builddir)/storage/maria/ma_loghandler.o
|
||||||
CLEANFILES = maria_control
|
noinst_PROGRAMS = ma_control_file-t trnman-t lockman-t lockman1-t \
|
||||||
|
lockman2-t \
|
||||||
|
mf_pagecache_single_1k-t mf_pagecache_single_8k-t \
|
||||||
|
mf_pagecache_single_64k-t \
|
||||||
|
mf_pagecache_consist_1k-t mf_pagecache_consist_64k-t \
|
||||||
|
mf_pagecache_consist_1kHC-t \
|
||||||
|
mf_pagecache_consist_64kHC-t \
|
||||||
|
mf_pagecache_consist_1kRD-t \
|
||||||
|
mf_pagecache_consist_64kRD-t \
|
||||||
|
mf_pagecache_consist_1kWR-t \
|
||||||
|
mf_pagecache_consist_64kWR-t \
|
||||||
|
ma_test_loghandler-t \
|
||||||
|
ma_test_loghandler_multigroup-t \
|
||||||
|
ma_test_loghandler_multithread-t \
|
||||||
|
ma_test_loghandler_pagecache-t
|
||||||
|
|
||||||
|
mf_pagecache_single_src = mf_pagecache_single.c $(top_srcdir)/mysys/mf_pagecache.c test_file.c
|
||||||
|
mf_pagecache_consist_src = mf_pagecache_consist.c $(top_srcdir)/mysys/mf_pagecache.c test_file.c
|
||||||
|
mf_pagecache_common_cppflags = -DEXTRA_DEBUG -DPAGECACHE_DEBUG -DMAIN
|
||||||
|
|
||||||
|
mf_pagecache_single_1k_t_SOURCES = $(mf_pagecache_single_src)
|
||||||
|
mf_pagecache_single_8k_t_SOURCES = $(mf_pagecache_single_src)
|
||||||
|
mf_pagecache_single_64k_t_SOURCES = $(mf_pagecache_single_src)
|
||||||
|
mf_pagecache_single_1k_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024
|
||||||
|
mf_pagecache_single_8k_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=8192
|
||||||
|
mf_pagecache_single_64k_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536
|
||||||
|
|
||||||
|
mf_pagecache_consist_1k_t_SOURCES = $(mf_pagecache_consist_src)
|
||||||
|
mf_pagecache_consist_1k_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024
|
||||||
|
mf_pagecache_consist_64k_t_SOURCES = $(mf_pagecache_consist_src)
|
||||||
|
mf_pagecache_consist_64k_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536
|
||||||
|
|
||||||
|
mf_pagecache_consist_1kHC_t_SOURCES = $(mf_pagecache_consist_src)
|
||||||
|
mf_pagecache_consist_1kHC_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 -DTEST_HIGH_CONCURENCY
|
||||||
|
mf_pagecache_consist_64kHC_t_SOURCES = $(mf_pagecache_consist_src)
|
||||||
|
mf_pagecache_consist_64kHC_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 -DTEST_HIGH_CONCURENCY
|
||||||
|
|
||||||
|
mf_pagecache_consist_1kRD_t_SOURCES = $(mf_pagecache_consist_src)
|
||||||
|
mf_pagecache_consist_1kRD_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 -DTEST_READERS
|
||||||
|
mf_pagecache_consist_64kRD_t_SOURCES = $(mf_pagecache_consist_src)
|
||||||
|
mf_pagecache_consist_64kRD_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 -DTEST_READERS
|
||||||
|
|
||||||
|
mf_pagecache_consist_1kWR_t_SOURCES = $(mf_pagecache_consist_src)
|
||||||
|
mf_pagecache_consist_1kWR_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 -DTEST_WRITERS
|
||||||
|
mf_pagecache_consist_64kWR_t_SOURCES = $(mf_pagecache_consist_src)
|
||||||
|
mf_pagecache_consist_64kWR_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 -DTEST_WRITERS
|
||||||
|
|
||||||
|
CLEANFILES = maria_control page_cache_test_file_1 \
|
||||||
|
maria_log.???????? maria_control
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "maria.h"
|
#include "maria.h"
|
||||||
#include "../../../storage/maria/ma_control_file.h"
|
#include "../../../storage/maria/maria_def.h"
|
||||||
#include <my_getopt.h>
|
#include <my_getopt.h>
|
||||||
|
|
||||||
char file_name[FN_REFLEN];
|
char file_name[FN_REFLEN];
|
||||||
|
540
storage/maria/unittest/ma_test_loghandler-t.c
Normal file
540
storage/maria/unittest/ma_test_loghandler-t.c
Normal file
@ -0,0 +1,540 @@
|
|||||||
|
#include "../maria_def.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
static const char *default_dbug_option;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PCACHE_SIZE (1024*1024*10)
|
||||||
|
|
||||||
|
#define LONG_BUFFER_SIZE (100 * 1024)
|
||||||
|
|
||||||
|
|
||||||
|
#define LOG_FLAGS TRANSLOG_SECTOR_PROTECTION | TRANSLOG_PAGE_CRC
|
||||||
|
#define LOG_FILE_SIZE 1024L*1024L*3L
|
||||||
|
#define ITERATIONS 1600
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define LOG_FLAGS 0
|
||||||
|
#define LOG_FILE_SIZE 1024L*1024L*1024L
|
||||||
|
#define ITERATIONS 181000
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define LOG_FLAGS 0
|
||||||
|
#define LOG_FILE_SIZE 1024L*1024L*3L
|
||||||
|
#define ITERATIONS 1600
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define LOG_FLAGS 0
|
||||||
|
#define LOG_FILE_SIZE 1024L*1024L*100L
|
||||||
|
#define ITERATIONS 65000
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check that the buffer filled correctly
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
check_content()
|
||||||
|
ptr Pointer to the buffer
|
||||||
|
length length of the buffer
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
1 - Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
static my_bool check_content(uchar *ptr, ulong length)
|
||||||
|
{
|
||||||
|
ulong i;
|
||||||
|
uchar buff[2];
|
||||||
|
for (i= 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if (i % 2 == 0)
|
||||||
|
int2store(buff, i >> 1);
|
||||||
|
if (ptr[i] != buff[i % 2])
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Byte # %lu is %x instead of %x",
|
||||||
|
i, (uint) ptr[i], (uint) buff[i % 2]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read whole record content, and check content (put with offset)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
read_and_check_content()
|
||||||
|
rec The record header buffer
|
||||||
|
buffer The buffer to read the record in
|
||||||
|
skip Skip this number of bytes ot the record content
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
1 - Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
static my_bool read_and_check_content(TRANSLOG_HEADER_BUFFER *rec,
|
||||||
|
uchar *buffer, uint skip)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(rec->record_length < LONG_BUFFER_SIZE * 2 + 7 * 2 + 2);
|
||||||
|
if (translog_read_record(&rec->lsn, 0, rec->record_length, buffer, NULL) !=
|
||||||
|
rec->record_length)
|
||||||
|
return 1;
|
||||||
|
return check_content(buffer + skip, rec->record_length - skip);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
uint32 rec_len;
|
||||||
|
uint pagen;
|
||||||
|
uchar long_tr_id[6];
|
||||||
|
uchar lsn_buff[23]=
|
||||||
|
{
|
||||||
|
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
|
||||||
|
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
|
||||||
|
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55
|
||||||
|
};
|
||||||
|
uchar long_buffer[LONG_BUFFER_SIZE * 2 + 7 * 2 + 2];
|
||||||
|
PAGECACHE pagecache;
|
||||||
|
LSN lsn, lsn_base, first_lsn, *lsn_ptr;
|
||||||
|
TRANSLOG_HEADER_BUFFER rec;
|
||||||
|
struct st_translog_scanner_data scanner;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
MY_INIT(argv[0]);
|
||||||
|
|
||||||
|
bzero(&pagecache, sizeof(pagecache));
|
||||||
|
maria_data_root= ".";
|
||||||
|
|
||||||
|
for (i= 0; i < (LONG_BUFFER_SIZE + 7 * 2 + 2); i+= 2)
|
||||||
|
{
|
||||||
|
int2store(long_buffer + i, (i >> 1));
|
||||||
|
/* long_buffer[i]= (i & 0xFF); */
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(long_tr_id, 6);
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
#if defined(__WIN__)
|
||||||
|
default_dbug_option= "d:t:i:O,\\ma_test_loghandler.trace";
|
||||||
|
#else
|
||||||
|
default_dbug_option= "d:t:i:o,/tmp/ma_test_loghandler.trace";
|
||||||
|
#endif
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
DBUG_SET(default_dbug_option);
|
||||||
|
DBUG_SET_INITIAL(default_dbug_option);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ma_control_file_create_or_open())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
|
||||||
|
TRANSLOG_PAGE_SIZE)) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (translog_init(".", LOG_FILE_SIZE, 50112, 0, &pagecache, LOG_FLAGS))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't init loghandler (%d)\n", errno);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
srandom(122334817L);
|
||||||
|
|
||||||
|
long_tr_id[5]= 0xff;
|
||||||
|
|
||||||
|
int4store(long_tr_id, 0);
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_LONG_TRANSACTION_ID,
|
||||||
|
0, NULL, 6, long_tr_id, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write record #%lu\n", (ulong) 0);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
lsn_base= first_lsn= lsn;
|
||||||
|
|
||||||
|
for (i= 1; i < ITERATIONS; i++)
|
||||||
|
{
|
||||||
|
if (i % 1000 == 0)
|
||||||
|
printf("write %d\n", i);
|
||||||
|
if (i % 2)
|
||||||
|
{
|
||||||
|
lsn7store(lsn_buff, &lsn_base);
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_CLR_END,
|
||||||
|
(i % 0xFFFF), NULL, 7, lsn_buff, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1 Can't write reference defore record #%lu\n",
|
||||||
|
(ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
lsn7store(lsn_buff, &lsn_base);
|
||||||
|
if ((rec_len= random() / (RAND_MAX / (LONG_BUFFER_SIZE + 1))) < 12)
|
||||||
|
rec_len= 12;
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_UNDO_KEY_INSERT,
|
||||||
|
(i % 0xFFFF),
|
||||||
|
NULL, 7, lsn_buff, rec_len, long_buffer, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1 Can't write var reference defore record #%lu\n",
|
||||||
|
(ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lsn7store(lsn_buff, &lsn_base);
|
||||||
|
lsn7store(lsn_buff + 7, &first_lsn);
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_UNDO_ROW_DELETE,
|
||||||
|
(i % 0xFFFF), NULL, 23, lsn_buff, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "0 Can't write reference defore record #%lu\n",
|
||||||
|
(ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
lsn7store(lsn_buff, &lsn_base);
|
||||||
|
lsn7store(lsn_buff + 7, &first_lsn);
|
||||||
|
if ((rec_len= random() / (RAND_MAX / (LONG_BUFFER_SIZE + 1))) < 19)
|
||||||
|
rec_len= 19;
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_UNDO_KEY_DELETE,
|
||||||
|
(i % 0xFFFF),
|
||||||
|
NULL, 14, lsn_buff, rec_len, long_buffer, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "0 Can't write var reference defore record #%lu\n",
|
||||||
|
(ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int4store(long_tr_id, i);
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_LONG_TRANSACTION_ID,
|
||||||
|
(i % 0xFFFF), NULL, 6, long_tr_id, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write record #%lu\n", (ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
lsn_base= lsn;
|
||||||
|
|
||||||
|
if ((rec_len= random() / (RAND_MAX / (LONG_BUFFER_SIZE + 1))) < 9)
|
||||||
|
rec_len= 9;
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_REDO_INSERT_ROW_HEAD,
|
||||||
|
(i % 0xFFFF), NULL, rec_len, long_buffer, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write variable record #%lu\n", (ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (translog_flush(&lsn))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't flush #%lu\n", (ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
translog_destroy();
|
||||||
|
end_pagecache(&pagecache, 1);
|
||||||
|
ma_control_file_end();
|
||||||
|
|
||||||
|
|
||||||
|
if (ma_control_file_create_or_open())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "pass2: Can't init control file (%d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
|
||||||
|
TRANSLOG_PAGE_SIZE)) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "pass2: Got error: init_pagecache() (errno: %d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (translog_init(".", LOG_FILE_SIZE, 50112, 0, &pagecache, LOG_FLAGS))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "pass2: Can't init loghandler (%d)\n", errno);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
srandom(122334817L);
|
||||||
|
|
||||||
|
|
||||||
|
rc= 1;
|
||||||
|
|
||||||
|
{
|
||||||
|
translog_size_t len= translog_read_record_header(&first_lsn, &rec);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "translog_read_record_header failed (%d)\n", errno);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.type !=LOGREC_LONG_TRANSACTION_ID || rec.short_trid != 0 ||
|
||||||
|
rec.record_length != 6 || uint4korr(rec.header) != 0 ||
|
||||||
|
(uint)rec.header[4] != 0 || rec.header[5] != 0xFF ||
|
||||||
|
first_lsn.file_no != rec.lsn.file_no ||
|
||||||
|
first_lsn.rec_offset != rec.lsn.rec_offset)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_LONG_TRANSACTION_ID data read(0)\n"
|
||||||
|
"type %u, strid %u, len %u, i: %u, 4: %u 5: %u, "
|
||||||
|
"lsn(0x%lx,0x%lx)\n",
|
||||||
|
(uint) rec.type, (uint) rec.short_trid, (uint) rec.record_length,
|
||||||
|
uint4korr(rec.header), (uint) rec.header[4], (uint) rec.header[5],
|
||||||
|
(ulong) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
lsn= first_lsn;
|
||||||
|
lsn_ptr= &first_lsn;
|
||||||
|
for (i= 1;; i++)
|
||||||
|
{
|
||||||
|
if (i % 1000 == 0)
|
||||||
|
printf("read %d\n", i);
|
||||||
|
len= translog_read_next_record_header(lsn_ptr, &rec, 1, &scanner);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1-%d translog_read_next_record_header failed (%d)\n",
|
||||||
|
i, errno);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO)
|
||||||
|
{
|
||||||
|
if (i != ITERATIONS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EOL met at iteration %u instead of %u\n",
|
||||||
|
i, ITERATIONS);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lsn_ptr= NULL; /* use scanner after its
|
||||||
|
initialization */
|
||||||
|
if (i % 2)
|
||||||
|
{
|
||||||
|
LSN ref;
|
||||||
|
lsn7korr(&ref, rec.header);
|
||||||
|
if (rec.type !=LOGREC_CLR_END || rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != 7 || ref.file_no != lsn.file_no ||
|
||||||
|
ref.rec_offset != lsn.rec_offset)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_CLR_END data read(%d)"
|
||||||
|
"type %u, strid %u, len %u, ref(%u,0x%lx), lsn(%u,0x%lx)\n",
|
||||||
|
i, (uint) rec.type, (uint) rec.short_trid,
|
||||||
|
(uint) rec.record_length,
|
||||||
|
(uint) ref.file_no, (ulong) ref.rec_offset,
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LSN ref1, ref2;
|
||||||
|
lsn7korr(&ref1, rec.header);
|
||||||
|
lsn7korr(&ref2, rec.header + 7);
|
||||||
|
if (rec.type !=LOGREC_UNDO_ROW_DELETE ||
|
||||||
|
rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != 23 ||
|
||||||
|
ref1.file_no != lsn.file_no ||
|
||||||
|
ref1.rec_offset != lsn.rec_offset ||
|
||||||
|
ref2.file_no != first_lsn.file_no ||
|
||||||
|
ref2.rec_offset != first_lsn.rec_offset ||
|
||||||
|
rec.header[22] != 0x55 || rec.header[21] != 0xAA ||
|
||||||
|
rec.header[20] != 0x55 || rec.header[19] != 0xAA ||
|
||||||
|
rec.header[18] != 0x55 || rec.header[17] != 0xAA ||
|
||||||
|
rec.header[16] != 0x55 || rec.header[15] != 0xAA ||
|
||||||
|
rec.header[14] != 0x55)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_UNDO_ROW_DELETE data read(%d)"
|
||||||
|
"type %u, strid %u, len %u, ref1(%u,0x%lx), "
|
||||||
|
"ref2(%u,0x%lx) %x%x%x%x%x%x%x%x%x "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
i, (uint) rec.type, (uint) rec.short_trid,
|
||||||
|
(uint) rec.record_length,
|
||||||
|
(uint) ref1.file_no, (ulong) ref1.rec_offset,
|
||||||
|
(uint) ref2.file_no, (ulong) ref2.rec_offset,
|
||||||
|
(uint) rec.header[14], (uint) rec.header[15],
|
||||||
|
(uint) rec.header[16], (uint) rec.header[17],
|
||||||
|
(uint) rec.header[18], (uint) rec.header[19],
|
||||||
|
(uint) rec.header[20], (uint) rec.header[21],
|
||||||
|
(uint) rec.header[22],
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len= translog_read_next_record_header(lsn_ptr, &rec, 1, &scanner);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1-%d translog_read_next_record_header (var) "
|
||||||
|
"failed (%d)\n", i, errno);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EOL met at the middle of iteration (first var) %u "
|
||||||
|
"instead of beginning of %u\n", i, ITERATIONS);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (i % 2)
|
||||||
|
{
|
||||||
|
LSN ref;
|
||||||
|
lsn7korr(&ref, rec.header);
|
||||||
|
if ((rec_len= random() / (RAND_MAX / (LONG_BUFFER_SIZE + 1))) < 12)
|
||||||
|
rec_len= 12;
|
||||||
|
if (rec.type !=LOGREC_UNDO_KEY_INSERT ||
|
||||||
|
rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != rec_len + 7 ||
|
||||||
|
len != 12 || ref.file_no != lsn.file_no ||
|
||||||
|
ref.rec_offset != lsn.rec_offset ||
|
||||||
|
check_content(rec.header + 7, len - 7))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_UNDO_KEY_INSERT data read(%d)"
|
||||||
|
"type %u (%d), strid %u (%d), len %lu, %lu + 7 (%d), "
|
||||||
|
"hdr len: %u (%d), "
|
||||||
|
"ref(%u,0x%lx), lsn(%u,0x%lx) (%d), content: %d\n",
|
||||||
|
i, (uint) rec.type,
|
||||||
|
rec.type !=LOGREC_UNDO_KEY_INSERT,
|
||||||
|
(uint) rec.short_trid,
|
||||||
|
rec.short_trid != (i % 0xFFFF),
|
||||||
|
(ulong) rec.record_length, (ulong) rec_len,
|
||||||
|
rec.record_length != rec_len + 7,
|
||||||
|
(uint) len,
|
||||||
|
len != 12,
|
||||||
|
(uint) ref.file_no, (ulong) ref.rec_offset,
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset,
|
||||||
|
(len != 12 || ref.file_no != lsn.file_no ||
|
||||||
|
ref.rec_offset != lsn.rec_offset),
|
||||||
|
check_content(rec.header + 7, len - 7));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (read_and_check_content(&rec, long_buffer, 7))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Incorrect LOGREC_UNDO_KEY_INSERT in whole rec read "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LSN ref1, ref2;
|
||||||
|
lsn7korr(&ref1, rec.header);
|
||||||
|
lsn7korr(&ref2, rec.header + 7);
|
||||||
|
if ((rec_len= random() / (RAND_MAX / (LONG_BUFFER_SIZE + 1))) < 19)
|
||||||
|
rec_len= 19;
|
||||||
|
if (rec.type !=LOGREC_UNDO_KEY_DELETE ||
|
||||||
|
rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != rec_len + 14 ||
|
||||||
|
len != 19 ||
|
||||||
|
ref1.file_no != lsn.file_no ||
|
||||||
|
ref1.rec_offset != lsn.rec_offset ||
|
||||||
|
ref2.file_no != first_lsn.file_no ||
|
||||||
|
ref2.rec_offset != first_lsn.rec_offset ||
|
||||||
|
check_content(rec.header + 14, len - 14))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_UNDO_KEY_DELETE data read(%d)"
|
||||||
|
"type %u, strid %u, len %lu != %lu + 7, hdr len: %u, "
|
||||||
|
"ref1(%u,0x%lx), ref2(%u,0x%lx), "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
i, (uint) rec.type, (uint) rec.short_trid,
|
||||||
|
(ulong) rec.record_length, (ulong) rec_len,
|
||||||
|
(uint) len,
|
||||||
|
(uint) ref1.file_no, (ulong) ref1.rec_offset,
|
||||||
|
(uint) ref2.file_no, (ulong) ref2.rec_offset,
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (read_and_check_content(&rec, long_buffer, 14))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Incorrect LOGREC_UNDO_KEY_DELETE in whole rec read "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
len= translog_read_next_record_header(lsn_ptr, &rec, 1, &scanner);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1-%d translog_read_next_record_header failed (%d)\n",
|
||||||
|
i, errno);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EOL met at the middle of iteration %u "
|
||||||
|
"instead of beginning of %u\n", i, ITERATIONS);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.type !=LOGREC_LONG_TRANSACTION_ID ||
|
||||||
|
rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != 6 || uint4korr(rec.header) != i ||
|
||||||
|
rec.header[4] != 0 || rec.header[5] != 0xFF)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_LONG_TRANSACTION_ID data read(%d)\n"
|
||||||
|
"type %u, strid %u, len %u, i: %u, 4: %u 5: %u "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
i, (uint) rec.type, (uint) rec.short_trid,
|
||||||
|
(uint) rec.record_length,
|
||||||
|
uint4korr(rec.header), (uint) rec.header[4],
|
||||||
|
(uint) rec.header[5],
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
lsn= rec.lsn;
|
||||||
|
|
||||||
|
len= translog_read_next_record_header(lsn_ptr, &rec, 1, &scanner);
|
||||||
|
if ((rec_len= random() / (RAND_MAX / (LONG_BUFFER_SIZE + 1))) < 9)
|
||||||
|
rec_len= 9;
|
||||||
|
if (rec.type !=LOGREC_REDO_INSERT_ROW_HEAD ||
|
||||||
|
rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != rec_len ||
|
||||||
|
len != 9 || check_content(rec.header, len))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_REDO_INSERT_ROW_HEAD data read(%d)"
|
||||||
|
"type %u, strid %u, len %lu != %lu, hdr len: %u, "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
i, (uint) rec.type, (uint) rec.short_trid,
|
||||||
|
(ulong) rec.record_length, (ulong) rec_len,
|
||||||
|
(uint) len, (uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (read_and_check_content(&rec, long_buffer, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Incorrect LOGREC_UNDO_KEY_DELETE in whole rec read "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc= 1;
|
||||||
|
err:
|
||||||
|
translog_destroy();
|
||||||
|
end_pagecache(&pagecache, 1);
|
||||||
|
ma_control_file_end();
|
||||||
|
|
||||||
|
return(test(exit_status() || rc));
|
||||||
|
}
|
570
storage/maria/unittest/ma_test_loghandler_multigroup-t.c
Normal file
570
storage/maria/unittest/ma_test_loghandler_multigroup-t.c
Normal file
@ -0,0 +1,570 @@
|
|||||||
|
#include "../maria_def.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
static const char *default_dbug_option;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PCACHE_SIZE (1024*1024*10)
|
||||||
|
|
||||||
|
#define LONG_BUFFER_SIZE ((1024L*1024L*1024L) + (1024L*1024L*512))
|
||||||
|
|
||||||
|
#define MIN_REC_LENGTH (1024L*1024L + 1024L*512L + 1)
|
||||||
|
|
||||||
|
#define SHOW_DIVIDER 2
|
||||||
|
|
||||||
|
#define LOG_FILE_SIZE (1024L*1024L*1024L + 1024L*1024L*512)
|
||||||
|
#define ITERATIONS 2
|
||||||
|
/*#define ITERATIONS 63 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define LOG_FILE_SIZE 1024L*1024L*3L
|
||||||
|
#define ITERATIONS 1600
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
#define LOG_FILE_SIZE 1024L*1024L*100L
|
||||||
|
#define ITERATIONS 65000
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check that the buffer filled correctly
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
check_content()
|
||||||
|
ptr Pointer to the buffer
|
||||||
|
length length of the buffer
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
1 - Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
static my_bool check_content(uchar *ptr, ulong length)
|
||||||
|
{
|
||||||
|
ulong i;
|
||||||
|
uchar buff[4];
|
||||||
|
DBUG_ENTER("check_content");
|
||||||
|
for (i= 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if (i % 4 == 0)
|
||||||
|
int4store(buff, (i >> 2));
|
||||||
|
if (ptr[i] != buff[i % 4])
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Byte # %lu is %x instead of %x",
|
||||||
|
i, (uint) ptr[i], (uint) buff[i % 4]);
|
||||||
|
DBUG_DUMP("mem", ptr +(ulong) (i > 16 ? i - 16 : 0),
|
||||||
|
(i > 16 ? 16 : i) + (i + 16 < length ? 16 : length - i));
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read whole record content, and check content (put with offset)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
read_and_check_content()
|
||||||
|
rec The record header buffer
|
||||||
|
buffer The buffer to read the record in
|
||||||
|
skip Skip this number of bytes ot the record content
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
1 - Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
static my_bool read_and_check_content(TRANSLOG_HEADER_BUFFER *rec,
|
||||||
|
uchar *buffer, uint skip)
|
||||||
|
{
|
||||||
|
int res= 0;
|
||||||
|
translog_size_t len;
|
||||||
|
DBUG_ENTER("read_and_check_content");
|
||||||
|
DBUG_ASSERT(rec->record_length < LONG_BUFFER_SIZE + 7 * 2 + 2);
|
||||||
|
if ((len= translog_read_record(&rec->lsn, 0, rec->record_length,
|
||||||
|
buffer, NULL)) != rec->record_length)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Requested %lu byte, read %lu\n",
|
||||||
|
(ulong) rec->record_length, (ulong) len);
|
||||||
|
res= 1;
|
||||||
|
}
|
||||||
|
res|= check_content(buffer + skip, rec->record_length - skip);
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32 get_len()
|
||||||
|
{
|
||||||
|
uint32 rec_len;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rec_len= random() /
|
||||||
|
(RAND_MAX / (LONG_BUFFER_SIZE - MIN_REC_LENGTH - 1)) + MIN_REC_LENGTH;
|
||||||
|
} while (rec_len >= LONG_BUFFER_SIZE);
|
||||||
|
return rec_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
uint32 rec_len;
|
||||||
|
uint pagen;
|
||||||
|
uchar long_tr_id[6];
|
||||||
|
uchar lsn_buff[23]=
|
||||||
|
{
|
||||||
|
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
|
||||||
|
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
|
||||||
|
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55
|
||||||
|
};
|
||||||
|
uchar *long_buffer= malloc(LONG_BUFFER_SIZE + 7 * 2 + 2);
|
||||||
|
PAGECACHE pagecache;
|
||||||
|
LSN lsn, lsn_base, first_lsn, *lsn_ptr;
|
||||||
|
TRANSLOG_HEADER_BUFFER rec;
|
||||||
|
struct st_translog_scanner_data scanner;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
MY_INIT(argv[0]);
|
||||||
|
|
||||||
|
bzero(&pagecache, sizeof(pagecache));
|
||||||
|
maria_data_root= ".";
|
||||||
|
|
||||||
|
{
|
||||||
|
uchar buff[4];
|
||||||
|
for (i= 0; i < (LONG_BUFFER_SIZE + 7 * 2 + 2); i++)
|
||||||
|
{
|
||||||
|
if (i % 4 == 0)
|
||||||
|
int4store(buff, (i >> 2));
|
||||||
|
long_buffer[i]= buff[i % 4];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(long_tr_id, 6);
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
#if defined(__WIN__)
|
||||||
|
default_dbug_option= "d:t:i:O,\\ma_test_loghandler.trace";
|
||||||
|
#else
|
||||||
|
default_dbug_option= "d:t:i:o,/tmp/ma_test_loghandler.trace";
|
||||||
|
#endif
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
DBUG_SET(default_dbug_option);
|
||||||
|
DBUG_SET_INITIAL(default_dbug_option);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ma_control_file_create_or_open())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
|
||||||
|
TRANSLOG_PAGE_SIZE)) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (translog_init(".", LOG_FILE_SIZE, 50112, 0, &pagecache, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't init loghandler (%d)\n", errno);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
srandom(122334817L);
|
||||||
|
|
||||||
|
long_tr_id[5]= 0xff;
|
||||||
|
|
||||||
|
int4store(long_tr_id, 0);
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_LONG_TRANSACTION_ID,
|
||||||
|
0, NULL, 6, long_tr_id, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write record #%lu\n", (ulong) 0);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
lsn_base= first_lsn= lsn;
|
||||||
|
|
||||||
|
for (i= 1; i < ITERATIONS; i++)
|
||||||
|
{
|
||||||
|
if (i % SHOW_DIVIDER == 0)
|
||||||
|
printf("write %d\n", i);
|
||||||
|
if (i % 2)
|
||||||
|
{
|
||||||
|
lsn7store(lsn_buff, &lsn_base);
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_CLR_END,
|
||||||
|
(i % 0xFFFF), NULL, 7, lsn_buff, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1 Can't write reference before record #%lu\n",
|
||||||
|
(ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
lsn7store(lsn_buff, &lsn_base);
|
||||||
|
rec_len= get_len();
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_UNDO_KEY_INSERT,
|
||||||
|
(i % 0xFFFF),
|
||||||
|
NULL, 7, lsn_buff, rec_len, long_buffer, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1 Can't write var reference before record #%lu\n",
|
||||||
|
(ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lsn7store(lsn_buff, &lsn_base);
|
||||||
|
lsn7store(lsn_buff + 7, &first_lsn);
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_UNDO_ROW_DELETE,
|
||||||
|
(i % 0xFFFF), NULL, 23, lsn_buff, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "0 Can't write reference before record #%lu\n",
|
||||||
|
(ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
lsn7store(lsn_buff, &lsn_base);
|
||||||
|
lsn7store(lsn_buff + 7, &first_lsn);
|
||||||
|
rec_len= get_len();
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_UNDO_KEY_DELETE,
|
||||||
|
(i % 0xFFFF),
|
||||||
|
NULL, 14, lsn_buff, rec_len, long_buffer, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "0 Can't write var reference before record #%lu\n",
|
||||||
|
(ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int4store(long_tr_id, i);
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_LONG_TRANSACTION_ID,
|
||||||
|
(i % 0xFFFF), NULL, 6, long_tr_id, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write record #%lu\n", (ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
lsn_base= lsn;
|
||||||
|
|
||||||
|
rec_len= get_len();
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_REDO_INSERT_ROW_HEAD,
|
||||||
|
(i % 0xFFFF), NULL, rec_len, long_buffer, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write variable record #%lu\n", (ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
translog_destroy();
|
||||||
|
end_pagecache(&pagecache, 1);
|
||||||
|
ma_control_file_end();
|
||||||
|
|
||||||
|
if (ma_control_file_create_or_open())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "pass2: Can't init control file (%d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
|
||||||
|
TRANSLOG_PAGE_SIZE)) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "pass2: Got error: init_pagecache() (errno: %d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (translog_init(".", LOG_FILE_SIZE, 50112, 0, &pagecache, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "pass2: Can't init loghandler (%d)\n", errno);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
srandom(122334817L);
|
||||||
|
|
||||||
|
rc= 1;
|
||||||
|
|
||||||
|
{
|
||||||
|
translog_size_t len= translog_read_record_header(&first_lsn, &rec);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "translog_read_record_header failed (%d)\n", errno);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.type !=LOGREC_LONG_TRANSACTION_ID || rec.short_trid != 0 ||
|
||||||
|
rec.record_length != 6 || uint4korr(rec.header) != 0 ||
|
||||||
|
(uint)rec.header[4] != 0 || rec.header[5] != 0xFF ||
|
||||||
|
first_lsn.file_no != rec.lsn.file_no ||
|
||||||
|
first_lsn.rec_offset != rec.lsn.rec_offset)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_LONG_TRANSACTION_ID data read(0)\n"
|
||||||
|
"type %u, strid %u, len %u, i: %u, 4: %u 5: %u, "
|
||||||
|
"lsn(0x%lx,0x%lx)\n",
|
||||||
|
(uint) rec.type, (uint) rec.short_trid, (uint) rec.record_length,
|
||||||
|
uint4korr(rec.header), (uint) rec.header[4], (uint) rec.header[5],
|
||||||
|
(ulong) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
lsn= first_lsn;
|
||||||
|
lsn_ptr= &first_lsn;
|
||||||
|
for (i= 1;; i++)
|
||||||
|
{
|
||||||
|
if (i % SHOW_DIVIDER == 0)
|
||||||
|
printf("read %d\n", i);
|
||||||
|
len= translog_read_next_record_header(lsn_ptr, &rec, 1, &scanner);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1-%d translog_read_next_record_header failed (%d)\n",
|
||||||
|
i, errno);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO)
|
||||||
|
{
|
||||||
|
if (i != ITERATIONS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EOL met at iteration %u instead of %u\n",
|
||||||
|
i, ITERATIONS);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lsn_ptr= NULL; /* use scanner after its
|
||||||
|
initialization */
|
||||||
|
|
||||||
|
if (i % 2)
|
||||||
|
{
|
||||||
|
LSN ref;
|
||||||
|
lsn7korr(&ref, rec.header);
|
||||||
|
if (rec.type !=LOGREC_CLR_END || rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != 7 || ref.file_no != lsn.file_no ||
|
||||||
|
ref.rec_offset != lsn.rec_offset)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_CLR_END data read(%d)"
|
||||||
|
"type %u, strid %u, len %u, ref(%u,0x%lx), lsn(%u,0x%lx)\n",
|
||||||
|
i, (uint) rec.type, (uint) rec.short_trid,
|
||||||
|
(uint) rec.record_length,
|
||||||
|
(uint) ref.file_no, (ulong) ref.rec_offset,
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LSN ref1, ref2;
|
||||||
|
lsn7korr(&ref1, rec.header);
|
||||||
|
lsn7korr(&ref2, rec.header + 7);
|
||||||
|
if (rec.type !=LOGREC_UNDO_ROW_DELETE ||
|
||||||
|
rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != 23 ||
|
||||||
|
ref1.file_no != lsn.file_no ||
|
||||||
|
ref1.rec_offset != lsn.rec_offset ||
|
||||||
|
ref2.file_no != first_lsn.file_no ||
|
||||||
|
ref2.rec_offset != first_lsn.rec_offset ||
|
||||||
|
rec.header[22] != 0x55 || rec.header[21] != 0xAA ||
|
||||||
|
rec.header[20] != 0x55 || rec.header[19] != 0xAA ||
|
||||||
|
rec.header[18] != 0x55 || rec.header[17] != 0xAA ||
|
||||||
|
rec.header[16] != 0x55 || rec.header[15] != 0xAA ||
|
||||||
|
rec.header[14] != 0x55)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_UNDO_ROW_DELETE data read(%d)"
|
||||||
|
"type %u, strid %u, len %u, ref1(%u,0x%lx), "
|
||||||
|
"ref2(%u,0x%lx) %x%x%x%x%x%x%x%x%x "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
i, (uint) rec.type, (uint) rec.short_trid,
|
||||||
|
(uint) rec.record_length,
|
||||||
|
(uint) ref1.file_no, (ulong) ref1.rec_offset,
|
||||||
|
(uint) ref2.file_no, (ulong) ref2.rec_offset,
|
||||||
|
(uint) rec.header[14], (uint) rec.header[15],
|
||||||
|
(uint) rec.header[16], (uint) rec.header[17],
|
||||||
|
(uint) rec.header[18], (uint) rec.header[19],
|
||||||
|
(uint) rec.header[20], (uint) rec.header[21],
|
||||||
|
(uint) rec.header[22],
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
|
||||||
|
len= translog_read_next_record_header(lsn_ptr, &rec, 1, &scanner);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1-%d translog_read_next_record_header (var) "
|
||||||
|
"failed (%d)\n", i, errno);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EOL met at the middle of iteration (first var) %u "
|
||||||
|
"instead of beginning of %u\n", i, ITERATIONS);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (i % 2)
|
||||||
|
{
|
||||||
|
LSN ref;
|
||||||
|
lsn7korr(&ref, rec.header);
|
||||||
|
rec_len= get_len();
|
||||||
|
if (rec.type !=LOGREC_UNDO_KEY_INSERT ||
|
||||||
|
rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != rec_len + 7 ||
|
||||||
|
len != 12 || ref.file_no != lsn.file_no ||
|
||||||
|
ref.rec_offset != lsn.rec_offset ||
|
||||||
|
check_content(rec.header + 7, len - 7))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_UNDO_KEY_INSERT data read(%d)"
|
||||||
|
"type %u (%d), strid %u (%d), len %lu, %lu + 7 (%d), "
|
||||||
|
"hdr len: %u (%d), "
|
||||||
|
"ref(%u,0x%lx), lsn(%u,0x%lx) (%d), content: %d\n",
|
||||||
|
i, (uint) rec.type,
|
||||||
|
rec.type !=LOGREC_UNDO_KEY_INSERT,
|
||||||
|
(uint) rec.short_trid,
|
||||||
|
rec.short_trid != (i % 0xFFFF),
|
||||||
|
(ulong) rec.record_length, (ulong) rec_len,
|
||||||
|
rec.record_length != rec_len + 7,
|
||||||
|
(uint) len,
|
||||||
|
len != 12,
|
||||||
|
(uint) ref.file_no, (ulong) ref.rec_offset,
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset,
|
||||||
|
(ref.file_no != lsn.file_no ||
|
||||||
|
ref.rec_offset != lsn.rec_offset),
|
||||||
|
check_content(rec.header + 7, len - 7));
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (read_and_check_content(&rec, long_buffer, 7))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Incorrect LOGREC_UNDO_KEY_INSERT in whole rec read "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LSN ref1, ref2;
|
||||||
|
lsn7korr(&ref1, rec.header);
|
||||||
|
lsn7korr(&ref2, rec.header + 7);
|
||||||
|
rec_len= get_len();
|
||||||
|
if (rec.type !=LOGREC_UNDO_KEY_DELETE ||
|
||||||
|
rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != rec_len + 14 ||
|
||||||
|
len != 19 ||
|
||||||
|
ref1.file_no != lsn.file_no ||
|
||||||
|
ref1.rec_offset != lsn.rec_offset ||
|
||||||
|
ref2.file_no != first_lsn.file_no ||
|
||||||
|
ref2.rec_offset != first_lsn.rec_offset ||
|
||||||
|
check_content(rec.header + 14, len - 14))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_UNDO_KEY_DELETE data read(%d)"
|
||||||
|
"type %u, strid %u, len %lu != %lu + 7, hdr len: %u, "
|
||||||
|
"ref1(%u,0x%lx), ref2(%u,0x%lx), "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
i, (uint) rec.type, (uint) rec.short_trid,
|
||||||
|
(ulong) rec.record_length, (ulong) rec_len,
|
||||||
|
(uint) len,
|
||||||
|
(uint) ref1.file_no, (ulong) ref1.rec_offset,
|
||||||
|
(uint) ref2.file_no, (ulong) ref2.rec_offset,
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (read_and_check_content(&rec, long_buffer, 14))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Incorrect LOGREC_UNDO_KEY_DELETE in whole rec read "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
|
||||||
|
len= translog_read_next_record_header(lsn_ptr, &rec, 1, &scanner);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1-%d translog_read_next_record_header failed (%d)\n",
|
||||||
|
i, errno);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EOL met at the middle of iteration %u "
|
||||||
|
"instead of beginning of %u\n", i, ITERATIONS);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.type !=LOGREC_LONG_TRANSACTION_ID ||
|
||||||
|
rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != 6 || uint4korr(rec.header) != i ||
|
||||||
|
rec.header[4] != 0 || rec.header[5] != 0xFF)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_LONG_TRANSACTION_ID data read(%d)\n"
|
||||||
|
"type %u, strid %u, len %u, i: %u, 4: %u 5: %u "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
i, (uint) rec.type, (uint) rec.short_trid,
|
||||||
|
(uint) rec.record_length,
|
||||||
|
uint4korr(rec.header), (uint) rec.header[4],
|
||||||
|
(uint) rec.header[5],
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
|
||||||
|
lsn= rec.lsn;
|
||||||
|
|
||||||
|
len= translog_read_next_record_header(lsn_ptr, &rec, 1, &scanner);
|
||||||
|
rec_len= get_len();
|
||||||
|
if (rec.type !=LOGREC_REDO_INSERT_ROW_HEAD ||
|
||||||
|
rec.short_trid != (i % 0xFFFF) ||
|
||||||
|
rec.record_length != rec_len ||
|
||||||
|
len != 9 || check_content(rec.header, len))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_REDO_INSERT_ROW_HEAD data read(%d)"
|
||||||
|
"type %u, strid %u, len %lu != %lu, hdr len: %u, "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
i, (uint) rec.type, (uint) rec.short_trid,
|
||||||
|
(ulong) rec.record_length, (ulong) rec_len,
|
||||||
|
(uint) len, (uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (read_and_check_content(&rec, long_buffer, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Incorrect LOGREC_UNDO_KEY_DELETE in whole rec read "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc= 0;
|
||||||
|
err:
|
||||||
|
translog_destroy();
|
||||||
|
end_pagecache(&pagecache, 1);
|
||||||
|
ma_control_file_end();
|
||||||
|
|
||||||
|
return (test(exit_status() || rc));
|
||||||
|
}
|
468
storage/maria/unittest/ma_test_loghandler_multithread-t.c
Normal file
468
storage/maria/unittest/ma_test_loghandler_multithread-t.c
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
#include "../maria_def.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
static const char *default_dbug_option;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PCACHE_SIZE (1024*1024*10)
|
||||||
|
|
||||||
|
/*#define LOG_FLAGS TRANSLOG_SECTOR_PROTECTION | TRANSLOG_PAGE_CRC */
|
||||||
|
#define LOG_FLAGS 0
|
||||||
|
/*#define LONG_BUFFER_SIZE (1024L*1024L*1024L + 1024L*1024L*512)*/
|
||||||
|
#define LONG_BUFFER_SIZE (1024L*1024L*1024L)
|
||||||
|
#define MIN_REC_LENGTH 30
|
||||||
|
#define SHOW_DIVIDER 10
|
||||||
|
#define LOG_FILE_SIZE (1024L*1024L*1024L + 1024L*1024L*512)
|
||||||
|
#define ITERATIONS 3
|
||||||
|
#define WRITERS 3
|
||||||
|
static uint number_of_writers= WRITERS;
|
||||||
|
|
||||||
|
static pthread_cond_t COND_thread_count;
|
||||||
|
static pthread_mutex_t LOCK_thread_count;
|
||||||
|
static uint thread_count;
|
||||||
|
|
||||||
|
static ulong lens[WRITERS][ITERATIONS];
|
||||||
|
static LSN lsns1[WRITERS][ITERATIONS];
|
||||||
|
static LSN lsns2[WRITERS][ITERATIONS];
|
||||||
|
static uchar *long_buffer;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get pseudo-random length of the field in
|
||||||
|
limits [MIN_REC_LENGTH..LONG_BUFFER_SIZE]
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
get_len()
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
length - length >= 0 length <= LONG_BUFFER_SIZE
|
||||||
|
*/
|
||||||
|
|
||||||
|
static uint32 get_len()
|
||||||
|
{
|
||||||
|
uint32 rec_len;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rec_len= random() /
|
||||||
|
(RAND_MAX / (LONG_BUFFER_SIZE - MIN_REC_LENGTH - 1)) + MIN_REC_LENGTH;
|
||||||
|
} while (rec_len >= LONG_BUFFER_SIZE);
|
||||||
|
return rec_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check that the buffer filled correctly
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
check_content()
|
||||||
|
ptr Pointer to the buffer
|
||||||
|
length length of the buffer
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
1 - Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
static my_bool check_content(uchar *ptr, ulong length)
|
||||||
|
{
|
||||||
|
ulong i;
|
||||||
|
for (i= 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if (ptr[i] != (i & 0xFF))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Byte # %lu is %x instead of %x",
|
||||||
|
i, (uint) ptr[i], (uint) (i & 0xFF));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read whole record content, and check content (put with offset)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
read_and_check_content()
|
||||||
|
rec The record header buffer
|
||||||
|
buffer The buffer to read the record in
|
||||||
|
skip Skip this number of bytes ot the record content
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
1 - Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static my_bool read_and_check_content(TRANSLOG_HEADER_BUFFER *rec,
|
||||||
|
uchar *buffer, uint skip)
|
||||||
|
{
|
||||||
|
int res= 0;
|
||||||
|
translog_size_t len;
|
||||||
|
DBUG_ENTER("read_and_check_content");
|
||||||
|
DBUG_ASSERT(rec->record_length < LONG_BUFFER_SIZE + 7 * 2 + 2);
|
||||||
|
if ((len= translog_read_record(&rec->lsn, 0, rec->record_length,
|
||||||
|
buffer, NULL)) != rec->record_length)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Requested %lu byte, read %lu\n",
|
||||||
|
(ulong) rec->record_length, (ulong) len);
|
||||||
|
res= 1;
|
||||||
|
}
|
||||||
|
res|= check_content(buffer + skip, rec->record_length - skip);
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writer(int num)
|
||||||
|
{
|
||||||
|
LSN lsn;
|
||||||
|
uchar long_tr_id[6];
|
||||||
|
uint i;
|
||||||
|
DBUG_ENTER("writer");
|
||||||
|
|
||||||
|
for (i= 0; i < ITERATIONS; i++)
|
||||||
|
{
|
||||||
|
uint len= get_len();
|
||||||
|
lens[num][i]= len;
|
||||||
|
|
||||||
|
int2store(long_tr_id, num);
|
||||||
|
int4store(long_tr_id + 2, i);
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_LONG_TRANSACTION_ID,
|
||||||
|
num, NULL, 6, long_tr_id, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write LOGREC_LONG_TRANSACTION_ID record #%lu "
|
||||||
|
"thread %i\n", (ulong) i, num);
|
||||||
|
translog_destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lsns1[num][i]= lsn;
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_REDO_INSERT_ROW_HEAD,
|
||||||
|
num, NULL, len, long_buffer, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write variable record #%lu\n", (ulong) i);
|
||||||
|
translog_destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lsns2[num][i]= lsn;
|
||||||
|
DBUG_PRINT("info", ("thread: %u, iteration: %u, len: %lu, "
|
||||||
|
"lsn1 (%lu,0x%lx) lsn2 (%lu,0x%lx)",
|
||||||
|
num, i, (ulong) lens[num][i],
|
||||||
|
(ulong) lsns1[num][i].file_no,
|
||||||
|
(ulong) lsns1[num][i].rec_offset,
|
||||||
|
(ulong) lsns2[num][i].file_no,
|
||||||
|
(ulong) lsns2[num][i].rec_offset));
|
||||||
|
printf("thread: %u, iteration: %u, len: %lu, "
|
||||||
|
"lsn1 (%lu,0x%lx) lsn2 (%lu,0x%lx)\n",
|
||||||
|
num, i, (ulong) lens[num][i],
|
||||||
|
(ulong) lsns1[num][i].file_no,
|
||||||
|
(ulong) lsns1[num][i].rec_offset,
|
||||||
|
(ulong) lsns2[num][i].file_no, (ulong) lsns2[num][i].rec_offset);
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *test_thread_writer(void *arg)
|
||||||
|
{
|
||||||
|
int param= *((int*) arg);
|
||||||
|
|
||||||
|
my_thread_init();
|
||||||
|
DBUG_ENTER("test_writer");
|
||||||
|
DBUG_PRINT("enter", ("param: %d", param));
|
||||||
|
|
||||||
|
writer(param);
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("Thread %s ended\n", my_thread_name()));
|
||||||
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
|
thread_count--;
|
||||||
|
VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are
|
||||||
|
ready */
|
||||||
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
free((gptr) arg);
|
||||||
|
my_thread_end();
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv __attribute__ ((unused)))
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
uint pagen;
|
||||||
|
PAGECACHE pagecache;
|
||||||
|
LSN first_lsn, *lsn_ptr;
|
||||||
|
TRANSLOG_HEADER_BUFFER rec;
|
||||||
|
struct st_translog_scanner_data scanner;
|
||||||
|
pthread_t tid;
|
||||||
|
pthread_attr_t thr_attr;
|
||||||
|
int *param, error;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
bzero(&pagecache, sizeof(pagecache));
|
||||||
|
maria_data_root= ".";
|
||||||
|
long_buffer= malloc(LONG_BUFFER_SIZE + 7 * 2 + 2);
|
||||||
|
if (long_buffer == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "End of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
for (i= 0; i < (LONG_BUFFER_SIZE + 7 * 2 + 2); i++)
|
||||||
|
long_buffer[i]= (i & 0xFF);
|
||||||
|
|
||||||
|
|
||||||
|
MY_INIT(argv[0]);
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
#if defined(__WIN__)
|
||||||
|
default_dbug_option= "d:t:i:O,\\ma_test_loghandler.trace";
|
||||||
|
#else
|
||||||
|
default_dbug_option= "d:t:i:o,/tmp/ma_test_loghandler.trace";
|
||||||
|
#endif
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
DBUG_SET(default_dbug_option);
|
||||||
|
DBUG_SET_INITIAL(default_dbug_option);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DBUG_ENTER("main");
|
||||||
|
DBUG_PRINT("info", ("Main thread: %s\n", my_thread_name()));
|
||||||
|
|
||||||
|
if ((error= pthread_cond_init(&COND_thread_count, NULL)))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "COND_thread_count: %d from pthread_cond_init "
|
||||||
|
"(errno: %d)\n", error, errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if ((error= pthread_mutex_init(&LOCK_thread_count, MY_MUTEX_INIT_FAST)))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "LOCK_thread_count: %d from pthread_cond_init "
|
||||||
|
"(errno: %d)\n", error, errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if ((error= pthread_attr_init(&thr_attr)))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Got error: %d from pthread_attr_init "
|
||||||
|
"(errno: %d)\n", error, errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if ((error= pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED)))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Got error: %d from pthread_attr_setdetachstate (errno: %d)\n",
|
||||||
|
error, errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#ifndef pthread_attr_setstacksize /* void return value */
|
||||||
|
if ((error= pthread_attr_setstacksize(&thr_attr, 65536L)))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Got error: %d from pthread_attr_setstacksize "
|
||||||
|
"(errno: %d)\n", error, errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_THR_SETCONCURRENCY
|
||||||
|
VOID(thr_setconcurrency(2));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
my_thread_global_init();
|
||||||
|
|
||||||
|
if (ma_control_file_create_or_open())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
|
||||||
|
TRANSLOG_PAGE_SIZE)) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (translog_init(".", LOG_FILE_SIZE, 50112, 0, &pagecache, LOG_FLAGS))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't init loghandler (%d)\n", errno);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
srandom(122334817L);
|
||||||
|
{
|
||||||
|
uchar long_tr_id[6]=
|
||||||
|
{
|
||||||
|
0x11, 0x22, 0x33, 0x44, 0x55, 0x66
|
||||||
|
};
|
||||||
|
|
||||||
|
if (translog_write_record(&first_lsn,
|
||||||
|
LOGREC_LONG_TRANSACTION_ID,
|
||||||
|
0, NULL, 6, long_tr_id, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write the first record\n");
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ((error= pthread_mutex_lock(&LOCK_thread_count)))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "LOCK_thread_count: %d from pthread_mutex_lock "
|
||||||
|
"(errno: %d)\n", error, errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (number_of_writers != 0)
|
||||||
|
{
|
||||||
|
param= (int*) malloc(sizeof(int));
|
||||||
|
*param= number_of_writers - 1;
|
||||||
|
if ((error= pthread_create(&tid, &thr_attr, test_thread_writer,
|
||||||
|
(void*) param)))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Got error: %d from pthread_create (errno: %d)\n",
|
||||||
|
error, errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
thread_count++;
|
||||||
|
number_of_writers--;
|
||||||
|
}
|
||||||
|
DBUG_PRINT("info", ("All threads are started"));
|
||||||
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
|
||||||
|
pthread_attr_destroy(&thr_attr);
|
||||||
|
|
||||||
|
/* wait finishing */
|
||||||
|
if ((error= pthread_mutex_lock(&LOCK_thread_count)))
|
||||||
|
fprintf(stderr, "LOCK_thread_count: %d from pthread_mutex_lock\n", error);
|
||||||
|
while (thread_count)
|
||||||
|
{
|
||||||
|
if ((error= pthread_cond_wait(&COND_thread_count, &LOCK_thread_count)))
|
||||||
|
fprintf(stderr, "COND_thread_count: %d from pthread_cond_wait\n", error);
|
||||||
|
}
|
||||||
|
if ((error= pthread_mutex_unlock(&LOCK_thread_count)))
|
||||||
|
fprintf(stderr, "LOCK_thread_count: %d from pthread_mutex_unlock\n", error);
|
||||||
|
DBUG_PRINT("info", ("All threads ended"));
|
||||||
|
|
||||||
|
/* Find last LSN and flush up to it (all our log) */
|
||||||
|
{
|
||||||
|
LSN max=
|
||||||
|
{
|
||||||
|
0, 0
|
||||||
|
};
|
||||||
|
for (i= 0; i < WRITERS; i++)
|
||||||
|
{
|
||||||
|
if (cmp_translog_addr(lsns2[i][ITERATIONS - 1], max) > 0)
|
||||||
|
max= lsns2[i][ITERATIONS - 1];
|
||||||
|
}
|
||||||
|
DBUG_PRINT("info", ("first lsn: (%lu,0x%lx), max lsn: (%lu,0x%lx)",
|
||||||
|
(ulong) first_lsn.file_no,
|
||||||
|
(ulong) first_lsn.rec_offset,
|
||||||
|
(ulong) max.file_no, (ulong) max.rec_offset));
|
||||||
|
translog_flush(&max);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc= 1;
|
||||||
|
|
||||||
|
{
|
||||||
|
uint indeces[WRITERS];
|
||||||
|
uint index, len, stage;
|
||||||
|
bzero(indeces, sizeof(uint) * WRITERS);
|
||||||
|
|
||||||
|
bzero(indeces, sizeof(indeces));
|
||||||
|
|
||||||
|
lsn_ptr= &first_lsn;
|
||||||
|
for (i= 0;; i++)
|
||||||
|
{
|
||||||
|
len= translog_read_next_record_header(lsn_ptr, &rec, 1, &scanner);
|
||||||
|
lsn_ptr= NULL;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "1-%d translog_read_next_record_header failed (%d)\n",
|
||||||
|
i, errno);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (rec.lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO)
|
||||||
|
{
|
||||||
|
if (i != WRITERS * ITERATIONS * 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EOL met at iteration %u instead of %u\n",
|
||||||
|
i, ITERATIONS * WRITERS * 2);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index= indeces[rec.short_trid] / 2;
|
||||||
|
stage= indeces[rec.short_trid] % 2;
|
||||||
|
printf("read(%d) thread: %d, iteration %d, stage %d\n",
|
||||||
|
i, (uint) rec.short_trid, index, stage);
|
||||||
|
if (stage == 0)
|
||||||
|
{
|
||||||
|
if (rec.type !=LOGREC_LONG_TRANSACTION_ID ||
|
||||||
|
rec.record_length != 6 ||
|
||||||
|
uint2korr(rec.header) != rec.short_trid ||
|
||||||
|
index != uint4korr(rec.header + 2) ||
|
||||||
|
cmp_translog_addr(lsns1[rec.short_trid][index], rec.lsn) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect LOGREC_LONG_TRANSACTION_ID data read(%d)\n"
|
||||||
|
"type %u, strid %u %u, len %u, i: %u %u, "
|
||||||
|
"lsn(%lu,0x%lx) (%lu,0x%lx)\n",
|
||||||
|
i, (uint) rec.type,
|
||||||
|
(uint) rec.short_trid, (uint) uint2korr(rec.header),
|
||||||
|
(uint) rec.record_length,
|
||||||
|
(uint) index, (uint) uint4korr(rec.header + 2),
|
||||||
|
(ulong) rec.lsn.file_no, (ulong) rec.lsn.rec_offset,
|
||||||
|
(ulong) lsns1[rec.short_trid][index].file_no,
|
||||||
|
(ulong) lsns1[rec.short_trid][index].rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (rec.type !=LOGREC_REDO_INSERT_ROW_HEAD ||
|
||||||
|
len != 9 ||
|
||||||
|
rec.record_length != lens[rec.short_trid][index] ||
|
||||||
|
cmp_translog_addr(lsns2[rec.short_trid][index], rec.lsn) != 0 ||
|
||||||
|
check_content(rec.header, len))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Incorrect LOGREC_REDO_INSERT_ROW_HEAD data read(%d) "
|
||||||
|
" thread: %d, iteration %d, stage %d\n"
|
||||||
|
"type %u (%d), len %u, length %lu %lu (%d) "
|
||||||
|
"lsn(%lu,0x%lx) (%lu,0x%lx)\n",
|
||||||
|
i, (uint) rec.short_trid, index, stage,
|
||||||
|
(uint) rec.type, (rec.type !=LOGREC_REDO_INSERT_ROW_HEAD),
|
||||||
|
(uint) len,
|
||||||
|
(ulong) rec.record_length, lens[rec.short_trid][index],
|
||||||
|
(rec.record_length != lens[rec.short_trid][index]),
|
||||||
|
(ulong) rec.lsn.file_no, (ulong) rec.lsn.rec_offset,
|
||||||
|
(ulong) lsns2[rec.short_trid][index].file_no,
|
||||||
|
(ulong) lsns2[rec.short_trid][index].rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (read_and_check_content(&rec, long_buffer, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Incorrect LOGREC_REDO_INSERT_ROW_HEAD in whole rec read "
|
||||||
|
"lsn(%u,0x%lx)\n",
|
||||||
|
(uint) rec.lsn.file_no, (ulong) rec.lsn.rec_offset);
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translog_free_record_header(&rec);
|
||||||
|
indeces[rec.short_trid]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc= 0;
|
||||||
|
err:
|
||||||
|
translog_destroy();
|
||||||
|
end_pagecache(&pagecache, 1);
|
||||||
|
ma_control_file_end();
|
||||||
|
|
||||||
|
DBUG_RETURN(test(exit_status() || rc));
|
||||||
|
}
|
140
storage/maria/unittest/ma_test_loghandler_pagecache-t.c
Normal file
140
storage/maria/unittest/ma_test_loghandler_pagecache-t.c
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#include "../maria_def.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
static const char *default_dbug_option;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PCACHE_SIZE (1024*1024*10)
|
||||||
|
#define PCACHE_PAGE TRANSLOG_PAGE_SIZE
|
||||||
|
#define LOG_FILE_SIZE (1024L*1024L*1024L + 1024L*1024L*512)
|
||||||
|
#define LOG_FLAGS 0
|
||||||
|
|
||||||
|
static char *first_translog_file= (char*)"maria_log.00000001";
|
||||||
|
static char *file1_name= (char*)"page_cache_test_file_1";
|
||||||
|
static PAGECACHE_FILE file1;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
uint pagen;
|
||||||
|
uchar long_tr_id[6];
|
||||||
|
PAGECACHE pagecache;
|
||||||
|
LSN lsn;
|
||||||
|
MY_STAT st, *stat;
|
||||||
|
|
||||||
|
MY_INIT(argv[0]);
|
||||||
|
|
||||||
|
bzero(&pagecache, sizeof(pagecache));
|
||||||
|
maria_data_root= ".";
|
||||||
|
/* be sure that we have no logs in the directory*/
|
||||||
|
if (my_stat(CONTROL_FILE_BASE_NAME, &st, MYF(0)))
|
||||||
|
my_delete(CONTROL_FILE_BASE_NAME, MYF(0));
|
||||||
|
if (my_stat(first_translog_file, &st, MYF(0)))
|
||||||
|
my_delete(first_translog_file, MYF(0));
|
||||||
|
|
||||||
|
bzero(long_tr_id, 6);
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
#if defined(__WIN__)
|
||||||
|
default_dbug_option= "d:t:i:O,\\ma_test_loghandler_pagecache.trace";
|
||||||
|
#else
|
||||||
|
default_dbug_option= "d:t:i:o,/tmp/ma_test_loghandler_pagecache.trace";
|
||||||
|
#endif
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
DBUG_SET(default_dbug_option);
|
||||||
|
DBUG_SET_INITIAL(default_dbug_option);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ma_control_file_create_or_open())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
|
||||||
|
PCACHE_PAGE)) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (translog_init(".", LOG_FILE_SIZE, 50112, 0, &pagecache, LOG_FLAGS))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't init loghandler (%d)\n", errno);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((stat= my_stat(first_translog_file, &st, MYF(0))) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "There is no %s (%d)\n", first_translog_file, errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (st.st_size != TRANSLOG_PAGE_SIZE)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"incorrect initial size of %s: %ld instead of %ld\n",
|
||||||
|
first_translog_file, (long)st.st_size, (long)TRANSLOG_PAGE_SIZE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
int4store(long_tr_id, 0);
|
||||||
|
if (translog_write_record(&lsn,
|
||||||
|
LOGREC_LONG_TRANSACTION_ID,
|
||||||
|
0, NULL, 6, long_tr_id, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write record #%lu\n", (ulong) 0);
|
||||||
|
translog_destroy();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((file1.file= my_open(file1_name,
|
||||||
|
O_CREAT | O_TRUNC | O_RDWR, MYF(0))) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Got error during file1 creation from open() (errno: %d)\n",
|
||||||
|
errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (chmod(file1_name, S_IRWXU | S_IRWXG | S_IRWXO) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Got error during file1 chmod() (errno: %d)\n",
|
||||||
|
errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uchar page[PCACHE_PAGE];
|
||||||
|
|
||||||
|
bzero(page, PCACHE_PAGE);
|
||||||
|
#define PAGE_LSN_OFFSET 0
|
||||||
|
lsn7store(page + PAGE_LSN_OFFSET, &lsn);
|
||||||
|
pagecache_write(&pagecache, &file1, 0, 3, (char*)page,
|
||||||
|
PAGECACHE_LSN_PAGE,
|
||||||
|
PAGECACHE_LOCK_LEFT_UNLOCKED,
|
||||||
|
PAGECACHE_PIN_LEFT_UNPINNED,
|
||||||
|
PAGECACHE_WRITE_DELAY,
|
||||||
|
0);
|
||||||
|
flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE);
|
||||||
|
}
|
||||||
|
if ((stat= my_stat(first_translog_file, &st, MYF(0))) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "can't stat %s (%d)\n", first_translog_file, errno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (st.st_size != TRANSLOG_PAGE_SIZE * 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"incorrect initial size of %s: %ld instead of %ld\n",
|
||||||
|
first_translog_file,
|
||||||
|
(long)st.st_size, (long)(TRANSLOG_PAGE_SIZE * 2));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
translog_destroy();
|
||||||
|
end_pagecache(&pagecache, 1);
|
||||||
|
ma_control_file_end();
|
||||||
|
my_delete(CONTROL_FILE_BASE_NAME, MYF(0));
|
||||||
|
my_delete(first_translog_file, MYF(0));
|
||||||
|
my_delete(file1_name, MYF(0));
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
@ -57,6 +57,29 @@ static uint flush_divider= 1000;
|
|||||||
#endif /*TEST_HIGH_CONCURENCY*/
|
#endif /*TEST_HIGH_CONCURENCY*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get pseudo-random length of the field in (0;limit)
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
get_len()
|
||||||
|
limit limit for generated value
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
length where length >= 0 & length < limit
|
||||||
|
*/
|
||||||
|
|
||||||
|
static uint get_len(uint limit)
|
||||||
|
{
|
||||||
|
uint32 rec_len;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rec_len= random() /
|
||||||
|
(RAND_MAX / limit);
|
||||||
|
} while (rec_len >= limit || rec_len == 0);
|
||||||
|
return rec_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* check page consistency */
|
/* check page consistency */
|
||||||
uint check_page(uchar *buff, ulong offset, int page_locked, int page_no,
|
uint check_page(uchar *buff, ulong offset, int page_locked, int page_no,
|
||||||
int tag)
|
int tag)
|
||||||
@ -70,7 +93,7 @@ uint check_page(uchar *buff, ulong offset, int page_locked, int page_no,
|
|||||||
{
|
{
|
||||||
uint len= *((uint *)(buff + end));
|
uint len= *((uint *)(buff + end));
|
||||||
uint j;
|
uint j;
|
||||||
end+= sizeof(uint)+ sizeof(uint);
|
end+= sizeof(uint) + sizeof(uint);
|
||||||
if (len + end > PAGE_SIZE)
|
if (len + end > PAGE_SIZE)
|
||||||
{
|
{
|
||||||
diag("incorrect field header #%u by offset %lu\n", i, offset + end + j);
|
diag("incorrect field header #%u by offset %lu\n", i, offset + end + j);
|
||||||
@ -178,7 +201,7 @@ void reader(int num)
|
|||||||
|
|
||||||
for (i= 0; i < number_of_tests; i++)
|
for (i= 0; i < number_of_tests; i++)
|
||||||
{
|
{
|
||||||
uint page= rand()/(RAND_MAX/number_of_pages);
|
uint page= get_len(number_of_pages);
|
||||||
pagecache_read(&pagecache, &file1, page, 3, (char*)buffr,
|
pagecache_read(&pagecache, &file1, page, 3, (char*)buffr,
|
||||||
PAGECACHE_PLAIN_PAGE,
|
PAGECACHE_PLAIN_PAGE,
|
||||||
PAGECACHE_LOCK_LEFT_UNLOCKED,
|
PAGECACHE_LOCK_LEFT_UNLOCKED,
|
||||||
@ -201,13 +224,13 @@ void writer(int num)
|
|||||||
for (i= 0; i < number_of_tests; i++)
|
for (i= 0; i < number_of_tests; i++)
|
||||||
{
|
{
|
||||||
uint end;
|
uint end;
|
||||||
uint page= rand()/(RAND_MAX/number_of_pages);
|
uint page= get_len(number_of_pages);
|
||||||
pagecache_read(&pagecache, &file1, page, 3, (char*)buffr,
|
pagecache_read(&pagecache, &file1, page, 3, (char*)buffr,
|
||||||
PAGECACHE_PLAIN_PAGE,
|
PAGECACHE_PLAIN_PAGE,
|
||||||
PAGECACHE_LOCK_WRITE,
|
PAGECACHE_LOCK_WRITE,
|
||||||
0);
|
0);
|
||||||
end= check_page(buffr, page * PAGE_SIZE, 1, page, num);
|
end= check_page(buffr, page * PAGE_SIZE, 1, page, num);
|
||||||
put_rec(buffr, end, rand()/(RAND_MAX/record_length_limit), num);
|
put_rec(buffr, end, get_len(record_length_limit), num);
|
||||||
pagecache_write(&pagecache, &file1, page, 3, (char*)buffr,
|
pagecache_write(&pagecache, &file1, page, 3, (char*)buffr,
|
||||||
PAGECACHE_PLAIN_PAGE,
|
PAGECACHE_PLAIN_PAGE,
|
||||||
PAGECACHE_LOCK_WRITE_UNLOCK,
|
PAGECACHE_LOCK_WRITE_UNLOCK,
|
||||||
@ -348,7 +371,7 @@ int main(int argc, char **argv __attribute__((unused)))
|
|||||||
|
|
||||||
|
|
||||||
if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
|
if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
|
||||||
PAGE_SIZE, 0)) == 0)
|
PAGE_SIZE)) == 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"Got error: init_pagecache() (errno: %d)\n",
|
fprintf(stderr,"Got error: init_pagecache() (errno: %d)\n",
|
||||||
errno);
|
errno);
|
@ -346,7 +346,7 @@ int simple_big_test()
|
|||||||
unsigned char *buffw= (unsigned char *)malloc(PAGE_SIZE);
|
unsigned char *buffw= (unsigned char *)malloc(PAGE_SIZE);
|
||||||
unsigned char *buffr= (unsigned char *)malloc(PAGE_SIZE);
|
unsigned char *buffr= (unsigned char *)malloc(PAGE_SIZE);
|
||||||
struct file_desc *desc=
|
struct file_desc *desc=
|
||||||
(struct file_desc *)malloc((PCACHE_SIZE/(PAGE_SIZE/2)) *
|
(struct file_desc *)malloc((PCACHE_SIZE/(PAGE_SIZE/2) + 1) *
|
||||||
sizeof(struct file_desc));
|
sizeof(struct file_desc));
|
||||||
int res, i;
|
int res, i;
|
||||||
DBUG_ENTER("simple_big_test");
|
DBUG_ENTER("simple_big_test");
|
||||||
@ -363,6 +363,8 @@ int simple_big_test()
|
|||||||
PAGECACHE_WRITE_DELAY,
|
PAGECACHE_WRITE_DELAY,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
desc[i].length= 0;
|
||||||
|
desc[i].content= NULL;
|
||||||
ok(1, "Simple big file write");
|
ok(1, "Simple big file write");
|
||||||
/* check written pages sequentally read */
|
/* check written pages sequentally read */
|
||||||
for (i= 0; i < PCACHE_SIZE/(PAGE_SIZE/2); i++)
|
for (i= 0; i < PCACHE_SIZE/(PAGE_SIZE/2); i++)
|
||||||
@ -528,7 +530,7 @@ int main(int argc, char **argv __attribute__((unused)))
|
|||||||
plan(12);
|
plan(12);
|
||||||
|
|
||||||
if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
|
if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
|
||||||
PAGE_SIZE, 0)) == 0)
|
PAGE_SIZE)) == 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"Got error: init_pagecache() (errno: %d)\n",
|
fprintf(stderr,"Got error: init_pagecache() (errno: %d)\n",
|
||||||
errno);
|
errno);
|
@ -7,45 +7,4 @@ LDADD = $(top_builddir)/unittest/mytap/libmytap.a \
|
|||||||
$(top_builddir)/dbug/libdbug.a \
|
$(top_builddir)/dbug/libdbug.a \
|
||||||
$(top_builddir)/strings/libmystrings.a
|
$(top_builddir)/strings/libmystrings.a
|
||||||
|
|
||||||
noinst_PROGRAMS = bitmap-t base64-t my_atomic-t \
|
noinst_PROGRAMS = bitmap-t base64-t my_atomic-t
|
||||||
mf_pagecache_single_1k-t mf_pagecache_single_8k-t \
|
|
||||||
mf_pagecache_single_64k-t \
|
|
||||||
mf_pagecache_consist_1k-t mf_pagecache_consist_64k-t \
|
|
||||||
mf_pagecache_consist_1kHC-t mf_pagecache_consist_64kHC-t \
|
|
||||||
mf_pagecache_consist_1kRD-t mf_pagecache_consist_64kRD-t \
|
|
||||||
mf_pagecache_consist_1kWR-t mf_pagecache_consist_64kWR-t
|
|
||||||
|
|
||||||
# tests for mysys/mf_pagecache.c
|
|
||||||
|
|
||||||
mf_pagecache_single_src = mf_pagecache_single.c $(top_srcdir)/mysys/mf_pagecache.c test_file.c
|
|
||||||
mf_pagecache_consist_src = mf_pagecache_consist.c $(top_srcdir)/mysys/mf_pagecache.c test_file.c
|
|
||||||
mf_pagecache_common_cppflags = -DEXTRA_DEBUG -DPAGECACHE_DEBUG -DMAIN
|
|
||||||
|
|
||||||
mf_pagecache_single_1k_t_SOURCES = $(mf_pagecache_single_src)
|
|
||||||
mf_pagecache_single_8k_t_SOURCES = $(mf_pagecache_single_src)
|
|
||||||
mf_pagecache_single_64k_t_SOURCES = $(mf_pagecache_single_src)
|
|
||||||
mf_pagecache_single_1k_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024
|
|
||||||
mf_pagecache_single_8k_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=8192
|
|
||||||
mf_pagecache_single_64k_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536
|
|
||||||
|
|
||||||
mf_pagecache_consist_1k_t_SOURCES = $(mf_pagecache_consist_src)
|
|
||||||
mf_pagecache_consist_1k_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024
|
|
||||||
mf_pagecache_consist_64k_t_SOURCES = $(mf_pagecache_consist_src)
|
|
||||||
mf_pagecache_consist_64k_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536
|
|
||||||
|
|
||||||
mf_pagecache_consist_1kHC_t_SOURCES = $(mf_pagecache_consist_src)
|
|
||||||
mf_pagecache_consist_1kHC_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 -DTEST_HIGH_CONCURENCY
|
|
||||||
mf_pagecache_consist_64kHC_t_SOURCES = $(mf_pagecache_consist_src)
|
|
||||||
mf_pagecache_consist_64kHC_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 -DTEST_HIGH_CONCURENCY
|
|
||||||
|
|
||||||
mf_pagecache_consist_1kRD_t_SOURCES = $(mf_pagecache_consist_src)
|
|
||||||
mf_pagecache_consist_1kRD_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 -DTEST_READERS
|
|
||||||
mf_pagecache_consist_64kRD_t_SOURCES = $(mf_pagecache_consist_src)
|
|
||||||
mf_pagecache_consist_64kRD_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 -DTEST_READERS
|
|
||||||
|
|
||||||
mf_pagecache_consist_1kWR_t_SOURCES = $(mf_pagecache_consist_src)
|
|
||||||
mf_pagecache_consist_1kWR_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 -DTEST_WRITERS
|
|
||||||
mf_pagecache_consist_64kWR_t_SOURCES = $(mf_pagecache_consist_src)
|
|
||||||
mf_pagecache_consist_64kWR_t_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 -DTEST_WRITERS
|
|
||||||
|
|
||||||
CLEANFILES = my_pagecache_debug.log page_cache_test_file_1
|
|
||||||
|
Reference in New Issue
Block a user