2007-11-29 14:18:54 +00:00
/* -*- mode: C; c-basic-offset: 4 -*- */
2008-01-24 15:10:32 +00:00
# ident "Copyright (c) 2007, 2008 Tokutek Inc. All rights reserved."
2007-11-29 14:18:54 +00:00
2007-07-13 19:37:47 +00:00
/* An in-memory Packed Memory Array dictionary.
The keys and values are arrays of bytes , but are not necessarily kept in scan order .
Only the pointers are kept .
*/
# include "key.h"
# include "memory.h"
# include "myassert.h"
2007-09-06 20:13:56 +00:00
# include "../include/db.h"
2007-07-13 19:37:47 +00:00
# include <stdio.h>
# include <errno.h>
/* Only needed for testing. */
# include <string.h>
2007-08-06 19:43:27 +00:00
# include "list.h"
2007-08-03 17:21:20 +00:00
# include "kv-pair.h"
# include "pma-internal.h"
2007-09-28 17:11:22 +00:00
# include "log.h"
2007-11-26 21:51:36 +00:00
# include "log_header.h"
2007-08-03 17:21:20 +00:00
2007-09-05 20:09:43 +00:00
/* get KEY_VALUE_OVERHEAD */
# include "brt-internal.h"
2007-07-13 19:37:47 +00:00
2007-11-14 17:58:38 +00:00
/**************************** static functions forward declarations. *********************/
2008-01-25 20:44:16 +00:00
/* resize the pma array to asksize. zero all array entries starting from startx.*/
2008-01-23 19:44:13 +00:00
static int pma_resize_array ( TOKUTXN , FILENUM , DISKOFF , PMA pma , int asksize , int startx , LSN * node_lsn ) ;
2007-12-04 10:02:59 +00:00
static int old_pma_resize_array ( PMA pma , int asksize , int startx ) {
2008-01-23 19:44:13 +00:00
return pma_resize_array ( ( TOKUTXN ) 0 , ( FILENUM ) { 0 } , ( DISKOFF ) 0 , pma , asksize , startx , ( LSN * ) 0 ) ;
2007-12-04 10:02:59 +00:00
}
2007-11-14 17:58:38 +00:00
2008-01-25 20:44:16 +00:00
/* extract pairs from the pma in the window delimited by lo and hi.*/
2007-12-05 19:41:39 +00:00
static struct kv_pair_tag * pma_extract_pairs ( PMA pma , int count , unsigned int lo , unsigned int hi ) ;
2007-11-14 17:58:38 +00:00
/*
* a deletion occured at index " here " in the pma . rebalance the windows around " here " . if
* necessary , shrink the pma .
*/
2008-01-25 20:44:16 +00:00
static void pma_delete_at ( PMA pma , int here ) ;
2007-11-14 17:58:38 +00:00
/**************************** end of static functions forward declarations. *********************/
2007-11-27 18:16:45 +00:00
static inline int kv_pair_inuse ( struct kv_pair * pair ) {
return pair ! = 0 ;
}
struct kv_pair_tag {
struct kv_pair * pair ;
int oldtag , newtag ;
} ;
2007-11-14 17:58:38 +00:00
2007-10-12 23:50:05 +00:00
# ifndef PMA_USE_MEMPOOL
# define PMA_USE_MEMPOOL 1
# endif
# if PMA_USE_MEMPOOL
2007-10-10 19:33:31 +00:00
/* allocate a kv pair from the pma kv memory pool */
2008-01-16 15:41:12 +00:00
static struct kv_pair * kv_pair_malloc_mempool ( const void * key , int keylen , const void * val , int vallen , struct mempool * mp ) {
2007-11-28 20:51:16 +00:00
struct kv_pair * kv = toku_mempool_malloc ( mp , sizeof ( struct kv_pair ) + keylen + vallen , 4 ) ;
2007-10-10 19:33:31 +00:00
if ( kv )
kv_pair_init ( kv , key , keylen , val , vallen ) ;
return kv ;
}
/* compress all of the kv pairs to the left edge of the memory pool and
update the pma index with the new kv pair locations */
2008-01-25 20:44:16 +00:00
2007-10-10 19:33:31 +00:00
static int pma_compress_kvspace ( PMA pma ) {
2007-11-28 20:51:16 +00:00
if ( toku_mempool_get_frag_size ( & pma - > kvspace ) = = 0 )
2007-10-10 19:33:31 +00:00
return - 1 ;
void * mp = toku_malloc ( pma - > kvspace . size ) ;
if ( mp = = 0 )
return - 2 ;
struct mempool new_kvspace ;
2007-11-28 20:51:16 +00:00
toku_mempool_init ( & new_kvspace , mp , pma - > kvspace . size ) ;
2007-12-05 19:41:39 +00:00
unsigned int i ;
2007-10-10 19:33:31 +00:00
for ( i = 0 ; i < pma - > N ; i + + ) {
struct kv_pair * kv = pma - > pairs [ i ] ;
if ( kv_pair_inuse ( kv ) ) {
2007-11-28 20:51:16 +00:00
struct kv_pair * newkv = toku_mempool_malloc ( & new_kvspace , kv_pair_size ( kv ) , 4 ) ;
2007-10-10 19:33:31 +00:00
assert ( newkv ) ;
memcpy ( newkv , kv , kv_pair_size ( kv ) ) ;
pma - > pairs [ i ] = newkv ;
}
}
toku_free ( pma - > kvspace . base ) ;
pma - > kvspace = new_kvspace ;
return 0 ;
}
2007-10-12 23:50:05 +00:00
# endif
2007-10-10 19:33:31 +00:00
/* malloc space for a kv pair from the pma memory pool and initialize it.
if the allocation fails , try to compress the memory pool and try again . */
2008-01-25 20:44:16 +00:00
2008-01-16 15:41:12 +00:00
static struct kv_pair * pma_malloc_kv_pair ( PMA pma __attribute__ ( ( unused ) ) , const void * k , int ksize , const void * v , int vsize ) {
2007-10-12 23:50:05 +00:00
# if PMA_USE_MEMPOOL
2007-10-10 19:33:31 +00:00
struct kv_pair * kv = kv_pair_malloc_mempool ( k , ksize , v , vsize , & pma - > kvspace ) ;
if ( kv = = 0 ) {
if ( 0 = = pma_compress_kvspace ( pma ) )
kv = kv_pair_malloc_mempool ( k , ksize , v , vsize , & pma - > kvspace ) ;
}
2007-10-12 23:50:05 +00:00
# else
struct kv_pair * kv = kv_pair_malloc ( k , ksize , v , vsize ) ;
# endif
2007-10-10 19:33:31 +00:00
return kv ;
}
2007-10-12 23:50:05 +00:00
static void pma_mfree_kv_pair ( PMA pma __attribute__ ( ( unused ) ) , struct kv_pair * kv ) {
# if PMA_USE_MEMPOOL
2007-11-28 20:51:16 +00:00
toku_mempool_mfree ( & pma - > kvspace , kv , kv_pair_size ( kv ) ) ;
2007-10-12 23:50:05 +00:00
# else
kv_pair_free ( kv ) ;
# endif
2007-10-10 19:33:31 +00:00
}
2007-11-20 00:32:25 +00:00
int toku_pma_n_entries ( PMA pma ) {
2007-07-13 19:37:47 +00:00
return pma - > n_pairs_present ;
}
2007-12-05 19:41:39 +00:00
unsigned int toku_pma_index_limit ( PMA pma ) {
2007-07-13 19:37:47 +00:00
return pma - > N ;
}
2007-08-03 17:21:20 +00:00
2007-12-05 19:41:39 +00:00
int toku_pmanode_valid ( PMA pma , unsigned int i ) {
assert ( i < toku_pma_index_limit ( pma ) ) ;
2008-01-25 20:44:16 +00:00
return kv_pair_inuse ( pma - > pairs [ i ] ) ;
2007-07-13 19:37:47 +00:00
}
2007-08-03 17:21:20 +00:00
2007-12-05 19:41:39 +00:00
bytevec toku_pmanode_key ( PMA pma , unsigned int i ) {
2007-08-03 17:21:20 +00:00
struct kv_pair * pair ;
2007-12-05 19:41:39 +00:00
assert ( i < toku_pma_index_limit ( pma ) ) ;
2007-08-03 17:21:20 +00:00
pair = pma - > pairs [ i ] ;
2008-01-25 20:44:16 +00:00
assert ( kv_pair_inuse ( pair ) ) ;
2007-08-30 15:15:14 +00:00
return kv_pair_key ( pair ) ;
2007-07-13 19:37:47 +00:00
}
2007-08-03 17:21:20 +00:00
2007-12-05 19:41:39 +00:00
ITEMLEN toku_pmanode_keylen ( PMA pma , unsigned int i ) {
2007-08-03 17:21:20 +00:00
struct kv_pair * pair ;
2007-12-05 19:41:39 +00:00
assert ( i < toku_pma_index_limit ( pma ) ) ;
2007-08-03 17:21:20 +00:00
pair = pma - > pairs [ i ] ;
2008-01-25 20:44:16 +00:00
assert ( kv_pair_inuse ( pair ) ) ;
2007-08-30 15:15:14 +00:00
return kv_pair_keylen ( pair ) ;
2007-07-13 19:37:47 +00:00
}
2007-08-03 17:21:20 +00:00
2007-12-05 19:41:39 +00:00
bytevec toku_pmanode_val ( PMA pma , unsigned int i ) {
2007-08-03 17:21:20 +00:00
struct kv_pair * pair ;
2007-12-05 19:41:39 +00:00
assert ( i < toku_pma_index_limit ( pma ) ) ;
2007-08-03 17:21:20 +00:00
pair = pma - > pairs [ i ] ;
2008-01-25 20:44:16 +00:00
assert ( kv_pair_inuse ( pair ) ) ;
2007-08-30 15:15:14 +00:00
return kv_pair_val ( pair ) ;
2007-07-13 19:37:47 +00:00
}
2007-08-03 17:21:20 +00:00
2007-12-05 19:41:39 +00:00
ITEMLEN toku_pmanode_vallen ( PMA pma , unsigned int i ) {
2007-08-03 17:21:20 +00:00
struct kv_pair * pair ;
2007-12-05 19:41:39 +00:00
assert ( i < toku_pma_index_limit ( pma ) ) ;
2007-08-03 17:21:20 +00:00
pair = pma - > pairs [ i ] ;
2008-01-25 20:44:16 +00:00
assert ( kv_pair_inuse ( pair ) ) ;
2007-08-30 15:15:14 +00:00
return kv_pair_vallen ( pair ) ;
2007-07-13 19:37:47 +00:00
}
/* Could pick the same one every time if we wanted. */
2007-11-20 00:32:25 +00:00
int toku_pma_random_pick ( PMA pma , bytevec * key , ITEMLEN * keylen , bytevec * val , ITEMLEN * vallen ) {
2007-07-13 19:37:47 +00:00
# if 1
2007-12-05 19:41:39 +00:00
unsigned int i ;
2007-08-30 15:15:14 +00:00
2007-07-13 19:37:47 +00:00
/* For now a simple implementation where we simply start at the beginning and look. */
2007-11-20 00:32:25 +00:00
for ( i = 0 ; i < toku_pma_index_limit ( pma ) ; i + + ) {
2007-08-30 15:15:14 +00:00
struct kv_pair * pair = pma - > pairs [ i ] ;
2008-01-25 20:44:16 +00:00
if ( kv_pair_inuse ( pair ) ) {
2007-08-30 15:15:14 +00:00
* key = kv_pair_key ( pair ) ;
* keylen = kv_pair_keylen ( pair ) ;
* val = kv_pair_val ( pair ) ;
* vallen = kv_pair_vallen ( pair ) ;
2007-07-13 19:37:47 +00:00
return 0 ;
}
}
return DB_NOTFOUND ;
# else
/* Maybe we should pick a random item to remove in order to reduce the unbalancing. */
int i ;
2007-11-20 00:32:25 +00:00
int l = toku_pma_index_limit ( pma ) ;
2007-07-13 19:37:47 +00:00
int r = random ( ) % l ;
/* For now a simple implementation where we simply start at the beginning and look. */
for ( i = 0 ; i < l ; i + + ) {
int ir = ( i + r ) % l ;
2007-08-30 15:15:14 +00:00
struct kv_pair * pair = pma - > pairs [ ir ] ;
2008-01-25 20:44:16 +00:00
if ( kv_pair_inuse ( pair ) ) {
2007-08-30 15:15:14 +00:00
* key = kv_pair_key ( pair ) ;
* keylen = kv_pair_keylen ( pair ) ;
* val = kv_pair_val ( pair ) ;
* vallen = kv_pair_vallen ( pair ) ;
2007-07-13 19:37:47 +00:00
return 0 ;
}
}
return DB_NOTFOUND ;
# endif
}
static int pma_count_finds = 0 ;
static int pma_count_divides = 0 ;
static int pma_count_scans = 0 ;
2007-08-30 15:15:14 +00:00
2007-11-20 00:32:25 +00:00
void toku_pma_show_stats ( void ) {
2007-07-13 19:37:47 +00:00
printf ( " %d finds, %d divides, %d scans \n " , pma_count_finds , pma_count_divides , pma_count_scans ) ;
}
2007-12-17 01:03:35 +00:00
static int pma_compare_dbt_kv ( PMA pma , DBT * k , DBT * v , struct kv_pair * kv ) {
DBT k2 , v2 ;
int cmp = pma - > compare_fun ( pma - > db , k , toku_fill_dbt ( & k2 , kv_pair_key ( kv ) , kv_pair_keylen ( kv ) ) ) ;
if ( cmp = = 0 & & v )
cmp = pma - > dup_compare_fun ( pma - > db , v , toku_fill_dbt ( & v2 , kv_pair_val ( kv ) , kv_pair_vallen ( kv ) ) ) ;
return cmp ;
}
2008-01-21 21:03:23 +00:00
/* search the index for a matching key and maybe value */
static unsigned int pma_search ( PMA pma , DBT * k , DBT * v , int lo , int hi , int * found ) {
2007-11-14 17:58:38 +00:00
assert ( 0 < = lo & & lo < = hi ) ;
if ( lo > = hi ) {
* found = 0 ;
return lo ;
} else {
int mi = ( lo + hi ) / 2 ;
assert ( lo < = mi & & mi < hi ) ;
int omi = mi ;
while ( mi < hi & & ! kv_pair_inuse ( pma - > pairs [ mi ] ) )
mi + + ;
if ( mi > = hi )
2008-01-21 21:03:23 +00:00
return pma_search ( pma , k , v , lo , omi , found ) ;
2008-01-25 20:44:16 +00:00
int cmp = pma_compare_dbt_kv ( pma , k , v , pma - > pairs [ mi ] ) ;
2007-11-14 17:58:38 +00:00
if ( cmp > 0 )
2008-01-21 21:03:23 +00:00
return pma_search ( pma , k , v , mi + 1 , hi , found ) ;
2007-11-14 17:58:38 +00:00
if ( cmp < 0 )
2008-01-21 21:03:23 +00:00
return pma_search ( pma , k , v , lo , mi , found ) ;
2007-11-14 17:58:38 +00:00
2008-01-21 21:03:23 +00:00
/* we have a match, try to find a better match on the left tree */
int here = pma_search ( pma , k , v , lo , mi , found ) ;
2007-11-14 17:58:38 +00:00
if ( * found = = 0 )
here = mi ;
* found = 1 ;
return here ;
}
}
2008-01-25 15:43:37 +00:00
static unsigned int pma_search_func ( PMA pma , brt_search_t * search , int lo , int hi , int * found ) {
assert ( 0 < = lo & & lo < = hi ) ;
if ( lo > = hi ) {
* found = 0 ;
return lo ;
} else {
int mi = ( lo + hi ) / 2 ;
assert ( lo < = mi & & mi < hi ) ;
int omi = mi ;
while ( mi < hi & & ! kv_pair_inuse ( pma - > pairs [ mi ] ) )
mi + + ;
if ( mi > = hi )
return pma_search_func ( pma , search , lo , omi , found ) ;
2008-01-25 20:44:16 +00:00
struct kv_pair * kv = pma - > pairs [ mi ] ;
2008-01-25 15:43:37 +00:00
DBT x , y ;
2008-01-25 20:44:16 +00:00
int cmp = search - > compare ( search , search - > k ? toku_fill_dbt ( & x , kv_pair_key ( kv ) , kv_pair_keylen ( kv ) ) : 0 ,
search - > v ? toku_fill_dbt ( & y , kv_pair_val ( kv ) , kv_pair_vallen ( kv ) ) : 0 ) ;
2008-01-25 15:43:37 +00:00
if ( cmp = = 0 ) {
if ( search - > direction = = BRT_SEARCH_LEFT )
return pma_search_func ( pma , search , mi + 1 , hi , found ) ;
else
return pma_search_func ( pma , search , lo , mi , found ) ;
}
/* we have a match, try to find a better match on the left or right subtrees */
int here ;
if ( search - > direction = = BRT_SEARCH_LEFT )
here = pma_search_func ( pma , search , lo , mi , found ) ;
else
here = pma_search_func ( pma , search , mi + 1 , hi , found ) ;
if ( * found = = 0 )
here = mi ;
* found = 1 ;
return here ;
}
}
2007-07-13 19:37:47 +00:00
// Return the smallest index such that no lower index contains a larger key.
2007-11-20 00:32:25 +00:00
// This will be in the range 0 (inclusive) to toku_pma_index_limit(pma) (inclusive).
// Thus the returned index may not be a valid index into the array if it is == toku_pma_index_limit(pma)
2007-07-13 19:37:47 +00:00
// For example: if the array is empty, that means we return 0.
2007-11-20 00:32:25 +00:00
// For example: if the array is full of small keys, that means we return toku_pma_index_limit(pma), which is off the end of teh array.
2007-07-13 19:37:47 +00:00
// For example: if the array is full of large keys, then we return 0.
2007-11-26 21:51:36 +00:00
int toku_pmainternal_find ( PMA pma , DBT * k ) {
2007-12-17 01:03:35 +00:00
int found ;
2008-01-21 21:03:23 +00:00
int lo = pma_search ( pma , k , 0 , 0 , pma - > N , & found ) ;
2007-11-14 17:58:38 +00:00
return lo ;
2007-07-13 19:37:47 +00:00
}
//int min (int i, int j) { if (i<j) return i; else return j; }
//int max (int i, int j) { if (i<j) return j; else return i; }
//double lg (int n) { return log((double)n)/log(2.0); }
2007-11-20 00:32:25 +00:00
int toku_pmainternal_printpairs ( struct kv_pair * pairs [ ] , int N ) {
2007-07-13 19:37:47 +00:00
int count = 0 ;
int i ;
printf ( " { " ) ;
for ( i = 0 ; i < N ; i + + ) {
2007-08-03 17:21:20 +00:00
if ( i ! = 0 ) printf ( " " ) ;
2008-01-25 20:44:16 +00:00
if ( kv_pair_inuse ( pairs [ i ] ) ) {
2007-09-04 13:51:12 +00:00
printf ( " %s " , ( char * ) kv_pair_key ( pairs [ i ] ) ) ;
2007-08-03 17:21:20 +00:00
count + + ;
}
else printf ( " _ " ) ;
2007-07-13 19:37:47 +00:00
}
printf ( " } " ) ;
return count ;
}
2007-11-20 00:32:25 +00:00
void toku_print_pma ( PMA pma ) {
2007-07-13 19:37:47 +00:00
int count ;
2007-11-20 00:32:25 +00:00
printf ( " N=%d n_present=%d " , toku_pma_index_limit ( pma ) , pma - > n_pairs_present ) ;
count = toku_pmainternal_printpairs ( pma - > pairs , toku_pma_index_limit ( pma ) ) ;
2007-07-13 19:37:47 +00:00
printf ( " \n " ) ;
assert ( count = = pma - > n_pairs_present ) ;
}
/* Smooth the data, and return the location of the null. */
2007-12-04 10:02:59 +00:00
static int distribute_data ( struct kv_pair * destpairs [ ] , int dcount ,
struct kv_pair_tag sourcepairs [ ] , int scount ,
PMA pma ) {
2007-07-13 19:37:47 +00:00
assert ( scount < = dcount ) ;
if ( scount = = 0 ) {
return - 1 ;
}
if ( scount = = 1 ) {
2007-08-06 19:43:27 +00:00
destpairs [ 0 ] = sourcepairs [ 0 ] . pair ;
if ( pma )
sourcepairs [ 0 ] . newtag = destpairs - pma - > pairs ;
2007-08-03 17:21:20 +00:00
if ( destpairs [ 0 ] = = 0 ) return 0 ;
2007-07-13 19:37:47 +00:00
else return - 1 ;
} else {
int r1 = distribute_data ( destpairs , dcount / 2 ,
2007-08-06 19:43:27 +00:00
sourcepairs , scount / 2 , pma ) ;
2007-07-13 19:37:47 +00:00
int r2 = distribute_data ( destpairs + dcount / 2 , dcount - dcount / 2 ,
2007-08-06 19:43:27 +00:00
sourcepairs + scount / 2 , scount - scount / 2 , pma ) ;
2007-07-13 19:37:47 +00:00
assert ( r1 = = - 1 | | r2 = = - 1 ) ;
if ( r1 ! = - 1 ) return r1 ;
else if ( r2 ! = - 1 ) return r2 + dcount / 2 ;
else return - 1 ;
}
}
2008-01-23 19:44:13 +00:00
static int pma_log_distribute ( TOKUTXN txn , FILENUM filenum , DISKOFF old_diskoff , DISKOFF new_diskoff , int n_pairs , struct kv_pair_tag * pairs , LSN * oldnode_lsn , LSN * newnode_lsn ) {
2008-01-16 13:50:23 +00:00
INTPAIRARRAY ipa ;
MALLOC_N ( n_pairs , ipa . array ) ;
if ( ipa . array = = 0 ) return errno ;
int j = 0 ;
int i ;
for ( i = 0 ; i < n_pairs ; i + + ) {
if ( pairs [ i ] . pair ! = 0 ) {
ipa . array [ j ] . a = pairs [ i ] . oldtag ;
ipa . array [ j ] . b = pairs [ i ] . newtag ;
j + + ;
}
}
ipa . size = j ;
int r = toku_log_pmadistribute ( txn , toku_txn_get_txnid ( txn ) , filenum , old_diskoff , new_diskoff , ipa ) ;
2008-01-23 19:44:13 +00:00
if ( txn & & oldnode_lsn ) * oldnode_lsn = toku_txn_get_last_lsn ( txn ) ;
if ( txn & & newnode_lsn ) * newnode_lsn = toku_txn_get_last_lsn ( txn ) ;
2008-01-16 13:50:23 +00:00
// if (0 && pma) {
// printf("Pma state:\n");
// PMA_ITERATE_IDX (pma, pidx, key, keylen, data, datalen,
// printf(" %d:(%d:%s) (%d:%s)\n", pidx, keylen, (char*)key, datalen, (char*)data));
// }
toku_free ( ipa . array ) ;
return r ;
}
2007-07-13 19:37:47 +00:00
/* spread the non-empty pairs around. There are n of them. Create an empty slot just before the IDXth
element , and return that slot ' s index in the smoothed array . */
2008-01-23 19:44:13 +00:00
int toku_pmainternal_smooth_region ( TOKUTXN txn , FILENUM filenum , DISKOFF diskoff , struct kv_pair * pairs [ ] , int n , int idx , int base , PMA pma , int * new_idx , LSN * node_lsn ) {
2007-07-13 19:37:47 +00:00
int i ;
int n_present = 0 ;
for ( i = 0 ; i < n ; i + + ) {
2007-09-04 13:51:12 +00:00
if ( kv_pair_inuse ( pairs [ i ] ) ) n_present + + ;
2007-07-13 19:37:47 +00:00
}
n_present + + ; // Save one for the blank guy.
{
2007-08-07 22:39:23 +00:00
//#define USE_MALLOC_IN_SMOOTH
# ifdef USE_MALLOC_IN_SMOOTH
struct kv_pair_tag * MALLOC_N ( n_present , tmppairs ) ;
# else
struct kv_pair_tag tmppairs [ n_present ] ;
# endif
2007-07-13 19:37:47 +00:00
int n_saved = 0 ;
2007-12-04 10:02:59 +00:00
int newidx ;
2007-08-06 19:43:27 +00:00
2007-07-13 19:37:47 +00:00
for ( i = 0 ; i < n ; i + + ) {
if ( i = = idx ) {
2007-08-06 19:43:27 +00:00
tmppairs [ n_saved + + ] . pair = 0 ;
2007-07-13 19:37:47 +00:00
}
2007-09-04 13:51:12 +00:00
if ( kv_pair_inuse ( pairs [ i ] ) ) {
2007-12-04 10:02:59 +00:00
tmppairs [ n_saved ] . oldtag = base + i ;
2007-08-06 19:43:27 +00:00
tmppairs [ n_saved + + ] . pair = pairs [ i ] ;
2007-07-13 19:37:47 +00:00
}
2007-12-04 10:02:59 +00:00
pairs [ i ] = 0 ;
2007-07-13 19:37:47 +00:00
}
if ( idx = = n ) {
2007-08-06 19:43:27 +00:00
tmppairs [ n_saved + + ] . pair = 0 ;
2007-07-13 19:37:47 +00:00
}
//printf(" temp="); printpairs(tmppairs, n_saved);
assert ( n_saved = = n_present ) ;
/* Now the tricky part. Distribute the data. */
2007-12-04 10:02:59 +00:00
newidx = distribute_data ( pairs , n ,
tmppairs , n_saved , pma ) ;
2008-01-16 13:50:23 +00:00
int r = pma_log_distribute ( txn , filenum , diskoff , diskoff ,
n_saved ,
2008-01-23 19:44:13 +00:00
tmppairs ,
node_lsn , node_lsn ) ;
2008-01-16 13:50:23 +00:00
if ( r ! = 0 ) goto cleanup ;
* new_idx = newidx ;
cleanup :
2007-08-07 22:39:23 +00:00
# ifdef USE_MALLOC_IN_SMOOTH
2007-07-20 18:00:14 +00:00
toku_free ( tmppairs ) ;
2007-08-07 22:39:23 +00:00
# endif
2007-12-04 10:02:59 +00:00
return 0 ;
2007-07-13 19:37:47 +00:00
}
}
2007-11-14 17:58:38 +00:00
int toku_lg ( int n ) {
2007-07-13 19:37:47 +00:00
int result = 0 ;
int two_to_result = 1 ;
while ( two_to_result < n ) {
result + + ;
two_to_result * = 2 ;
}
return result ;
}
2007-08-30 15:15:14 +00:00
/* Calculate densitysteps and uplgN, given N. */
2007-11-20 00:32:25 +00:00
void toku_pmainternal_calculate_parameters ( PMA pma ) {
int N = toku_pma_index_limit ( pma ) ;
2007-11-14 17:58:38 +00:00
int lgN = toku_lg ( N ) ;
2007-07-13 19:37:47 +00:00
int n_divisions = 0 ;
//printf("N=%d lgN=%d\n", N, lgN);
while ( N / 2 > = lgN ) {
n_divisions + + ;
N / = 2 ;
}
pma - > uplgN = N ;
//printf("uplgN = %d n_divisions=%d\n", pma->uplgN, n_divisions);
assert ( n_divisions > 0 ) ;
2007-08-30 15:15:14 +00:00
pma - > udt_step = ( PMA_UDT_HIGH - PMA_UDT_LOW ) / n_divisions ;
pma - > ldt_step = ( PMA_LDT_HIGH - PMA_LDT_LOW ) / n_divisions ;
2007-07-13 19:37:47 +00:00
}
2007-11-20 00:32:25 +00:00
int toku_pmainternal_count_region ( struct kv_pair * pairs [ ] , int lo , int hi ) {
2007-07-13 19:37:47 +00:00
int n = 0 ;
while ( lo < hi ) {
2007-09-04 13:51:12 +00:00
if ( kv_pair_inuse ( pairs [ lo ] ) ) n + + ;
2007-07-13 19:37:47 +00:00
lo + + ;
}
return n ;
}
2008-01-15 21:50:45 +00:00
/* find the smallest power of 2 >= n */
static unsigned int pma_array_size ( PMA pma __attribute__ ( ( unused ) ) , int asksize ) {
int n = PMA_MIN_ARRAY_SIZE ;
while ( n < asksize )
n * = 2 ;
return n ;
}
2007-11-26 21:51:36 +00:00
int toku_pma_create ( PMA * pma , pma_compare_fun_t compare_fun , DB * db , FILENUM filenum , int maxsize ) {
2007-07-30 18:35:40 +00:00
int error ;
2007-08-07 23:13:56 +00:00
TAGMALLOC ( PMA , result ) ;
2007-07-13 19:37:47 +00:00
if ( result = = 0 ) return - 1 ;
2007-11-14 17:58:38 +00:00
result - > dup_mode = 0 ;
2007-07-13 19:37:47 +00:00
result - > n_pairs_present = 0 ;
2007-07-30 18:35:40 +00:00
result - > pairs = 0 ;
2007-07-23 15:11:54 +00:00
result - > compare_fun = compare_fun ;
2008-01-25 22:12:02 +00:00
result - > dup_compare_fun = 0 ;
2007-11-26 21:51:36 +00:00
result - > db = db ;
result - > filenum = filenum ;
2007-08-06 19:43:27 +00:00
result - > skey = 0 ;
2007-07-23 20:10:16 +00:00
result - > sval = 0 ;
2007-08-30 15:15:14 +00:00
result - > N = PMA_MIN_ARRAY_SIZE ;
2007-08-06 19:43:27 +00:00
result - > pairs = 0 ;
2008-01-15 21:50:45 +00:00
{
unsigned int n = pma_array_size ( result , result - > N ) ;
error = toku_resize_pma_exactly ( result , 0 , n ) ;
if ( error ) {
toku_free ( result ) ;
return - 1 ;
}
toku_pmainternal_calculate_parameters ( result ) ;
2007-07-30 18:35:40 +00:00
}
2007-10-10 19:33:31 +00:00
if ( maxsize = = 0 )
maxsize = 4 * 1024 ;
maxsize = maxsize + maxsize / 4 ;
2007-10-12 23:50:05 +00:00
# if PMA_USE_MEMPOOL
2007-10-10 19:33:31 +00:00
void * mpbase = toku_malloc ( maxsize ) ; assert ( mpbase ) ;
2007-11-28 20:51:16 +00:00
toku_mempool_init ( & result - > kvspace , mpbase , maxsize ) ;
2007-10-12 23:50:05 +00:00
# endif
2007-07-13 19:37:47 +00:00
* pma = result ;
2007-08-03 17:21:20 +00:00
assert ( ( unsigned long ) result - > pairs [ result - > N ] = = 0xdeadbeefL ) ;
2007-07-13 19:37:47 +00:00
return 0 ;
}
2008-01-25 20:44:16 +00:00
2007-12-04 17:59:03 +00:00
int toku_resize_pma_exactly ( PMA pma , int oldsize , int newsize ) {
pma - > N = newsize ;
2007-07-30 16:32:46 +00:00
2007-08-30 15:15:14 +00:00
if ( pma - > pairs = = 0 )
pma - > pairs = toku_malloc ( ( 1 + pma - > N ) * sizeof ( struct kv_pair * ) ) ;
else
pma - > pairs = toku_realloc ( pma - > pairs , ( 1 + pma - > N ) * sizeof ( struct kv_pair * ) ) ;
2007-07-30 18:35:40 +00:00
if ( pma - > pairs = = 0 )
return - 1 ;
2007-08-03 17:21:20 +00:00
pma - > pairs [ pma - > N ] = ( void * ) 0xdeadbeef ;
2007-07-30 16:32:46 +00:00
2007-12-05 19:41:39 +00:00
unsigned int i ;
2007-12-04 17:59:03 +00:00
for ( i = oldsize ; i < pma - > N ; i + + ) {
2007-08-03 17:21:20 +00:00
pma - > pairs [ i ] = 0 ;
2007-07-30 16:32:46 +00:00
}
2007-12-04 17:59:03 +00:00
return 0 ;
}
2008-01-25 21:50:07 +00:00
static int pma_resize_array_nolog ( PMA pma , int asksize , int startz , unsigned int * oldn , unsigned int * newn ) {
2007-12-05 19:41:39 +00:00
unsigned int oldN = pma - > N ;
unsigned int n = pma_array_size ( pma , asksize ) ;
2007-12-04 17:59:03 +00:00
int r = toku_resize_pma_exactly ( pma , startz , n ) ;
if ( r ! = 0 ) return r ;
2007-11-20 00:32:25 +00:00
toku_pmainternal_calculate_parameters ( pma ) ;
2008-01-25 21:50:07 +00:00
* oldn = oldN ;
* newn = n ;
return 0 ;
}
static int pma_resize_array ( TOKUTXN txn , FILENUM filenum , DISKOFF offset , PMA pma , int asksize , int startz , LSN * node_lsn ) {
unsigned int oldN , n ;
int r = pma_resize_array_nolog ( pma , asksize , startz , & oldN , & n ) ;
if ( r ! = 0 ) return r ;
2007-12-04 10:02:59 +00:00
toku_log_resizepma ( txn , toku_txn_get_txnid ( txn ) , filenum , offset , oldN , n ) ;
2008-01-23 19:44:13 +00:00
if ( txn & & node_lsn ) * node_lsn = toku_txn_get_last_lsn ( txn ) ;
2007-07-30 16:32:46 +00:00
return 0 ;
}
2007-11-20 00:32:25 +00:00
int toku_pma_set_compare ( PMA pma , pma_compare_fun_t compare_fun ) {
2007-11-16 22:44:56 +00:00
pma - > compare_fun = compare_fun ;
return 0 ;
}
2007-11-20 00:32:25 +00:00
int toku_pma_set_dup_mode ( PMA pma , int dup_mode ) {
2008-01-07 19:06:05 +00:00
if ( ! ( dup_mode = = 0 | | dup_mode = = ( TOKU_DB_DUP + TOKU_DB_DUPSORT ) ) )
return EINVAL ;
2007-11-14 17:58:38 +00:00
pma - > dup_mode = dup_mode ;
return 0 ;
}
2007-11-20 00:32:25 +00:00
int toku_pma_set_dup_compare ( PMA pma , pma_compare_fun_t dup_compare_fun ) {
2007-11-14 17:58:38 +00:00
pma - > dup_compare_fun = dup_compare_fun ;
return 0 ;
}
2007-12-17 17:09:54 +00:00
/* find the next matching key in the pma starting from index here */
static int pma_next_key ( PMA pma , DBT * k , DBT * v , int here , int n , int * found ) {
assert ( 0 < = here ) ;
* found = 0 ;
while ( here < n & & ! kv_pair_inuse ( pma - > pairs [ here ] ) )
here + = 1 ;
if ( here < n ) {
2008-01-25 20:44:16 +00:00
int cmp = pma_compare_dbt_kv ( pma , k , v , pma - > pairs [ here ] ) ;
2007-12-17 17:09:54 +00:00
if ( cmp = = 0 )
* found = 1 ;
}
return here ;
}
2007-07-13 19:37:47 +00:00
/* Make some space for a key to go at idx (the thing currently at idx should end up at to the right.) */
2007-12-04 10:02:59 +00:00
/* (Making space may involve moving things around, including the hole at index.) */
2008-01-23 19:44:13 +00:00
int toku_pmainternal_make_space_at ( TOKUTXN txn , FILENUM filenum , DISKOFF offset , PMA pma , int idx , unsigned int * new_index , LSN * node_lsn ) {
2007-07-13 19:37:47 +00:00
/* Within a range LO to HI we have a limit of how much packing we will tolerate.
* We allow the entire array to be 50 % full .
* We allow a region of size lgN to be full .
* At sizes in between , we interpolate .
*/
2007-12-05 19:41:39 +00:00
unsigned int size = pma - > uplgN ;
2007-07-13 19:37:47 +00:00
int lo = idx ;
int hi = idx ;
2007-08-30 15:15:14 +00:00
double udt = PMA_UDT_HIGH ;
2007-07-13 19:37:47 +00:00
while ( 1 ) {
/* set hi-lo equal size, make sure it is a supserset of (hi,lo). */
lo = idx - size / 2 ;
hi = idx + size / 2 ;
//printf("lo=%d hi=%d\n", lo, hi);
if ( lo < 0 ) { hi - = lo ; lo = 0 ; }
2007-12-05 19:41:39 +00:00
else if ( ( unsigned ) hi > toku_pma_index_limit ( pma ) ) { lo - = ( hi - toku_pma_index_limit ( pma ) ) ; hi = toku_pma_index_limit ( pma ) ; }
2007-07-13 19:37:47 +00:00
else { ; /* nothing */ }
//printf("lo=%d hi=%d\n", lo, hi);
2007-12-05 19:41:39 +00:00
assert ( 0 < = lo ) ; assert ( lo < hi ) ; assert ( ( unsigned ) hi < = toku_pma_index_limit ( pma ) ) ; assert ( ( unsigned ) ( hi - lo ) = = size ) ; // separate into separate assertions so that gcov doesn't see branches not taken.
2007-08-30 15:15:14 +00:00
assert ( udt > 0.499 ) ; assert ( udt < = 1 ) ;
2007-12-05 19:41:39 +00:00
if ( udt < 0.5001 ) { assert ( lo = = 0 ) ; assert ( ( unsigned ) hi = = toku_pma_index_limit ( pma ) ) ; }
2007-07-13 19:37:47 +00:00
{
int count = ( 1 + /* Don't forget space for the new guy. */
2007-11-20 00:32:25 +00:00
toku_pmainternal_count_region ( pma - > pairs , lo , hi ) ) ;
2007-08-30 15:15:14 +00:00
double density = ( double ) count / ( double ) ( hi - lo ) ;
if ( density < = udt )
break ;
2007-12-05 19:41:39 +00:00
if ( lo = = 0 & & ( unsigned ) hi = = toku_pma_index_limit ( pma ) ) {
2007-07-13 19:37:47 +00:00
/* The array needs to be doubled in size. */
2007-11-14 17:58:38 +00:00
2007-11-20 00:32:25 +00:00
assert ( size = = toku_pma_index_limit ( pma ) ) ;
2007-07-13 19:37:47 +00:00
size * = 2 ;
2007-11-14 17:58:38 +00:00
2007-08-30 15:15:14 +00:00
// printf("pma_make_space_realloc %d to %d hi %d\n", pma->N, size, hi);
2008-01-23 19:44:13 +00:00
pma_resize_array ( txn , filenum , offset , pma , size , hi , node_lsn ) ;
2007-11-14 17:58:38 +00:00
2007-07-13 19:37:47 +00:00
hi = size ;
//printf("doubled N\n");
break ;
}
}
2007-08-30 15:15:14 +00:00
udt - = pma - > udt_step ;
2007-07-13 19:37:47 +00:00
size * = 2 ;
}
//printf("%s:%d Smoothing from %d to %d to density %f\n", __FILE__, __LINE__, lo, hi, density);
{
2007-12-04 10:02:59 +00:00
int sub_new_index ;
2008-01-23 19:44:13 +00:00
int r = toku_pmainternal_smooth_region ( txn , filenum , offset , pma - > pairs + lo , hi - lo , idx - lo , lo , pma , & sub_new_index , node_lsn ) ;
2007-12-04 10:02:59 +00:00
if ( r ! = 0 ) return r ;
* new_index = sub_new_index + lo ;
return 0 ;
2007-07-13 19:37:47 +00:00
}
}
2007-11-26 21:51:36 +00:00
enum pma_errors toku_pma_lookup ( PMA pma , DBT * k , DBT * v ) {
2007-12-05 19:41:39 +00:00
int found ;
2008-01-25 20:44:16 +00:00
unsigned int here = pma_search ( pma , k , 0 , 0 , pma - > N , & found ) ;
2008-01-21 21:03:23 +00:00
struct kv_pair * kv = pma - > pairs [ here ] ;
2008-01-25 20:44:16 +00:00
if ( found & & kv_pair_inuse ( kv ) )
2008-01-21 21:03:23 +00:00
return toku_dbt_set_value ( v , kv - > key + kv - > keylen , kv - > vallen , & pma - > sval ) ;
else
2007-08-03 17:21:20 +00:00
return DB_NOTFOUND ;
2008-01-25 15:43:37 +00:00
}
int toku_pma_search ( PMA pma , brt_search_t * search , DBT * foundk , DBT * foundv ) {
int found ;
unsigned int here = pma_search_func ( pma , search , 0 , pma - > N , & found ) ;
struct kv_pair * kv = pma - > pairs [ here ] ;
2008-01-25 20:44:16 +00:00
if ( found & & kv_pair_inuse ( kv ) ) {
2008-01-25 15:43:37 +00:00
int r = 0 ;
if ( foundk )
r = toku_dbt_set_value ( foundk , kv_pair_key ( kv ) , kv_pair_keylen ( kv ) , & pma - > skey ) ;
if ( r = = 0 & & foundv )
r = toku_dbt_set_value ( foundv , kv_pair_val ( kv ) , kv_pair_vallen ( kv ) , & pma - > sval ) ;
return r ;
} else
return DB_NOTFOUND ;
2007-07-13 19:37:47 +00:00
}
/* returns 0 if OK.
* You must have freed all the cursors , otherwise returns nonzero and does nothing . */
2007-11-20 00:32:25 +00:00
int toku_pma_free ( PMA * pmap ) {
2007-07-13 19:37:47 +00:00
PMA pma = * pmap ;
2007-08-16 13:10:29 +00:00
if ( pma - > n_pairs_present > 0 ) {
2007-12-05 19:41:39 +00:00
unsigned int i ;
2007-08-16 13:10:29 +00:00
for ( i = 0 ; i < pma - > N ; i + + ) {
2007-09-04 13:51:12 +00:00
struct kv_pair * kv = pma - > pairs [ i ] ;
if ( kv_pair_inuse ( kv ) ) {
2007-10-10 19:33:31 +00:00
pma_mfree_kv_pair ( pma , kv ) ;
2007-08-16 13:10:29 +00:00
pma - > pairs [ i ] = 0 ;
pma - > n_pairs_present - - ;
}
2007-08-03 17:21:20 +00:00
}
2007-07-13 19:37:47 +00:00
}
2007-08-16 13:10:29 +00:00
assert ( pma - > n_pairs_present = = 0 ) ;
2007-10-12 23:50:05 +00:00
# if PMA_USE_MEMPOOL
2007-11-28 20:51:16 +00:00
void * mpbase = toku_mempool_get_base ( & pma - > kvspace ) ;
toku_mempool_fini ( & pma - > kvspace ) ;
2007-10-12 23:50:05 +00:00
toku_free ( mpbase ) ;
# endif
2007-07-20 18:00:14 +00:00
toku_free ( pma - > pairs ) ;
2007-07-23 20:10:16 +00:00
if ( pma - > skey ) toku_free ( pma - > skey ) ;
if ( pma - > sval ) toku_free ( pma - > sval ) ;
2007-07-31 21:59:33 +00:00
toku_free ( pma ) ;
2007-07-13 19:37:47 +00:00
* pmap = 0 ;
return 0 ;
}
/* Copies keylen and datalen */
2007-11-14 17:58:38 +00:00
/* returns an error if the key is already present. */
2008-01-23 19:44:13 +00:00
int toku_pma_insert ( PMA pma , DBT * k , DBT * v , TOKUTXN txn , FILENUM filenum , DISKOFF diskoff , u_int32_t rand4fingerprint , u_int32_t * fingerprint , LSN * node_lsn ) {
2007-12-05 19:41:39 +00:00
int found ;
2008-01-25 20:44:16 +00:00
unsigned int idx = pma_search ( pma , k , pma - > dup_mode & TOKU_DB_DUPSORT ? v : 0 , 0 , pma - > N , & found ) ;
if ( found )
return BRT_ALREADY_THERE ; /* It is already here. Return an error. */
2007-09-04 13:51:12 +00:00
if ( kv_pair_inuse ( pma - > pairs [ idx ] ) ) {
2007-12-05 19:41:39 +00:00
unsigned int newidx ;
2008-01-23 19:44:13 +00:00
int r = toku_pmainternal_make_space_at ( txn , filenum , diskoff , pma , idx , & newidx , ( LSN * ) 0 ) ; /* returns the new idx. */
2007-12-04 10:02:59 +00:00
if ( r ! = 0 ) return r ;
idx = newidx ;
2007-07-13 19:37:47 +00:00
}
2007-12-05 19:41:39 +00:00
assert ( idx < pma - > N ) ;
2007-09-04 13:51:12 +00:00
assert ( ! kv_pair_inuse ( pma - > pairs [ idx ] ) ) ;
2007-10-10 19:33:31 +00:00
pma - > pairs [ idx ] = pma_malloc_kv_pair ( pma , k - > data , k - > size , v - > data , v - > size ) ;
2007-08-03 17:21:20 +00:00
assert ( pma - > pairs [ idx ] ) ;
2007-07-13 19:37:47 +00:00
pma - > n_pairs_present + + ;
2007-11-14 17:58:38 +00:00
* fingerprint + = rand4fingerprint * toku_calccrc32_kvpair ( k - > data , k - > size , v - > data , v - > size ) ;
2007-11-26 21:51:36 +00:00
{
const struct kv_pair * pair = pma - > pairs [ idx ] ;
const BYTESTRING key = { pair - > keylen , ( char * ) kv_pair_key_const ( pair ) } ;
const BYTESTRING data = { pair - > vallen , ( char * ) kv_pair_val_const ( pair ) } ;
2008-01-23 19:44:13 +00:00
int r = toku_log_insertinleaf ( txn , toku_txn_get_txnid ( txn ) , pma - > filenum , diskoff , idx , key , data ) ;
if ( txn & & node_lsn ) * node_lsn = toku_txn_get_last_lsn ( txn ) ;
return r ;
2007-11-26 21:51:36 +00:00
}
2007-07-13 19:37:47 +00:00
}
2008-01-02 20:33:51 +00:00
static int pma_delete_dup ( PMA pma , DBT * k , DBT * v , u_int32_t rand4sem , u_int32_t * fingerprint , u_int32_t * deleted_size ) {
2007-11-14 17:58:38 +00:00
/* find the left most matching key in the pma */
2007-12-05 19:41:39 +00:00
int found ;
2008-01-25 20:44:16 +00:00
unsigned int lefthere = pma_search ( pma , k , v , 0 , pma - > N , & found ) ;
2007-11-14 17:58:38 +00:00
int rightfound = found , righthere = lefthere ;
while ( rightfound ) {
struct kv_pair * kv = pma - > pairs [ righthere ] ;
2008-01-25 20:44:16 +00:00
if ( kv_pair_inuse ( kv ) ) {
2007-12-04 22:18:21 +00:00
* deleted_size + = PMA_ITEM_OVERHEAD + KEY_VALUE_OVERHEAD + kv_pair_keylen ( kv ) + kv_pair_vallen ( kv ) ;
2007-11-14 17:58:38 +00:00
* fingerprint - = rand4sem * toku_calccrc32_kvpair ( kv_pair_key_const ( kv ) , kv_pair_keylen ( kv ) , kv_pair_val_const ( kv ) , kv_pair_vallen ( kv ) ) ;
2008-01-25 20:44:16 +00:00
pma_mfree_kv_pair ( pma , kv ) ;
pma - > pairs [ righthere ] = 0 ;
pma - > n_pairs_present - - ;
2007-11-14 17:58:38 +00:00
}
/* find the next matching key in the pma */
2008-01-02 20:33:51 +00:00
righthere = pma_next_key ( pma , k , v , righthere + 1 , pma - > N , & rightfound ) ;
2007-11-14 17:58:38 +00:00
}
if ( found ) {
/* check the density of the region centered around the deleted pairs */
2008-01-25 20:44:16 +00:00
pma_delete_at ( pma , ( lefthere + righthere ) / 2 ) ;
2007-11-14 17:58:38 +00:00
}
return found ? BRT_OK : DB_NOTFOUND ;
}
2007-08-30 15:15:14 +00:00
2008-01-02 20:33:51 +00:00
static int pma_delete_nodup ( PMA pma , DBT * k , DBT * v , u_int32_t rand4sem , u_int32_t * fingerprint , u_int32_t * deleted_size ) {
/* find the left most matching key in the pma */
int found ;
unsigned int here ;
2008-01-21 21:03:23 +00:00
here = pma_search ( pma , k , v , 0 , pma - > N , & found ) ;
2008-01-02 20:33:51 +00:00
struct kv_pair * kv = pma - > pairs [ here ] ;
2008-01-25 20:44:16 +00:00
if ( ! found | | ! kv_pair_inuse ( kv ) )
2007-11-14 17:58:38 +00:00
return DB_NOTFOUND ;
2007-12-04 22:18:21 +00:00
* deleted_size = PMA_ITEM_OVERHEAD + KEY_VALUE_OVERHEAD + kv_pair_keylen ( kv ) + kv_pair_vallen ( kv ) ;
2007-11-14 17:58:38 +00:00
* fingerprint - = rand4sem * toku_calccrc32_kvpair ( kv_pair_key_const ( kv ) , kv_pair_keylen ( kv ) , kv_pair_val_const ( kv ) , kv_pair_vallen ( kv ) ) ;
2008-01-25 20:44:16 +00:00
pma_mfree_kv_pair ( pma , kv ) ;
pma - > pairs [ here ] = 0 ;
pma - > n_pairs_present - - ;
pma_delete_at ( pma , here ) ;
2007-07-13 19:37:47 +00:00
return BRT_OK ;
}
2008-01-02 20:33:51 +00:00
int toku_pma_delete ( PMA pma , DBT * k , DBT * v , u_int32_t rand4sem , u_int32_t * fingerprint , u_int32_t * deleted_size ) {
v = v ;
2007-11-15 14:44:05 +00:00
u_int32_t my_deleted_size ;
if ( ! deleted_size )
deleted_size = & my_deleted_size ;
* deleted_size = 0 ;
2008-01-07 19:06:05 +00:00
if ( pma - > dup_mode & TOKU_DB_DUPSORT )
2008-01-02 20:33:51 +00:00
return pma_delete_dup ( pma , k , v , rand4sem , fingerprint , deleted_size ) ;
2007-11-14 17:58:38 +00:00
else
2008-01-02 20:33:51 +00:00
return pma_delete_nodup ( pma , k , v , rand4sem , fingerprint , deleted_size ) ;
2007-11-14 17:58:38 +00:00
}
2008-01-25 20:44:16 +00:00
static void pma_delete_at ( PMA pma , int here ) {
2007-08-30 15:15:14 +00:00
int count ;
struct kv_pair_tag * newpairs ;
2007-12-05 19:41:39 +00:00
unsigned int lgN = pma - > uplgN ;
unsigned int size = lgN ;
double ldt = PMA_LDT_HIGH ;
2007-08-30 15:15:14 +00:00
/* check the density of regions from lg(N) size to the entire array */
for ( ; ; ) {
int lo , hi ;
double density ;
/* select a region centered on here */
lo = here - size / 2 ;
hi = here + size / 2 ;
if ( lo < 0 ) {
hi - = lo ;
lo = 0 ;
2007-12-05 19:41:39 +00:00
if ( ( unsigned ) hi > pma - > N )
2007-08-30 15:15:14 +00:00
hi = pma - > N ;
2007-12-05 19:41:39 +00:00
} else if ( ( unsigned ) hi > pma - > N ) {
2007-08-30 15:15:14 +00:00
lo - = hi - pma - > N ;
hi = pma - > N ;
if ( lo < 0 )
lo = 0 ;
}
assert ( lo < = hi ) ;
/* compute the density of the region */
2007-11-20 00:32:25 +00:00
count = toku_pmainternal_count_region ( pma - > pairs , lo , hi ) ;
2007-08-30 15:15:14 +00:00
density = ( double ) count / ( ( double ) ( hi - lo ) ) ;
/* rebalance if the density exceeds the lower threadshold */
if ( 0 ) printf ( " check size %d h %d density %d/%d %f %d-%d ldt %f \n " , size ,
lgN , count , hi - lo , density , lo , hi , ldt ) ;
if ( density > = ldt ) {
if ( size = = lgN )
return ;
if ( 0 ) printf ( " delete_at_rebalance %d over %d %d \n " , count , lo , hi ) ;
2007-12-05 19:41:39 +00:00
newpairs = pma_extract_pairs ( pma , count , lo , hi ) ;
2007-08-30 15:15:14 +00:00
distribute_data ( pma - > pairs + lo , hi - lo , newpairs , count , pma ) ;
toku_free ( newpairs ) ;
return ;
}
ldt - = pma - > ldt_step ;
size * = 2 ;
2007-12-05 19:41:39 +00:00
if ( 0 = = lo & & pma - > N = = ( unsigned ) hi )
2007-08-30 15:15:14 +00:00
break ;
}
/* shrink */
2007-12-05 19:41:39 +00:00
size = pma_array_size ( pma , count + count / 4 ) ;
2007-08-30 15:15:14 +00:00
if ( size = = pma - > N )
return ;
if ( 0 ) printf ( " shrink %d from %d to %d \n " , count , pma - > N , size ) ;
2007-12-05 19:41:39 +00:00
newpairs = pma_extract_pairs ( pma , count , 0 , pma - > N ) ;
2007-08-30 15:15:14 +00:00
assert ( newpairs ) ;
2007-12-04 10:02:59 +00:00
old_pma_resize_array ( pma , size , 0 ) ;
2007-08-30 15:15:14 +00:00
distribute_data ( pma - > pairs , pma - > N , newpairs , count , pma ) ;
toku_free ( newpairs ) ;
}
2007-11-20 00:32:25 +00:00
int toku_pma_insert_or_replace ( PMA pma , DBT * k , DBT * v ,
2007-11-26 21:51:36 +00:00
int * replaced_v_size , /* If it is a replacement, set to the size of the old value, otherwise set to -1. */
2007-12-04 10:02:59 +00:00
TOKUTXN txn , FILENUM filenum , DISKOFF diskoff ,
2008-01-23 19:44:13 +00:00
u_int32_t rand4fingerprint , u_int32_t * fingerprint ,
LSN * node_lsn ) {
2007-08-13 18:19:57 +00:00
//printf("%s:%d v->size=%d\n", __FILE__, __LINE__, v->size);
2007-09-28 17:11:22 +00:00
int r ;
2007-12-05 19:41:39 +00:00
int found ;
2008-01-25 20:44:16 +00:00
unsigned int idx = pma_search ( pma , k , pma - > dup_mode & TOKU_DB_DUPSORT ? v : 0 , 0 , pma - > N , & found ) ;
2008-01-21 21:03:23 +00:00
if ( found ) {
struct kv_pair * kv = pma - > pairs [ idx ] ;
2008-01-25 20:44:16 +00:00
* replaced_v_size = kv - > vallen ;
* fingerprint - = rand4fingerprint * toku_calccrc32_kvpair ( kv_pair_key_const ( kv ) , kv_pair_keylen ( kv ) , kv_pair_val_const ( kv ) , kv_pair_vallen ( kv ) ) ;
2008-01-25 21:50:07 +00:00
{
const BYTESTRING deletedkey = { kv - > keylen , kv_pair_key ( kv ) } ;
const BYTESTRING deleteddata = { kv - > vallen , kv_pair_val ( kv ) } ;
r = toku_log_deleteinleaf ( txn , toku_txn_get_txnid ( txn ) , pma - > filenum , diskoff , idx , deletedkey , deleteddata ) ;
if ( r ! = 0 ) return r ;
}
2008-01-25 20:44:16 +00:00
if ( txn & & node_lsn ) * node_lsn = toku_txn_get_last_lsn ( txn ) ;
2008-01-21 21:03:23 +00:00
if ( v - > size = = ( unsigned int ) kv_pair_vallen ( kv ) ) {
memcpy ( kv_pair_val ( kv ) , v - > data , v - > size ) ;
} else {
pma_mfree_kv_pair ( pma , kv ) ;
pma - > pairs [ idx ] = pma_malloc_kv_pair ( pma , k - > data , k - > size , v - > data , v - > size ) ;
assert ( pma - > pairs [ idx ] ) ;
2007-08-13 18:01:09 +00:00
}
2008-01-25 21:50:07 +00:00
/* idx is live here */
goto logit_and_update_fingerprint ;
2007-08-13 18:01:09 +00:00
}
2007-09-04 13:51:12 +00:00
if ( kv_pair_inuse ( pma - > pairs [ idx ] ) ) {
2007-12-05 19:41:39 +00:00
unsigned int newidx ;
2008-01-23 19:44:13 +00:00
r = toku_pmainternal_make_space_at ( txn , filenum , diskoff , pma , idx , & newidx , node_lsn ) ; /* returns the new idx. */
2007-12-04 10:02:59 +00:00
if ( r ! = 0 ) return r ;
idx = newidx ;
2007-08-13 18:01:09 +00:00
}
2007-09-04 13:51:12 +00:00
assert ( ! kv_pair_inuse ( pma - > pairs [ idx ] ) ) ;
2007-08-13 18:19:57 +00:00
//printf("%s:%d v->size=%d\n", __FILE__, __LINE__, v->size);
2007-10-10 19:33:31 +00:00
pma - > pairs [ idx ] = pma_malloc_kv_pair ( pma , k - > data , k - > size , v - > data , v - > size ) ;
2007-08-13 18:01:09 +00:00
assert ( pma - > pairs [ idx ] ) ;
pma - > n_pairs_present + + ;
* replaced_v_size = - 1 ;
2007-09-28 17:11:22 +00:00
//printf("%s:%d txn=%p\n", __FILE__, __LINE__, txn);
2008-01-25 21:50:07 +00:00
logit_and_update_fingerprint :
2007-11-26 21:51:36 +00:00
{
const struct kv_pair * pair = pma - > pairs [ idx ] ;
const BYTESTRING key = { pair - > keylen , ( char * ) kv_pair_key_const ( pair ) } ;
const BYTESTRING data = { pair - > vallen , ( char * ) kv_pair_val_const ( pair ) } ;
r = toku_log_insertinleaf ( txn , toku_txn_get_txnid ( txn ) , pma - > filenum , diskoff , idx , key , data ) ;
2008-01-23 19:44:13 +00:00
if ( txn & & node_lsn ) * node_lsn = toku_txn_get_last_lsn ( txn ) ;
2007-11-26 21:51:36 +00:00
}
2007-11-14 17:58:38 +00:00
* fingerprint + = rand4fingerprint * toku_calccrc32_kvpair ( k - > data , k - > size , v - > data , v - > size ) ;
2007-09-28 17:11:22 +00:00
return r ;
2007-08-13 18:01:09 +00:00
}
2007-11-20 00:32:25 +00:00
void toku_pma_iterate ( PMA pma , void ( * f ) ( bytevec , ITEMLEN , bytevec , ITEMLEN , void * ) , void * v ) {
2007-12-05 19:41:39 +00:00
unsigned int i ;
2007-11-20 00:32:25 +00:00
for ( i = 0 ; i < toku_pma_index_limit ( pma ) ; i + + ) {
2007-08-03 17:21:20 +00:00
struct kv_pair * pair = pma - > pairs [ i ] ;
if ( pair ) {
f ( pair - > key , pair - > keylen ,
pair - > key + pair - > keylen , pair - > vallen , v ) ;
}
2007-07-13 19:37:47 +00:00
}
}
2007-07-30 16:32:46 +00:00
2007-12-05 19:41:39 +00:00
static struct kv_pair_tag * pma_extract_pairs ( PMA pma , int npairs , unsigned int lo , unsigned int hi ) {
2007-08-06 19:43:27 +00:00
struct kv_pair_tag * pairs ;
2007-12-05 19:41:39 +00:00
unsigned int i ;
2007-07-30 16:32:46 +00:00
int lastpair ;
2007-08-06 19:43:27 +00:00
pairs = toku_malloc ( npairs * sizeof ( struct kv_pair_tag ) ) ;
2007-08-03 17:21:20 +00:00
if ( pairs = = 0 )
return 0 ;
2007-07-30 16:32:46 +00:00
lastpair = 0 ;
2007-08-03 17:21:20 +00:00
for ( i = lo ; i < hi ; i + + ) {
2007-12-05 19:41:39 +00:00
assert ( i < pma - > N ) ;
2007-08-03 17:21:20 +00:00
if ( pma - > pairs [ i ] ! = 0 ) {
2007-08-30 15:15:14 +00:00
assert ( pma - > pairs [ i ] ! = ( void * ) 0xdeadbeef ) ;
2007-08-06 19:43:27 +00:00
pairs [ lastpair ] . pair = pma - > pairs [ i ] ;
pairs [ lastpair ] . oldtag = i ;
2007-08-03 17:21:20 +00:00
pma - > pairs [ i ] = 0 ;
2007-07-30 16:32:46 +00:00
lastpair + = 1 ;
}
}
assert ( lastpair = = npairs ) ;
return pairs ;
}
2007-10-12 23:50:05 +00:00
# if PMA_USE_MEMPOOL
2007-10-10 19:33:31 +00:00
static void __pma_relocate_kvpairs ( PMA pma ) {
2007-12-05 19:41:39 +00:00
unsigned int i ;
2007-10-10 19:33:31 +00:00
for ( i = 0 ; i < pma - > N ; i + + ) {
struct kv_pair * kv = pma - > pairs [ i ] ;
if ( kv ) {
pma - > pairs [ i ] = kv_pair_malloc_mempool ( kv_pair_key ( kv ) , kv_pair_keylen ( kv ) , kv_pair_val ( kv ) ,
kv_pair_vallen ( kv ) , & pma - > kvspace ) ;
assert ( pma - > pairs [ i ] ) ;
}
}
}
2007-10-12 23:50:05 +00:00
# endif
2007-11-16 22:44:56 +00:00
2007-12-04 10:02:59 +00:00
int toku_pma_split ( TOKUTXN txn , FILENUM filenum ,
2008-01-23 19:44:13 +00:00
DISKOFF diskoff , PMA pma , unsigned int * pma_size_p , u_int32_t rand4fp , u_int32_t * fingerprint_p , LSN * lsn ,
2008-01-22 16:27:54 +00:00
DBT * splitk ,
2008-01-23 19:44:13 +00:00
DISKOFF newdiskoff , PMA newpma , unsigned int * newpma_size_p , u_int32_t newrand4fp , u_int32_t * newfingerprint_p , LSN * newlsn ) {
2007-07-30 16:32:46 +00:00
int error ;
int npairs ;
2007-08-06 19:43:27 +00:00
struct kv_pair_tag * pairs ;
2007-07-30 16:32:46 +00:00
int i ;
2007-08-09 18:54:58 +00:00
int n ;
2007-07-30 16:32:46 +00:00
int spliti ;
/* extract the pairs */
2008-01-22 16:27:54 +00:00
npairs = toku_pma_n_entries ( pma ) ;
2007-11-15 14:44:05 +00:00
if ( npairs = = 0 ) {
if ( splitk )
memset ( splitk , 0 , sizeof * splitk ) ;
2007-08-09 18:54:58 +00:00
return 0 ;
2007-11-15 14:44:05 +00:00
}
2007-08-09 18:54:58 +00:00
/* TODO move pairs to the stack */
2008-01-22 16:27:54 +00:00
pairs = pma_extract_pairs ( pma , npairs , 0 , pma - > N ) ;
2007-08-03 17:21:20 +00:00
assert ( pairs ) ;
2008-01-22 16:27:54 +00:00
assert ( toku_pma_n_entries ( newpma ) = = 0 ) ;
2007-07-30 16:32:46 +00:00
2007-08-09 18:54:58 +00:00
/* debug check the kv length sum */
2008-01-22 16:27:54 +00:00
unsigned int sumlen = 0 ;
2007-07-30 16:32:46 +00:00
for ( i = 0 ; i < npairs ; i + + )
2007-12-04 22:18:21 +00:00
sumlen + = kv_pair_keylen ( pairs [ i ] . pair ) + kv_pair_vallen ( pairs [ i ] . pair ) + PMA_ITEM_OVERHEAD + KEY_VALUE_OVERHEAD ;
2007-08-09 18:54:58 +00:00
2008-01-22 16:27:54 +00:00
if ( pma_size_p )
assert ( * pma_size_p = = sumlen ) ;
2007-07-30 16:32:46 +00:00
2008-01-22 16:27:54 +00:00
unsigned int runlen = 0 ;
2007-08-09 18:54:58 +00:00
for ( i = 0 ; i < npairs ; ) {
2007-12-04 22:18:21 +00:00
runlen + = kv_pair_keylen ( pairs [ i ] . pair ) + kv_pair_vallen ( pairs [ i ] . pair ) + PMA_ITEM_OVERHEAD + KEY_VALUE_OVERHEAD ;
2007-08-09 18:54:58 +00:00
i + + ;
if ( 2 * runlen > = sumlen )
2007-07-30 16:32:46 +00:00
break ;
}
spliti = i ;
2008-01-22 16:27:54 +00:00
unsigned int revised_leftpmasize = runlen ;
unsigned int revised_rightpmasize = sumlen - runlen ;
u_int32_t revised_left_fingerprint ;
u_int32_t revised_right_fingerprint ;
2007-11-14 17:58:38 +00:00
{
u_int32_t sum = 0 ;
for ( i = spliti ; i < npairs ; i + + ) {
sum + = toku_calccrc32_kvpair ( kv_pair_key_const ( pairs [ i ] . pair ) , kv_pair_keylen ( pairs [ i ] . pair ) ,
kv_pair_val_const ( pairs [ i ] . pair ) , kv_pair_vallen ( pairs [ i ] . pair ) ) ;
}
2008-01-22 16:27:54 +00:00
revised_left_fingerprint = - rand4fp * sum ;
revised_right_fingerprint = newrand4fp * sum ;
2007-11-14 17:58:38 +00:00
}
2007-11-15 14:44:05 +00:00
if ( splitk ) {
2007-11-16 22:44:56 +00:00
struct kv_pair * a = pairs [ spliti - 1 ] . pair ;
2008-01-22 16:27:54 +00:00
if ( pma - > dup_mode & TOKU_DB_DUPSORT ) {
2007-11-27 18:16:45 +00:00
splitk - > data = kv_pair_malloc ( kv_pair_key ( a ) , kv_pair_keylen ( a ) , kv_pair_val ( a ) , kv_pair_vallen ( a ) ) ;
splitk - > size = kv_pair_keylen ( a ) + kv_pair_vallen ( a ) ;
2007-11-16 22:44:56 +00:00
} else {
2007-11-27 18:16:45 +00:00
splitk - > data = kv_pair_malloc ( kv_pair_key ( a ) , kv_pair_keylen ( a ) , 0 , 0 ) ;
2007-11-16 22:44:56 +00:00
splitk - > size = kv_pair_keylen ( a ) ;
}
2008-01-08 21:02:36 +00:00
splitk - > flags = 0 ;
2007-11-15 14:44:05 +00:00
}
2007-08-09 18:54:58 +00:00
/* put the second half of pairs into the right pma */
2008-01-22 18:33:51 +00:00
/* Do this first, so that the logging will move the stuff out of the left pma first, and then later when we redistribute in the left PMA, we won't overwrite something. */
2007-08-09 18:54:58 +00:00
n = npairs - spliti ;
2008-01-23 19:44:13 +00:00
error = pma_resize_array ( txn , filenum , newdiskoff , newpma , n + n / 4 , 0 , newlsn ) ;
2007-07-30 18:35:40 +00:00
assert ( error = = 0 ) ;
2008-01-22 16:27:54 +00:00
distribute_data ( newpma - > pairs , toku_pma_index_limit ( newpma ) , & pairs [ spliti ] , n , newpma ) ;
2008-01-22 18:33:51 +00:00
{
2008-01-23 19:44:13 +00:00
int r = pma_log_distribute ( txn , filenum , diskoff , newdiskoff , n , & pairs [ spliti ] , lsn , newlsn ) ;
2008-01-22 18:33:51 +00:00
if ( r ! = 0 ) { toku_free ( pairs ) ; return r ; }
}
2007-10-12 23:50:05 +00:00
# if PMA_USE_MEMPOOL
2008-01-22 16:27:54 +00:00
__pma_relocate_kvpairs ( newpma ) ;
// If it's in an mpool, we must free those pairs.
for ( i = spliti ; i < npairs ; i + + ) {
pma_mfree_kv_pair ( pma , pairs [ i ] . pair ) ;
}
2007-10-12 23:50:05 +00:00
# endif
2008-01-22 16:27:54 +00:00
newpma - > n_pairs_present = n ;
2007-07-30 16:32:46 +00:00
2008-01-22 18:33:51 +00:00
/* put the first half of pairs into the left pma */
n = spliti ;
2008-01-25 21:50:07 +00:00
// Since the new array is smaller than the old one, during recovery we need to do the resize after moving the elements.
// But we must actually do the resize first here so we can determine the size.
unsigned int oldn_for_logging , newn_for_logging ;
error = pma_resize_array_nolog ( pma , n + n / 4 , 0 , // zeros the elements
& oldn_for_logging , & newn_for_logging ) ;
2008-01-22 18:33:51 +00:00
assert ( error = = 0 ) ;
distribute_data ( pma - > pairs , toku_pma_index_limit ( pma ) , & pairs [ 0 ] , n , pma ) ;
{
2008-01-23 19:44:13 +00:00
int r = pma_log_distribute ( txn , filenum , diskoff , diskoff , spliti , & pairs [ 0 ] , lsn , lsn ) ;
2008-01-22 18:33:51 +00:00
if ( r ! = 0 ) { toku_free ( pairs ) ; return r ; }
2008-01-25 21:50:07 +00:00
r = toku_log_resizepma ( txn , toku_txn_get_txnid ( txn ) , filenum , diskoff , oldn_for_logging , newn_for_logging ) ;
if ( r ! = 0 ) { toku_free ( pairs ) ; return r ; }
if ( txn & & lsn ) * lsn = toku_txn_get_last_lsn ( txn ) ;
2008-01-22 18:33:51 +00:00
}
// Don't have to relocate kvpairs, because these ones are still there.
pma - > n_pairs_present = spliti ;
2007-07-30 16:32:46 +00:00
toku_free ( pairs ) ;
2008-01-22 16:27:54 +00:00
/* The remaining cursors are in the left pma */
if ( fingerprint_p ) * fingerprint_p + = revised_left_fingerprint ;
if ( newfingerprint_p ) * newfingerprint_p + = revised_right_fingerprint ;
if ( pma_size_p ) * pma_size_p = revised_leftpmasize ;
if ( newpma_size_p ) * newpma_size_p = revised_rightpmasize ;
2007-08-06 19:43:27 +00:00
2007-07-30 16:32:46 +00:00
return 0 ;
}
2007-08-03 17:21:20 +00:00
2007-11-14 17:58:38 +00:00
static void __pma_bulk_cleanup ( struct pma * pma , struct kv_pair_tag * pairs , int n ) {
2007-08-06 19:43:27 +00:00
int i ;
for ( i = 0 ; i < n ; i + + )
if ( pairs [ i ] . pair )
2007-10-10 19:33:31 +00:00
pma_mfree_kv_pair ( pma , pairs [ i ] . pair ) ;
2007-08-06 19:43:27 +00:00
}
2008-01-23 19:44:13 +00:00
int toku_pma_bulk_insert ( TOKUTXN txn , FILENUM filenum , DISKOFF diskoff , PMA pma , DBT * keys , DBT * vals , int n_newpairs , u_int32_t rand4fp , u_int32_t * sum , LSN * node_lsn ) {
2007-08-06 19:43:27 +00:00
struct kv_pair_tag * newpairs ;
int i ;
int error ;
2007-11-14 17:58:38 +00:00
u_int32_t delta = 0 ;
2007-08-06 19:43:27 +00:00
2007-08-09 18:54:58 +00:00
if ( n_newpairs = = 0 )
return 0 ;
2007-11-20 00:32:25 +00:00
if ( toku_pma_n_entries ( pma ) > 0 )
2007-08-09 18:54:58 +00:00
return - 2 ;
/* TODO put newpairs on the stack */
2007-08-06 19:43:27 +00:00
newpairs = toku_malloc ( n_newpairs * sizeof ( struct kv_pair_tag ) ) ;
if ( newpairs = = 0 ) {
2007-08-09 18:54:58 +00:00
error = - 3 ; return error ;
2007-08-06 19:43:27 +00:00
}
for ( i = 0 ; i < n_newpairs ; i + + ) {
2007-11-14 17:58:38 +00:00
delta + = rand4fp * toku_calccrc32_kvpair ( keys [ i ] . data , keys [ i ] . size , vals [ i ] . data , vals [ i ] . size ) ;
2007-10-12 23:50:05 +00:00
# if PMA_USE_MEMPOOL
2007-10-10 19:33:31 +00:00
newpairs [ i ] . pair = kv_pair_malloc_mempool ( keys [ i ] . data , keys [ i ] . size ,
vals [ i ] . data , vals [ i ] . size , & pma - > kvspace ) ;
2007-10-12 23:50:05 +00:00
# else
newpairs [ i ] . pair = kv_pair_malloc ( keys [ i ] . data , keys [ i ] . size , vals [ i ] . data , vals [ i ] . size ) ;
# endif
2007-08-06 19:43:27 +00:00
if ( newpairs [ i ] . pair = = 0 ) {
2007-10-10 19:33:31 +00:00
__pma_bulk_cleanup ( pma , newpairs , i ) ;
2007-08-06 19:43:27 +00:00
toku_free ( newpairs ) ;
2007-08-09 18:54:58 +00:00
error = - 4 ; return error ;
2007-08-06 19:43:27 +00:00
}
}
2008-01-23 19:44:13 +00:00
error = pma_resize_array ( txn , filenum , diskoff , pma , n_newpairs + n_newpairs / 4 , 0 , node_lsn ) ;
2007-08-09 18:54:58 +00:00
if ( error ) {
2007-10-10 19:33:31 +00:00
__pma_bulk_cleanup ( pma , newpairs , n_newpairs ) ;
2007-08-09 18:54:58 +00:00
toku_free ( newpairs ) ;
error = - 5 ; return error ;
}
2007-11-20 00:32:25 +00:00
distribute_data ( pma - > pairs , toku_pma_index_limit ( pma ) , newpairs , n_newpairs , pma ) ;
2007-08-09 18:54:58 +00:00
pma - > n_pairs_present = n_newpairs ;
2007-08-06 19:43:27 +00:00
toku_free ( newpairs ) ;
2007-11-14 17:58:38 +00:00
* sum + = delta ;
2007-08-06 19:43:27 +00:00
2007-08-09 18:54:58 +00:00
return 0 ;
2007-08-06 19:43:27 +00:00
}
2007-11-14 17:58:38 +00:00
/* verify that the keys in the pma index are sorted subject to the pma mode
* no duplications , duplicates , sorted duplicates .
*/
2007-11-26 21:51:36 +00:00
void toku_pma_verify ( PMA pma ) {
2007-12-05 19:41:39 +00:00
unsigned int i ;
2007-11-14 17:58:38 +00:00
struct kv_pair * kv ;
/* find the first key in the index */
for ( i = 0 ; i < pma - > N ; i + + ) {
kv = pma - > pairs [ i ] ;
if ( kv_pair_inuse ( kv ) ) {
i + = 1 ;
break ;
}
}
/* compare the current key with the next key in the index */
struct kv_pair * nextkv ;
for ( ; i < pma - > N ; i + + ) {
nextkv = pma - > pairs [ i ] ;
if ( kv_pair_inuse ( nextkv ) ) {
DBT kv_dbt , nextkv_dbt ;
2007-11-29 15:17:46 +00:00
toku_fill_dbt ( & kv_dbt , kv_pair_key ( kv ) , kv_pair_keylen ( kv ) ) ;
toku_fill_dbt ( & nextkv_dbt , kv_pair_key ( nextkv ) , kv_pair_keylen ( nextkv ) ) ;
2007-11-26 21:51:36 +00:00
int r = pma - > compare_fun ( pma - > db , & kv_dbt , & nextkv_dbt ) ;
2007-11-14 17:58:38 +00:00
if ( pma - > dup_mode = = 0 )
assert ( r < 0 ) ;
2008-01-07 19:06:05 +00:00
else if ( pma - > dup_mode & TOKU_DB_DUPSORT )
2007-11-14 17:58:38 +00:00
assert ( r < = 0 ) ;
2007-11-19 20:22:56 +00:00
if ( r = = 0 & & ( pma - > dup_mode & TOKU_DB_DUPSORT ) ) {
2007-11-29 15:17:46 +00:00
toku_fill_dbt ( & kv_dbt , kv_pair_val ( kv ) , kv_pair_vallen ( kv ) ) ;
toku_fill_dbt ( & nextkv_dbt , kv_pair_val ( nextkv ) , kv_pair_vallen ( nextkv ) ) ;
2007-11-26 21:51:36 +00:00
r = pma - > dup_compare_fun ( pma - > db , & kv_dbt , & nextkv_dbt ) ;
2007-11-14 17:58:38 +00:00
assert ( r < = 0 ) ;
}
kv = nextkv ;
}
}
# if PMA_USE_MEMPOOL
/* verify all kv pairs are in the memory pool */
for ( i = 0 ; i < pma - > N ; i + + ) {
kv = pma - > pairs [ i ] ;
if ( kv_pair_inuse ( kv ) ) {
2007-11-28 20:51:16 +00:00
assert ( toku_mempool_inrange ( & pma - > kvspace , kv , kv_pair_size ( kv ) ) ) ;
2007-11-14 17:58:38 +00:00
}
}
# endif
}
2007-11-15 14:44:05 +00:00
2007-11-20 00:32:25 +00:00
void toku_pma_verify_fingerprint ( PMA pma , u_int32_t rand4fingerprint , u_int32_t fingerprint ) {
2007-11-14 17:58:38 +00:00
u_int32_t actual_fingerprint = 0 ;
PMA_ITERATE ( pma , kv , kl , dv , dl ,
actual_fingerprint + = rand4fingerprint * toku_calccrc32_kvpair ( kv , kl , dv , dl )
) ;
assert ( actual_fingerprint = = fingerprint ) ;
}
2007-11-27 10:48:31 +00:00
// If the index is wrong or there is a value already, return nonzero
// There should be no cursors, but if there were they wouldn't need to be updated.
2007-12-05 19:41:39 +00:00
int toku_pma_set_at_index ( PMA pma , unsigned int idx , DBT * key , DBT * value ) {
if ( idx > = pma - > N ) return - 1 ;
2007-11-27 10:48:31 +00:00
if ( kv_pair_inuse ( pma - > pairs [ idx ] ) ) return - 1 ;
pma - > pairs [ idx ] = pma_malloc_kv_pair ( pma , key - > data , key - > size , value - > data , value - > size ) ;
pma - > n_pairs_present + + ;
return 0 ;
}
2007-12-04 17:59:03 +00:00
2008-01-11 22:24:43 +00:00
int toku_pma_clear_at_index ( PMA pma , unsigned int idx ) {
if ( idx > = pma - > N ) return - 1 ;
if ( ! kv_pair_inuse ( pma - > pairs [ idx ] ) ) return - 1 ;
pma_mfree_kv_pair ( pma , pma - > pairs [ idx ] ) ;
pma - > pairs [ idx ] = 0 ;
2008-01-12 12:21:07 +00:00
pma - > n_pairs_present - - ;
2008-01-11 22:24:43 +00:00
return 0 ;
}
2008-01-16 15:41:12 +00:00
// Move from a to b
static void pma_move ( PMA pmaa , int idxa , u_int32_t randa , u_int32_t * fingerprinta , u_int32_t * n_in_bufa ,
PMA pmab , int idxb , u_int32_t randb , u_int32_t * fingerprintb , u_int32_t * n_in_bufb ) {
if ( pmaa = = pmab ) {
assert ( pmab - > pairs [ idxb ] = = 0 ) ;
pmab - > pairs [ idxb ] = pmaa - > pairs [ idxa ] ;
pmaa - > pairs [ idxa ] = 0 ;
} else {
struct kv_pair * pair = pmaa - > pairs [ idxa ] ;
u_int32_t fdiff = toku_calccrc32_kvpair ( kv_pair_key_const ( pair ) , kv_pair_keylen ( pair ) , kv_pair_val_const ( pair ) , kv_pair_vallen ( pair ) ) ;
u_int32_t sizediff = PMA_ITEM_OVERHEAD + KEY_VALUE_OVERHEAD + kv_pair_keylen ( pair ) + kv_pair_vallen ( pair ) ;
* fingerprinta - = randa * fdiff ; * fingerprintb + = randb * fdiff ;
* n_in_bufa - = sizediff ; * n_in_bufb + = sizediff ;
pmab - > pairs [ idxb ] = pma_malloc_kv_pair ( pmab , kv_pair_key_const ( pair ) , kv_pair_keylen ( pair ) , kv_pair_val_const ( pair ) , kv_pair_vallen ( pair ) ) ;
pma_mfree_kv_pair ( pmaa , pair ) ;
pmaa - > pairs [ idxa ] = 0 ;
pmaa - > n_pairs_present - - ;
pmab - > n_pairs_present + + ;
}
}
2007-12-04 17:59:03 +00:00
// assume no cursors
2008-01-16 13:50:23 +00:00
// Move stuff from pmaa to pmab
2008-01-16 15:41:12 +00:00
int toku_pma_move_indices ( PMA pma_from , PMA pma_to , INTPAIRARRAY fromto ,
u_int32_t rand_from , u_int32_t * fingerprint_from ,
u_int32_t rand_to , u_int32_t * fingerprint_to ,
u_int32_t * n_in_buf_from , u_int32_t * n_in_buf_to
) {
2007-12-04 17:59:03 +00:00
u_int32_t i ;
for ( i = 0 ; i < fromto . size ; i + + ) {
// First handle the case for sliding something left. We can simply move it.
{
int a = fromto . array [ i ] . a ;
int b = fromto . array [ i ] . b ;
if ( b = = a ) continue ;
if ( b < a ) {
2008-01-16 15:41:12 +00:00
pma_move ( pma_from , a , rand_from , fingerprint_from , n_in_buf_from ,
pma_to , b , rand_to , fingerprint_to , n_in_buf_to ) ;
2007-12-04 17:59:03 +00:00
continue ;
}
}
// Otherwise slide things to the right We have to find the rightmost thing that slides right and move it first.
{
// We must slide things to the right.
// Find the next index that does want to go to the left
u_int32_t j ;
2007-12-05 20:00:19 +00:00
for ( j = i + 1 ; j < fromto . size & & fromto . array [ j ] . a < fromto . array [ j ] . b ; j + + ) {
2007-12-04 17:59:03 +00:00
/*nothing */
}
// everything from i (inclusive) to j (exclusive) wants to slide to the right.
u_int32_t jdown ;
for ( jdown = j - 1 ; 1 ; jdown - - ) {
int a = fromto . array [ jdown ] . a ;
int b = fromto . array [ jdown ] . b ;
if ( a ! = b ) {
2008-01-16 15:41:12 +00:00
pma_move ( pma_from , a , rand_from , fingerprint_from , n_in_buf_from ,
pma_to , b , rand_to , fingerprint_to , n_in_buf_to ) ;
2007-12-04 17:59:03 +00:00
}
if ( i = = jdown ) break ; // Do it this way so everything can be unsigned and we won't try to go negative.
}
i = j - 1 ;
}
}
return 0 ;
}
2008-01-13 05:52:43 +00:00
static void reverse_fromto ( INTPAIRARRAY fromto ) {
u_int32_t i ;
for ( i = 0 ; i < fromto . size ; i + + ) {
int tmp = fromto . array [ i ] . a ;
fromto . array [ i ] . a = fromto . array [ i ] . b ;
fromto . array [ i ] . b = tmp ;
}
}
2008-01-16 15:41:12 +00:00
int toku_pma_move_indices_back ( PMA pma_backto , PMA pma_backfrom , INTPAIRARRAY fromto ,
u_int32_t rand_backto , u_int32_t * fingerprint_backto ,
u_int32_t rand_backfrom , u_int32_t * fingerprint_backfrom ,
u_int32_t * n_in_buf_backto , u_int32_t * n_in_buf_backfrom
) {
2008-01-13 05:52:43 +00:00
int r ;
reverse_fromto ( fromto ) ;
2008-01-16 15:41:12 +00:00
r = toku_pma_move_indices ( pma_backfrom , pma_backto , fromto ,
rand_backfrom , fingerprint_backfrom ,
rand_backto , fingerprint_backto ,
n_in_buf_backfrom , n_in_buf_backto
) ;
2008-01-13 05:52:43 +00:00
reverse_fromto ( fromto ) ;
return r ;
}