From cd876fb11883f68f93027a70b5f3f99ad9234f27 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Aug 2006 19:19:47 +0200 Subject: amd64 atomic ops lock-free alloc (WL#3229), lock-free hash (WL#3230) bit functions made inline include/Makefile.am: lf.h added mysys/Makefile.am: lf_hash.c lf_dynarray.c lf_alloc-pin.c include/atomic/nolock.h: amd64 atomic ops include/atomic/rwlock.h: s/rw_lock/mutex/g include/atomic/x86-gcc.h: amd64 atomic ops try PAUSE include/my_global.h: STATIC_INLINE mysys/mf_keycache.c: make bit functions inline mysys/my_atomic.c: STATIC_INLINE mysys/my_bitmap.c: make bit functions inline sql/ha_myisam.cc: make bit functions inline sql/item_func.cc: make bit functions inline include/my_atomic.h: STATIC_INLINE mysys/my_bit.c: make bit functions inline sql/sql_select.cc: make bit functions inline storage/myisam/mi_create.c: make bit functions inline storage/myisam/mi_test2.c: make bit functions inline storage/myisam/myisamchk.c: make bit functions inline mysys/my_init.c: thread_size moved to mysys sql/mysql_priv.h: thread_size moved to mysys sql/set_var.cc: thread_size moved to mysys include/my_sys.h: thread_size moved to mysys sql/mysqld.cc: thread_size moved to mysys sql/sql_parse.cc: thread_size moved to mysys sql/sql_test.cc: thread_size moved to mysys include/lf.h: dylf_dynarray refactored to remove 65536 elements limit mysys/lf_alloc-pin.c: dylf_dynarray refactored to remove 65536 elements limit mysys/lf_dynarray.c: dylf_dynarray refactored to remove 65536 elements limit mysys/lf_hash.c: dylf_dynarray refactored to remove 65536 elements limit unittest/mysys/my_atomic-t.c: fix to commit (remove debug code) --- unittest/mysys/my_atomic-t.c | 190 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 165 insertions(+), 25 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index 71408ce957f..1e7206441eb 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -14,13 +14,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include +//#define MY_ATOMIC_MODE_RWLOCKS +//#define MY_ATOMIC_MODE_DUMMY + #include + +#include #include #include +#include -int32 a32,b32,c32; +volatile uint32 a32,b32,c32; my_atomic_rwlock_t rwl; +LF_ALLOCATOR lf_allocator; +LF_HASH lf_hash; pthread_attr_t thr_attr; pthread_mutex_t mutex; @@ -30,9 +37,9 @@ int N; /* add and sub a random number in a loop. Must get 0 at the end */ pthread_handler_t test_atomic_add_handler(void *arg) { - int m=*(int *)arg; + int m=(*(int *)arg)/2; int32 x; - for (x=((int)(&m)); m ; m--) + for (x=((int)(intptr)(&m)); m ; m--) { x=x*m+0x87654321; my_atomic_rwlock_wrlock(&rwl); @@ -61,15 +68,9 @@ pthread_handler_t test_atomic_add_handler(void *arg) pthread_handler_t test_atomic_swap_handler(void *arg) { int m=*(int *)arg; - int32 x; - - my_atomic_rwlock_wrlock(&rwl); - x=my_atomic_add32(&b32, 1); - my_atomic_rwlock_wrunlock(&rwl); + uint32 x=my_atomic_add32(&b32, 1); - my_atomic_rwlock_wrlock(&rwl); my_atomic_add32(&a32, x); - my_atomic_rwlock_wrunlock(&rwl); for (; m ; m--) { @@ -98,29 +99,29 @@ pthread_handler_t test_atomic_swap_handler(void *arg) /* same as test_atomic_add_handler, but my_atomic_add32 is emulated with - (slower) my_atomic_cas32 + my_atomic_cas32 - notice that the slowdown is proportional to the + number of CPUs */ pthread_handler_t test_atomic_cas_handler(void *arg) { - int m=*(int *)arg, ok; - int32 x,y; - for (x=((int)(&m)); m ; m--) + int m=(*(int *)arg)/2, ok=0; + int32 x, y; + for (x=((int)(intptr)(&m)); m ; m--) { my_atomic_rwlock_wrlock(&rwl); y=my_atomic_load32(&a32); my_atomic_rwlock_wrunlock(&rwl); - x=x*m+0x87654321; do { my_atomic_rwlock_wrlock(&rwl); ok=my_atomic_cas32(&a32, &y, y+x); my_atomic_rwlock_wrunlock(&rwl); - } while (!ok); + } while (!ok) ; do { my_atomic_rwlock_wrlock(&rwl); ok=my_atomic_cas32(&a32, &y, y-x); my_atomic_rwlock_wrunlock(&rwl); - } while (!ok); + } while (!ok) ; } pthread_mutex_lock(&mutex); N--; @@ -129,6 +130,128 @@ pthread_handler_t test_atomic_cas_handler(void *arg) return 0; } +/* + pin allocator - alloc and release an element in a loop +*/ +pthread_handler_t test_lf_pinbox(void *arg) +{ + int m=*(int *)arg; + int32 x=0; + LF_PINS *pins; + + pins=lf_pinbox_get_pins(&lf_allocator.pinbox); + + for (x=((int)(intptr)(&m)); m ; m--) + { + lf_pinbox_put_pins(pins); + pins=lf_pinbox_get_pins(&lf_allocator.pinbox); + } + lf_pinbox_put_pins(pins); + pthread_mutex_lock(&mutex); + N--; + if (!N) + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); + return 0; +} + +typedef union { + int32 data; + void *not_used; /* to guarantee sizeof(TLA) >= sizeof(void *) */ +} TLA; + +pthread_handler_t test_lf_alloc(void *arg) +{ + int m=(*(int *)arg)/2; + int32 x,y=0; + LF_PINS *pins; + + pins=lf_alloc_get_pins(&lf_allocator); + + for (x=((int)(intptr)(&m)); m ; m--) + { + TLA *node1, *node2; + x=x*m+0x87654321; + node1=(TLA *)lf_alloc_new(pins); + node1->data=x; + y+=node1->data; + node1->data=0; + node2=(TLA *)lf_alloc_new(pins); + node2->data=x; + y-=node2->data; + node2->data=0; + lf_alloc_free(pins, node1); + lf_alloc_free(pins, node2); + } + lf_alloc_put_pins(pins); + my_atomic_rwlock_wrlock(&rwl); + my_atomic_add32(&a32, y); + my_atomic_rwlock_wrunlock(&rwl); + pthread_mutex_lock(&mutex); + N--; + if (!N) + { + diag("%d mallocs, %d pins in stack", + lf_allocator.mallocs, lf_allocator.pinbox.pins_in_stack); +#ifdef MY_LF_EXTRA_DEBUG + a32|=lf_allocator.mallocs - lf_alloc_in_pool(&lf_allocator); +#endif + pthread_cond_signal(&cond); + } + pthread_mutex_unlock(&mutex); + return 0; +} + +#define N_TLH 1000 +pthread_handler_t test_lf_hash(void *arg) +{ + int m=(*(int *)arg)/(2*N_TLH); + int32 x,y,z,sum=0, ins=0; + LF_PINS *pins; + + pins=lf_hash_get_pins(&lf_hash); + + for (x=((int)(intptr)(&m)); m ; m--) + { + int i; + y=x; + for (i=0; i < N_TLH; i++) + { + x=x*(m+i)+0x87654321; + z=(x<0) ? -x : x; + if (lf_hash_insert(&lf_hash, pins, &z)) + { + sum+=z; + ins++; + } + } + for (i=0; i < N_TLH; i++) + { + y=y*(m+i)+0x87654321; + z=(y<0) ? -y : y; + if (lf_hash_delete(&lf_hash, pins, (uchar *)&z, sizeof(z))) + sum-=z; + } + } + lf_hash_put_pins(pins); + my_atomic_rwlock_wrlock(&rwl); + my_atomic_add32(&a32, sum); + my_atomic_add32(&b32, ins); + my_atomic_rwlock_wrunlock(&rwl); + pthread_mutex_lock(&mutex); + N--; + if (!N) + { + diag("%d mallocs, %d pins in stack, %d hash size, %d inserts", + lf_hash.alloc.mallocs, lf_hash.alloc.pinbox.pins_in_stack, + lf_hash.size, b32); + a32|=lf_hash.count; + pthread_cond_signal(&cond); + } + pthread_mutex_unlock(&mutex); + return 0; +} + void test_atomic(const char *test, pthread_handler handler, int n, int m) { pthread_t t; @@ -141,23 +264,24 @@ void test_atomic(const char *test, pthread_handler handler, int n, int m) diag("Testing %s with %d threads, %d iterations... ", test, n, m); for (N=n ; n ; n--) pthread_create(&t, &thr_attr, handler, &m); - pthread_mutex_lock(&mutex); while (N) pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); now=my_getsystime()-now; - ok(a32 == 0, "tested %s in %g secs", test, ((double)now)/1e7); + ok(a32 == 0, "tested %s in %g secs (%d)", test, ((double)now)/1e7, a32); } int main() { int err; - diag("N CPUs: %d", my_getncpus()); + my_init(); + + diag("N CPUs: %d, atomic ops: %s", my_getncpus(), MY_ATOMIC_MODE); err= my_atomic_initialize(); - plan(4); + plan(7); ok(err == 0, "my_atomic_initialize() returned %d", err); pthread_attr_init(&thr_attr); @@ -165,15 +289,31 @@ int main() pthread_mutex_init(&mutex, 0); pthread_cond_init(&cond, 0); my_atomic_rwlock_init(&rwl); + lf_alloc_init(&lf_allocator, sizeof(TLA)); + lf_hash_init(&lf_hash, sizeof(int), LF_HASH_UNIQUE, 0, sizeof(int), 0, + &my_charset_bin); + +#ifdef MY_ATOMIC_MODE_RWLOCKS +#define CYCLES 10000 +#else +#define CYCLES 1000000 +#endif +#define THREADS 100 - test_atomic("my_atomic_add32", test_atomic_add_handler, 100,1000000); - test_atomic("my_atomic_swap32", test_atomic_swap_handler, 100,1000000); - test_atomic("my_atomic_cas32", test_atomic_cas_handler, 100,1000000); + test_atomic("my_atomic_add32", test_atomic_add_handler, THREADS,CYCLES); + test_atomic("my_atomic_swap32", test_atomic_swap_handler, THREADS,CYCLES); + test_atomic("my_atomic_cas32", test_atomic_cas_handler, THREADS,CYCLES); + test_atomic("lf_pinbox", test_lf_pinbox, THREADS,CYCLES); + test_atomic("lf_alloc", test_lf_alloc, THREADS,CYCLES); + test_atomic("lf_hash", test_lf_hash, THREADS,CYCLES); + lf_hash_end(&lf_hash); + lf_alloc_end(&lf_allocator); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); pthread_attr_destroy(&thr_attr); my_atomic_rwlock_destroy(&rwl); + my_end(0); return exit_status(); } -- cgit v1.2.1 From 74d050d000ff9db79e36931988386fe7988f8dd2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 Aug 2006 15:20:58 +0200 Subject: maria transaction manager with unit tests include/lf.h: few lf API changes mysys/lf_alloc-pin.c: few lf API changes mysys/lf_dynarray.c: few lf API changes mysys/lf_hash.c: few lf API changes storage/maria/Makefile.am: transaction manager unittest/Makefile.am: maria transaction manager unittest/mysys/my_atomic-t.c: ensure that values are positive storage/maria/trxman.h: New BitKeeper file ``storage/maria/trxman.h'' unittest/maria/Makefile.am: New BitKeeper file ``unittest/maria/Makefile.am'' unittest/maria/trxman-t.c: New BitKeeper file ``unittest/maria/trxman-t.c'' storage/maria/trxman.c: comment clarified --- unittest/Makefile.am | 4 +- unittest/maria/Makefile.am | 12 ++++ unittest/maria/trxman-t.c | 138 +++++++++++++++++++++++++++++++++++++++++++ unittest/mysys/my_atomic-t.c | 17 +++--- 4 files changed, 159 insertions(+), 12 deletions(-) create mode 100644 unittest/maria/Makefile.am create mode 100644 unittest/maria/trxman-t.c (limited to 'unittest') diff --git a/unittest/Makefile.am b/unittest/Makefile.am index ca3291efde0..295ecd7186f 100644 --- a/unittest/Makefile.am +++ b/unittest/Makefile.am @@ -1,10 +1,10 @@ -SUBDIRS = mytap . mysys examples +SUBDIRS = mytap mysys maria examples noinst_SCRIPTS = unit EXTRA_DIST = unit.pl CLEANFILES = unit -unittests = mytap mysys +unittests = mytap mysys maria test: unit ./unit run $(unittests) diff --git a/unittest/maria/Makefile.am b/unittest/maria/Makefile.am new file mode 100644 index 00000000000..667d1e09a07 --- /dev/null +++ b/unittest/maria/Makefile.am @@ -0,0 +1,12 @@ + +AM_CPPFLAGS = @ZLIB_INCLUDES@ -I$(top_builddir)/include +AM_CPPFLAGS += -I$(top_srcdir)/include -I$(top_srcdir)/unittest/mytap + +LDADD = $(top_builddir)/unittest/mytap/libmytap.a \ + $(top_builddir)/storage/maria/libmaria.a \ + $(top_builddir)/mysys/libmysys.a \ + $(top_builddir)/dbug/libdbug.a \ + $(top_builddir)/strings/libmystrings.a + +noinst_PROGRAMS = trxman-t + diff --git a/unittest/maria/trxman-t.c b/unittest/maria/trxman-t.c new file mode 100644 index 00000000000..a29bf5abc8e --- /dev/null +++ b/unittest/maria/trxman-t.c @@ -0,0 +1,138 @@ +/* Copyright (C) 2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include + +#include +#include +#include +#include +#include "../../storage/maria/trxman.h" + +pthread_attr_t rt_attr; +pthread_mutex_t rt_mutex; +pthread_cond_t rt_cond; +int rt_num_threads; + +int litmus; + +/* template for a test: the goal is to have litmus==0 if the test passed + +#define ITER nnn +pthread_handler_t test_XXXXXXXX(void *arg) +{ + int m=(*(int *)arg)/ITER, x; + + for (x=((int)(intptr)(&m)); m ; m--) + { + // do something with litmus + } + // do something more with litmus + + pthread_mutex_lock(&rt_mutex); + rt_num_threads--; + if (!rt_num_threads) + { + diag("whatever diagnostics we want", blabla, foobar); + pthread_cond_signal(&rt_cond); + } + pthread_mutex_unlock(&rt_mutex); + return 0; +} +#undef ITER + +*/ + +/* + create and end (commit or rollback) transactions randomly +*/ +#define MAX_ITER 100 +pthread_handler_t test_trxman(void *arg) +{ + int m=(*(int *)arg); + uint x, y, i, j, n; + TRX *trx[MAX_ITER]; + + for (x=((int)(intptr)(&m)); m > 0; ) + { + y= x= (x*3628273133 + 1500450271) % 9576890767; /* three prime numbers */ + m-= n= x % MAX_ITER; + for (i=0; i < n; i++) + trx[i]=trxman_new_trx(); + for (i=0; i < n; i++) + { + y=(y*19 + 7) % 31; + trxman_end_trx(trx[i], y & 1); + } + } + + pthread_mutex_lock(&rt_mutex); + rt_num_threads--; + if (!rt_num_threads) + pthread_cond_signal(&rt_cond); + pthread_mutex_unlock(&rt_mutex); + return 0; +} +#undef MAX_ITER + +void run_test(const char *test, pthread_handler handler, int n, int m) +{ + pthread_t t; + ulonglong now=my_getsystime(); + + litmus= 0; + + diag("Testing %s with %d threads, %d iterations... ", test, n, m); + for (rt_num_threads=n ; n ; n--) + pthread_create(&t, &rt_attr, handler, &m); + pthread_mutex_lock(&rt_mutex); + while (rt_num_threads) + pthread_cond_wait(&rt_cond, &rt_mutex); + pthread_mutex_unlock(&rt_mutex); + now=my_getsystime()-now; + ok(litmus == 0, "tested %s in %g secs (%d)", test, ((double)now)/1e7, litmus); +} + +int global_malloc=0; +int main() +{ + plan(1); + + if (my_atomic_initialize()) + return exit_status(); + + my_init(); + + pthread_attr_init(&rt_attr); + pthread_attr_setdetachstate(&rt_attr,PTHREAD_CREATE_DETACHED); + pthread_mutex_init(&rt_mutex, 0); + pthread_cond_init(&rt_cond, 0); + +#define CYCLES 10000 +#define THREADS 10 + + trxman_init(); + run_test("trxman", test_trxman, THREADS,CYCLES); + trxman_destroy(); + diag("mallocs: %d\n", global_malloc); + + pthread_mutex_destroy(&rt_mutex); + pthread_cond_destroy(&rt_cond); + pthread_attr_destroy(&rt_attr); + my_end(0); + return exit_status(); +} + diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index 1e7206441eb..8962131d45a 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -14,9 +14,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -//#define MY_ATOMIC_MODE_RWLOCKS -//#define MY_ATOMIC_MODE_DUMMY - #include #include @@ -41,7 +38,7 @@ pthread_handler_t test_atomic_add_handler(void *arg) int32 x; for (x=((int)(intptr)(&m)); m ; m--) { - x=x*m+0x87654321; + x=(x*m+0x87654321) & INT_MAX32; my_atomic_rwlock_wrlock(&rwl); my_atomic_add32(&a32, x); my_atomic_rwlock_wrunlock(&rwl); @@ -111,7 +108,7 @@ pthread_handler_t test_atomic_cas_handler(void *arg) my_atomic_rwlock_wrlock(&rwl); y=my_atomic_load32(&a32); my_atomic_rwlock_wrunlock(&rwl); - x=x*m+0x87654321; + x=(x*m+0x87654321) & INT_MAX32; do { my_atomic_rwlock_wrlock(&rwl); ok=my_atomic_cas32(&a32, &y, y+x); @@ -171,7 +168,7 @@ pthread_handler_t test_lf_alloc(void *arg) for (x=((int)(intptr)(&m)); m ; m--) { TLA *node1, *node2; - x=x*m+0x87654321; + x=(x*m+0x87654321) & INT_MAX32; node1=(TLA *)lf_alloc_new(pins); node1->data=x; y+=node1->data; @@ -217,7 +214,7 @@ pthread_handler_t test_lf_hash(void *arg) y=x; for (i=0; i < N_TLH; i++) { - x=x*(m+i)+0x87654321; + x=(x*(m+i)+0x87654321) & INT_MAX32; z=(x<0) ? -x : x; if (lf_hash_insert(&lf_hash, pins, &z)) { @@ -227,7 +224,7 @@ pthread_handler_t test_lf_hash(void *arg) } for (i=0; i < N_TLH; i++) { - y=y*(m+i)+0x87654321; + y=(y*(m+i)+0x87654321) & INT_MAX32; z=(y<0) ? -y : y; if (lf_hash_delete(&lf_hash, pins, (uchar *)&z, sizeof(z))) sum-=z; @@ -307,8 +304,8 @@ int main() test_atomic("lf_alloc", test_lf_alloc, THREADS,CYCLES); test_atomic("lf_hash", test_lf_hash, THREADS,CYCLES); - lf_hash_end(&lf_hash); - lf_alloc_end(&lf_allocator); + lf_hash_destroy(&lf_hash); + lf_alloc_destroy(&lf_allocator); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); pthread_attr_destroy(&thr_attr); -- cgit v1.2.1 From d83bc171b6775281d556604b47d6d13a8bf5cecf Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Aug 2006 17:27:21 +0200 Subject: renamed global variables --- unittest/maria/trxman-t.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'unittest') diff --git a/unittest/maria/trxman-t.c b/unittest/maria/trxman-t.c index a29bf5abc8e..7536e5534bf 100644 --- a/unittest/maria/trxman-t.c +++ b/unittest/maria/trxman-t.c @@ -106,7 +106,6 @@ void run_test(const char *test, pthread_handler handler, int n, int m) ok(litmus == 0, "tested %s in %g secs (%d)", test, ((double)now)/1e7, litmus); } -int global_malloc=0; int main() { plan(1); @@ -127,7 +126,7 @@ int main() trxman_init(); run_test("trxman", test_trxman, THREADS,CYCLES); trxman_destroy(); - diag("mallocs: %d\n", global_malloc); + diag("mallocs: %d\n", trxman_allocated_transactions); pthread_mutex_destroy(&rt_mutex); pthread_cond_destroy(&rt_cond); -- cgit v1.2.1 From 26fb36067a97b21e12fc2704fd08f9ddfd231ded Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Sep 2006 16:12:31 +0200 Subject: WL#3234 Maria control file manager. Fitting ma_control_file_test into the mytap unittest framework: new directories: - unittest/storage/ for unit tests of any storage engine - unittest/storage/maria for ... Maria, containing ma_control_file-t. Later, older tests like ma_test*, ma_test_all (but which is Unix dependent in its current form) could move here too. The plugins macro enable building of unittest/storage/X for any enabled engine X which has such a directory. If Falcon wants to have unit tests there too, I may have to merge this patch into 5.x one day. config/ac-macros/plugins.m4: If a storage engine has a directory in unittest/storage, build this directory. configure.in: build storage engines' unit tests. storage/maria/Makefile.am: ma_control_file_test moves to unittest/storage/maria storage/maria/ma_control_file.c: more error codes when opening the control file fails. ma_control_file_end() may now return an error if my_close() failed. storage/maria/ma_control_file.h: more error codes when opening the control file fails. unittest/Makefile.am: adding unit tests for storage engines. Note that unit.pl simply recurses into "storage", so if a unit test for storage engine X has been built previously, and now you re-configure (without making clean) to disable this engine, then the unit test of X will not be rebuilt but will still be present in storage/X, so will be run. unittest/storage/maria/ma_control_file-t.c: Making the test fit the mytap framework (return all the way up the stack instead of assert(); use the mytap functions plan(), ok() etc). Adding test of file too short/long. unittest/storage/maria/Makefile.am: a_control_file-t is added to the Maria unit tests. Later, older tests (ma_test1 etc) could also move here. unittest/storage/Makefile.am: New BitKeeper file ``unittest/storage/Makefile.am'' --- unittest/Makefile.am | 4 +- unittest/storage/Makefile.am | 27 ++ unittest/storage/maria/Makefile.am | 29 ++ unittest/storage/maria/ma_control_file-t.c | 448 +++++++++++++++++++++++++++++ 4 files changed, 506 insertions(+), 2 deletions(-) create mode 100644 unittest/storage/Makefile.am create mode 100644 unittest/storage/maria/Makefile.am create mode 100644 unittest/storage/maria/ma_control_file-t.c (limited to 'unittest') diff --git a/unittest/Makefile.am b/unittest/Makefile.am index ca3291efde0..176ac020bea 100644 --- a/unittest/Makefile.am +++ b/unittest/Makefile.am @@ -1,10 +1,10 @@ -SUBDIRS = mytap . mysys examples +SUBDIRS = mytap . mysys storage examples noinst_SCRIPTS = unit EXTRA_DIST = unit.pl CLEANFILES = unit -unittests = mytap mysys +unittests = mytap mysys storage test: unit ./unit run $(unittests) diff --git a/unittest/storage/Makefile.am b/unittest/storage/Makefile.am new file mode 100644 index 00000000000..21de2de75fc --- /dev/null +++ b/unittest/storage/Makefile.am @@ -0,0 +1,27 @@ +# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Process this file with automake to create Makefile.in + +AUTOMAKE_OPTIONS = foreign + +# These are built from source in the Docs directory +EXTRA_DIST = +# Cannot use @mysql_se_dirs@ as not all engines have unit tests here +SUBDIRS = @mysql_se_unittest_dirs@ + +# Don't update the files from bitkeeper +%::SCCS/s.% diff --git a/unittest/storage/maria/Makefile.am b/unittest/storage/maria/Makefile.am new file mode 100644 index 00000000000..eae2990aea9 --- /dev/null +++ b/unittest/storage/maria/Makefile.am @@ -0,0 +1,29 @@ +# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +AM_CPPFLAGS = @ZLIB_INCLUDES@ -I$(top_builddir)/include +AM_CPPFLAGS += -I$(top_srcdir)/include -I$(top_srcdir)/unittest/mytap + +# 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). +LDADD= $(top_builddir)/unittest/mytap/libmytap.a \ + $(top_builddir)/storage/maria/libmaria.a \ + $(top_builddir)/storage/myisam/libmyisam.a \ + $(top_builddir)/mysys/libmysys.a \ + $(top_builddir)/dbug/libdbug.a \ + $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@ +noinst_PROGRAMS = ma_control_file-t +CLEANFILES = maria_control diff --git a/unittest/storage/maria/ma_control_file-t.c b/unittest/storage/maria/ma_control_file-t.c new file mode 100644 index 00000000000..3ea6932c754 --- /dev/null +++ b/unittest/storage/maria/ma_control_file-t.c @@ -0,0 +1,448 @@ +/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Unit test of the control file module of the Maria engine WL#3234 */ + +/* + Note that it is not possible to test the durability of the write (can't + pull the plug programmatically :) +*/ + +#include +#include +#include + +#ifndef WITH_MARIA_STORAGE_ENGINE +/* + If Maria is not compiled in, normally we don't come to building this test. +*/ +#error "Maria engine is not compiled in, test cannot be built" +#endif + +#include "maria.h" +#include "../../../storage/maria/ma_control_file.h" +#include + +char file_name[FN_REFLEN]; + +/* The values we'll set and expect the control file module to return */ +LSN expect_checkpoint_lsn; +uint32 expect_logno; + +static int delete_file(); +/* + Those are test-specific wrappers around the module's API functions: after + calling the module's API functions they perform checks on the result. +*/ +static int close_file(); /* wraps ma_control_file_end */ +static int create_or_open_file(); /* wraps ma_control_file_open_or_create */ +static int write_file(); /* wraps ma_control_file_write_and_force */ + +/* Tests */ +static int test_one_log(); +static int test_five_logs(); +static int test_3_checkpoints_and_2_logs(); +static int test_binary_content(); +static int test_start_stop(); +static int test_2_open_and_2_close(); +static int test_bad_magic_string(); +static int test_bad_checksum(); +static int test_bad_size(); + +/* Utility */ +static int verify_module_values_match_expected(); +static int verify_module_values_are_impossible(); +static void usage(); +static void get_options(int argc, char *argv[]); + +/* + If "expr" is FALSE, this macro will make the function print a diagnostic + message and immediately return 1. + This is inspired from assert() but does not crash the binary (sometimes we + may want to see how other tests go even if one fails). + RET_ERR means "return error". +*/ + +#define RET_ERR_UNLESS(expr) \ + {if (!(expr)) {diag("line %d: failure: '%s'", __LINE__, #expr); return 1;}} + + +int main(int argc,char *argv[]) +{ + MY_INIT(argv[0]); + + plan(9); + + diag("Unit tests for control file"); + + get_options(argc,argv); + + diag("Deleting control file at startup, if there is an old one"); + RET_ERR_UNLESS(0 == delete_file()); /* if fails, can't continue */ + + diag("Tests of normal conditions"); + ok(0 == test_one_log(), "test of creating one log"); + ok(0 == test_five_logs(), "test of creating five logs"); + ok(0 == test_3_checkpoints_and_2_logs(), + "test of creating three checkpoints and two logs"); + ok(0 == test_binary_content(), "test of the binary content of the file"); + ok(0 == test_start_stop(), "test of multiple starts and stops"); + diag("Tests of abnormal conditions"); + ok(0 == test_2_open_and_2_close(), + "test of two open and two close (strange call sequence)"); + ok(0 == test_bad_magic_string(), "test of bad magic string"); + ok(0 == test_bad_checksum(), "test of bad checksum"); + ok(0 == test_bad_size(), "test of too small/big file"); + + return exit_status(); +} + + +static int delete_file() +{ + RET_ERR_UNLESS(fn_format(file_name, CONTROL_FILE_BASE_NAME, + maria_data_root, "", MYF(MY_WME)) != NullS); + /* + Maybe file does not exist, ignore error. + The error will however be printed on stderr. + */ + my_delete(file_name, MYF(MY_WME)); + expect_checkpoint_lsn= CONTROL_FILE_IMPOSSIBLE_LSN; + expect_logno= CONTROL_FILE_IMPOSSIBLE_FILENO; + + return 0; +} + +/* + Verifies that global values last_checkpoint_lsn and last_logno (belonging + to the module) match what we expect. +*/ +static int verify_module_values_match_expected() +{ + RET_ERR_UNLESS(last_logno == expect_logno); + RET_ERR_UNLESS(last_checkpoint_lsn.file_no == + expect_checkpoint_lsn.file_no); + RET_ERR_UNLESS(last_checkpoint_lsn.rec_offset == + expect_checkpoint_lsn.rec_offset); + return 0; +} + + +/* + Verifies that global values last_checkpoint_lsn and last_logno (belonging + to the module) are impossible (this is used when the file has been closed). +*/ +static int verify_module_values_are_impossible() +{ + RET_ERR_UNLESS(last_logno == CONTROL_FILE_IMPOSSIBLE_FILENO); + RET_ERR_UNLESS(last_checkpoint_lsn.file_no == + CONTROL_FILE_IMPOSSIBLE_FILENO); + RET_ERR_UNLESS(last_checkpoint_lsn.rec_offset == + CONTROL_FILE_IMPOSSIBLE_LOG_OFFSET); + return 0; +} + + +static int close_file() +{ + /* Simulate shutdown */ + ma_control_file_end(); + /* Verify amnesia */ + RET_ERR_UNLESS(verify_module_values_are_impossible() == 0); + return 0; +} + +static int create_or_open_file() +{ + RET_ERR_UNLESS(ma_control_file_create_or_open() == CONTROL_FILE_OK); + /* Check that the module reports expected information */ + RET_ERR_UNLESS(verify_module_values_match_expected() == 0); + return 0; +} + +static int write_file(const LSN *checkpoint_lsn, + uint32 logno, + uint objs_to_write) +{ + RET_ERR_UNLESS(ma_control_file_write_and_force(checkpoint_lsn, logno, + objs_to_write) == 0); + /* Check that the module reports expected information */ + RET_ERR_UNLESS(verify_module_values_match_expected() == 0); + return 0; +} + +static int test_one_log() +{ + uint objs_to_write; + + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO; + expect_logno= 123; + RET_ERR_UNLESS(write_file(NULL, expect_logno, + objs_to_write) == 0); + RET_ERR_UNLESS(close_file() == 0); + return 0; +} + +static int test_five_logs() +{ + uint objs_to_write; + uint i; + + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO; + expect_logno= 100; + for (i= 0; i<5; i++) + { + expect_logno*= 3; + RET_ERR_UNLESS(write_file(NULL, expect_logno, + objs_to_write) == 0); + } + RET_ERR_UNLESS(close_file() == 0); + return 0; +} + +static int test_3_checkpoints_and_2_logs() +{ + uint objs_to_write; + /* + Simulate one checkpoint, one log creation, two checkpoints, one + log creation. + */ + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN; + expect_checkpoint_lsn= (LSN){5, 10000}; + RET_ERR_UNLESS(write_file(&expect_checkpoint_lsn, + expect_logno, objs_to_write) == 0); + + objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO; + expect_logno= 17; + RET_ERR_UNLESS(write_file(&expect_checkpoint_lsn, + expect_logno, objs_to_write) == 0); + + objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN; + expect_checkpoint_lsn= (LSN){17, 20000}; + RET_ERR_UNLESS(write_file(&expect_checkpoint_lsn, + expect_logno, objs_to_write) == 0); + + objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN; + expect_checkpoint_lsn= (LSN){17, 45000}; + RET_ERR_UNLESS(write_file(&expect_checkpoint_lsn, + expect_logno, objs_to_write) == 0); + + objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO; + expect_logno= 19; + RET_ERR_UNLESS(write_file(&expect_checkpoint_lsn, + expect_logno, objs_to_write) == 0); + RET_ERR_UNLESS(close_file() == 0); + return 0; +} + +static int test_binary_content() +{ + uint i; + int fd; + + /* + TEST4: actually check by ourselves the content of the file. + Note that constants (offsets) are hard-coded here, precisely to prevent + someone from changing them in the control file module and breaking + backward-compatibility. + TODO: when we reach the format-freeze state, we may even just do a + comparison with a raw binary string, to not depend on any uint4korr + future change/breakage. + */ + + char buffer[17]; + RET_ERR_UNLESS((fd= my_open(file_name, + O_BINARY | O_RDWR, + MYF(MY_WME))) >= 0); + RET_ERR_UNLESS(my_read(fd, buffer, 17, MYF(MY_FNABP | MY_WME)) == 0); + RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + i= uint4korr(buffer+5); + RET_ERR_UNLESS(i == last_checkpoint_lsn.file_no); + i= uint4korr(buffer+9); + RET_ERR_UNLESS(i == last_checkpoint_lsn.rec_offset); + i= uint4korr(buffer+13); + RET_ERR_UNLESS(i == last_logno); + RET_ERR_UNLESS(close_file() == 0); + return 0; +} + +static int test_start_stop() +{ + /* TEST5: Simulate start/nothing/stop/start/nothing/stop/start */ + + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + RET_ERR_UNLESS(close_file() == 0); + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + RET_ERR_UNLESS(close_file() == 0); + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + RET_ERR_UNLESS(close_file() == 0); + return 0; +} + +static int test_2_open_and_2_close() +{ + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + RET_ERR_UNLESS(close_file() == 0); + RET_ERR_UNLESS(close_file() == 0); + return 0; +} + + +static int test_bad_magic_string() +{ + char buffer[4]; + int fd; + + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + RET_ERR_UNLESS(close_file() == 0); + + /* Corrupt magic string */ + RET_ERR_UNLESS((fd= my_open(file_name, + O_BINARY | O_RDWR, + MYF(MY_WME))) >= 0); + RET_ERR_UNLESS(my_pread(fd, buffer, 4, 0, MYF(MY_FNABP | MY_WME)) == 0); + RET_ERR_UNLESS(my_pwrite(fd, "papa", 4, 0, MYF(MY_FNABP | MY_WME)) == 0); + + /* Check that control file module sees the problem */ + RET_ERR_UNLESS(ma_control_file_create_or_open() == + CONTROL_FILE_BAD_MAGIC_STRING); + /* Restore magic string */ + RET_ERR_UNLESS(my_pwrite(fd, buffer, 4, 0, MYF(MY_FNABP | MY_WME)) == 0); + RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + RET_ERR_UNLESS(close_file() == 0); + return 0; +} + +static int test_bad_checksum() +{ + char buffer[4]; + int fd; + + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + RET_ERR_UNLESS(close_file() == 0); + + /* Corrupt checksum */ + RET_ERR_UNLESS((fd= my_open(file_name, + O_BINARY | O_RDWR, + MYF(MY_WME))) >= 0); + RET_ERR_UNLESS(my_pread(fd, buffer, 1, 4, MYF(MY_FNABP | MY_WME)) == 0); + buffer[0]+= 3; /* mangle checksum */ + RET_ERR_UNLESS(my_pwrite(fd, buffer+1, 1, 4, MYF(MY_FNABP | MY_WME)) == 0); + /* Check that control file module sees the problem */ + RET_ERR_UNLESS(ma_control_file_create_or_open() == + CONTROL_FILE_BAD_CHECKSUM); + /* Restore checksum */ + buffer[0]-= 3; + RET_ERR_UNLESS(my_pwrite(fd, buffer+1, 1, 4, MYF(MY_FNABP | MY_WME)) == 0); + RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); + + return 0; +} + + +static int test_bad_size() +{ + char buffer[]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + int fd; + + /* A too short file */ + RET_ERR_UNLESS(delete_file() == 0); + RET_ERR_UNLESS((fd= my_open(file_name, + O_BINARY | O_RDWR | O_CREAT, + MYF(MY_WME))) >= 0); + RET_ERR_UNLESS(my_write(fd, buffer, 10, MYF(MY_FNABP | MY_WME)) == 0); + /* Check that control file module sees the problem */ + RET_ERR_UNLESS(ma_control_file_create_or_open() == CONTROL_FILE_TOO_SMALL); + RET_ERR_UNLESS(my_write(fd, buffer, 30, MYF(MY_FNABP | MY_WME)) == 0); + /* Check that control file module sees the problem */ + RET_ERR_UNLESS(ma_control_file_create_or_open() == CONTROL_FILE_TOO_BIG); + RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); + + /* Leave a correct control file */ + RET_ERR_UNLESS(delete_file() == 0); + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + RET_ERR_UNLESS(close_file() == 0); + + return 0; +} + + +static struct my_option my_long_options[] = +{ +#ifndef DBUG_OFF + {"debug", '#', "Debug log.", + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#endif + {"help", '?', "Display help and exit", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"version", 'V', "Print version number and exit", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; + + +static void version() +{ + printf("ma_control_file_test: unit test for the control file " + "module of the Maria storage engine. Ver 1.0 \n"); +} + +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch(optid) { + case 'V': + version(); + exit(0); + case '#': + DBUG_PUSH (argument); + break; + case '?': + version(); + usage(); + exit(0); + } + return 0; +} + + +/* Read options */ + +static void get_options(int argc, char *argv[]) +{ + int ho_error; + + if ((ho_error=handle_options(&argc, &argv, my_long_options, + get_one_option))) + exit(ho_error); + + return; +} /* get options */ + + +static void usage() +{ + printf("Usage: %s [options]\n\n", my_progname); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} -- cgit v1.2.1 From 15b9ce2201453ce7ecc346b053910023e7d51b83 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 15:52:01 +0200 Subject: WL#3234 Maria control file Fixes after Brian's and Serg's comments: storage engine's unit tests are now in storage//unittest instead of unittest/storage/ BitKeeper/deleted/.del-Makefile.am~78ea2e42d44d121f: Delete: unittest/storage/maria/Makefile.am BitKeeper/deleted/.del-Makefile.am~80497dbf1a80bdf3: Delete: unittest/storage/Makefile.am storage/maria/unittest/ma_control_file-t.c: Rename: unittest/storage/maria/ma_control_file-t.c -> storage/maria/unittest/ma_control_file-t.c config/ac-macros/plugins.m4: we change from unittest/storage// to storage//unittest: if the engine is enabled has such a directory, build this directory, and add it to the list of unit tests to run. configure.in: this dir does not exist anymore storage/maria/Makefile.am: to build Maria unittests, libmaria must be built. unittest/Makefile.am: unittest/storage is removed. target "unitests" is defined at "configure" time based on enabled engines. storage/maria/unittest/Makefile.am: simple Makefile.am to build ma_control_file-t --- unittest/Makefile.am | 4 +- unittest/storage/Makefile.am | 27 -- unittest/storage/maria/Makefile.am | 29 -- unittest/storage/maria/ma_control_file-t.c | 448 ----------------------------- 4 files changed, 2 insertions(+), 506 deletions(-) delete mode 100644 unittest/storage/Makefile.am delete mode 100644 unittest/storage/maria/Makefile.am delete mode 100644 unittest/storage/maria/ma_control_file-t.c (limited to 'unittest') diff --git a/unittest/Makefile.am b/unittest/Makefile.am index 176ac020bea..76004e67fae 100644 --- a/unittest/Makefile.am +++ b/unittest/Makefile.am @@ -1,10 +1,10 @@ -SUBDIRS = mytap . mysys storage examples +SUBDIRS = mytap . mysys examples noinst_SCRIPTS = unit EXTRA_DIST = unit.pl CLEANFILES = unit -unittests = mytap mysys storage +unittests = mytap mysys @mysql_se_unittest_dirs@ test: unit ./unit run $(unittests) diff --git a/unittest/storage/Makefile.am b/unittest/storage/Makefile.am deleted file mode 100644 index 21de2de75fc..00000000000 --- a/unittest/storage/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -# Process this file with automake to create Makefile.in - -AUTOMAKE_OPTIONS = foreign - -# These are built from source in the Docs directory -EXTRA_DIST = -# Cannot use @mysql_se_dirs@ as not all engines have unit tests here -SUBDIRS = @mysql_se_unittest_dirs@ - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/unittest/storage/maria/Makefile.am b/unittest/storage/maria/Makefile.am deleted file mode 100644 index eae2990aea9..00000000000 --- a/unittest/storage/maria/Makefile.am +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -AM_CPPFLAGS = @ZLIB_INCLUDES@ -I$(top_builddir)/include -AM_CPPFLAGS += -I$(top_srcdir)/include -I$(top_srcdir)/unittest/mytap - -# 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). -LDADD= $(top_builddir)/unittest/mytap/libmytap.a \ - $(top_builddir)/storage/maria/libmaria.a \ - $(top_builddir)/storage/myisam/libmyisam.a \ - $(top_builddir)/mysys/libmysys.a \ - $(top_builddir)/dbug/libdbug.a \ - $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@ -noinst_PROGRAMS = ma_control_file-t -CLEANFILES = maria_control diff --git a/unittest/storage/maria/ma_control_file-t.c b/unittest/storage/maria/ma_control_file-t.c deleted file mode 100644 index 3ea6932c754..00000000000 --- a/unittest/storage/maria/ma_control_file-t.c +++ /dev/null @@ -1,448 +0,0 @@ -/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* Unit test of the control file module of the Maria engine WL#3234 */ - -/* - Note that it is not possible to test the durability of the write (can't - pull the plug programmatically :) -*/ - -#include -#include -#include - -#ifndef WITH_MARIA_STORAGE_ENGINE -/* - If Maria is not compiled in, normally we don't come to building this test. -*/ -#error "Maria engine is not compiled in, test cannot be built" -#endif - -#include "maria.h" -#include "../../../storage/maria/ma_control_file.h" -#include - -char file_name[FN_REFLEN]; - -/* The values we'll set and expect the control file module to return */ -LSN expect_checkpoint_lsn; -uint32 expect_logno; - -static int delete_file(); -/* - Those are test-specific wrappers around the module's API functions: after - calling the module's API functions they perform checks on the result. -*/ -static int close_file(); /* wraps ma_control_file_end */ -static int create_or_open_file(); /* wraps ma_control_file_open_or_create */ -static int write_file(); /* wraps ma_control_file_write_and_force */ - -/* Tests */ -static int test_one_log(); -static int test_five_logs(); -static int test_3_checkpoints_and_2_logs(); -static int test_binary_content(); -static int test_start_stop(); -static int test_2_open_and_2_close(); -static int test_bad_magic_string(); -static int test_bad_checksum(); -static int test_bad_size(); - -/* Utility */ -static int verify_module_values_match_expected(); -static int verify_module_values_are_impossible(); -static void usage(); -static void get_options(int argc, char *argv[]); - -/* - If "expr" is FALSE, this macro will make the function print a diagnostic - message and immediately return 1. - This is inspired from assert() but does not crash the binary (sometimes we - may want to see how other tests go even if one fails). - RET_ERR means "return error". -*/ - -#define RET_ERR_UNLESS(expr) \ - {if (!(expr)) {diag("line %d: failure: '%s'", __LINE__, #expr); return 1;}} - - -int main(int argc,char *argv[]) -{ - MY_INIT(argv[0]); - - plan(9); - - diag("Unit tests for control file"); - - get_options(argc,argv); - - diag("Deleting control file at startup, if there is an old one"); - RET_ERR_UNLESS(0 == delete_file()); /* if fails, can't continue */ - - diag("Tests of normal conditions"); - ok(0 == test_one_log(), "test of creating one log"); - ok(0 == test_five_logs(), "test of creating five logs"); - ok(0 == test_3_checkpoints_and_2_logs(), - "test of creating three checkpoints and two logs"); - ok(0 == test_binary_content(), "test of the binary content of the file"); - ok(0 == test_start_stop(), "test of multiple starts and stops"); - diag("Tests of abnormal conditions"); - ok(0 == test_2_open_and_2_close(), - "test of two open and two close (strange call sequence)"); - ok(0 == test_bad_magic_string(), "test of bad magic string"); - ok(0 == test_bad_checksum(), "test of bad checksum"); - ok(0 == test_bad_size(), "test of too small/big file"); - - return exit_status(); -} - - -static int delete_file() -{ - RET_ERR_UNLESS(fn_format(file_name, CONTROL_FILE_BASE_NAME, - maria_data_root, "", MYF(MY_WME)) != NullS); - /* - Maybe file does not exist, ignore error. - The error will however be printed on stderr. - */ - my_delete(file_name, MYF(MY_WME)); - expect_checkpoint_lsn= CONTROL_FILE_IMPOSSIBLE_LSN; - expect_logno= CONTROL_FILE_IMPOSSIBLE_FILENO; - - return 0; -} - -/* - Verifies that global values last_checkpoint_lsn and last_logno (belonging - to the module) match what we expect. -*/ -static int verify_module_values_match_expected() -{ - RET_ERR_UNLESS(last_logno == expect_logno); - RET_ERR_UNLESS(last_checkpoint_lsn.file_no == - expect_checkpoint_lsn.file_no); - RET_ERR_UNLESS(last_checkpoint_lsn.rec_offset == - expect_checkpoint_lsn.rec_offset); - return 0; -} - - -/* - Verifies that global values last_checkpoint_lsn and last_logno (belonging - to the module) are impossible (this is used when the file has been closed). -*/ -static int verify_module_values_are_impossible() -{ - RET_ERR_UNLESS(last_logno == CONTROL_FILE_IMPOSSIBLE_FILENO); - RET_ERR_UNLESS(last_checkpoint_lsn.file_no == - CONTROL_FILE_IMPOSSIBLE_FILENO); - RET_ERR_UNLESS(last_checkpoint_lsn.rec_offset == - CONTROL_FILE_IMPOSSIBLE_LOG_OFFSET); - return 0; -} - - -static int close_file() -{ - /* Simulate shutdown */ - ma_control_file_end(); - /* Verify amnesia */ - RET_ERR_UNLESS(verify_module_values_are_impossible() == 0); - return 0; -} - -static int create_or_open_file() -{ - RET_ERR_UNLESS(ma_control_file_create_or_open() == CONTROL_FILE_OK); - /* Check that the module reports expected information */ - RET_ERR_UNLESS(verify_module_values_match_expected() == 0); - return 0; -} - -static int write_file(const LSN *checkpoint_lsn, - uint32 logno, - uint objs_to_write) -{ - RET_ERR_UNLESS(ma_control_file_write_and_force(checkpoint_lsn, logno, - objs_to_write) == 0); - /* Check that the module reports expected information */ - RET_ERR_UNLESS(verify_module_values_match_expected() == 0); - return 0; -} - -static int test_one_log() -{ - uint objs_to_write; - - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO; - expect_logno= 123; - RET_ERR_UNLESS(write_file(NULL, expect_logno, - objs_to_write) == 0); - RET_ERR_UNLESS(close_file() == 0); - return 0; -} - -static int test_five_logs() -{ - uint objs_to_write; - uint i; - - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO; - expect_logno= 100; - for (i= 0; i<5; i++) - { - expect_logno*= 3; - RET_ERR_UNLESS(write_file(NULL, expect_logno, - objs_to_write) == 0); - } - RET_ERR_UNLESS(close_file() == 0); - return 0; -} - -static int test_3_checkpoints_and_2_logs() -{ - uint objs_to_write; - /* - Simulate one checkpoint, one log creation, two checkpoints, one - log creation. - */ - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN; - expect_checkpoint_lsn= (LSN){5, 10000}; - RET_ERR_UNLESS(write_file(&expect_checkpoint_lsn, - expect_logno, objs_to_write) == 0); - - objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO; - expect_logno= 17; - RET_ERR_UNLESS(write_file(&expect_checkpoint_lsn, - expect_logno, objs_to_write) == 0); - - objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN; - expect_checkpoint_lsn= (LSN){17, 20000}; - RET_ERR_UNLESS(write_file(&expect_checkpoint_lsn, - expect_logno, objs_to_write) == 0); - - objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN; - expect_checkpoint_lsn= (LSN){17, 45000}; - RET_ERR_UNLESS(write_file(&expect_checkpoint_lsn, - expect_logno, objs_to_write) == 0); - - objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO; - expect_logno= 19; - RET_ERR_UNLESS(write_file(&expect_checkpoint_lsn, - expect_logno, objs_to_write) == 0); - RET_ERR_UNLESS(close_file() == 0); - return 0; -} - -static int test_binary_content() -{ - uint i; - int fd; - - /* - TEST4: actually check by ourselves the content of the file. - Note that constants (offsets) are hard-coded here, precisely to prevent - someone from changing them in the control file module and breaking - backward-compatibility. - TODO: when we reach the format-freeze state, we may even just do a - comparison with a raw binary string, to not depend on any uint4korr - future change/breakage. - */ - - char buffer[17]; - RET_ERR_UNLESS((fd= my_open(file_name, - O_BINARY | O_RDWR, - MYF(MY_WME))) >= 0); - RET_ERR_UNLESS(my_read(fd, buffer, 17, MYF(MY_FNABP | MY_WME)) == 0); - RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - i= uint4korr(buffer+5); - RET_ERR_UNLESS(i == last_checkpoint_lsn.file_no); - i= uint4korr(buffer+9); - RET_ERR_UNLESS(i == last_checkpoint_lsn.rec_offset); - i= uint4korr(buffer+13); - RET_ERR_UNLESS(i == last_logno); - RET_ERR_UNLESS(close_file() == 0); - return 0; -} - -static int test_start_stop() -{ - /* TEST5: Simulate start/nothing/stop/start/nothing/stop/start */ - - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - RET_ERR_UNLESS(close_file() == 0); - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - RET_ERR_UNLESS(close_file() == 0); - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - RET_ERR_UNLESS(close_file() == 0); - return 0; -} - -static int test_2_open_and_2_close() -{ - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - RET_ERR_UNLESS(close_file() == 0); - RET_ERR_UNLESS(close_file() == 0); - return 0; -} - - -static int test_bad_magic_string() -{ - char buffer[4]; - int fd; - - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - RET_ERR_UNLESS(close_file() == 0); - - /* Corrupt magic string */ - RET_ERR_UNLESS((fd= my_open(file_name, - O_BINARY | O_RDWR, - MYF(MY_WME))) >= 0); - RET_ERR_UNLESS(my_pread(fd, buffer, 4, 0, MYF(MY_FNABP | MY_WME)) == 0); - RET_ERR_UNLESS(my_pwrite(fd, "papa", 4, 0, MYF(MY_FNABP | MY_WME)) == 0); - - /* Check that control file module sees the problem */ - RET_ERR_UNLESS(ma_control_file_create_or_open() == - CONTROL_FILE_BAD_MAGIC_STRING); - /* Restore magic string */ - RET_ERR_UNLESS(my_pwrite(fd, buffer, 4, 0, MYF(MY_FNABP | MY_WME)) == 0); - RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - RET_ERR_UNLESS(close_file() == 0); - return 0; -} - -static int test_bad_checksum() -{ - char buffer[4]; - int fd; - - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - RET_ERR_UNLESS(close_file() == 0); - - /* Corrupt checksum */ - RET_ERR_UNLESS((fd= my_open(file_name, - O_BINARY | O_RDWR, - MYF(MY_WME))) >= 0); - RET_ERR_UNLESS(my_pread(fd, buffer, 1, 4, MYF(MY_FNABP | MY_WME)) == 0); - buffer[0]+= 3; /* mangle checksum */ - RET_ERR_UNLESS(my_pwrite(fd, buffer+1, 1, 4, MYF(MY_FNABP | MY_WME)) == 0); - /* Check that control file module sees the problem */ - RET_ERR_UNLESS(ma_control_file_create_or_open() == - CONTROL_FILE_BAD_CHECKSUM); - /* Restore checksum */ - buffer[0]-= 3; - RET_ERR_UNLESS(my_pwrite(fd, buffer+1, 1, 4, MYF(MY_FNABP | MY_WME)) == 0); - RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); - - return 0; -} - - -static int test_bad_size() -{ - char buffer[]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - int fd; - - /* A too short file */ - RET_ERR_UNLESS(delete_file() == 0); - RET_ERR_UNLESS((fd= my_open(file_name, - O_BINARY | O_RDWR | O_CREAT, - MYF(MY_WME))) >= 0); - RET_ERR_UNLESS(my_write(fd, buffer, 10, MYF(MY_FNABP | MY_WME)) == 0); - /* Check that control file module sees the problem */ - RET_ERR_UNLESS(ma_control_file_create_or_open() == CONTROL_FILE_TOO_SMALL); - RET_ERR_UNLESS(my_write(fd, buffer, 30, MYF(MY_FNABP | MY_WME)) == 0); - /* Check that control file module sees the problem */ - RET_ERR_UNLESS(ma_control_file_create_or_open() == CONTROL_FILE_TOO_BIG); - RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); - - /* Leave a correct control file */ - RET_ERR_UNLESS(delete_file() == 0); - RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - RET_ERR_UNLESS(close_file() == 0); - - return 0; -} - - -static struct my_option my_long_options[] = -{ -#ifndef DBUG_OFF - {"debug", '#', "Debug log.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif - {"help", '?', "Display help and exit", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"version", 'V', "Print version number and exit", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} -}; - - -static void version() -{ - printf("ma_control_file_test: unit test for the control file " - "module of the Maria storage engine. Ver 1.0 \n"); -} - -static my_bool -get_one_option(int optid, const struct my_option *opt __attribute__((unused)), - char *argument) -{ - switch(optid) { - case 'V': - version(); - exit(0); - case '#': - DBUG_PUSH (argument); - break; - case '?': - version(); - usage(); - exit(0); - } - return 0; -} - - -/* Read options */ - -static void get_options(int argc, char *argv[]) -{ - int ho_error; - - if ((ho_error=handle_options(&argc, &argv, my_long_options, - get_one_option))) - exit(ho_error); - - return; -} /* get options */ - - -static void usage() -{ - printf("Usage: %s [options]\n\n", my_progname); - my_print_help(my_long_options); - my_print_variables(my_long_options); -} -- cgit v1.2.1 From 09a7f30973304620e00b934597b72f7dd7eeb966 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Sep 2006 11:05:35 +0200 Subject: WL#3234 Maria Control file manager last round of fixes to the storage engines' and plugins' unit tests structure. Will extract a total patch and push it in 5.1 as has been approved. Makefile.am: unittest must be before storage and plugin, because engine and plugin may have unit tests which link with libtap which is found in unitttest. config/ac-macros/plugins.m4: When enabling an engine/plugin, add its directory to the list of directories where unit tests should be searched. That is, its directory will be recursively searched by our unit test framework which will execute any executable *-t file. storage/maria/ma_control_file.c: those my_message pollute the output of unit tests. storage/maria/plug.in: When Maria is enabled, add its unittest Makefile. unittest/Makefile.am: plugins too --- unittest/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'unittest') diff --git a/unittest/Makefile.am b/unittest/Makefile.am index 76004e67fae..7323ef5fb77 100644 --- a/unittest/Makefile.am +++ b/unittest/Makefile.am @@ -4,7 +4,7 @@ noinst_SCRIPTS = unit EXTRA_DIST = unit.pl CLEANFILES = unit -unittests = mytap mysys @mysql_se_unittest_dirs@ +unittests = mytap mysys @mysql_se_unittest_dirs@ @mysql_pg_unittest_dirs@ test: unit ./unit run $(unittests) -- cgit v1.2.1 From c2872bafde6d6ec2444c293f7a8aa397eb1dbb59 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Oct 2006 11:37:27 +0200 Subject: push for trnman review (lockmanager still fails unit tests) BitKeeper/deleted/.del-Makefile.am~4375ae3d4de2bdf0: Delete: unittest/maria/Makefile.am configure.in: silence up configure warnings, don't generate unittest/maria/Makefile include/atomic/nolock.h: s/LOCK/LOCK_prefix/ include/atomic/x86-gcc.h: s/LOCK/LOCK_prefix/ include/atomic/x86-msvc.h: s/LOCK/LOCK_prefix/ include/lf.h: pin asserts, renames include/my_atomic.h: move cleanup include/my_bit.h: s/uint/uint32/ mysys/lf_dynarray.c: style fixes, split for() in two, remove if()s mysys/lf_hash.c: renames, minor fixes mysys/my_atomic.c: run-time assert -> compile-time assert storage/maria/Makefile.am: lockman here storage/maria/unittest/Makefile.am: new unit tests storage/maria/unittest/trnman-t.c: lots of changes storage/maria/lockman.c: many changes: second meaning of "blocker" portability: s/gettimeofday/my_getsystime/ move mutex/cond out of LOCK_OWNER - it creates a race condition that will be fixed in a separate changeset increment lm->count for every element, not only for distinct ones - because we cannot decrease it for distinct elements only :( storage/maria/lockman.h: move mutex/cond out of LOCK_OWNER storage/maria/trnman.c: move mutex/cond out of LOCK_OWNER atomic-ops to access short_trid_to_trn[] storage/maria/trnman.h: move mutex/cond out of LOCK_OWNER storage/maria/unittest/lockman-t.c: unit stress test --- unittest/maria/Makefile.am | 12 ---- unittest/maria/trxman-t.c | 137 --------------------------------------------- 2 files changed, 149 deletions(-) delete mode 100644 unittest/maria/Makefile.am delete mode 100644 unittest/maria/trxman-t.c (limited to 'unittest') diff --git a/unittest/maria/Makefile.am b/unittest/maria/Makefile.am deleted file mode 100644 index 667d1e09a07..00000000000 --- a/unittest/maria/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ - -AM_CPPFLAGS = @ZLIB_INCLUDES@ -I$(top_builddir)/include -AM_CPPFLAGS += -I$(top_srcdir)/include -I$(top_srcdir)/unittest/mytap - -LDADD = $(top_builddir)/unittest/mytap/libmytap.a \ - $(top_builddir)/storage/maria/libmaria.a \ - $(top_builddir)/mysys/libmysys.a \ - $(top_builddir)/dbug/libdbug.a \ - $(top_builddir)/strings/libmystrings.a - -noinst_PROGRAMS = trxman-t - diff --git a/unittest/maria/trxman-t.c b/unittest/maria/trxman-t.c deleted file mode 100644 index 7536e5534bf..00000000000 --- a/unittest/maria/trxman-t.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright (C) 2006 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include - -#include -#include -#include -#include -#include "../../storage/maria/trxman.h" - -pthread_attr_t rt_attr; -pthread_mutex_t rt_mutex; -pthread_cond_t rt_cond; -int rt_num_threads; - -int litmus; - -/* template for a test: the goal is to have litmus==0 if the test passed - -#define ITER nnn -pthread_handler_t test_XXXXXXXX(void *arg) -{ - int m=(*(int *)arg)/ITER, x; - - for (x=((int)(intptr)(&m)); m ; m--) - { - // do something with litmus - } - // do something more with litmus - - pthread_mutex_lock(&rt_mutex); - rt_num_threads--; - if (!rt_num_threads) - { - diag("whatever diagnostics we want", blabla, foobar); - pthread_cond_signal(&rt_cond); - } - pthread_mutex_unlock(&rt_mutex); - return 0; -} -#undef ITER - -*/ - -/* - create and end (commit or rollback) transactions randomly -*/ -#define MAX_ITER 100 -pthread_handler_t test_trxman(void *arg) -{ - int m=(*(int *)arg); - uint x, y, i, j, n; - TRX *trx[MAX_ITER]; - - for (x=((int)(intptr)(&m)); m > 0; ) - { - y= x= (x*3628273133 + 1500450271) % 9576890767; /* three prime numbers */ - m-= n= x % MAX_ITER; - for (i=0; i < n; i++) - trx[i]=trxman_new_trx(); - for (i=0; i < n; i++) - { - y=(y*19 + 7) % 31; - trxman_end_trx(trx[i], y & 1); - } - } - - pthread_mutex_lock(&rt_mutex); - rt_num_threads--; - if (!rt_num_threads) - pthread_cond_signal(&rt_cond); - pthread_mutex_unlock(&rt_mutex); - return 0; -} -#undef MAX_ITER - -void run_test(const char *test, pthread_handler handler, int n, int m) -{ - pthread_t t; - ulonglong now=my_getsystime(); - - litmus= 0; - - diag("Testing %s with %d threads, %d iterations... ", test, n, m); - for (rt_num_threads=n ; n ; n--) - pthread_create(&t, &rt_attr, handler, &m); - pthread_mutex_lock(&rt_mutex); - while (rt_num_threads) - pthread_cond_wait(&rt_cond, &rt_mutex); - pthread_mutex_unlock(&rt_mutex); - now=my_getsystime()-now; - ok(litmus == 0, "tested %s in %g secs (%d)", test, ((double)now)/1e7, litmus); -} - -int main() -{ - plan(1); - - if (my_atomic_initialize()) - return exit_status(); - - my_init(); - - pthread_attr_init(&rt_attr); - pthread_attr_setdetachstate(&rt_attr,PTHREAD_CREATE_DETACHED); - pthread_mutex_init(&rt_mutex, 0); - pthread_cond_init(&rt_cond, 0); - -#define CYCLES 10000 -#define THREADS 10 - - trxman_init(); - run_test("trxman", test_trxman, THREADS,CYCLES); - trxman_destroy(); - diag("mallocs: %d\n", trxman_allocated_transactions); - - pthread_mutex_destroy(&rt_mutex); - pthread_cond_destroy(&rt_cond); - pthread_attr_destroy(&rt_attr); - my_end(0); - return exit_status(); -} - -- cgit v1.2.1 From 12a55aeabc353fdc1c3829ddd8baacb142160c80 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Oct 2006 17:24:07 +0200 Subject: lock manager passed unit tests storage/maria/trnman.c: comments include/my_dbug.h: make DBUG_ASSERT always a statement storage/maria/lockman.h: comments include/lf.h: lf_pinbox - don't use a fixed-size purgatory. mysys/lf_alloc-pin.c: lf_pinbox - don't use a fixed-size purgatory. mysys/lf_hash.c: lf_pinbox - don't use a fixed-size purgatory. storage/maria/lockman.c: removed IGNORE_ME/UPGDARED matching - it was wrong in the first place. updated for "lf_pinbox - don't use a fixed-size purgatory" storage/maria/unittest/lockman-t.c: IGNORE_ME/UPGRADED pair counting bugtest. more tests unittest/mysys/my_atomic-t.c: lf_pinbox - don't use a fixed-size purgatory. --- unittest/mysys/my_atomic-t.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index 881f80a66f8..e2177b94720 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -154,7 +154,7 @@ pthread_handler_t test_lf_pinbox(void *arg) typedef union { int32 data; - void *not_used; /* to guarantee sizeof(TLA) >= sizeof(void *) */ + void *not_used; } TLA; pthread_handler_t test_lf_alloc(void *arg) @@ -294,7 +294,7 @@ int main() pthread_mutex_init(&mutex, 0); pthread_cond_init(&cond, 0); my_atomic_rwlock_init(&rwl); - lf_alloc_init(&lf_allocator, sizeof(TLA)); + lf_alloc_init(&lf_allocator, sizeof(TLA), offsetof(TLA, not_used)); lf_hash_init(&lf_hash, sizeof(int), LF_HASH_UNIQUE, 0, sizeof(int), 0, &my_charset_bin); -- cgit v1.2.1 From d1852da743be3a636bba35114d1342b4b11039f0 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 21 Oct 2006 20:06:56 +0200 Subject: less confusing and more correct name for my_atomic_swap --- unittest/mysys/my_atomic-t.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index e2177b94720..a3b2241f5ed 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -62,7 +62,7 @@ pthread_handler_t test_atomic_add_handler(void *arg) 5. subtract result from a32 must get 0 in a32 at the end */ -pthread_handler_t test_atomic_swap_handler(void *arg) +pthread_handler_t test_atomic_fas_handler(void *arg) { int m=*(int *)arg; uint32 x=my_atomic_add32(&b32, 1); @@ -72,14 +72,14 @@ pthread_handler_t test_atomic_swap_handler(void *arg) for (; m ; m--) { my_atomic_rwlock_wrlock(&rwl); - x=my_atomic_swap32(&c32, x); + x=my_atomic_fas32(&c32, x); my_atomic_rwlock_wrunlock(&rwl); } if (!x) { my_atomic_rwlock_wrlock(&rwl); - x=my_atomic_swap32(&c32, x); + x=my_atomic_fas32(&c32, x); my_atomic_rwlock_wrunlock(&rwl); } @@ -306,7 +306,7 @@ int main() #define THREADS 100 test_atomic("my_atomic_add32", test_atomic_add_handler, THREADS,CYCLES); - test_atomic("my_atomic_swap32", test_atomic_swap_handler, THREADS,CYCLES); + test_atomic("my_atomic_fas32", test_atomic_fas_handler, THREADS,CYCLES); test_atomic("my_atomic_cas32", test_atomic_cas_handler, THREADS,CYCLES); test_atomic("lf_pinbox", test_lf_pinbox, THREADS,CYCLES); test_atomic("lf_alloc", test_lf_alloc, THREADS,CYCLES); -- cgit v1.2.1 From 32739cbbcac9b8af23b4708db21bf2854b5e27a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Oct 2006 16:05:18 +0200 Subject: make sure all test threads really exit before main() - workaround for NPTL bug in some linux kernels (Bug#22320) --- unittest/mysys/my_atomic-t.c | 171 ++++++++++++++++++------------------------- 1 file changed, 72 insertions(+), 99 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index a3b2241f5ed..88fa2b03242 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -21,24 +21,19 @@ #include #include -volatile uint32 a32,b32,c32; +volatile uint32 a32,b32,c32, N; my_atomic_rwlock_t rwl; LF_ALLOCATOR lf_allocator; LF_HASH lf_hash; -pthread_attr_t thr_attr; -pthread_mutex_t mutex; -pthread_cond_t cond; -int N; - /* add and sub a random number in a loop. Must get 0 at the end */ pthread_handler_t test_atomic_add_handler(void *arg) { - int m=(*(int *)arg)/2; + int m= (*(int *)arg)/2; int32 x; - for (x=((int)(intptr)(&m)); m ; m--) + for (x= ((int)(intptr)(&m)); m ; m--) { - x=(x*m+0x87654321) & INT_MAX32; + x= (x*m+0x87654321) & INT_MAX32; my_atomic_rwlock_wrlock(&rwl); my_atomic_add32(&a32, x); my_atomic_rwlock_wrunlock(&rwl); @@ -47,10 +42,6 @@ pthread_handler_t test_atomic_add_handler(void *arg) my_atomic_add32(&a32, -x); my_atomic_rwlock_wrunlock(&rwl); } - pthread_mutex_lock(&mutex); - N--; - if (!N) pthread_cond_signal(&cond); - pthread_mutex_unlock(&mutex); return 0; } @@ -64,22 +55,22 @@ pthread_handler_t test_atomic_add_handler(void *arg) */ pthread_handler_t test_atomic_fas_handler(void *arg) { - int m=*(int *)arg; - uint32 x=my_atomic_add32(&b32, 1); + int m= *(int *)arg; + uint32 x= my_atomic_add32(&b32, 1); my_atomic_add32(&a32, x); for (; m ; m--) { my_atomic_rwlock_wrlock(&rwl); - x=my_atomic_fas32(&c32, x); + x= my_atomic_fas32(&c32, x); my_atomic_rwlock_wrunlock(&rwl); } if (!x) { my_atomic_rwlock_wrlock(&rwl); - x=my_atomic_fas32(&c32, x); + x= my_atomic_fas32(&c32, x); my_atomic_rwlock_wrunlock(&rwl); } @@ -87,10 +78,6 @@ pthread_handler_t test_atomic_fas_handler(void *arg) my_atomic_add32(&a32, -x); my_atomic_rwlock_wrunlock(&rwl); - pthread_mutex_lock(&mutex); - N--; - if (!N) pthread_cond_signal(&cond); - pthread_mutex_unlock(&mutex); return 0; } @@ -101,29 +88,25 @@ pthread_handler_t test_atomic_fas_handler(void *arg) */ pthread_handler_t test_atomic_cas_handler(void *arg) { - int m=(*(int *)arg)/2, ok=0; + int m= (*(int *)arg)/2, ok= 0; int32 x, y; - for (x=((int)(intptr)(&m)); m ; m--) + for (x= ((int)(intptr)(&m)); m ; m--) { my_atomic_rwlock_wrlock(&rwl); - y=my_atomic_load32(&a32); + y= my_atomic_load32(&a32); my_atomic_rwlock_wrunlock(&rwl); - x=(x*m+0x87654321) & INT_MAX32; + x= (x*m+0x87654321) & INT_MAX32; do { my_atomic_rwlock_wrlock(&rwl); - ok=my_atomic_cas32(&a32, &y, y+x); + ok= my_atomic_cas32(&a32, &y, y+x); my_atomic_rwlock_wrunlock(&rwl); } while (!ok) ; do { my_atomic_rwlock_wrlock(&rwl); - ok=my_atomic_cas32(&a32, &y, y-x); + ok= my_atomic_cas32(&a32, &y, y-x); my_atomic_rwlock_wrunlock(&rwl); } while (!ok) ; } - pthread_mutex_lock(&mutex); - N--; - if (!N) pthread_cond_signal(&cond); - pthread_mutex_unlock(&mutex); return 0; } @@ -132,23 +115,18 @@ pthread_handler_t test_atomic_cas_handler(void *arg) */ pthread_handler_t test_lf_pinbox(void *arg) { - int m=*(int *)arg; - int32 x=0; + int m= *(int *)arg; + int32 x= 0; LF_PINS *pins; - pins=lf_pinbox_get_pins(&lf_allocator.pinbox); + pins= lf_pinbox_get_pins(&lf_allocator.pinbox); - for (x=((int)(intptr)(&m)); m ; m--) + for (x= ((int)(intptr)(&m)); m ; m--) { lf_pinbox_put_pins(pins); - pins=lf_pinbox_get_pins(&lf_allocator.pinbox); + pins= lf_pinbox_get_pins(&lf_allocator.pinbox); } lf_pinbox_put_pins(pins); - pthread_mutex_lock(&mutex); - N--; - if (!N) - pthread_cond_signal(&cond); - pthread_mutex_unlock(&mutex); return 0; } @@ -159,122 +137,124 @@ typedef union { pthread_handler_t test_lf_alloc(void *arg) { - int m=(*(int *)arg)/2; - int32 x,y=0; + int m= (*(int *)arg)/2; + int32 x,y= 0; LF_PINS *pins; - pins=lf_alloc_get_pins(&lf_allocator); + pins= lf_alloc_get_pins(&lf_allocator); - for (x=((int)(intptr)(&m)); m ; m--) + for (x= ((int)(intptr)(&m)); m ; m--) { TLA *node1, *node2; - x=(x*m+0x87654321) & INT_MAX32; - node1=(TLA *)lf_alloc_new(pins); - node1->data=x; - y+=node1->data; - node1->data=0; - node2=(TLA *)lf_alloc_new(pins); - node2->data=x; - y-=node2->data; - node2->data=0; + x= (x*m+0x87654321) & INT_MAX32; + node1= (TLA *)lf_alloc_new(pins); + node1->data= x; + y+= node1->data; + node1->data= 0; + node2= (TLA *)lf_alloc_new(pins); + node2->data= x; + y-= node2->data; + node2->data= 0; lf_alloc_free(pins, node1); lf_alloc_free(pins, node2); } lf_alloc_put_pins(pins); my_atomic_rwlock_wrlock(&rwl); my_atomic_add32(&a32, y); - my_atomic_rwlock_wrunlock(&rwl); - pthread_mutex_lock(&mutex); - N--; - if (!N) + + if (my_atomic_add32(&N, -1) == 1) { diag("%d mallocs, %d pins in stack", lf_allocator.mallocs, lf_allocator.pinbox.pins_in_stack); #ifdef MY_LF_EXTRA_DEBUG - a32|=lf_allocator.mallocs - lf_alloc_in_pool(&lf_allocator); + a32|= lf_allocator.mallocs - lf_alloc_in_pool(&lf_allocator); #endif - pthread_cond_signal(&cond); } - pthread_mutex_unlock(&mutex); + my_atomic_rwlock_wrunlock(&rwl); return 0; } #define N_TLH 1000 pthread_handler_t test_lf_hash(void *arg) { - int m=(*(int *)arg)/(2*N_TLH); - int32 x,y,z,sum=0, ins=0; + int m= (*(int *)arg)/(2*N_TLH); + int32 x,y,z,sum= 0, ins= 0; LF_PINS *pins; - pins=lf_hash_get_pins(&lf_hash); + pins= lf_hash_get_pins(&lf_hash); - for (x=((int)(intptr)(&m)); m ; m--) + for (x= ((int)(intptr)(&m)); m ; m--) { int i; - y=x; - for (i=0; i < N_TLH; i++) + y= x; + for (i= 0; i < N_TLH; i++) { - x=(x*(m+i)+0x87654321) & INT_MAX32; - z=(x<0) ? -x : x; + x= (x*(m+i)+0x87654321) & INT_MAX32; + z= (x<0) ? -x : x; if (lf_hash_insert(&lf_hash, pins, &z)) { - sum+=z; + sum+= z; ins++; } } - for (i=0; i < N_TLH; i++) + for (i= 0; i < N_TLH; i++) { - y=(y*(m+i)+0x87654321) & INT_MAX32; - z=(y<0) ? -y : y; + y= (y*(m+i)+0x87654321) & INT_MAX32; + z= (y<0) ? -y : y; if (lf_hash_delete(&lf_hash, pins, (uchar *)&z, sizeof(z))) - sum-=z; + sum-= z; } } lf_hash_put_pins(pins); my_atomic_rwlock_wrlock(&rwl); my_atomic_add32(&a32, sum); my_atomic_add32(&b32, ins); - my_atomic_rwlock_wrunlock(&rwl); - pthread_mutex_lock(&mutex); - N--; - if (!N) + my_atomic_add32(&a32, y); + + if (my_atomic_add32(&N, -1) == 1) { diag("%d mallocs, %d pins in stack, %d hash size, %d inserts", lf_hash.alloc.mallocs, lf_hash.alloc.pinbox.pins_in_stack, lf_hash.size, b32); - a32|=lf_hash.count; - pthread_cond_signal(&cond); + a32|= lf_hash.count; } - pthread_mutex_unlock(&mutex); + my_atomic_rwlock_wrunlock(&rwl); return 0; } void test_atomic(const char *test, pthread_handler handler, int n, int m) { - pthread_t t; - ulonglong now=my_getsystime(); + pthread_t *threads; + ulonglong now= my_getsystime(); + int i; a32= 0; b32= 0; c32= 0; + threads= (pthread_t *)my_malloc(sizeof(void *)*n, MYF(0)); + if (!threads) + { + diag("Out of memory"); + abort(); + } + diag("Testing %s with %d threads, %d iterations... ", test, n, m); - for (N=n ; n ; n--) + N= n; + for (i= 0 ; i < n ; i++) { - if (pthread_create(&t, &thr_attr, handler, &m) != 0) + if (pthread_create(threads+i, 0, handler, &m) != 0) { diag("Could not create thread"); - a32= 1; - goto err; + abort(); } } - pthread_mutex_lock(&mutex); - while (N) - pthread_cond_wait(&cond, &mutex); - pthread_mutex_unlock(&mutex); - now=my_getsystime()-now; + for (i= 0 ; i < n ; i++) + pthread_join(threads[i], 0); + now= my_getsystime()-now; err: ok(a32 == 0, "tested %s in %g secs (%d)", test, ((double)now)/1e7, a32); + my_free((void *)threads, MYF(0)); } int main() @@ -289,10 +269,6 @@ int main() plan(7); ok(err == 0, "my_atomic_initialize() returned %d", err); - pthread_attr_init(&thr_attr); - pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); - pthread_mutex_init(&mutex, 0); - pthread_cond_init(&cond, 0); my_atomic_rwlock_init(&rwl); lf_alloc_init(&lf_allocator, sizeof(TLA), offsetof(TLA, not_used)); lf_hash_init(&lf_hash, sizeof(int), LF_HASH_UNIQUE, 0, sizeof(int), 0, @@ -315,9 +291,6 @@ int main() lf_hash_destroy(&lf_hash); lf_alloc_destroy(&lf_allocator); - pthread_mutex_destroy(&mutex); - pthread_cond_destroy(&cond); - pthread_attr_destroy(&thr_attr); my_atomic_rwlock_destroy(&rwl); my_end(0); return exit_status(); -- cgit v1.2.1 From 7ca33ae5b592143eb773ccfb71ee76d871374b46 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Oct 2006 17:09:31 +0200 Subject: comments, minor changes --- comments mysys/lf_alloc-pin.c: comments mysys/lf_dynarray.c: comments mysys/lf_hash.c: comments, charset-aware comparison storage/maria/trnman.c: comments storage/maria/unittest/lockman-t.c: test case for a bug unittest/mysys/my_atomic-t.c: removed mistakenly copied line --- unittest/mysys/my_atomic-t.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index 88fa2b03242..a33e233c29a 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -209,7 +209,6 @@ pthread_handler_t test_lf_hash(void *arg) my_atomic_rwlock_wrlock(&rwl); my_atomic_add32(&a32, sum); my_atomic_add32(&b32, ins); - my_atomic_add32(&a32, y); if (my_atomic_add32(&N, -1) == 1) { @@ -281,12 +280,12 @@ int main() #endif #define THREADS 100 - test_atomic("my_atomic_add32", test_atomic_add_handler, THREADS,CYCLES); - test_atomic("my_atomic_fas32", test_atomic_fas_handler, THREADS,CYCLES); - test_atomic("my_atomic_cas32", test_atomic_cas_handler, THREADS,CYCLES); - test_atomic("lf_pinbox", test_lf_pinbox, THREADS,CYCLES); - test_atomic("lf_alloc", test_lf_alloc, THREADS,CYCLES); - test_atomic("lf_hash", test_lf_hash, THREADS,CYCLES); + test_atomic("my_atomic_add32", test_atomic_add_handler, THREADS,CYCLES); + test_atomic("my_atomic_fas32", test_atomic_fas_handler, THREADS,CYCLES); + test_atomic("my_atomic_cas32", test_atomic_cas_handler, THREADS,CYCLES); + test_atomic("lf_pinbox", test_lf_pinbox, THREADS,CYCLES); + test_atomic("lf_alloc", test_lf_alloc, THREADS,CYCLES); + test_atomic("lf_hash", test_lf_hash, THREADS,CYCLES/10); lf_hash_destroy(&lf_hash); lf_alloc_destroy(&lf_allocator); -- cgit v1.2.1 From 6691ce30ecd82baf9877242c078a5e1d12a78369 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Nov 2006 22:53:53 +0100 Subject: Maria - WL#3134 Key cache to Page cache conversion Moving the test_pagecache_ tests from mysys to unittest/mysys. Means fixing includes to work with the new directory, some Makefile.am editing, replacing memset() with bfill(). test_page_cache_*.c renamed to mf_pagecache_*-t.c (-t is the standard suffix for tests in the mytap protocol). Also added plan() and exit_status() calls to tests. Sanja, I put some TODOs for you at the start of mf_pagecache_*.c unittest/mysys/test_file.h: Rename: mysys/test_file.h -> unittest/mysys/test_file.h mysys/Makefile.am: pagecache test files move to top/unittest/mysys mysys/mf_pagecache.c: my_bit.h needed to compile. unittest/mysys/Makefile.am: INCLUDES is a better place for includes than AM_CPPFLAGS (the latter get overriden by prog_CPPFLAGS, which is not desirable here). Adding pagecache's test programs (moved from mysys); test_pagecache_* has been renamed to mf_pagecache*-t (-t is the required suffix for test executables in the mytap framework). unittest/mysys/mf_pagecache_consist.c: fixing includes to work with the new directory. The test must return an exit code informing if any part failed. TODOs for Sanja. unittest/mysys/mf_pagecache_single.c: fixing includes to work with new directory. adding a plan() to account for the number of tests. Adding exit_status() to tell how many tests failed. memset() was giving a compilation warning (implicit declaration etc), properly due to me removing stdio.h etc, so I replaced it with bfill(). TODOs for Sanja. unittest/mysys/test_file.c: moved from mysys (piece of the page cache tests) and includes fixed. --- unittest/mysys/Makefile.am | 46 ++- unittest/mysys/mf_pagecache_consist.c | 445 ++++++++++++++++++++++++++ unittest/mysys/mf_pagecache_single.c | 587 ++++++++++++++++++++++++++++++++++ unittest/mysys/test_file.c | 68 ++++ unittest/mysys/test_file.h | 14 + 5 files changed, 1157 insertions(+), 3 deletions(-) create mode 100755 unittest/mysys/mf_pagecache_consist.c create mode 100644 unittest/mysys/mf_pagecache_single.c create mode 100644 unittest/mysys/test_file.c create mode 100644 unittest/mysys/test_file.h (limited to 'unittest') diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am index 8e6255b9e68..9b230272329 100644 --- a/unittest/mysys/Makefile.am +++ b/unittest/mysys/Makefile.am @@ -1,11 +1,51 @@ +INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \ + -I$(top_srcdir)/include -I$(top_srcdir)/unittest/mytap -AM_CPPFLAGS = @ZLIB_INCLUDES@ -I$(top_builddir)/include -AM_CPPFLAGS += -I$(top_srcdir)/include -I$(top_srcdir)/unittest/mytap LDADD = $(top_builddir)/unittest/mytap/libmytap.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/dbug/libdbug.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 diff --git a/unittest/mysys/mf_pagecache_consist.c b/unittest/mysys/mf_pagecache_consist.c new file mode 100755 index 00000000000..f7724222a09 --- /dev/null +++ b/unittest/mysys/mf_pagecache_consist.c @@ -0,0 +1,445 @@ +/* + TODO: use pthread_join instead of wait_for_thread_count_to_be_zero, like in + my_atomic-t.c (see BUG#22320). + Use diag() instead of fprintf(stderr). Use ok() and plan(). +*/ + +#include +#include +#include +#include "test_file.h" + +#define PCACHE_SIZE (PAGE_SIZE*1024*8) + +#ifndef DBUG_OFF +static const char* default_dbug_option; +#endif + +static char *file1_name= (char*)"page_cache_test_file_1"; +static PAGECACHE_FILE file1; +static pthread_cond_t COND_thread_count; +static pthread_mutex_t LOCK_thread_count; +static uint thread_count; +static PAGECACHE pagecache; + +#ifdef TEST_HIGH_CONCURENCY +static uint number_of_readers= 10; +static uint number_of_writers= 20; +static uint number_of_tests= 30000; +static uint record_length_limit= PAGE_SIZE/200; +static uint number_of_pages= 20; +static uint flush_divider= 1000; +#else /*TEST_HIGH_CONCURENCY*/ +#ifdef TEST_READERS +static uint number_of_readers= 10; +static uint number_of_writers= 1; +static uint number_of_tests= 30000; +static uint record_length_limit= PAGE_SIZE/200; +static uint number_of_pages= 20; +static uint flush_divider= 1000; +#else /*TEST_READERS*/ +#ifdef TEST_WRITERS +static uint number_of_readers= 0; +static uint number_of_writers= 10; +static uint number_of_tests= 30000; +static uint record_length_limit= PAGE_SIZE/200; +static uint number_of_pages= 20; +static uint flush_divider= 1000; +#else /*TEST_WRITERS*/ +static uint number_of_readers= 10; +static uint number_of_writers= 10; +static uint number_of_tests= 50000; +static uint record_length_limit= PAGE_SIZE/200; +static uint number_of_pages= 20000; +static uint flush_divider= 1000; +#endif /*TEST_WRITERS*/ +#endif /*TEST_READERS*/ +#endif /*TEST_HIGH_CONCURENCY*/ + + +/* check page consistency */ +uint check_page(uchar *buff, ulong offset, int page_locked, int page_no, + int tag) +{ + uint end= sizeof(uint); + uint num= *((uint *)buff); + uint i; + DBUG_ENTER("check_page"); + + for (i= 0; i < num; i++) + { + uint len= *((uint *)(buff + end)); + uint j; + end+= sizeof(uint)+ sizeof(uint); + if (len + end > PAGE_SIZE) + { + diag("incorrect field header #%u by offset %lu\n", i, offset + end + j); + goto err; + } + for(j= 0; j < len; j++) + { + if (buff[end + j] != (uchar)((i+1) % 256)) + { + diag("incorrect %lu byte\n", offset + end + j); + goto err; + } + } + end+= len; + } + for(i= end; i < PAGE_SIZE; i++) + { + if (buff[i] != 0) + { + int h; + DBUG_PRINT("err", + ("byte %lu (%lu + %u), page %u (%s, end: %u, recs: %u, tag: %d) should be 0\n", + offset + i, offset, i, page_no, + (page_locked ? "locked" : "unlocked"), + end, num, tag)); + diag("byte %lu (%lu + %u), page %u (%s, end: %u, recs: %u, tag: %d) should be 0\n", + offset + i, offset, i, page_no, + (page_locked ? "locked" : "unlocked"), + end, num, tag); + h= my_open("wrong_page", O_CREAT | O_TRUNC | O_RDWR, MYF(0)); + my_pwrite(h, buff, PAGE_SIZE, 0, MYF(0)); + my_close(h, MYF(0)); + goto err; + } + } + DBUG_RETURN(end); +err: + DBUG_PRINT("err", ("try to flush")); + if (page_locked) + { + pagecache_delete_page(&pagecache, &file1, page_no, + PAGECACHE_LOCK_LEFT_WRITELOCKED, 1); + } + else + { + flush_pagecache_blocks(&pagecache, &file1, FLUSH_RELEASE); + } + exit(1); +} + +void put_rec(uchar *buff, uint end, uint len, uint tag) +{ + uint i; + uint num= *((uint *)buff); + if (!len) + len= 1; + if (end + sizeof(uint)*2 + len > PAGE_SIZE) + return; + *((uint *)(buff + end))= len; + end+= sizeof(uint); + *((uint *)(buff + end))= tag; + end+= sizeof(uint); + num++; + *((uint *)buff)= num; + *((uint*)(buff + end))= len; + for (i= end; i < (len + end); i++) + { + buff[i]= (uchar) num % 256; + } +} + +/* + Recreate and reopen a file for test + + SYNOPSIS + reset_file() + file File to reset + file_name Path (and name) of file which should be reset +*/ + +void reset_file(PAGECACHE_FILE file, char *file_name) +{ + flush_pagecache_blocks(&pagecache, &file1, FLUSH_RELEASE); + if (my_close(file1.file, MYF(0)) != 0) + { + diag("Got error during %s closing from close() (errno: %d)\n", + file_name, errno); + exit(1); + } + my_delete(file_name, MYF(0)); + if ((file.file= my_open(file_name, + O_CREAT | O_TRUNC | O_RDWR, MYF(0))) == -1) + { + diag("Got error during %s creation from open() (errno: %d)\n", + file_name, errno); + exit(1); + } +} + + +void reader(int num) +{ + unsigned char *buffr= malloc(PAGE_SIZE); + uint i; + + for (i= 0; i < number_of_tests; i++) + { + uint page= rand()/(RAND_MAX/number_of_pages); + pagecache_read(&pagecache, &file1, page, 3, (char*)buffr, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + 0); + check_page(buffr, page * PAGE_SIZE, 0, page, -num); + if (i % 500 == 0) + printf("reader%d: %d\n", num, i); + + } + printf("reader%d: done\n", num); + free(buffr); +} + + +void writer(int num) +{ + unsigned char *buffr= malloc(PAGE_SIZE); + uint i; + + for (i= 0; i < number_of_tests; i++) + { + uint end; + uint page= rand()/(RAND_MAX/number_of_pages); + pagecache_read(&pagecache, &file1, page, 3, (char*)buffr, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_WRITE, + 0); + end= check_page(buffr, page * PAGE_SIZE, 1, page, num); + put_rec(buffr, end, rand()/(RAND_MAX/record_length_limit), num); + pagecache_write(&pagecache, &file1, page, 3, (char*)buffr, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_WRITE_UNLOCK, + PAGECACHE_UNPIN, + PAGECACHE_WRITE_DELAY, + 0); + + if (i % flush_divider == 0) + flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); + if (i % 500 == 0) + printf("writer%d: %d\n", num, i); + } + printf("writer%d: done\n", num); + free(buffr); +} + + +static void *test_thread_reader(void *arg) +{ + int param=*((int*) arg); + + my_thread_init(); + DBUG_ENTER("test_reader"); + DBUG_PRINT("enter", ("param: %d", param)); + + reader(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); +} + +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))) +{ + pthread_t tid; + pthread_attr_t thr_attr; + int *param, error, pagen; + + MY_INIT(argv[0]); + +#ifndef DBUG_OFF +#if defined(__WIN__) + default_dbug_option= "d:t:i:O,\\test_pagecache_consist.trace"; +#else + default_dbug_option= "d:t:i:o,/tmp/test_pagecache_consist.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 ((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); + } + DBUG_PRINT("info", ("file1: %d", file1.file)); + if (chmod(file1_name, S_IRWXU | S_IRWXG | S_IRWXO) != 0) + { + fprintf(stderr, "Got error during file1 chmod() (errno: %d)\n", + errno); + exit(1); + } + my_pwrite(file1.file, "test file", 9, 0, MYF(0)); + + 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 ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, + PAGE_SIZE, 0)) == 0) + { + fprintf(stderr,"Got error: init_pagecache() (errno: %d)\n", + errno); + exit(1); + } + DBUG_PRINT("info", ("Page cache %d pages", pagen)); + { + unsigned char *buffr= malloc(PAGE_SIZE); + uint i; + memset(buffr, '\0', PAGE_SIZE); + for (i= 0; i < number_of_pages; i++) + { + pagecache_write(&pagecache, &file1, i, 3, (char*)buffr, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + PAGECACHE_PIN_LEFT_UNPINNED, + PAGECACHE_WRITE_DELAY, + 0); + } + flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); + free(buffr); + } + 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_readers != 0 || number_of_writers != 0) + { + if (number_of_readers != 0) + { + param=(int*) malloc(sizeof(int)); + *param= number_of_readers; + if ((error= pthread_create(&tid, &thr_attr, test_thread_reader, + (void*) param))) + { + fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n", + error,errno); + exit(1); + } + thread_count++; + number_of_readers--; + } + if (number_of_writers != 0) + { + param=(int*) malloc(sizeof(int)); + *param= number_of_writers; + 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", ("Thread 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", ("thread ended")); + + end_pagecache(&pagecache, 1); + DBUG_PRINT("info", ("Page cache ended")); + + if (my_close(file1.file, MYF(0)) != 0) + { + fprintf(stderr, "Got error during file1 closing from close() (errno: %d)\n", + errno); + exit(1); + } + /*my_delete(file1_name, MYF(0));*/ + my_thread_global_end(); + + DBUG_PRINT("info", ("file1 (%d) closed", file1.file)); + + DBUG_PRINT("info", ("Program end")); + + DBUG_RETURN(exit_status()); +} diff --git a/unittest/mysys/mf_pagecache_single.c b/unittest/mysys/mf_pagecache_single.c new file mode 100644 index 00000000000..49ecd2986ab --- /dev/null +++ b/unittest/mysys/mf_pagecache_single.c @@ -0,0 +1,587 @@ +/* + TODO: use pthread_join instead of wait_for_thread_count_to_be_zero, like in + my_atomic-t.c (see BUG#22320). + Use diag() instead of fprintf(stderr). +*/ +#include +#include +#include +#include "test_file.h" + +#define PCACHE_SIZE (PAGE_SIZE*1024*10) + +#ifndef DBUG_OFF +static const char* default_dbug_option; +#endif + +static char *file1_name= (char*)"page_cache_test_file_1"; +static PAGECACHE_FILE file1; +static pthread_cond_t COND_thread_count; +static pthread_mutex_t LOCK_thread_count; +static uint thread_count; +static PAGECACHE pagecache; + +/* + File contance descriptors +*/ +static struct file_desc simple_read_write_test_file[]= +{ + {PAGE_SIZE, '\1'}, + { 0, 0} +}; +static struct file_desc simple_read_change_write_read_test_file[]= +{ + {PAGE_SIZE/2, '\65'}, + {PAGE_SIZE/2, '\1'}, + { 0, 0} +}; +static struct file_desc simple_pin_test_file1[]= +{ + {PAGE_SIZE*2, '\1'}, + { 0, 0} +}; +static struct file_desc simple_pin_test_file2[]= +{ + {PAGE_SIZE/2, '\1'}, + {PAGE_SIZE/2, (unsigned char)129}, + {PAGE_SIZE, '\1'}, + { 0, 0} +}; +static struct file_desc simple_delete_forget_test_file[]= +{ + {PAGE_SIZE, '\1'}, + { 0, 0} +}; +static struct file_desc simple_delete_flush_test_file[]= +{ + {PAGE_SIZE, '\2'}, + { 0, 0} +}; + + +/* + Recreate and reopen a file for test + + SYNOPSIS + reset_file() + file File to reset + file_name Path (and name) of file which should be reset +*/ + +void reset_file(PAGECACHE_FILE file, char *file_name) +{ + flush_pagecache_blocks(&pagecache, &file1, FLUSH_RELEASE); + if (my_close(file1.file, MYF(0)) != 0) + { + diag("Got error during %s closing from close() (errno: %d)\n", + file_name, errno); + exit(1); + } + my_delete(file_name, MYF(0)); + if ((file.file= my_open(file_name, + O_CREAT | O_TRUNC | O_RDWR, MYF(0))) == -1) + { + diag("Got error during %s creation from open() (errno: %d)\n", + file_name, errno); + exit(1); + } +} + +/* + Write then read page, check file on disk +*/ + +int simple_read_write_test() +{ + unsigned char *buffw= malloc(PAGE_SIZE); + unsigned char *buffr= malloc(PAGE_SIZE); + int res; + DBUG_ENTER("simple_read_write_test"); + bfill(buffw, PAGE_SIZE, '\1'); + pagecache_write(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + PAGECACHE_PIN_LEFT_UNPINNED, + PAGECACHE_WRITE_DELAY, + 0); + pagecache_read(&pagecache, &file1, 0, 3, (char*)buffr, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + 0); + ok((res= test(memcmp(buffr, buffw, PAGE_SIZE) == 0)), + "Simple write-read page "); + flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); + ok((res&= test(test_file(file1, file1_name, PAGE_SIZE, PAGE_SIZE, + simple_read_write_test_file))), + "Simple write-read page file"); + if (res) + reset_file(file1, file1_name); + free(buffw); + free(buffr); + DBUG_RETURN(res); +} + + +/* + Prepare page, then read (and lock), change (write new value and unlock), + then check the page in the cache and on the disk +*/ +int simple_read_change_write_read_test() +{ + unsigned char *buffw= malloc(PAGE_SIZE); + unsigned char *buffr= malloc(PAGE_SIZE); + int res; + DBUG_ENTER("simple_read_change_write_read_test"); + /* prepare the file */ + bfill(buffw, PAGE_SIZE, '\1'); + pagecache_write(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + PAGECACHE_PIN_LEFT_UNPINNED, + PAGECACHE_WRITE_DELAY, + 0); + flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); + /* test */ + pagecache_read(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_WRITE, + 0); + bfill(buffw, PAGE_SIZE/2, '\65'); + pagecache_write(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_WRITE_UNLOCK, + PAGECACHE_UNPIN, + PAGECACHE_WRITE_DELAY, + 0); + + pagecache_read(&pagecache, &file1, 0, 3, (char*)buffr, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + 0); + ok((res= test(memcmp(buffr, buffw, PAGE_SIZE) == 0)), + "Simple read-change-write-read page "); + flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); + ok((res&= test(test_file(file1, file1_name, PAGE_SIZE, PAGE_SIZE, + simple_read_change_write_read_test_file))), + "Simple read-change-write-read page file"); + if (res) + reset_file(file1, file1_name); + free(buffw); + free(buffr); + DBUG_RETURN(res); +} + + +/* + Prepare page, read page 0 (and pin) then write page 1 and page 0. + Flush the file (shold flush only page 1 and return 1 (page 0 is + still pinned). + Check file on the disk. + Unpin and flush. + Check file on the disk. +*/ +int simple_pin_test() +{ + unsigned char *buffw= malloc(PAGE_SIZE); + unsigned char *buffr= malloc(PAGE_SIZE); + int res; + DBUG_ENTER("simple_pin_test"); + /* prepare the file */ + bfill(buffw, PAGE_SIZE, '\1'); + pagecache_write(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + PAGECACHE_PIN_LEFT_UNPINNED, + PAGECACHE_WRITE_DELAY, + 0); + /* test */ + if (flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE)) + { + diag("error in flush_pagecache_blocks\n"); + exit(1); + } + pagecache_read(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_WRITE, + 0); + pagecache_write(&pagecache, &file1, 1, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + PAGECACHE_PIN_LEFT_UNPINNED, + PAGECACHE_WRITE_DELAY, + 0); + bfill(buffw + PAGE_SIZE/2, PAGE_SIZE/2, ((unsigned char) 129)); + pagecache_write(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_WRITE_TO_READ, + PAGECACHE_PIN_LEFT_PINNED, + PAGECACHE_WRITE_DELAY, + 0); + /* + We have to get error because one page of the file is pinned, + other page should be flushed + */ + if (!flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE)) + { + diag("Did not get error in flush_pagecache_blocks\n"); + res= 0; + goto err; + } + ok((res= test(test_file(file1, file1_name, PAGE_SIZE*2, PAGE_SIZE*2, + simple_pin_test_file1))), + "Simple pin page file with pin"); + pagecache_unlock_page(&pagecache, + &file1, + 0, + PAGECACHE_LOCK_READ_UNLOCK, + PAGECACHE_UNPIN, + 0, 0); + if (flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE)) + { + diag("Got error in flush_pagecache_blocks\n"); + res= 0; + goto err; + } + ok((res&= test(test_file(file1, file1_name, PAGE_SIZE*2, PAGE_SIZE, + simple_pin_test_file2))), + "Simple pin page result file"); + if (res) + reset_file(file1, file1_name); +err: + free(buffw); + free(buffr); + DBUG_RETURN(res); +} + +/* + Prepare page, write new value, then delete page from cache without flush, + on the disk should be page with old content written during preparation +*/ + +int simple_delete_forget_test() +{ + unsigned char *buffw= malloc(PAGE_SIZE); + unsigned char *buffr= malloc(PAGE_SIZE); + int res; + DBUG_ENTER("simple_delete_forget_test"); + /* prepare the file */ + bfill(buffw, PAGE_SIZE, '\1'); + pagecache_write(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + PAGECACHE_PIN_LEFT_UNPINNED, + PAGECACHE_WRITE_DELAY, + 0); + flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); + /* test */ + bfill(buffw, PAGE_SIZE, '\2'); + pagecache_write(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + PAGECACHE_PIN_LEFT_UNPINNED, + PAGECACHE_WRITE_DELAY, + 0); + pagecache_delete_page(&pagecache, &file1, 0, + PAGECACHE_LOCK_WRITE, 0); + flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); + ok((res= test(test_file(file1, file1_name, PAGE_SIZE, PAGE_SIZE, + simple_delete_forget_test_file))), + "Simple delete-forget page file"); + if (res) + reset_file(file1, file1_name); + free(buffw); + free(buffr); + DBUG_RETURN(res); +} + +/* + Prepare page with locking, write new content to the page, + delete page with flush and on existing lock, + check that page on disk contain new value. +*/ + +int simple_delete_flush_test() +{ + unsigned char *buffw= malloc(PAGE_SIZE); + unsigned char *buffr= malloc(PAGE_SIZE); + int res; + DBUG_ENTER("simple_delete_flush_test"); + /* prepare the file */ + bfill(buffw, PAGE_SIZE, '\1'); + pagecache_write(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_WRITE, + PAGECACHE_PIN, + PAGECACHE_WRITE_DELAY, + 0); + flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); + /* test */ + bfill(buffw, PAGE_SIZE, '\2'); + pagecache_write(&pagecache, &file1, 0, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_WRITELOCKED, + PAGECACHE_PIN_LEFT_PINNED, + PAGECACHE_WRITE_DELAY, + 0); + pagecache_delete_page(&pagecache, &file1, 0, + PAGECACHE_LOCK_LEFT_WRITELOCKED, 1); + flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); + ok((res= test(test_file(file1, file1_name, PAGE_SIZE, PAGE_SIZE, + simple_delete_flush_test_file))), + "Simple delete-forget page file"); + if (res) + reset_file(file1, file1_name); + free(buffw); + free(buffr); + DBUG_RETURN(res); +} + + +/* + write then read file bigger then cache +*/ + +int simple_big_test() +{ + unsigned char *buffw= (unsigned char *)malloc(PAGE_SIZE); + unsigned char *buffr= (unsigned char *)malloc(PAGE_SIZE); + struct file_desc *desc= + (struct file_desc *)malloc((PCACHE_SIZE/(PAGE_SIZE/2)) * + sizeof(struct file_desc)); + int res, i; + DBUG_ENTER("simple_big_test"); + /* prepare the file twice larger then cache */ + for (i= 0; i < PCACHE_SIZE/(PAGE_SIZE/2); i++) + { + bfill(buffw, PAGE_SIZE, (unsigned char) (i & 0xff)); + desc[i].length= PAGE_SIZE; + desc[i].content= (i & 0xff); + pagecache_write(&pagecache, &file1, i, 3, (char*)buffw, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + PAGECACHE_PIN_LEFT_UNPINNED, + PAGECACHE_WRITE_DELAY, + 0); + } + ok(1, "Simple big file write"); + /* check written pages sequentally read */ + for (i= 0; i < PCACHE_SIZE/(PAGE_SIZE/2); i++) + { + int j; + pagecache_read(&pagecache, &file1, i, 3, (char*)buffr, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + 0); + for(j= 0; j < PAGE_SIZE; j++) + { + if (buffr[j] != (i & 0xff)) + { + diag("simple_big_test seq: page %u byte %u mismatch\n", i, j); + return 0; + } + } + } + ok(1, "simple big file sequentally read"); + /* chack random reads */ + for (i= 0; i < PCACHE_SIZE/(PAGE_SIZE); i++) + { + int j, page; + page= rand() % (PCACHE_SIZE/(PAGE_SIZE/2)); + pagecache_read(&pagecache, &file1, page, 3, (char*)buffr, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + 0); + for(j= 0; j < PAGE_SIZE; j++) + { + if (buffr[j] != (page & 0xff)) + { + diag("simple_big_test rnd: page %u byte %u mismatch\n", page, j); + return 0; + } + } + } + ok(1, "simple big file random read"); + flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); + + ok((res= test(test_file(file1, file1_name, PCACHE_SIZE*2, PAGE_SIZE, + desc))), + "Simple big file"); + if (res) + reset_file(file1, file1_name); + free(buffw); + free(buffr); + DBUG_RETURN(res); +} +/* + Thread function +*/ + +static void *test_thread(void *arg) +{ + int param=*((int*) arg); + + my_thread_init(); + DBUG_ENTER("test_thread"); + + DBUG_PRINT("enter", ("param: %d", param)); + + if (!simple_read_write_test() || + !simple_read_change_write_read_test() || + !simple_pin_test() || + !simple_delete_forget_test() || + !simple_delete_flush_test() || + !simple_big_test()) + exit(1); + + 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))) +{ + pthread_t tid; + pthread_attr_t thr_attr; + int *param, error, pagen; + + MY_INIT(argv[0]); + +#ifndef DBUG_OFF +#if defined(__WIN__) + default_dbug_option= "d:t:i:O,\\test_pagecache_single.trace"; +#else + default_dbug_option= "d:t:i:o,/tmp/test_pagecache_single.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 ((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); + } + DBUG_PRINT("info", ("file1: %d", file1.file)); + if (chmod(file1_name, S_IRWXU | S_IRWXG | S_IRWXO) != 0) + { + fprintf(stderr, "Got error during file1 chmod() (errno: %d)\n", + errno); + exit(1); + } + my_pwrite(file1.file, "test file", 9, 0, MYF(0)); + + if ((error= pthread_cond_init(&COND_thread_count, NULL))) + { + fprintf(stderr, "Got error: %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, "Got error: %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(); + + plan(12); + + if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, + PAGE_SIZE, 0)) == 0) + { + fprintf(stderr,"Got error: init_pagecache() (errno: %d)\n", + errno); + exit(1); + } + DBUG_PRINT("info", ("Page cache %d pages", pagen)); + + if ((error=pthread_mutex_lock(&LOCK_thread_count))) + { + fprintf(stderr,"Got error: %d from pthread_mutex_lock (errno: %d)\n", + error,errno); + exit(1); + } + param=(int*) malloc(sizeof(int)); + *param= 1; + if ((error= pthread_create(&tid, &thr_attr, test_thread, (void*) param))) + { + fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n", + error,errno); + exit(1); + } + thread_count++; + DBUG_PRINT("info", ("Thread started")); + pthread_mutex_unlock(&LOCK_thread_count); + + pthread_attr_destroy(&thr_attr); + + if ((error= pthread_mutex_lock(&LOCK_thread_count))) + fprintf(stderr,"Got error: %d from pthread_mutex_lock\n",error); + while (thread_count) + { + if ((error= pthread_cond_wait(&COND_thread_count,&LOCK_thread_count))) + fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error); + } + if ((error= pthread_mutex_unlock(&LOCK_thread_count))) + fprintf(stderr,"Got error: %d from pthread_mutex_unlock\n",error); + DBUG_PRINT("info", ("thread ended")); + + end_pagecache(&pagecache, 1); + DBUG_PRINT("info", ("Page cache ended")); + + if (my_close(file1.file, MYF(0)) != 0) + { + fprintf(stderr, "Got error during file1 closing from close() (errno: %d)\n", + errno); + exit(1); + } + /*my_delete(file1_name, MYF(0));*/ + my_thread_global_end(); + + DBUG_PRINT("info", ("file1 (%d) closed", file1.file)); + + DBUG_PRINT("info", ("Program end")); + + DBUG_RETURN(exit_status()); +} diff --git a/unittest/mysys/test_file.c b/unittest/mysys/test_file.c new file mode 100644 index 00000000000..758d0bfa81b --- /dev/null +++ b/unittest/mysys/test_file.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include "test_file.h" + + +/* + Check that file contance correspond to descriptor + + SYNOPSIS + test_file() + file File to test + file_name Path (and name) of file which is tested + size size of file + buff_size size of buffer which is enought to check the file + desc file descriptor to check with + + RETURN + 1 file if OK + 0 error +*/ + +int test_file(PAGECACHE_FILE file, char *file_name, + off_t size, size_t buff_size, struct file_desc *desc) +{ + MY_STAT stat_buff, *stat; + unsigned char *buffr= malloc(buff_size); + off_t pos= 0; + size_t byte; + int step= 0; + + if ((stat= my_stat(file_name, &stat_buff, MYF(0))) == NULL) + { + diag("Can't stat() %s (errno: %d)\n", file_name, errno); + return 0; + } + if (stat->st_size != size) + { + diag("file %s size is %lu (should be %lu)\n", + file_name, (ulong) stat->st_size, (ulong) size); + return 0; + } + /* check content */ + my_seek(file.file, 0, SEEK_SET, MYF(0)); + while (desc[step].length != 0) + { + if (my_read(file.file, (char*)buffr, desc[step].length, MYF(0)) != + desc[step].length) + { + diag("Can't read %u bytes from %s (errno: %d)\n", + (uint)desc[step].length, file_name, errno); + return 0; + } + for (byte= 0; byte < desc[step].length; byte++) + { + if (buffr[byte] != desc[step].content) + { + diag("content of %s mismatch 0x%x in position %lu instead of 0x%x\n", + file_name, (uint) buffr[byte], (ulong) (pos + byte), + desc[step].content); + return 0; + } + } + pos+= desc[step].length; + step++; + } + return 1; +} diff --git a/unittest/mysys/test_file.h b/unittest/mysys/test_file.h new file mode 100644 index 00000000000..ea787c123ed --- /dev/null +++ b/unittest/mysys/test_file.h @@ -0,0 +1,14 @@ + +#include + +/* + File content descriptor +*/ +struct file_desc +{ + unsigned int length; + unsigned char content; +}; + +int test_file(PAGECACHE_FILE file, char *file_name, + off_t size, size_t buff_size, struct file_desc *desc); -- cgit v1.2.1 From 354d4a7e06074beb0a08afab06b0f5dfd63d7d1d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Nov 2006 15:53:26 +0100 Subject: shut up signedness warnings in atomic ops in gcc unittest/mysys/my_atomic-t.c: try both signed and unsigned arguments for atomic ops --- unittest/mysys/my_atomic-t.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index a33e233c29a..314335944d3 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -21,7 +21,8 @@ #include #include -volatile uint32 a32,b32,c32, N; +volatile uint32 a32,b32; +volatile int32 c32, N; my_atomic_rwlock_t rwl; LF_ALLOCATOR lf_allocator; LF_HASH lf_hash; @@ -98,7 +99,7 @@ pthread_handler_t test_atomic_cas_handler(void *arg) x= (x*m+0x87654321) & INT_MAX32; do { my_atomic_rwlock_wrlock(&rwl); - ok= my_atomic_cas32(&a32, &y, y+x); + ok= my_atomic_cas32(&a32, &y, (uint32)y+x); my_atomic_rwlock_wrunlock(&rwl); } while (!ok) ; do { -- cgit v1.2.1 From 3345ed80a569bbd96fb9e0f3d9a0d5e1c0e1b3b7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Nov 2006 12:14:36 +0100 Subject: Maria - pagecache unit tests: add test_file.h to the tarball unittest/mysys/Makefile.am: add test_file.h in the tarball --- unittest/mysys/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am index 9b230272329..3ef1c3af587 100644 --- a/unittest/mysys/Makefile.am +++ b/unittest/mysys/Makefile.am @@ -17,8 +17,8 @@ noinst_PROGRAMS = bitmap-t base64-t my_atomic-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_single_src = mf_pagecache_single.c $(top_srcdir)/mysys/mf_pagecache.c test_file.c test_file.h +mf_pagecache_consist_src = mf_pagecache_consist.c $(top_srcdir)/mysys/mf_pagecache.c test_file.c test_file.h mf_pagecache_common_cppflags = -DEXTRA_DEBUG -DPAGECACHE_DEBUG -DMAIN mf_pagecache_single_1k_t_SOURCES = $(mf_pagecache_single_src) -- cgit v1.2.1 From 9fcc34b4ae1bdcf8aeb4dad0295b7d3534491a17 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Nov 2006 15:12:28 +0100 Subject: Maria - misc fixes: don't run tests depending on the generic lock manager which will be removed; don't run page cache unit tests by default (too intensive). storage/maria/unittest/Makefile.am: don't run tests depending on the generic lock manager (it will be removed in the end), one of them crashes. unittest/mysys/Makefile.am: page cache tests put a too high load, causes problems on shared machines; so we still build them but give them a suffix so that they are not run by the default "test-unit" Makefile target. --- unittest/mysys/Makefile.am | 68 ++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 32 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am index 3ef1c3af587..8dd0416dbac 100644 --- a/unittest/mysys/Makefile.am +++ b/unittest/mysys/Makefile.am @@ -7,13 +7,17 @@ LDADD = $(top_builddir)/unittest/mytap/libmytap.a \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/strings/libmystrings.a +# tests with the "big" suffix are too big to run for every push, +# cause load problems on shared machines. So we build them, +# but don't run them by default (for this, a non "-t" suffix is used). +# You can run them by hand (how: see "test" target in upper dir). 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 + mf_pagecache_single_1k-t-big mf_pagecache_single_8k-t-big \ + mf_pagecache_single_64k-t-big \ + mf_pagecache_consist_1k-t-big mf_pagecache_consist_64k-t-big \ + mf_pagecache_consist_1kHC-t-big mf_pagecache_consist_64kHC-t-big \ + mf_pagecache_consist_1kRD-t-big mf_pagecache_consist_64kRD-t-big \ + mf_pagecache_consist_1kWR-t-big mf_pagecache_consist_64kWR-t-big # tests for mysys/mf_pagecache.c @@ -21,31 +25,31 @@ mf_pagecache_single_src = mf_pagecache_single.c $(top_srcdir)/mysys/mf_pagecache mf_pagecache_consist_src = mf_pagecache_consist.c $(top_srcdir)/mysys/mf_pagecache.c test_file.c test_file.h 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 +mf_pagecache_single_1k_t_big_SOURCES = $(mf_pagecache_single_src) +mf_pagecache_single_8k_t_big_SOURCES = $(mf_pagecache_single_src) +mf_pagecache_single_64k_t_big_SOURCES = $(mf_pagecache_single_src) +mf_pagecache_single_1k_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 +mf_pagecache_single_8k_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=8192 +mf_pagecache_single_64k_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 + +mf_pagecache_consist_1k_t_big_SOURCES = $(mf_pagecache_consist_src) +mf_pagecache_consist_1k_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 +mf_pagecache_consist_64k_t_big_SOURCES = $(mf_pagecache_consist_src) +mf_pagecache_consist_64k_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 + +mf_pagecache_consist_1kHC_t_big_SOURCES = $(mf_pagecache_consist_src) +mf_pagecache_consist_1kHC_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 -DTEST_HIGH_CONCURENCY +mf_pagecache_consist_64kHC_t_big_SOURCES = $(mf_pagecache_consist_src) +mf_pagecache_consist_64kHC_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 -DTEST_HIGH_CONCURENCY + +mf_pagecache_consist_1kRD_t_big_SOURCES = $(mf_pagecache_consist_src) +mf_pagecache_consist_1kRD_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 -DTEST_READERS +mf_pagecache_consist_64kRD_t_big_SOURCES = $(mf_pagecache_consist_src) +mf_pagecache_consist_64kRD_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 -DTEST_READERS + +mf_pagecache_consist_1kWR_t_big_SOURCES = $(mf_pagecache_consist_src) +mf_pagecache_consist_1kWR_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 -DTEST_WRITERS +mf_pagecache_consist_64kWR_t_big_SOURCES = $(mf_pagecache_consist_src) +mf_pagecache_consist_64kWR_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 -DTEST_WRITERS CLEANFILES = my_pagecache_debug.log page_cache_test_file_1 -- cgit v1.2.1 From b72903fe54cf83c3dcbec7e3532e23bf946249ba Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 3 Dec 2006 17:06:27 +0100 Subject: Maria: * merging changes done to the key cache since May 2006 into Maria * enabling two small enough page cache's unit tests by default * fix to have non-buffered output in unit tests (to not have a false timeout killing in pushbuild) (patch given by Serg) * removing some warnings of gcc -ansi include/lf.h: getting rid of "warning: ISO C does not allow extra `;' outside of a function" (gcc -ansi) mysys/lf_hash.c: getting rid of "warning: ISO C does not allow extra `;' outside of a function" (gcc -ansi) mysys/mf_pagecache.c: Cosmetic changes to minimize the diff with the key cache. #define PAGECACHE_DEBUG_LOG is not needed (just define PAGECACHE_DEBUG if you want) (this change removes "warning: 'pagecache_debug_print' declared `static' but never defined"). Importing changes made to mf_keycache.c since May 2006, into the page cache. Disabling online resizing in the page cache. Fix for "warning: ISO C90 forbids mixed declarations and code". unittest/mysys/Makefile.am: Of the page cache's unit tests, two are small enough to run on pushbuild, renaming them to a -t suffix. unittest/mytap/tap.c: pushbuild kills a test after seeing no output from it for 10 minutes; so we set the mytap framework to not buffer output (patch given by Serg) so that output is seen more frequently and not "all at the end of the test". --- unittest/mysys/Makefile.am | 15 +++++++++------ unittest/mytap/tap.c | 2 ++ 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am index 8dd0416dbac..f7b72255a72 100644 --- a/unittest/mysys/Makefile.am +++ b/unittest/mysys/Makefile.am @@ -12,7 +12,7 @@ LDADD = $(top_builddir)/unittest/mytap/libmytap.a \ # but don't run them by default (for this, a non "-t" suffix is used). # You can run them by hand (how: see "test" target in upper dir). noinst_PROGRAMS = bitmap-t base64-t my_atomic-t \ - mf_pagecache_single_1k-t-big mf_pagecache_single_8k-t-big \ + mf_pagecache_single_1k-t mf_pagecache_single_8k-t \ mf_pagecache_single_64k-t-big \ mf_pagecache_consist_1k-t-big mf_pagecache_consist_64k-t-big \ mf_pagecache_consist_1kHC-t-big mf_pagecache_consist_64kHC-t-big \ @@ -25,11 +25,14 @@ mf_pagecache_single_src = mf_pagecache_single.c $(top_srcdir)/mysys/mf_pagecache mf_pagecache_consist_src = mf_pagecache_consist.c $(top_srcdir)/mysys/mf_pagecache.c test_file.c test_file.h mf_pagecache_common_cppflags = -DEXTRA_DEBUG -DPAGECACHE_DEBUG -DMAIN -mf_pagecache_single_1k_t_big_SOURCES = $(mf_pagecache_single_src) -mf_pagecache_single_8k_t_big_SOURCES = $(mf_pagecache_single_src) +# Those two take reasonable resources (<100 MB) for < 1 minute +mf_pagecache_single_1k_t_SOURCES = $(mf_pagecache_single_src) +mf_pagecache_single_8k_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 + +# All others below are big mf_pagecache_single_64k_t_big_SOURCES = $(mf_pagecache_single_src) -mf_pagecache_single_1k_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=1024 -mf_pagecache_single_8k_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=8192 mf_pagecache_single_64k_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 mf_pagecache_consist_1k_t_big_SOURCES = $(mf_pagecache_consist_src) @@ -52,4 +55,4 @@ mf_pagecache_consist_1kWR_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPA mf_pagecache_consist_64kWR_t_big_SOURCES = $(mf_pagecache_consist_src) mf_pagecache_consist_64kWR_t_big_CPPFLAGS = $(mf_pagecache_common_cppflags) -DPAGE_SIZE=65536 -DTEST_WRITERS -CLEANFILES = my_pagecache_debug.log page_cache_test_file_1 +CLEANFILES = pagecache_debug.log page_cache_test_file_1 diff --git a/unittest/mytap/tap.c b/unittest/mytap/tap.c index 17ec51863d9..51330ad820b 100644 --- a/unittest/mytap/tap.c +++ b/unittest/mytap/tap.c @@ -150,6 +150,8 @@ static signal_entry install_signal[]= { void plan(int const count) { + + setvbuf(tapout, 0, _IONBF, 0); /* provide output at once */ /* Install signal handler */ -- cgit v1.2.1 From 5750daa4cf73eba0a6f1d9909844bf106228ae80 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Dec 2006 15:31:04 +0100 Subject: Maria - post-review change of "fixes for gcc -ansi". And reducing the time taken by my_atomic-t. include/lf.h: fix to be able to add a ";" at the end of the macro's invokation (removing it here, removes a warning from "gcc -ansi" about a standalone ";"). mysys/lf_hash.c: ";" is ok now after LF_REQUIRE_PINS mysys/mf_pagecache.c: comment fix unittest/mysys/my_atomic-t.c: decreasing number of iterations to make test take less time. --- unittest/mysys/my_atomic-t.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index 314335944d3..02e07acd67b 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -275,9 +275,9 @@ int main() &my_charset_bin); #ifdef MY_ATOMIC_MODE_RWLOCKS -#define CYCLES 10000 +#define CYCLES 3000 #else -#define CYCLES 1000000 +#define CYCLES 300000 #endif #define THREADS 100 -- cgit v1.2.1 From 7199c905590391f64802913369aab7d288eff4c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Dec 2006 17:24:02 +0100 Subject: WL#3071 Maria checkpoint - cleanups, simplifications - moving the construction of the "dirty pages table" into the pagecache where it belongs (because it's the pagecache which knows dirty pages). TODO: do the same soon for the "transactions table". - fix for a small bug in the pagecache (decrementation of "changed_blocks") include/pagecache.h: prototype mysys/mf_pagecache.c: m_string.h moves up for LEX_STRING to be known for pagecache.h. In pagecache_delete_page(), we must decrement "blocks_changed" even if we just delete the page without flushing it. A new function pagecache_collect_changed_blocks_with_LSN() (used by the Checkpoint module), which stores information about the changed blocks (a.k.a. "the dirty pages table") into a LEX_STRING. This function is not tested now, it will be when there is a Checkpoint. storage/maria/ma_checkpoint.c: refining the checkpoint code: factoring functions, moving the construction of the "dirty pages table" into mf_pagecache.c (I'll do the same with the construction of the "transactions table" once Serg tells me what's the best way to do it). storage/maria/ma_least_recently_dirtied.c: Simplifying the thread which does background flushing of least-recently-dirtied pages: - in first version that thread will not flush, just do checkpoints - in 2nd version, flushing should re-use existing page cache functions like flush_pagecache_blocks(). unittest/mysys/test_file.h: m_string.h moves up for LEX_STRING to be known in pagecache.h --- unittest/mysys/test_file.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'unittest') diff --git a/unittest/mysys/test_file.h b/unittest/mysys/test_file.h index ea787c123ed..bfc660b13d0 100644 --- a/unittest/mysys/test_file.h +++ b/unittest/mysys/test_file.h @@ -1,4 +1,4 @@ - +#include #include /* -- cgit v1.2.1 From c2f2a41ed32522fa89f5c79fec42ab60e0b4aa62 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Dec 2006 19:15:53 +0100 Subject: Maria - merging recent changes done to MyISAM into Maria. Plus compiler warnings, and a fix to the pagecache unit tests for IA64 include/maria.h: merging MyISAM into Maria include/myisam.h: post-merge fixes mysql-test/r/maria.result: merging MyISAM into Maria mysql-test/t/maria.test: merging MyISAM into Maria sql/mysqld.cc: post-merge fixes storage/maria/ha_maria.cc: merging MyISAM into Maria storage/maria/ha_maria.h: merging MyISAM into Maria storage/maria/ma_check.c: merging MyISAM into Maria storage/maria/ma_open.c: merging MyISAM into Maria storage/maria/ma_packrec.c: merging MyISAM into Maria storage/maria/ma_range.c: merging MyISAM into Maria storage/maria/ma_sort.c: merging MyISAM into Maria storage/maria/maria_def.h: merging MyISAM into Maria storage/maria/maria_pack.c: merging MyISAM into Maria storage/maria/plug.in: merging MyISAM into Maria storage/myisam/myisamdef.h: merging MyISAM into Maria storage/myisam/myisampack.c: fix for compiler warnings unittest/mysys/mf_pagecache_consist.c: this sets the stack size lower than the minimum on IA64, we remove it (it made the test fail) unittest/mysys/mf_pagecache_single.c: this sets the stack size lower than the minimum on IA64, we remove it (it made the test fail) --- unittest/mysys/mf_pagecache_consist.c | 8 -------- unittest/mysys/mf_pagecache_single.c | 8 -------- 2 files changed, 16 deletions(-) (limited to 'unittest') diff --git a/unittest/mysys/mf_pagecache_consist.c b/unittest/mysys/mf_pagecache_consist.c index f7724222a09..95c2135edad 100755 --- a/unittest/mysys/mf_pagecache_consist.c +++ b/unittest/mysys/mf_pagecache_consist.c @@ -332,14 +332,6 @@ int main(int argc, char **argv __attribute__((unused))) 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 diff --git a/unittest/mysys/mf_pagecache_single.c b/unittest/mysys/mf_pagecache_single.c index 49ecd2986ab..9c467343156 100644 --- a/unittest/mysys/mf_pagecache_single.c +++ b/unittest/mysys/mf_pagecache_single.c @@ -511,14 +511,6 @@ int main(int argc, char **argv __attribute__((unused))) 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 -- cgit v1.2.1