2007-11-14 17:58:38 +00:00
/* -*- mode: C; c-basic-offset: 4 -*- */
2013-04-16 23:59:44 -04:00
# ident "$Id$"
2008-01-24 15:10:32 +00:00
# ident "Copyright (c) 2007, 2008 Tokutek Inc. All rights reserved."
2007-11-14 17:58:38 +00:00
2013-04-16 23:57:20 -04:00
# include "includes.h"
2007-12-22 23:12:40 +00:00
# include "test.h"
2007-09-21 17:55:49 +00:00
2013-04-16 23:57:35 -04:00
// this mutex is used by some of the tests to serialize access to some
// global data, especially between the test thread and the cachetable
// writeback threads
toku_pthread_mutex_t test_mutex ;
2013-04-16 23:58:00 -04:00
static inline void test_mutex_init ( void ) {
2013-04-16 23:57:35 -04:00
int r = toku_pthread_mutex_init ( & test_mutex , 0 ) ; assert ( r = = 0 ) ;
}
2013-04-16 23:58:00 -04:00
static inline void test_mutex_destroy ( void ) {
2013-04-16 23:57:35 -04:00
int r = toku_pthread_mutex_destroy ( & test_mutex ) ; assert ( r = = 0 ) ;
}
2013-04-16 23:58:00 -04:00
static inline void test_mutex_lock ( void ) {
2013-04-16 23:57:35 -04:00
int r = toku_pthread_mutex_lock ( & test_mutex ) ; assert ( r = = 0 ) ;
}
2013-04-16 23:58:00 -04:00
static inline void test_mutex_unlock ( void ) {
2013-04-16 23:57:35 -04:00
int r = toku_pthread_mutex_unlock ( & test_mutex ) ; assert ( r = = 0 ) ;
}
2008-08-22 17:50:05 +00:00
// hook my_malloc_always_fails into malloc to control malloc and verify
// the correct recovery from malloc failures
2013-04-16 23:57:27 -04:00
# if defined(__linux__)
2013-04-16 23:57:38 -04:00
# define DO_MALLOC_HOOK 1
2013-04-16 23:57:27 -04:00
# else
# define DO_MALLOC_HOOK 0
# endif
2008-08-22 17:50:05 +00:00
# if DO_MALLOC_HOOK
static void * my_malloc_always_fails ( size_t n , const __malloc_ptr_t p ) {
n = n ; p = p ;
return 0 ;
}
# endif
// verify that cachetable creation and close works
2013-04-16 23:57:20 -04:00
static void
test_cachetable_create ( void ) {
2008-08-22 17:50:05 +00:00
CACHETABLE ct = 0 ;
int r ;
r = toku_create_cachetable ( & ct , 0 , ZERO_LSN , NULL_LOGGER ) ;
assert ( r = = 0 ) ;
r = toku_cachetable_close ( & ct ) ;
assert ( r = = 0 & & ct = = 0 ) ;
}
// verify that cachetable create with no memory returns ENOMEM
2013-04-16 23:57:33 -04:00
# if DO_MALLOC_HOOK
2008-08-22 17:50:05 +00:00
2013-04-16 23:57:20 -04:00
static void
test_cachetable_create_no_memory ( void ) {
2008-08-22 17:50:05 +00:00
void * ( * orig_malloc_hook ) ( size_t , const __malloc_ptr_t ) = __malloc_hook ;
__malloc_hook = my_malloc_always_fails ;
CACHETABLE ct = 0 ;
int r ;
r = toku_create_cachetable ( & ct , 0 , ZERO_LSN , NULL_LOGGER ) ;
assert ( r = = ENOMEM ) ;
__malloc_hook = orig_malloc_hook ;
}
2013-04-16 23:57:27 -04:00
# endif
2007-11-29 18:14:40 +00:00
static const int test_object_size = 1 ;
2007-10-19 14:07:41 +00:00
2007-07-13 19:37:47 +00:00
struct item {
CACHEKEY key ;
char * something ;
} ;
2008-08-22 17:50:05 +00:00
static volatile int expect_n_flushes = 0 ;
static volatile CACHEKEY flushes [ 100 ] ;
2007-07-13 19:37:47 +00:00
2013-04-16 23:57:35 -04:00
static void expect_init ( void ) {
test_mutex_lock ( ) ;
expect_n_flushes = 0 ;
test_mutex_unlock ( ) ;
}
2013-04-16 23:57:18 -04:00
static void expect1 ( int64_t blocknum_n ) {
2013-04-16 23:57:35 -04:00
test_mutex_lock ( ) ;
2007-07-13 19:37:47 +00:00
expect_n_flushes = 1 ;
2013-04-16 23:57:18 -04:00
flushes [ 0 ] . b = blocknum_n ;
//if (verbose) printf("%s:%d %lld\n", __FUNCTION__, 0, key.b);
2013-04-16 23:57:35 -04:00
test_mutex_unlock ( ) ;
2007-07-13 19:37:47 +00:00
}
2013-04-16 23:57:18 -04:00
static void expectN ( int64_t blocknum_n ) {
2013-04-16 23:57:35 -04:00
test_mutex_lock ( ) ;
2013-04-16 23:57:18 -04:00
//if (verbose) printf("%s:%d %lld\n", __FUNCTION__, expect_n_flushes, key);
flushes [ expect_n_flushes + + ] . b = blocknum_n ;
2013-04-16 23:57:35 -04:00
test_mutex_unlock ( ) ;
2007-07-13 19:37:47 +00:00
}
2007-11-29 18:14:40 +00:00
static CACHEFILE expect_f ;
2007-07-13 19:37:47 +00:00
2013-04-16 23:57:18 -04:00
static void flush ( CACHEFILE f ,
2013-04-16 23:59:02 -04:00
int UU ( fd ) ,
2013-04-16 23:57:18 -04:00
CACHEKEY key ,
void * value ,
void * extra __attribute__ ( ( __unused__ ) ) ,
long size __attribute__ ( ( __unused__ ) ) ,
BOOL write_me __attribute__ ( ( __unused__ ) ) ,
BOOL keep_me __attribute__ ( ( __unused__ ) ) ,
2013-04-16 23:57:47 -04:00
BOOL for_checkpoint __attribute__ ( ( __unused__ ) ) ) {
2007-07-13 19:37:47 +00:00
struct item * it = value ;
int i ;
2008-08-22 17:50:05 +00:00
if ( keep_me ) return ;
2013-04-16 23:57:18 -04:00
if ( verbose ) printf ( " Flushing % " PRId64 " (it=>key=% " PRId64 " ) \n " , key . b , it - > key . b ) ;
2007-07-13 19:37:47 +00:00
2013-04-16 23:57:35 -04:00
test_mutex_lock ( ) ;
2007-07-13 19:37:47 +00:00
assert ( expect_f = = f ) ;
assert ( strcmp ( it - > something , " something " ) = = 0 ) ;
2013-04-16 23:57:18 -04:00
assert ( it - > key . b = = key . b ) ;
2007-07-13 19:37:47 +00:00
/* Verify that we expected the flush. */
for ( i = 0 ; i < expect_n_flushes ; i + + ) {
2013-04-16 23:57:18 -04:00
if ( key . b = = flushes [ i ] . b ) {
2007-07-13 19:37:47 +00:00
flushes [ i ] = flushes [ expect_n_flushes - 1 ] ;
expect_n_flushes - - ;
goto found_flush ;
}
}
2013-04-16 23:57:18 -04:00
fprintf ( stderr , " % " PRId64 " was flushed, but I didn't expect it \n " , key . b ) ;
2007-07-13 19:37:47 +00:00
abort ( ) ;
found_flush :
2013-04-16 23:57:35 -04:00
test_mutex_unlock ( ) ;
2007-07-20 18:00:14 +00:00
toku_free ( value ) ;
2007-07-13 19:37:47 +00:00
}
2013-04-16 23:57:18 -04:00
static struct item * make_item ( u_int64_t key ) {
2007-07-13 19:37:47 +00:00
struct item * MALLOC ( it ) ;
2013-04-16 23:57:18 -04:00
it - > key . b = key ;
2007-07-13 19:37:47 +00:00
it - > something = " something " ;
return it ;
}
2013-04-16 23:57:18 -04:00
static CACHEKEY did_fetch = { - 1 } ;
2013-04-16 23:59:25 -04:00
static int fetch ( CACHEFILE f , int UU ( fd ) , CACHEKEY key , u_int32_t fullhash __attribute__ ( ( __unused__ ) ) , void * * value , long * sizep __attribute__ ( ( __unused__ ) ) , int * dirtyp , void * extraargs ) {
2013-04-16 23:57:18 -04:00
if ( verbose ) printf ( " Fetch % " PRId64 " \n " , key . b ) ;
2007-07-13 19:37:47 +00:00
assert ( expect_f = = f ) ;
assert ( ( long ) extraargs = = 23 ) ;
2013-04-16 23:57:18 -04:00
* value = make_item ( key . b ) ;
2013-04-16 23:57:38 -04:00
* sizep = test_object_size ;
2013-04-16 23:59:25 -04:00
* dirtyp = 0 ;
2007-07-13 19:37:47 +00:00
did_fetch = key ;
return 0 ;
}
2013-04-16 23:59:48 -04:00
static void
pe_est_callback (
void * UU ( brtnode_pv ) ,
long * bytes_freed_estimate ,
enum partial_eviction_cost * cost ,
void * UU ( write_extraargs )
)
{
* bytes_freed_estimate = 0 ;
* cost = PE_CHEAP ;
}
2013-04-16 23:59:40 -04:00
static int
pe_callback (
void * brtnode_pv __attribute__ ( ( __unused__ ) ) ,
long bytes_to_free __attribute__ ( ( __unused__ ) ) ,
long * bytes_freed ,
void * extraargs __attribute__ ( ( __unused__ ) )
)
{
* bytes_freed = 0 ;
return 0 ;
}
2013-04-16 23:59:41 -04:00
static BOOL pf_req_callback ( void * UU ( brtnode_pv ) , void * UU ( read_extraargs ) ) {
return FALSE ;
}
2013-04-16 23:59:41 -04:00
static int pf_callback ( void * UU ( brtnode_pv ) , void * UU ( read_extraargs ) , int UU ( fd ) , long * UU ( sizep ) ) {
2013-04-16 23:59:41 -04:00
assert ( FALSE ) ;
}
2013-04-16 23:59:40 -04:00
2013-04-16 23:57:41 -04:00
static void maybe_flush ( CACHETABLE t ) {
toku_cachetable_maybe_flush_some ( t ) ;
}
2008-08-22 17:50:05 +00:00
// verify that a sequence of cachetable operations causes a particular sequence of
// callbacks
2007-07-13 19:37:47 +00:00
2007-11-29 18:14:40 +00:00
static void test0 ( void ) {
2007-07-13 19:37:47 +00:00
void * t3 = ( void * ) 23 ;
CACHETABLE t ;
CACHEFILE f ;
int r ;
2008-05-04 16:56:15 +00:00
char fname [ ] = __FILE__ " test.dat " ;
2013-04-16 23:57:35 -04:00
2007-11-19 23:47:44 +00:00
r = toku_create_cachetable ( & t , 5 , ZERO_LSN , NULL_LOGGER ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:47 -04:00
unlink ( fname ) ;
2013-04-16 23:59:03 -04:00
r = toku_cachetable_openf ( & f , t , fname , O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2008-08-26 14:07:27 +00:00
TOKULOGGER logger = toku_cachefile_logger ( f ) ;
assert ( logger = = NULL_LOGGER ) ;
2007-07-13 19:37:47 +00:00
expect_f = f ;
expect_n_flushes = 0 ;
2013-04-16 23:57:18 -04:00
u_int32_t h1 = toku_cachetable_hash ( f , make_blocknum ( 1 ) ) ;
u_int32_t h2 = toku_cachetable_hash ( f , make_blocknum ( 2 ) ) ;
u_int32_t h3 = toku_cachetable_hash ( f , make_blocknum ( 3 ) ) ;
u_int32_t h4 = toku_cachetable_hash ( f , make_blocknum ( 4 ) ) ;
u_int32_t h5 = toku_cachetable_hash ( f , make_blocknum ( 5 ) ) ;
u_int32_t h6 = toku_cachetable_hash ( f , make_blocknum ( 6 ) ) ;
u_int32_t h7 = toku_cachetable_hash ( f , make_blocknum ( 7 ) ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , make_blocknum ( 1 ) , h1 , make_item ( 1 ) , test_object_size , flush , pe_est_callback , pe_callback , t3 ) ; /* 1P */ /* this is the lru list. 1 is pinned. */
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
assert ( expect_n_flushes = = 0 ) ;
2013-04-16 23:57:35 -04:00
expect_init ( ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , make_blocknum ( 2 ) , h2 , make_item ( 2 ) , test_object_size , flush , pe_est_callback , pe_callback , t3 ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 2 ) , h2 , CACHETABLE_DIRTY , 1 ) ; /* 2U 1P */
2007-07-13 19:37:47 +00:00
assert ( expect_n_flushes = = 0 ) ;
2013-04-16 23:57:35 -04:00
expect_init ( ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , make_blocknum ( 3 ) , h3 , make_item ( 3 ) , test_object_size , flush , pe_est_callback , pe_callback , t3 ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
assert ( expect_n_flushes = = 0 ) ; /* 3P 2U 1P */ /* 3 is most recently used (pinned), 2 is next (unpinned), 1 is least recent (pinned) */
2013-04-16 23:57:35 -04:00
expect_init ( ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , make_blocknum ( 4 ) , h4 , make_item ( 4 ) , test_object_size , flush , pe_est_callback , pe_callback , t3 ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
assert ( expect_n_flushes = = 0 ) ; /* 4P 3P 2U 1P */
2013-04-16 23:57:35 -04:00
expect_init ( ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , make_blocknum ( 5 ) , h5 , make_item ( 5 ) , test_object_size , flush , pe_est_callback , pe_callback , t3 ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 5 ) , h5 , CACHETABLE_DIRTY , test_object_size ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 3 ) , h3 , CACHETABLE_DIRTY , test_object_size ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
assert ( expect_n_flushes = = 0 ) ; /* 5U 4P 3U 2U 1P */
expect1 ( 2 ) ; /* 2 is the oldest unpinned item. */
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , make_blocknum ( 6 ) , h6 , make_item ( 6 ) , test_object_size , flush , pe_est_callback , pe_callback , t3 ) ; /* 6P 5U 4P 3U 1P */
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:35 -04:00
test_mutex_lock ( ) ;
while ( expect_n_flushes ! = 0 ) {
2013-04-16 23:57:41 -04:00
test_mutex_unlock ( ) ; toku_pthread_yield ( ) ; maybe_flush ( t ) ; test_mutex_lock ( ) ;
2013-04-16 23:57:35 -04:00
}
2007-07-13 19:37:47 +00:00
assert ( expect_n_flushes = = 0 ) ;
2013-04-16 23:57:35 -04:00
test_mutex_unlock ( ) ;
2007-07-13 19:37:47 +00:00
expect1 ( 3 ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , make_blocknum ( 7 ) , h7 , make_item ( 7 ) , test_object_size , flush , pe_est_callback , pe_callback , t3 ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:35 -04:00
test_mutex_lock ( ) ;
while ( expect_n_flushes ! = 0 ) {
2013-04-16 23:57:41 -04:00
test_mutex_unlock ( ) ; toku_pthread_yield ( ) ; maybe_flush ( t ) ; test_mutex_lock ( ) ;
2013-04-16 23:57:35 -04:00
}
2007-07-13 19:37:47 +00:00
assert ( expect_n_flushes = = 0 ) ;
2013-04-16 23:57:35 -04:00
test_mutex_unlock ( ) ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 7 ) , h7 , CACHETABLE_DIRTY , test_object_size ) ; /* 7U 6P 5U 4P 1P */
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
{
void * item_v = 0 ;
2013-04-16 23:57:35 -04:00
expect_init ( ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_get_and_pin ( f , make_blocknum ( 5 ) , toku_cachetable_hash ( f , make_blocknum ( 5 ) ) , & item_v , NULL , flush , fetch , pe_est_callback , pe_callback , pf_req_callback , pf_callback , t3 , t3 ) ; /* 5P 7U 6P 4P 1P */
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
assert ( ( ( struct item * ) item_v ) - > key . b = = 5 ) ;
2007-07-13 19:37:47 +00:00
assert ( strcmp ( ( ( struct item * ) item_v ) - > something , " something " ) = = 0 ) ;
2013-04-16 23:57:35 -04:00
test_mutex_lock ( ) ;
2007-07-13 19:37:47 +00:00
assert ( expect_n_flushes = = 0 ) ;
2013-04-16 23:57:35 -04:00
test_mutex_unlock ( ) ;
2007-07-13 19:37:47 +00:00
}
{
void * item_v = 0 ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 4 ) , h4 , CACHETABLE_DIRTY , test_object_size ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
expect1 ( 4 ) ;
2013-04-16 23:57:18 -04:00
did_fetch = make_blocknum ( - 1 ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_get_and_pin ( f , make_blocknum ( 2 ) , toku_cachetable_hash ( f , make_blocknum ( 2 ) ) , & item_v , NULL , flush , fetch , pe_est_callback , pe_callback , pf_req_callback , pf_callback , t3 , t3 ) ; /* 2p 5P 7U 6P 1P */
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
assert ( did_fetch . b = = 2 ) ; /* Expect that 2 is fetched in. */
assert ( ( ( struct item * ) item_v ) - > key . b = = 2 ) ;
2007-07-13 19:37:47 +00:00
assert ( strcmp ( ( ( struct item * ) item_v ) - > something , " something " ) = = 0 ) ;
2013-04-16 23:57:35 -04:00
test_mutex_lock ( ) ;
while ( expect_n_flushes ! = 0 ) {
2013-04-16 23:57:41 -04:00
test_mutex_unlock ( ) ; toku_pthread_yield ( ) ; maybe_flush ( t ) ; test_mutex_lock ( ) ;
2013-04-16 23:57:35 -04:00
}
2007-09-21 17:55:49 +00:00
assert ( expect_n_flushes = = 0 ) ;
2013-04-16 23:57:35 -04:00
test_mutex_unlock ( ) ;
2007-07-13 19:37:47 +00:00
}
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 2 ) , h2 , CACHETABLE_DIRTY , test_object_size ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 5 ) , h5 , CACHETABLE_DIRTY , test_object_size ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 6 ) , h6 , CACHETABLE_DIRTY , test_object_size ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 1 ) , h1 , CACHETABLE_DIRTY , test_object_size ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2007-11-19 23:47:44 +00:00
r = toku_cachetable_assert_all_unpinned ( t ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2007-12-22 23:12:40 +00:00
if ( verbose ) printf ( " Closing \n " ) ;
2007-07-13 19:37:47 +00:00
expect1 ( 2 ) ;
expectN ( 5 ) ;
expectN ( 7 ) ;
expectN ( 6 ) ;
expectN ( 1 ) ;
2013-04-16 23:58:06 -04:00
r = toku_cachefile_close ( & f , 0 , FALSE , ZERO_LSN ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2007-11-19 23:47:44 +00:00
r = toku_cachetable_close ( & t ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
assert ( expect_n_flushes = = 0 ) ;
2008-08-22 17:50:05 +00:00
expect_f = 0 ;
2013-04-16 23:59:22 -04:00
2007-07-13 19:37:47 +00:00
}
2013-04-16 23:59:02 -04:00
static void flush_n ( CACHEFILE f __attribute__ ( ( __unused__ ) ) , int UU ( fd ) , CACHEKEY key __attribute__ ( ( __unused__ ) ) ,
2013-04-16 23:57:18 -04:00
void * value ,
void * extra __attribute__ ( ( __unused__ ) ) ,
2007-11-14 17:58:38 +00:00
long size __attribute__ ( ( __unused__ ) ) ,
BOOL write_me __attribute__ ( ( __unused__ ) ) , BOOL keep_me __attribute__ ( ( __unused__ ) ) ,
2013-04-16 23:57:47 -04:00
BOOL for_checkpoint __attribute__ ( ( __unused__ ) ) ) {
2007-07-13 19:37:47 +00:00
int * v = value ;
assert ( * v = = 0 ) ;
}
2013-04-16 23:59:02 -04:00
static int fetch_n ( CACHEFILE f __attribute__ ( ( __unused__ ) ) , int UU ( fd ) , CACHEKEY key __attribute__ ( ( __unused__ ) ) ,
2008-06-17 17:05:19 +00:00
u_int32_t fullhash __attribute__ ( ( __unused__ ) ) ,
2013-04-16 23:59:25 -04:00
void * * value , long * sizep __attribute__ ( ( __unused__ ) ) ,
int * dirtyp , void * extraargs ) {
2007-07-13 19:37:47 +00:00
assert ( ( long ) extraargs = = 42 ) ;
* value = 0 ;
2013-04-16 23:59:25 -04:00
* dirtyp = 0 ;
2007-07-13 19:37:47 +00:00
return 0 ;
}
2007-11-29 18:14:40 +00:00
static void test_nested_pin ( void ) {
2007-07-13 19:37:47 +00:00
void * f2 = ( void * ) 42 ;
CACHETABLE t ;
CACHEFILE f ;
int i0 , i1 ;
int r ;
2008-04-07 20:32:10 +00:00
void * vv , * vv2 ;
2008-05-04 16:56:15 +00:00
char fname [ ] = __FILE__ " test_ct.dat " ;
2007-11-19 23:47:44 +00:00
r = toku_create_cachetable ( & t , 1 , ZERO_LSN , NULL_LOGGER ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:47 -04:00
unlink ( fname ) ;
2013-04-16 23:59:03 -04:00
r = toku_cachetable_openf ( & f , t , fname , O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
expect_f = f ;
i0 = 0 ; i1 = 0 ;
2013-04-16 23:57:18 -04:00
u_int32_t f1hash = toku_cachetable_hash ( f , make_blocknum ( 1 ) ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , make_blocknum ( 1 ) , f1hash , & i0 , 1 , flush_n , pe_est_callback , pe_callback , f2 ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_get_and_pin ( f , make_blocknum ( 1 ) , f1hash , & vv , NULL , flush_n , fetch_n , pe_est_callback , pe_callback , pf_req_callback , pf_callback , f2 , f2 ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
assert ( vv = = & i0 ) ;
assert ( i0 = = 0 ) ;
2013-04-16 23:57:38 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 1 ) , f1hash , CACHETABLE_CLEAN , test_object_size ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_maybe_get_and_pin ( f , make_blocknum ( 1 ) , f1hash , & vv2 ) ;
2008-04-07 20:32:10 +00:00
assert ( r = = 0 ) ;
assert ( vv2 = = vv ) ;
2013-04-16 23:57:38 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 1 ) , f1hash , CACHETABLE_CLEAN , test_object_size ) ;
2008-08-22 17:50:05 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
u_int32_t f2hash = toku_cachetable_hash ( f , make_blocknum ( 2 ) ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , make_blocknum ( 2 ) , f2hash , & i1 , test_object_size , flush_n , pe_est_callback , pe_callback , f2 ) ;
2008-04-07 20:32:10 +00:00
assert ( r = = 0 ) ; // The other one is pinned, but now the cachetable fails gracefully: It allows the pin to happen
2013-04-16 23:57:38 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 1 ) , f1hash , CACHETABLE_CLEAN , test_object_size ) ;
2007-07-13 19:37:47 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:38 -04:00
r = toku_cachetable_unpin ( f , make_blocknum ( 2 ) , f2hash , CACHETABLE_CLEAN , test_object_size ) ;
2008-08-22 17:50:05 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:28 -04:00
// toku_os_usleep(1*1000000);
2013-04-16 23:58:06 -04:00
r = toku_cachefile_close ( & f , 0 , FALSE , ZERO_LSN ) ; assert ( r = = 0 ) ;
2007-11-19 23:47:44 +00:00
r = toku_cachetable_close ( & t ) ; assert ( r = = 0 ) ;
2007-07-13 19:37:47 +00:00
}
2007-11-29 18:14:40 +00:00
static void null_flush ( CACHEFILE cf __attribute__ ( ( __unused__ ) ) ,
2013-04-16 23:59:02 -04:00
int UU ( fd ) ,
2008-08-22 17:50:05 +00:00
CACHEKEY k __attribute__ ( ( __unused__ ) ) ,
void * v __attribute__ ( ( __unused__ ) ) ,
2013-04-16 23:57:18 -04:00
void * extra __attribute__ ( ( __unused__ ) ) ,
2008-08-22 17:50:05 +00:00
long size __attribute__ ( ( __unused__ ) ) ,
BOOL write_me __attribute__ ( ( __unused__ ) ) ,
BOOL keep_me __attribute__ ( ( __unused__ ) ) ,
2013-04-16 23:57:47 -04:00
BOOL for_checkpoint __attribute__ ( ( __unused__ ) ) ) {
2007-07-13 19:37:47 +00:00
}
2008-08-22 17:50:05 +00:00
2013-04-16 23:59:25 -04:00
static int add123_fetch ( CACHEFILE cf , int UU ( fd ) , CACHEKEY key , u_int32_t fullhash , void * * value , long * sizep __attribute__ ( ( __unused__ ) ) , int * dirtyp , void * extraargs ) {
2008-06-17 17:05:19 +00:00
assert ( fullhash = = toku_cachetable_hash ( cf , key ) ) ;
2007-07-13 19:37:47 +00:00
assert ( ( long ) extraargs = = 123 ) ;
2013-04-16 23:57:18 -04:00
* value = ( void * ) ( ( unsigned long ) key . b + 123L ) ;
2013-04-16 23:59:25 -04:00
* dirtyp = 0 ;
2007-07-13 19:37:47 +00:00
return 0 ;
}
2008-08-22 17:50:05 +00:00
2013-04-16 23:59:25 -04:00
static int add222_fetch ( CACHEFILE cf , int UU ( fd ) , CACHEKEY key , u_int32_t fullhash , void * * value , long * sizep __attribute__ ( ( __unused__ ) ) , int * dirtyp , void * extraargs ) {
2008-06-17 17:05:19 +00:00
assert ( fullhash = = toku_cachetable_hash ( cf , key ) ) ;
2007-07-13 19:37:47 +00:00
assert ( ( long ) extraargs = = 222 ) ;
2013-04-16 23:57:18 -04:00
* value = ( void * ) ( ( unsigned long ) key . b + 222L ) ;
2013-04-16 23:59:25 -04:00
* dirtyp = 0 ;
2007-07-13 19:37:47 +00:00
return 0 ;
}
2013-04-16 23:58:59 -04:00
# if !TOKU_WINDOWS
2013-04-16 23:57:27 -04:00
2007-11-29 18:14:40 +00:00
static void test_multi_filehandles ( void ) {
2007-07-13 19:37:47 +00:00
CACHETABLE t ;
CACHEFILE f1 , f2 , f3 ;
2008-05-04 16:56:15 +00:00
char fname1 [ ] = __FILE__ " test_ct.dat " ;
char fname2 [ ] = __FILE__ " test2_ct.dat " ;
char fname3 [ ] = __FILE__ " test3_ct.dat " ;
2007-07-13 19:37:47 +00:00
int r ;
void * v ;
2013-04-16 23:57:47 -04:00
unlink ( fname1 ) ;
unlink ( fname2 ) ;
2007-07-13 19:37:47 +00:00
2007-11-19 23:47:44 +00:00
r = toku_create_cachetable ( & t , 4 , ZERO_LSN , NULL_LOGGER ) ; assert ( r = = 0 ) ;
2013-04-16 23:59:03 -04:00
r = toku_cachetable_openf ( & f1 , t , fname1 , O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO ) ; assert ( r = = 0 ) ;
2007-07-13 19:37:47 +00:00
r = link ( fname1 , fname2 ) ; assert ( r = = 0 ) ;
2013-04-16 23:59:03 -04:00
r = toku_cachetable_openf ( & f2 , t , fname2 , O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO ) ; assert ( r = = 0 ) ;
r = toku_cachetable_openf ( & f3 , t , fname3 , O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO ) ; assert ( r = = 0 ) ;
2007-07-13 19:37:47 +00:00
assert ( f1 = = f2 ) ;
assert ( f1 ! = f3 ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f1 , make_blocknum ( 1 ) , toku_cachetable_hash ( f1 , make_blocknum ( 1 ) ) , ( void * ) 124 , test_object_size , null_flush , pe_est_callback , pe_callback , ( void * ) 123 ) ; assert ( r = = 0 ) ;
r = toku_cachetable_get_and_pin ( f2 , make_blocknum ( 1 ) , toku_cachetable_hash ( f2 , make_blocknum ( 1 ) ) , & v , NULL , null_flush , add123_fetch , pe_est_callback , pe_callback , pf_req_callback , pf_callback , ( void * ) 123 , ( void * ) 123 ) ; assert ( r = = 0 ) ;
2007-07-13 19:37:47 +00:00
assert ( ( unsigned long ) v = = 124 ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_get_and_pin ( f2 , make_blocknum ( 2 ) , toku_cachetable_hash ( f2 , make_blocknum ( 2 ) ) , & v , NULL , null_flush , add123_fetch , pe_est_callback , pe_callback , pf_req_callback , pf_callback , ( void * ) 123 , ( void * ) 123 ) ; assert ( r = = 0 ) ;
2007-07-13 19:37:47 +00:00
assert ( ( unsigned long ) v = = 125 ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_get_and_pin ( f3 , make_blocknum ( 2 ) , toku_cachetable_hash ( f3 , make_blocknum ( 2 ) ) , & v , NULL , null_flush , add222_fetch , pe_est_callback , pe_callback , pf_req_callback , pf_callback , ( void * ) 222 , ( void * ) 222 ) ; assert ( r = = 0 ) ;
2007-07-13 19:37:47 +00:00
assert ( ( unsigned long ) v = = 224 ) ;
2008-08-22 17:50:05 +00:00
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f1 , make_blocknum ( 1 ) , toku_cachetable_hash ( f1 , make_blocknum ( 1 ) ) , CACHETABLE_CLEAN , 0 ) ; assert ( r = = 0 ) ;
2013-04-16 23:59:40 -04:00
// r = toku_cachetable_unpin(f1, make_blocknum(2), toku_cachetable_hash(f1, make_blocknum(2)), CACHETABLE_CLEAN, 0); assert(r==0);
2013-04-16 23:58:06 -04:00
r = toku_cachefile_close ( & f1 , 0 , FALSE , ZERO_LSN ) ; assert ( r = = 0 ) ;
2008-08-22 17:50:05 +00:00
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f2 , make_blocknum ( 1 ) , toku_cachetable_hash ( f2 , make_blocknum ( 1 ) ) , CACHETABLE_CLEAN , 0 ) ; assert ( r = = 0 ) ;
r = toku_cachetable_unpin ( f2 , make_blocknum ( 2 ) , toku_cachetable_hash ( f2 , make_blocknum ( 2 ) ) , CACHETABLE_CLEAN , 0 ) ; assert ( r = = 0 ) ;
2013-04-16 23:58:06 -04:00
r = toku_cachefile_close ( & f2 , 0 , FALSE , ZERO_LSN ) ; assert ( r = = 0 ) ;
2008-08-22 17:50:05 +00:00
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( f3 , make_blocknum ( 2 ) , toku_cachetable_hash ( f3 , make_blocknum ( 2 ) ) , CACHETABLE_CLEAN , 0 ) ; assert ( r = = 0 ) ;
2013-04-16 23:58:06 -04:00
r = toku_cachefile_close ( & f3 , 0 , FALSE , ZERO_LSN ) ; assert ( r = = 0 ) ;
2008-08-22 17:50:05 +00:00
2007-11-19 23:47:44 +00:00
r = toku_cachetable_close ( & t ) ; assert ( r = = 0 ) ;
2007-07-13 19:37:47 +00:00
}
2013-04-16 23:57:27 -04:00
# endif
2013-04-16 23:57:18 -04:00
static void test_dirty_flush ( CACHEFILE f ,
2013-04-16 23:59:02 -04:00
int UU ( fd ) ,
2013-04-16 23:57:18 -04:00
CACHEKEY key ,
void * value ,
void * extra __attribute__ ( ( __unused__ ) ) ,
long size ,
BOOL do_write ,
BOOL keep ,
2013-04-16 23:57:47 -04:00
BOOL for_checkpoint __attribute__ ( ( __unused__ ) ) ) {
2013-04-16 23:57:27 -04:00
if ( verbose ) printf ( " test_dirty_flush %p % " PRId64 " %p %ld %u %u \n " , f , key . b , value , size , ( unsigned ) do_write , ( unsigned ) keep ) ;
2007-09-17 16:23:05 +00:00
}
2013-04-16 23:59:25 -04:00
static int test_dirty_fetch ( CACHEFILE f , int UU ( fd ) , CACHEKEY key , u_int32_t fullhash , void * * value_ptr , long * size_ptr , int * dirtyp , void * arg ) {
2007-09-17 16:23:05 +00:00
* value_ptr = arg ;
2013-04-16 23:59:25 -04:00
* dirtyp = 0 ;
2008-06-17 17:05:19 +00:00
assert ( fullhash = = toku_cachetable_hash ( f , key ) ) ;
2013-04-16 23:57:18 -04:00
if ( verbose ) printf ( " test_dirty_fetch %p % " PRId64 " %p %ld %p \n " , f , key . b , * value_ptr , * size_ptr , arg ) ;
2007-09-17 16:23:05 +00:00
return 0 ;
}
2013-04-16 23:58:00 -04:00
static void test_dirty ( void ) {
2007-12-22 23:12:40 +00:00
if ( verbose ) printf ( " test_dirty \n " ) ;
2007-09-21 17:55:49 +00:00
2007-09-17 16:23:05 +00:00
CACHETABLE t ;
CACHEFILE f ;
CACHEKEY key ; void * value ;
2007-09-21 17:55:49 +00:00
int dirty ; long long pinned ; long entry_size ;
2007-09-17 16:23:05 +00:00
int r ;
2007-11-19 23:47:44 +00:00
r = toku_create_cachetable ( & t , 4 , ZERO_LSN , NULL_LOGGER ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
2008-05-04 16:56:15 +00:00
char * fname = __FILE__ " test.dat " ;
2013-04-16 23:57:47 -04:00
unlink ( fname ) ;
2013-04-16 23:59:03 -04:00
r = toku_cachetable_openf ( & f , t , fname , O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
key = make_blocknum ( 1 ) ; value = ( void * ) 1 ;
2008-06-17 17:05:19 +00:00
u_int32_t hkey = toku_cachetable_hash ( f , key ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , key , hkey , value , test_object_size , test_dirty_flush , pe_est_callback , pe_callback , 0 ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
// cachetable_print_state(t);
2008-06-05 22:09:59 +00:00
r = toku_cachetable_get_key_state ( t , key , f , & value , & dirty , & pinned , & entry_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
assert ( dirty = = 1 ) ;
assert ( pinned = = 1 ) ;
2008-06-17 17:05:19 +00:00
r = toku_cachetable_unpin ( f , key , hkey , CACHETABLE_CLEAN , 0 ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
2008-06-05 22:09:59 +00:00
r = toku_cachetable_get_key_state ( t , key , f , & value , & dirty , & pinned , & entry_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
assert ( dirty = = 1 ) ;
assert ( pinned = = 0 ) ;
2008-06-17 17:05:19 +00:00
r = toku_cachetable_get_and_pin ( f , key , hkey , & value , NULL , test_dirty_flush ,
2013-04-16 23:59:48 -04:00
test_dirty_fetch , pe_est_callback , pe_callback , pf_req_callback , pf_callback , 0 , 0 ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
// cachetable_print_state(t);
2008-06-05 22:09:59 +00:00
r = toku_cachetable_get_key_state ( t , key , f , & value , & dirty , & pinned , & entry_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
assert ( dirty = = 1 ) ;
assert ( pinned = = 1 ) ;
2008-06-17 17:05:19 +00:00
r = toku_cachetable_unpin ( f , key , hkey , CACHETABLE_CLEAN , test_object_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
// cachetable_print_state(t);
2008-06-05 22:09:59 +00:00
r = toku_cachetable_get_key_state ( t , key , f , & value , & dirty , & pinned , & entry_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
assert ( dirty = = 1 ) ;
assert ( pinned = = 0 ) ;
2013-04-16 23:57:18 -04:00
key = make_blocknum ( 2 ) ;
2008-06-17 17:05:19 +00:00
hkey = toku_cachetable_hash ( f , key ) ;
r = toku_cachetable_get_and_pin ( f , key , hkey ,
& value , NULL , test_dirty_flush ,
2013-04-16 23:59:48 -04:00
test_dirty_fetch , pe_est_callback , pe_callback , pf_req_callback , pf_callback , 0 , 0 ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
// cachetable_print_state(t);
2008-06-05 22:09:59 +00:00
r = toku_cachetable_get_key_state ( t , key , f , & value , & dirty , & pinned , & entry_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
assert ( dirty = = 0 ) ;
assert ( pinned = = 1 ) ;
2008-06-17 17:05:19 +00:00
r = toku_cachetable_unpin ( f , key , hkey , CACHETABLE_CLEAN , test_object_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
// cachetable_print_state(t);
2008-06-05 22:09:59 +00:00
r = toku_cachetable_get_key_state ( t , key , f , & value , & dirty , & pinned , & entry_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
assert ( dirty = = 0 ) ;
assert ( pinned = = 0 ) ;
2008-06-17 17:05:19 +00:00
r = toku_cachetable_get_and_pin ( f , key , hkey ,
& value , NULL , test_dirty_flush ,
2013-04-16 23:59:48 -04:00
test_dirty_fetch , pe_est_callback , pe_callback , pf_req_callback , pf_callback , 0 , 0 ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
// cachetable_print_state(t);
2008-06-05 22:09:59 +00:00
r = toku_cachetable_get_key_state ( t , key , f , & value , & dirty , & pinned , & entry_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
assert ( dirty = = 0 ) ;
assert ( pinned = = 1 ) ;
2008-06-17 17:05:19 +00:00
r = toku_cachetable_unpin ( f , key , hkey , CACHETABLE_DIRTY , test_object_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
// cachetable_print_state(t);
2008-06-05 22:09:59 +00:00
r = toku_cachetable_get_key_state ( t , key , f , & value , & dirty , & pinned , & entry_size ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
assert ( dirty = = 1 ) ;
assert ( pinned = = 0 ) ;
2007-09-21 17:55:49 +00:00
2013-04-16 23:58:06 -04:00
r = toku_cachefile_close ( & f , 0 , FALSE , ZERO_LSN ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
2007-11-19 23:47:44 +00:00
r = toku_cachetable_close ( & t ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
}
2007-11-29 18:14:40 +00:00
static int test_size_debug ;
static CACHEKEY test_size_flush_key ;
2007-09-21 17:55:49 +00:00
2013-04-16 23:57:18 -04:00
static void test_size_flush_callback ( CACHEFILE f ,
2013-04-16 23:59:02 -04:00
int UU ( fd ) ,
2013-04-16 23:57:18 -04:00
CACHEKEY key ,
void * value ,
void * extra __attribute__ ( ( __unused__ ) ) ,
long size ,
BOOL do_write ,
BOOL keep ,
2013-04-16 23:57:47 -04:00
BOOL for_checkpoint __attribute__ ( ( __unused__ ) ) ) {
2013-04-16 23:57:27 -04:00
if ( test_size_debug & & verbose ) printf ( " test_size_flush %p % " PRId64 " %p %ld %u %u \n " , f , key . b , value , size , ( unsigned ) do_write , ( unsigned ) keep ) ;
2008-08-22 17:50:05 +00:00
if ( keep ) {
2013-04-16 23:57:41 -04:00
if ( do_write ) {
test_mutex_lock ( ) ;
test_size_flush_key = key ;
test_mutex_unlock ( ) ;
}
} else {
assert ( ! do_write ) ;
2008-08-22 17:50:05 +00:00
}
2007-09-21 17:55:49 +00:00
}
2013-04-16 23:58:00 -04:00
static void test_size_resize ( void ) {
2007-12-22 23:12:40 +00:00
if ( verbose ) printf ( " test_size_resize \n " ) ;
2007-09-21 17:55:49 +00:00
CACHETABLE t ;
CACHEFILE f ;
int r ;
int n = 3 ;
long size = 1 ;
2007-11-19 23:47:44 +00:00
r = toku_create_cachetable ( & t , n * size , ZERO_LSN , NULL_LOGGER ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
2008-05-04 16:56:15 +00:00
char * fname = __FILE__ " test.dat " ;
2013-04-16 23:57:47 -04:00
unlink ( fname ) ;
2013-04-16 23:59:03 -04:00
r = toku_cachetable_openf ( & f , t , fname , O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
CACHEKEY key = make_blocknum ( 42 ) ;
2007-09-21 17:55:49 +00:00
void * value = ( void * ) - 42 ;
2008-06-17 17:05:19 +00:00
u_int32_t hkey = toku_cachetable_hash ( f , key ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , key , hkey , value , size , test_size_flush_callback , pe_est_callback , pe_callback , 0 ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
2007-09-17 16:23:05 +00:00
2007-09-21 17:55:49 +00:00
void * entry_value ; int dirty ; long long pinned ; long entry_size ;
2008-06-05 22:09:59 +00:00
r = toku_cachetable_get_key_state ( t , key , f , & entry_value , & dirty , & pinned , & entry_size ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
assert ( dirty = = 1 ) ;
assert ( pinned = = 1 ) ;
assert ( entry_value = = value ) ;
assert ( entry_size = = size ) ;
long long new_size = 2 * size ;
2008-06-17 17:05:19 +00:00
r = toku_cachetable_unpin ( f , key , hkey , CACHETABLE_CLEAN , new_size ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
void * current_value ;
long current_size ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_get_and_pin ( f , key , hkey , & current_value , & current_size , test_size_flush_callback , 0 , pe_est_callback , pe_callback , pf_req_callback , pf_callback , 0 , 0 ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
assert ( current_value = = value ) ;
assert ( current_size = = new_size ) ;
2008-06-17 17:05:19 +00:00
r = toku_cachetable_unpin ( f , key , hkey , CACHETABLE_CLEAN , new_size ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:58:06 -04:00
r = toku_cachefile_close ( & f , 0 , FALSE , ZERO_LSN ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
2007-11-19 23:47:44 +00:00
r = toku_cachetable_close ( & t ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
}
2013-04-16 23:57:19 -04:00
static int min2 ( int a , int b ) { return a < b ? a : b ; }
2013-04-16 23:59:40 -04:00
__attribute__ ( ( unused ) )
2013-04-16 23:58:00 -04:00
static void test_size_flush ( void ) {
2007-12-22 23:12:40 +00:00
if ( verbose ) printf ( " test_size_flush \n " ) ;
2007-09-21 17:55:49 +00:00
CACHETABLE t ;
CACHEFILE f ;
int r ;
const int n = 8 ;
long long size = 1 * 1024 * 1024 ;
2007-11-19 23:47:44 +00:00
r = toku_create_cachetable ( & t , n * size , ZERO_LSN , NULL_LOGGER ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
2008-05-04 16:56:15 +00:00
char * fname = __FILE__ " test.dat " ;
2013-04-16 23:57:47 -04:00
unlink ( fname ) ;
2013-04-16 23:59:03 -04:00
r = toku_cachetable_openf ( & f , t , fname , O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
/* put 2*n keys into the table, ensure flushes occur in key order */
2013-04-16 23:57:35 -04:00
test_mutex_lock ( ) ;
2013-04-16 23:57:18 -04:00
test_size_flush_key = make_blocknum ( - 1 ) ;
2013-04-16 23:57:35 -04:00
test_mutex_unlock ( ) ;
2007-09-21 17:55:49 +00:00
int i ;
2013-04-16 23:57:18 -04:00
CACHEKEY expect_flush_key = make_blocknum ( 0 ) ;
2007-09-21 17:55:49 +00:00
for ( i = 0 ; i < 2 * n ; i + + ) {
2013-04-16 23:57:18 -04:00
CACHEKEY key = make_blocknum ( i ) ;
2007-09-21 18:34:34 +00:00
void * value = ( void * ) ( long ) - i ;
2007-09-21 17:55:49 +00:00
// printf("test_size put %lld %p %lld\n", key, value, size);
2008-06-17 17:05:19 +00:00
u_int32_t hkey = toku_cachetable_hash ( f , key ) ;
2013-04-16 23:59:48 -04:00
r = toku_cachetable_put ( f , key , hkey , value , size , test_size_flush_callback , pe_est_callback , pe_callback , 0 ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
2013-04-16 23:59:47 -04:00
int n_entries , hash_size ; long size_current , size_limit , size_max ;
toku_cachetable_get_state ( t , & n_entries , & hash_size , & size_current , & size_limit , & size_max ) ;
2008-08-22 17:50:05 +00:00
while ( n_entries ! = min2 ( i + 1 , n ) ) {
2013-04-16 23:57:41 -04:00
toku_pthread_yield ( ) ; maybe_flush ( t ) ;
2013-04-16 23:59:47 -04:00
toku_cachetable_get_state ( t , & n_entries , 0 , 0 , 0 , 0 ) ;
2008-08-22 17:50:05 +00:00
}
2007-09-21 17:55:49 +00:00
assert ( n_entries = = min2 ( i + 1 , n ) ) ;
void * entry_value ; int dirty ; long long pinned ; long entry_size ;
2008-06-05 22:09:59 +00:00
r = toku_cachetable_get_key_state ( t , key , f , & entry_value , & dirty , & pinned , & entry_size ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
assert ( dirty = = 1 ) ;
assert ( pinned = = 1 ) ;
assert ( entry_value = = value ) ;
assert ( entry_size = = size ) ;
2013-04-16 23:57:35 -04:00
test_mutex_lock ( ) ;
2013-04-16 23:57:18 -04:00
if ( test_size_flush_key . b ! = - 1 ) {
assert ( test_size_flush_key . b = = expect_flush_key . b ) ;
assert ( expect_flush_key . b = = i - n ) ;
expect_flush_key . b + = 1 ;
2007-09-21 17:55:49 +00:00
}
2013-04-16 23:57:35 -04:00
test_mutex_unlock ( ) ;
2007-09-21 17:55:49 +00:00
2008-06-17 17:05:19 +00:00
r = toku_cachetable_unpin ( f , key , hkey , CACHETABLE_CLEAN , size ) ;
2007-09-21 17:55:49 +00:00
assert ( r = = 0 ) ;
}
2013-04-16 23:58:06 -04:00
r = toku_cachefile_close ( & f , 0 , FALSE , ZERO_LSN ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
2007-11-19 23:47:44 +00:00
r = toku_cachetable_close ( & t ) ;
2007-09-17 16:23:05 +00:00
assert ( r = = 0 ) ;
}
2013-04-16 23:57:32 -04:00
int
test_main ( int argc , const char * argv [ ] ) {
2008-08-22 17:50:05 +00:00
// defaults
2013-04-16 23:57:27 -04:00
# if defined(__linux__)
2008-08-22 17:50:05 +00:00
int do_malloc_fail = 0 ;
2013-04-16 23:57:27 -04:00
# endif
2007-11-14 17:58:38 +00:00
2008-08-22 17:50:05 +00:00
// parse args
2013-04-16 23:57:20 -04:00
default_parse_args ( argc , argv ) ;
2007-11-14 17:58:38 +00:00
int i ;
2008-08-22 17:50:05 +00:00
for ( i = 1 ; i < argc ; i + + ) {
const char * arg = argv [ i ] ;
if ( strcmp ( arg , " -v " ) = = 0 ) {
verbose + + ;
continue ;
}
2013-04-16 23:57:27 -04:00
# if defined(__linux__)
2008-08-22 17:50:05 +00:00
if ( strcmp ( arg , " -malloc-fail " ) = = 0 ) {
do_malloc_fail = 1 ;
continue ;
}
2013-04-16 23:57:27 -04:00
# endif
2007-11-14 17:58:38 +00:00
}
2013-04-16 23:57:35 -04:00
test_mutex_init ( ) ;
2008-08-22 17:50:05 +00:00
// run tests
2013-04-16 23:58:59 -04:00
# if !TOKU_WINDOWS
2008-08-22 17:50:05 +00:00
test_multi_filehandles ( ) ;
2013-04-16 23:57:27 -04:00
# endif
2008-08-22 17:50:05 +00:00
test_cachetable_create ( ) ;
2013-04-16 23:57:33 -04:00
# if DO_MALLOC_HOOK
2008-08-22 17:50:05 +00:00
if ( do_malloc_fail )
test_cachetable_create_no_memory ( ) ; // fails with valgrind
2013-04-16 23:57:27 -04:00
# endif
2008-08-22 17:50:05 +00:00
for ( i = 0 ; i < 1 ; i + + ) {
test0 ( ) ;
test_nested_pin ( ) ;
2013-04-16 23:58:59 -04:00
# if !TOKU_WINDOWS
2008-08-22 17:50:05 +00:00
test_multi_filehandles ( ) ;
2013-04-16 23:57:27 -04:00
# endif
2008-08-22 17:50:05 +00:00
test_dirty ( ) ;
test_size_resize ( ) ;
2013-04-16 23:59:40 -04:00
//test_size_flush();
2008-08-22 17:50:05 +00:00
}
2013-04-16 23:57:35 -04:00
test_mutex_destroy ( ) ;
2013-04-16 23:59:22 -04:00
2007-12-22 23:12:40 +00:00
if ( verbose ) printf ( " ok \n " ) ;
2007-07-13 19:37:47 +00:00
return 0 ;
}