2007-11-29 14:18:54 +00:00
/* -*- mode: C; c-basic-offset: 4 -*- */
# ident "Copyright (c) 2007 Tokutek Inc. All rights reserved."
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. *********************/
/*
* finish a deletion from the pma . called when there are no cursor references
* to the kv pair .
*/
static void __pma_delete_finish ( PMA pma , int here ) ;
/*
* resize the pma array to asksize . zero all array entries starting from startx .
*/
2007-12-04 10:02:59 +00:00
static int pma_resize_array ( TOKUTXN , FILENUM , DISKOFF , PMA pma , int asksize , int startx ) ;
static int old_pma_resize_array ( PMA pma , int asksize , int startx ) {
return pma_resize_array ( ( TOKUTXN ) 0 , ( FILENUM ) { 0 } , ( DISKOFF ) 0 , pma , asksize , startx ) ;
}
2007-11-14 17:58:38 +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
/*
* update the cursors in a cursor set given a set of tagged pairs .
*/
static void __pma_update_cursors ( PMA pma , struct list * cursorset , struct kv_pair_tag * tpairs , int n ) ;
/*
* update this pma ' s cursors given a set of tagged pairs .
*/
static void __pma_update_my_cursors ( PMA pma , struct kv_pair_tag * tpairs , int n ) ;
/*
* a deletion occured at index " here " in the pma . rebalance the windows around " here " . if
* necessary , shrink the pma .
*/
static void __pma_delete_at ( PMA pma , int here ) ;
/*
* if the pma entry at here is deleted and there are no more references to it
* then finish the deletion
*/
static void __pma_delete_resume ( PMA pma , int here ) ;
/*
* count the number of cursors that reference a pma pair
*/
static int __pma_count_cursor_refs ( PMA pma , int here ) ;
/**************************** end of static functions forward declarations. *********************/
2007-11-27 18:16:45 +00:00
/* use the low bit in the kv_pair pointer to indicate an inuse pair that is deleted */
static inline int kv_pair_inuse ( struct kv_pair * pair ) {
return pair ! = 0 ;
}
static inline int kv_pair_deleted ( struct kv_pair * pair ) {
return ( ( long ) pair & 1 ) ! = 0 ;
}
static inline int kv_pair_valid ( struct kv_pair * pair ) {
return kv_pair_inuse ( pair ) & & ! kv_pair_deleted ( pair ) ;
}
static inline struct kv_pair * kv_pair_set_deleted ( struct kv_pair * pair ) {
return ( struct kv_pair * ) ( ( long ) pair | 1 ) ;
}
static inline struct kv_pair * kv_pair_ptr ( struct kv_pair * pair ) {
return ( struct kv_pair * ) ( ( long ) pair & ~ 1 ) ;
}
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 */
static struct kv_pair * kv_pair_malloc_mempool ( void * key , int keylen , 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 */
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 ) ) {
kv = kv_pair_ptr ( 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 ) ) ;
if ( kv_pair_deleted ( pma - > pairs [ i ] ) )
kv_pair_set_deleted ( newkv ) ;
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 . */
2007-10-12 23:50:05 +00:00
static struct kv_pair * pma_malloc_kv_pair ( PMA pma __attribute__ ( ( unused ) ) , void * k , int ksize , void * v , int vsize ) {
# 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 ) {
2007-10-10 19:33:31 +00:00
kv = kv_pair_ptr ( kv ) ;
2007-10-12 23:50:05 +00:00
# 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 ) ) ;
2007-09-05 13:52:52 +00:00
return kv_pair_valid ( 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 ] ;
2007-09-04 13:51:12 +00:00
assert ( kv_pair_valid ( 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 ] ;
2007-09-04 13:51:12 +00:00
assert ( kv_pair_valid ( 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 ] ;
2007-09-04 13:51:12 +00:00
assert ( kv_pair_valid ( 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 ] ;
2007-09-04 13:51:12 +00:00
assert ( kv_pair_valid ( 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 ] ;
2007-09-04 13:51:12 +00:00
if ( kv_pair_valid ( 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 ] ;
2007-09-04 13:51:12 +00:00
if ( kv_pair_valid ( 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 ;
}
2007-11-14 17:58:38 +00:00
/* search the index for a matching key */
2007-12-17 01:03:35 +00:00
static unsigned int __pma_search ( PMA pma , DBT * k , 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 )
2007-11-26 21:51:36 +00:00
return __pma_search ( pma , k , lo , omi , found ) ;
2007-12-17 01:03:35 +00:00
int cmp = pma_compare_dbt_kv ( pma , k , 0 , kv_pair_ptr ( pma - > pairs [ mi ] ) ) ;
2007-11-14 17:58:38 +00:00
if ( cmp > 0 )
2007-11-26 21:51:36 +00:00
return __pma_search ( pma , k , mi + 1 , hi , found ) ;
2007-11-14 17:58:38 +00:00
if ( cmp < 0 )
2007-11-26 21:51:36 +00:00
return __pma_search ( pma , k , lo , mi , found ) ;
2007-11-14 17:58:38 +00:00
* found = 1 ;
return mi ;
}
}
/* search the index for the rightmost matching key */
2007-12-17 01:03:35 +00:00
static unsigned int pma_right_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 )
2007-12-17 01:03:35 +00:00
return pma_right_search ( pma , k , v , lo , omi , found ) ;
int cmp = pma_compare_dbt_kv ( pma , k , v , kv_pair_ptr ( pma - > pairs [ mi ] ) ) ;
2007-11-14 17:58:38 +00:00
if ( cmp > 0 )
2007-12-17 01:03:35 +00:00
return pma_right_search ( pma , k , v , mi + 1 , hi , found ) ;
2007-11-14 17:58:38 +00:00
if ( cmp < 0 )
2007-12-17 01:03:35 +00:00
return pma_right_search ( pma , k , v , lo , mi , found ) ;
2007-11-14 17:58:38 +00:00
/* we have a match, try to find a match on the right tree */
int here ;
2007-12-17 01:03:35 +00:00
here = pma_right_search ( pma , k , v , mi + 1 , hi , found ) ;
2007-11-14 17:58:38 +00:00
if ( * found = = 0 )
here = mi ;
* found = 1 ;
return here ;
}
}
/* search the index for the left most matching key */
2007-12-17 01:03:35 +00:00
static unsigned int pma_left_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 )
2007-12-17 01:03:35 +00:00
return pma_left_search ( pma , k , v , lo , omi , found ) ;
int cmp = pma_compare_dbt_kv ( pma , k , v , kv_pair_ptr ( pma - > pairs [ mi ] ) ) ;
2007-11-14 17:58:38 +00:00
if ( cmp > 0 )
2007-12-17 01:03:35 +00:00
return pma_left_search ( pma , k , v , mi + 1 , hi , found ) ;
2007-11-14 17:58:38 +00:00
if ( cmp < 0 )
2007-12-17 01:03:35 +00:00
return pma_left_search ( pma , k , v , lo , mi , found ) ;
2007-11-14 17:58:38 +00:00
/* we have a match, try to find a match on the left tree */
int here ;
2007-12-17 01:03:35 +00:00
here = pma_left_search ( pma , k , v , lo , mi , found ) ;
2007-11-14 17:58:38 +00:00
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-11-14 17:58:38 +00:00
# if 1
2007-11-20 00:32:25 +00:00
int lo = 0 , hi = toku_pma_index_limit ( pma ) ;
2007-07-13 19:37:47 +00:00
/* lo and hi are the minimum and maximum values (inclusive) that we could possibly return. */
pma_count_finds + + ;
while ( lo < hi ) {
int mid ;
// Scan forward looking for a non-null value.
for ( mid = ( lo + hi ) / 2 ; mid < hi ; mid + + ) {
2007-09-04 13:51:12 +00:00
struct kv_pair * kv = pma - > pairs [ mid ] ;
if ( kv_pair_inuse ( kv ) ) {
2007-07-13 19:37:47 +00:00
// Found one.
2007-09-04 13:51:12 +00:00
kv = kv_pair_ptr ( kv ) ;
2007-07-23 20:10:16 +00:00
DBT k2 ;
2007-11-29 15:17:46 +00:00
int cmp = pma - > compare_fun ( pma - > db , k , toku_fill_dbt ( & k2 , kv - > key , kv - > keylen ) ) ;
2007-07-13 19:37:47 +00:00
if ( cmp = = 0 ) return mid ;
else if ( cmp < 0 ) {
/* key is smaller than the midpoint, so look in the low half. */
hi = ( lo + hi ) / 2 ; /* recalculate the midpoint, since mid is no necessarily the midpoint now. */
pma_count_divides + + ;
goto next_range ;
} else {
/* key is larger than the midpoint. So look in the high half. */
lo = mid + 1 ; /* The smallest value we could want to return is lo. */
pma_count_divides + + ;
goto next_range ;
}
/* Not reached */
}
pma_count_scans + + ;
}
/* If we got here, all from mid to hi were null, so adjust hi to the midpoint. */
/* If the whole array is null, we'll end up returning index 0, which is good. */
hi = ( lo + hi ) / 2 ;
pma_count_divides + + ;
next_range : ; /* We have adjusted lo and hi, so look again. */
}
assert ( 0 < = lo ) ;
assert ( lo = = hi ) ;
2007-12-05 19:41:39 +00:00
assert ( ( unsigned ) hi < = toku_pma_index_limit ( pma ) ) ;
2007-07-13 19:37:47 +00:00
return lo ;
2007-11-14 17:58:38 +00:00
# else
2007-12-17 01:03:35 +00:00
int found ;
int lo = __pma_search ( pma , k , 0 , pma - > N , & found ) ;
2007-11-14 17:58:38 +00:00
return lo ;
# endif
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 ( " " ) ;
2007-09-04 13:51:12 +00:00
if ( kv_pair_valid ( pairs [ i ] ) ) {
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 ;
}
}
/* 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 . */
2007-12-04 10:02:59 +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 ) {
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 ) ;
{
INTPAIRARRAY ipa ;
2007-12-04 16:16:30 +00:00
ipa . size = n_saved - 1 ; /* Don't move the blank spot. */
2007-12-04 10:02:59 +00:00
MALLOC_N ( n_saved , ipa . array ) ;
if ( ipa . array = = 0 ) return errno ;
2007-12-04 16:16:30 +00:00
int j = 0 ;
2007-12-04 10:02:59 +00:00
for ( i = 0 ; i < n_saved ; i + + ) {
2007-12-05 18:22:42 +00:00
if ( tmppairs [ i ] . pair ! = 0 ) {
2007-12-04 16:16:30 +00:00
ipa . array [ j ] . a = tmppairs [ i ] . oldtag ;
ipa . array [ j ] . b = tmppairs [ i ] . newtag ;
j + + ;
}
2007-12-04 10:02:59 +00:00
}
int r = toku_log_pmadistribute ( txn , toku_txn_get_txnid ( txn ) , filenum , diskoff , ipa ) ;
2007-12-05 19:41:39 +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 ) ) ;
}
2007-12-04 10:02:59 +00:00
toku_free ( ipa . array ) ;
if ( r ! = 0 ) return r ;
}
2007-08-30 15:15:14 +00:00
if ( pma & & ! list_empty ( & pma - > cursors ) )
__pma_update_my_cursors ( pma , tmppairs , n_present ) ;
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
* new_idx = newidx ;
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 ;
}
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-08-06 19:43:27 +00:00
list_init ( & result - > cursors ) ;
2007-07-23 15:11:54 +00:00
result - > compare_fun = compare_fun ;
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 ;
2007-12-04 10:02:59 +00:00
error = old_pma_resize_array ( result , result - > N , 0 ) ;
2007-07-30 18:35:40 +00:00
if ( error ) {
toku_free ( result ) ;
return - 1 ;
}
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 ;
}
2007-08-30 15:15:14 +00:00
/* find the smallest power of 2 >= n */
2007-12-05 19:41:39 +00:00
static unsigned int pma_array_size ( PMA pma __attribute__ ( ( unused ) ) , int asksize ) {
2007-08-30 15:15:14 +00:00
int n = PMA_MIN_ARRAY_SIZE ;
2007-07-30 18:35:40 +00:00
while ( n < asksize )
n * = 2 ;
2007-08-30 15:15:14 +00:00
return n ;
}
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 ;
}
static int pma_resize_array ( TOKUTXN txn , FILENUM filenum , DISKOFF offset , PMA pma , int asksize , int startz ) {
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 ) ;
2007-12-04 10:02:59 +00:00
toku_log_resizepma ( txn , toku_txn_get_txnid ( txn ) , filenum , offset , oldN , n ) ;
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-11-30 15:17:37 +00:00
int toku_pma_cursor ( PMA pma , PMA_CURSOR * cursp , void * * sskey , void * * ssval ) {
2007-07-13 19:37:47 +00:00
PMA_CURSOR MALLOC ( curs ) ;
assert ( curs ! = 0 ) ;
2007-08-06 19:43:27 +00:00
if ( errno ! = 0 ) return errno ;
2007-07-13 19:37:47 +00:00
curs - > position = - 1 ; /* undefined */
curs - > pma = pma ;
2007-11-30 15:17:37 +00:00
curs - > sskey = sskey ;
curs - > ssval = ssval ;
2007-08-06 19:43:27 +00:00
list_push ( & pma - > cursors , & curs - > next ) ;
2007-07-13 19:37:47 +00:00
* cursp = curs ;
return 0 ;
}
2007-11-20 00:32:25 +00:00
int toku_pma_cursor_get_pma ( PMA_CURSOR c , PMA * pmap ) {
2007-08-20 15:50:46 +00:00
* pmap = c - > pma ;
return 0 ;
}
2007-11-20 00:32:25 +00:00
int toku_pma_cursor_set_position_last ( PMA_CURSOR c ) {
2007-07-13 19:37:47 +00:00
PMA pma = c - > pma ;
2007-09-11 14:53:21 +00:00
int result = 0 ;
int old_position = c - > position ;
2007-07-13 19:37:47 +00:00
c - > position = pma - > N - 1 ;
2007-09-04 13:51:12 +00:00
while ( ! kv_pair_valid ( c - > pma - > pairs [ c - > position ] ) ) {
2007-09-11 14:53:21 +00:00
if ( c - > position > 0 )
c - > position - - ;
else {
c - > position = - 1 ;
result = DB_NOTFOUND ;
break ;
}
2007-07-13 19:37:47 +00:00
}
2007-09-11 14:53:21 +00:00
if ( old_position ! = c - > position )
__pma_delete_resume ( pma , old_position ) ;
return result ;
2007-07-13 19:37:47 +00:00
}
2007-11-20 00:32:25 +00:00
int toku_pma_cursor_set_position_prev ( PMA_CURSOR c ) {
2007-08-06 19:43:27 +00:00
PMA pma = c - > pma ;
int old_position = c - > position ;
c - > position - - ;
while ( c - > position > = 0 ) {
2007-09-04 13:51:12 +00:00
if ( kv_pair_valid ( pma - > pairs [ c - > position ] ) ) {
2007-09-10 17:53:30 +00:00
__pma_delete_resume ( pma , old_position ) ;
2007-08-06 19:43:27 +00:00
return 0 ;
2007-09-04 13:51:12 +00:00
}
2007-08-06 19:43:27 +00:00
c - > position - - ;
}
c - > position = old_position ;
return DB_NOTFOUND ;
}
2007-11-20 00:32:25 +00:00
int toku_pma_cursor_set_position_first ( PMA_CURSOR c ) {
2007-07-13 19:37:47 +00:00
PMA pma = c - > pma ;
2007-09-11 14:53:21 +00:00
int result = 0 ;
int old_position = c - > position ;
2007-07-13 19:37:47 +00:00
c - > position = 0 ;
2007-09-04 13:51:12 +00:00
while ( ! kv_pair_valid ( c - > pma - > pairs [ c - > position ] ) ) {
2007-12-05 19:41:39 +00:00
if ( c - > position + 1 < ( signed ) pma - > N )
2007-09-11 14:53:21 +00:00
c - > position + + ;
else {
c - > position = - 1 ;
result = DB_NOTFOUND ;
break ;
}
2007-07-13 19:37:47 +00:00
}
2007-09-11 14:53:21 +00:00
if ( old_position ! = c - > position )
__pma_delete_resume ( pma , old_position ) ;
return result ;
2007-07-13 19:37:47 +00:00
}
2007-11-20 00:32:25 +00:00
int toku_pma_cursor_set_position_next ( PMA_CURSOR c ) {
2007-07-20 12:41:23 +00:00
PMA pma = c - > pma ;
int old_position = c - > position ;
c - > position + + ;
2007-12-05 19:41:39 +00:00
while ( c - > position < ( signed ) pma - > N ) {
2007-09-04 13:51:12 +00:00
if ( kv_pair_valid ( c - > pma - > pairs [ c - > position ] ) ) {
2007-09-10 17:53:30 +00:00
__pma_delete_resume ( pma , old_position ) ;
2007-09-04 13:51:12 +00:00
return 0 ;
}
c - > position + + ;
2007-07-20 12:41:23 +00:00
}
c - > position = old_position ;
return DB_NOTFOUND ;
}
2007-12-06 00:32:44 +00:00
int toku_pma_cursor_get_current ( PMA_CURSOR c , DBT * key , DBT * val , int even_deleted ) {
2007-09-04 13:51:12 +00:00
if ( c - > position = = - 1 )
return DB_NOTFOUND ;
2007-07-13 19:37:47 +00:00
PMA pma = c - > pma ;
2007-08-03 17:21:20 +00:00
struct kv_pair * pair = pma - > pairs [ c - > position ] ;
2007-12-06 00:32:44 +00:00
if ( ! kv_pair_inuse ( pair ) | | ( kv_pair_deleted ( pair ) & & ! even_deleted ) )
2007-12-07 20:32:59 +00:00
return DB_KEYEMPTY ;
2007-12-06 00:32:44 +00:00
pair = kv_pair_ptr ( pair ) ;
2008-01-07 22:28:36 +00:00
if ( key ) {
int r = toku_dbt_set_value ( key , kv_pair_key ( pair ) , kv_pair_keylen ( pair ) , c - > sskey ) ;
if ( r ! = 0 ) return r ;
}
if ( val ) {
int r = toku_dbt_set_value ( val , kv_pair_val ( pair ) , kv_pair_vallen ( pair ) , c - > ssval ) ;
if ( r ! = 0 ) return r ;
}
2007-07-13 19:37:47 +00:00
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 ) {
int cmp = pma_compare_dbt_kv ( pma , k , v , kv_pair_ptr ( pma - > pairs [ here ] ) ) ;
if ( cmp = = 0 )
* found = 1 ;
}
return here ;
}
2008-01-10 20:07:42 +00:00
#if 0 /* not used yet */
2007-12-17 17:09:54 +00:00
/* find the previous matching key in the pma starting from index here */
static int pma_prev_key ( PMA pma , DBT * k , DBT * v , int here , int n , int * found ) {
assert ( here < n ) ;
* found = 0 ;
while ( 0 < = here & & ! kv_pair_inuse ( pma - > pairs [ here ] ) )
here - = 1 ;
if ( 0 < = here ) {
int cmp = pma_compare_dbt_kv ( pma , k , v , kv_pair_ptr ( pma - > pairs [ here ] ) ) ;
if ( cmp = = 0 )
* found = 1 ;
}
return here ;
}
2008-01-10 20:07:42 +00:00
# endif
2007-12-17 17:09:54 +00:00
2007-11-26 21:51:36 +00:00
int toku_pma_cursor_set_both ( PMA_CURSOR c , DBT * key , DBT * val ) {
2007-09-12 20:30:36 +00:00
PMA pma = c - > pma ;
2007-12-14 20:51:27 +00:00
unsigned int here ; int found ;
2007-12-17 01:03:35 +00:00
here = pma_left_search ( pma , key , val , 0 , pma - > N , & found ) ;
2007-12-05 19:41:39 +00:00
assert ( here < = toku_pma_index_limit ( pma ) ) ;
2007-09-12 20:30:36 +00:00
int r = DB_NOTFOUND ;
2007-12-17 17:09:54 +00:00
/* skip any deleted pairs that match */
while ( found & & ! kv_pair_valid ( pma - > pairs [ here ] ) )
here = pma_next_key ( pma , key , val , here + 1 , pma - > N , & found ) ;
if ( found ) {
2007-12-17 01:03:35 +00:00
__pma_delete_resume ( c - > pma , c - > position ) ;
c - > position = here ;
r = 0 ;
2007-09-12 20:30:36 +00:00
}
return r ;
2007-09-10 17:53:30 +00:00
}
2007-12-17 01:03:35 +00:00
int toku_pma_cursor_set_range_both ( PMA_CURSOR c , DBT * key , DBT * val ) {
2007-09-10 17:53:30 +00:00
PMA pma = c - > pma ;
2007-12-17 01:03:35 +00:00
unsigned int here ; int found ;
here = pma_left_search ( pma , key , val , 0 , pma - > N , & found ) ;
2007-12-05 19:41:39 +00:00
assert ( here < = toku_pma_index_limit ( pma ) ) ;
2007-09-10 17:53:30 +00:00
/* find the first valid pair where key[here] >= key */
2007-09-12 20:30:36 +00:00
int r = DB_NOTFOUND ;
2007-09-10 17:53:30 +00:00
while ( here < pma - > N ) {
2007-12-17 01:03:35 +00:00
if ( kv_pair_valid ( pma - > pairs [ here ] ) ) {
2007-09-10 17:53:30 +00:00
__pma_delete_resume ( c - > pma , c - > position ) ;
c - > position = here ;
2007-09-12 20:30:36 +00:00
r = 0 ;
break ;
2007-09-10 17:53:30 +00:00
}
here + = 1 ;
}
2007-09-12 20:30:36 +00:00
return r ;
2007-09-10 17:53:30 +00:00
}
2007-07-13 19:37:47 +00:00
2008-01-10 20:07:42 +00:00
int toku_pma_cursor_delete_under ( PMA_CURSOR c , int * kvsize , u_int32_t rand4sem , u_int32_t * fingerprint ) {
2007-09-11 18:32:10 +00:00
int r = DB_NOTFOUND ;
if ( c - > position > = 0 ) {
PMA pma = c - > pma ;
2007-12-05 19:41:39 +00:00
assert ( ( unsigned ) c - > position < pma - > N ) ;
2007-09-11 18:32:10 +00:00
struct kv_pair * kv = pma - > pairs [ c - > position ] ;
if ( kv_pair_valid ( kv ) ) {
2007-09-12 20:30:36 +00:00
if ( kvsize )
* kvsize = kv_pair_keylen ( kv ) + kv_pair_vallen ( kv ) ;
2007-12-07 22:27:52 +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 ) ) ;
2007-09-11 18:32:10 +00:00
pma - > pairs [ c - > position ] = kv_pair_set_deleted ( kv ) ;
r = 0 ;
}
}
return r ;
}
2007-11-20 00:32:25 +00:00
int toku_pma_cursor_free ( PMA_CURSOR * cursp ) {
2007-07-13 19:37:47 +00:00
PMA_CURSOR curs = * cursp ;
2007-09-04 13:51:12 +00:00
PMA pma = curs - > pma ;
2007-08-06 19:43:27 +00:00
list_remove ( & curs - > next ) ;
2007-09-04 13:51:12 +00:00
if ( curs - > position > = 0 & & kv_pair_deleted ( pma - > pairs [ curs - > position ] ) & &
__pma_count_cursor_refs ( pma , curs - > position ) = = 0 ) {
__pma_delete_finish ( pma , curs - > position ) ;
}
2007-11-30 15:17:37 +00:00
// It's not our job to free the sskey and ssval blocks.
2007-07-20 18:00:14 +00:00
toku_free ( curs ) ;
2007-07-13 19:37:47 +00:00
* cursp = 0 ;
return 0 ;
}
/* 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.) */
2007-12-05 19:41:39 +00:00
int toku_pmainternal_make_space_at ( TOKUTXN txn , FILENUM filenum , DISKOFF offset , PMA pma , int idx , unsigned int * new_index ) {
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);
2007-12-04 10:02:59 +00:00
pma_resize_array ( txn , filenum , offset , pma , size , hi ) ;
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 ;
int r = toku_pmainternal_smooth_region ( txn , filenum , offset , pma - > pairs + lo , hi - lo , idx - lo , lo , pma , & sub_new_index ) ;
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
unsigned int here ;
int found ;
2008-01-07 19:06:05 +00:00
if ( pma - > dup_mode & TOKU_DB_DUPSORT ) {
2007-12-17 01:03:35 +00:00
here = pma_left_search ( pma , k , 0 , 0 , pma - > N , & found ) ;
2007-11-14 17:58:38 +00:00
} else
2007-11-26 21:51:36 +00:00
here = toku_pmainternal_find ( pma , k ) ;
2007-12-05 19:41:39 +00:00
assert ( here < = toku_pma_index_limit ( pma ) ) ;
2007-11-20 00:32:25 +00:00
if ( here = = toku_pma_index_limit ( pma ) ) return DB_NOTFOUND ;
2007-07-23 20:10:16 +00:00
DBT k2 ;
2007-08-03 17:21:20 +00:00
struct kv_pair * pair ;
2007-11-14 17:58:38 +00:00
pair = pma - > pairs [ here ] ;
2007-11-29 15:17:46 +00:00
if ( kv_pair_valid ( pair ) & & pma - > compare_fun ( pma - > db , k , toku_fill_dbt ( & k2 , pair - > key , pair - > keylen ) ) = = 0 ) {
return toku_dbt_set_value ( v , pair - > key + pair - > keylen , pair - > vallen , & pma - > sval ) ;
2007-07-13 19:37:47 +00:00
} else {
2007-08-03 17:21:20 +00:00
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 ( ! list_empty ( & pma - > cursors ) )
return - 1 ;
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. */
2007-12-04 10:02:59 +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 ) {
2007-12-05 19:41:39 +00:00
int found ;
unsigned int idx ;
2007-11-14 17:58:38 +00:00
2007-11-19 20:22:56 +00:00
if ( pma - > dup_mode & TOKU_DB_DUPSORT ) {
2007-12-17 01:03:35 +00:00
idx = pma_right_search ( pma , k , v , 0 , pma - > N , & found ) ;
2007-12-14 13:18:47 +00:00
if ( found ) return BRT_ALREADY_THERE ;
2007-11-14 17:58:38 +00:00
} else {
2007-11-26 21:51:36 +00:00
idx = toku_pmainternal_find ( pma , k ) ;
2007-11-20 00:32:25 +00:00
if ( idx < toku_pma_index_limit ( pma ) & & pma - > pairs [ idx ] ) {
2007-11-14 17:58:38 +00:00
DBT k2 ;
struct kv_pair * kv = kv_pair_ptr ( pma - > pairs [ idx ] ) ;
2007-11-29 15:17:46 +00:00
if ( 0 = = pma - > compare_fun ( pma - > db , k , toku_fill_dbt ( & k2 , kv - > key , kv - > keylen ) ) ) {
2007-11-14 17:58:38 +00:00
if ( kv_pair_deleted ( pma - > pairs [ idx ] ) ) {
pma_mfree_kv_pair ( pma , pma - > pairs [ idx ] ) ;
pma - > pairs [ idx ] = pma_malloc_kv_pair ( pma , k - > data , k - > size , v - > data , v - > size ) ;
assert ( pma - > pairs [ idx ] ) ;
* fingerprint + = rand4fingerprint * toku_calccrc32_kvpair ( k - > data , k - > size , v - > data , v - > size ) ;
2007-11-29 18:14:40 +00:00
int r = toku_logger_log_phys_add_or_delete_in_leaf ( pma - > db , txn , diskoff , 0 , pma - > pairs [ idx ] ) ;
2007-11-14 17:58:38 +00:00
return r ;
} else
return BRT_ALREADY_THERE ; /* It is already here. Return an error. */
}
}
2007-07-13 19:37:47 +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 ;
2007-12-04 10:02:59 +00:00
int r = toku_pmainternal_make_space_at ( txn , filenum , diskoff , pma , idx , & newidx ) ; /* returns the new idx. */
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 ) } ;
return toku_log_insertinleaf ( txn , toku_txn_get_txnid ( txn ) , pma - > filenum , diskoff , idx , key , data ) ;
}
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 ;
unsigned int lefthere ;
2008-01-02 20:33:51 +00:00
lefthere = pma_left_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 ] ;
if ( kv_pair_valid ( kv ) ) {
/* mark the pair as deleted */
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 ) ) ;
pma - > pairs [ righthere ] = kv_pair_set_deleted ( kv ) ;
if ( __pma_count_cursor_refs ( pma , righthere ) = = 0 ) {
pma_mfree_kv_pair ( pma , kv ) ;
pma - > pairs [ righthere ] = 0 ;
pma - > n_pairs_present - - ;
}
}
/* 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 */
__pma_delete_at ( pma , ( lefthere + righthere ) / 2 ) ;
}
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 ;
here = pma_left_search ( pma , k , v , 0 , pma - > N , & found ) ;
if ( ! found )
return DB_NOTFOUND ;
struct kv_pair * kv = pma - > pairs [ here ] ;
if ( ! kv_pair_valid ( 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-02 20:33:51 +00:00
pma - > pairs [ here ] = kv_pair_set_deleted ( kv ) ;
if ( __pma_count_cursor_refs ( pma , here ) = = 0 )
__pma_delete_finish ( 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
}
2007-09-10 17:53:30 +00:00
void __pma_delete_resume ( PMA pma , int here ) {
if ( here > = 0 & & kv_pair_deleted ( pma - > pairs [ here ] ) & & __pma_count_cursor_refs ( pma , here ) = = 0 )
__pma_delete_finish ( pma , here ) ;
}
2007-11-14 17:58:38 +00:00
static void __pma_delete_finish ( PMA pma , int here ) {
2007-09-04 13:51:12 +00:00
struct kv_pair * kv = pma - > pairs [ here ] ;
if ( ! kv_pair_inuse ( kv ) )
return ;
2007-10-10 19:33:31 +00:00
pma_mfree_kv_pair ( pma , kv ) ;
2007-09-04 13:51:12 +00:00
pma - > pairs [ here ] = 0 ;
pma - > n_pairs_present - - ;
__pma_delete_at ( pma , here ) ;
}
2007-11-14 17:58:38 +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 ) ;
__pma_update_my_cursors ( pma , newpairs , count ) ;
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 ) ;
/* update the cursors */
__pma_update_my_cursors ( pma , newpairs , count ) ;
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 ,
2007-11-26 21:51:36 +00:00
u_int32_t rand4fingerprint , u_int32_t * fingerprint ) {
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-14 13:18:47 +00:00
struct kv_pair * kv ;
2007-12-05 19:41:39 +00:00
unsigned int idx ;
int found ;
2007-11-19 20:22:56 +00:00
if ( pma - > dup_mode & TOKU_DB_DUPSORT ) {
2007-12-17 01:03:35 +00:00
idx = pma_right_search ( pma , k , v , 0 , pma - > N , & found ) ;
2007-12-14 13:18:47 +00:00
if ( found ) {
2007-12-16 20:57:35 +00:00
kv = kv_pair_ptr ( pma - > pairs [ idx ] ) ; goto replaceit ;
2007-12-14 13:18:47 +00:00
}
2007-11-15 14:44:05 +00:00
} else {
2007-11-26 21:51:36 +00:00
idx = toku_pmainternal_find ( pma , k ) ;
2007-11-20 00:32:25 +00:00
if ( idx < toku_pma_index_limit ( pma ) & & ( kv = pma - > pairs [ idx ] ) ) {
2007-11-15 14:44:05 +00:00
DBT k2 ;
// printf("%s:%d\n", __FILE__, __LINE__);
kv = kv_pair_ptr ( kv ) ;
2007-11-29 15:17:46 +00:00
if ( 0 = = pma - > compare_fun ( pma - > db , k , toku_fill_dbt ( & k2 , kv - > key , kv - > keylen ) ) ) {
2007-12-14 13:18:47 +00:00
replaceit :
2007-12-16 20:57:35 +00:00
if ( kv_pair_deleted ( pma - > pairs [ idx ] ) ) {
* replaced_v_size = - 1 ;
pma - > pairs [ idx ] = kv ;
} else {
2007-11-15 14:44:05 +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 ) ) ;
2007-11-29 18:14:40 +00:00
r = toku_logger_log_phys_add_or_delete_in_leaf ( pma - > db , txn , diskoff , 0 , kv ) ;
2007-11-15 14:44:05 +00:00
if ( r ! = 0 ) return r ;
}
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-11-29 18:14:40 +00:00
r = toku_logger_log_phys_add_or_delete_in_leaf ( pma - > db , txn , diskoff , 0 , pma - > pairs [ idx ] ) ;
2007-11-15 14:44:05 +00:00
* fingerprint + = rand4fingerprint * toku_calccrc32_kvpair ( k - > data , k - > size , v - > data , v - > size ) ;
return r ;
2007-10-10 19:33:31 +00:00
}
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 ;
2007-12-04 10:02:59 +00:00
r = toku_pmainternal_make_space_at ( txn , filenum , diskoff , pma , idx , & newidx ) ; /* returns the new idx. */
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);
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 ) ;
}
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-09-04 13:51:12 +00:00
int __pma_count_cursor_refs ( PMA pma , int here ) {
int refs = 0 ;
struct list * list ;
struct pma_cursor * cursor ;
list = list_head ( & pma - > cursors ) ;
while ( list ! = & pma - > cursors ) {
cursor = list_struct ( list , struct pma_cursor , next ) ;
if ( cursor - > position = = here )
refs + = 1 ;
list = list - > next ;
}
return refs ;
}
2007-11-14 17:58:38 +00:00
static void __pma_update_cursors_position ( PMA pma , struct list * cursor_set , int oldposition , int newposition ) {
2007-08-06 19:43:27 +00:00
struct list * list , * nextlist ;
struct pma_cursor * cursor ;
list = list_head ( cursor_set ) ;
while ( list ! = cursor_set ) {
nextlist = list - > next ; /* may be removed later */
cursor = list_struct ( list , struct pma_cursor , next ) ;
if ( cursor - > position = = oldposition ) {
2007-08-30 15:15:14 +00:00
if ( 0 ) printf ( " cursor %p %d -> %d \n " , cursor , oldposition , newposition ) ;
2007-08-06 19:43:27 +00:00
cursor - > position = newposition ;
cursor - > pma = pma ;
list_remove ( list ) ;
list_push ( & pma - > cursors , list ) ;
}
list = nextlist ;
}
}
2007-08-30 15:15:14 +00:00
void __pma_update_cursors ( PMA pma , struct list * cursor_set , struct kv_pair_tag * tpairs , int n ) {
2007-08-06 19:43:27 +00:00
/* short cut */
if ( list_empty ( cursor_set ) )
return ;
/* update all cursors to their new positions */
2007-08-30 15:15:14 +00:00
int i ;
2007-08-06 19:43:27 +00:00
for ( i = 0 ; i < n ; i + + ) {
2007-08-30 15:15:14 +00:00
if ( tpairs [ i ] . pair & & tpairs [ i ] . oldtag > = 0 )
__pma_update_cursors_position ( pma , cursor_set , tpairs [ i ] . oldtag , tpairs [ i ] . newtag ) ;
2007-08-06 19:43:27 +00:00
}
}
2007-11-14 17:58:38 +00:00
static void __pma_update_my_cursors ( PMA pma , struct kv_pair_tag * tpairs , int n ) {
2007-08-30 15:15:14 +00:00
if ( list_empty ( & pma - > cursors ) )
return ;
struct list cursors ;
list_move ( & cursors , & pma - > cursors ) ;
__pma_update_cursors ( pma , & cursors , tpairs , n ) ;
while ( ! list_empty ( & cursors ) ) {
struct list * list = list_head ( & cursors ) ;
list_remove ( list ) ;
list_push ( & pma - > cursors , list ) ;
}
}
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 ,
PMA origpma , unsigned int * origpma_size , DBT * splitk ,
DISKOFF leftdiskoff , PMA leftpma , unsigned int * leftpma_size , u_int32_t leftrand4fp , u_int32_t * leftfingerprint ,
DISKOFF rightdiskoff , PMA rightpma , unsigned int * rightpma_size , u_int32_t rightrand4fp , u_int32_t * rightfingerprint ) {
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 sumlen ;
int runlen ;
int i ;
2007-08-09 18:54:58 +00:00
int n ;
2007-07-30 16:32:46 +00:00
int spliti ;
2007-08-06 19:43:27 +00:00
struct list cursors ;
2007-07-30 16:32:46 +00:00
/* extract the pairs */
2007-11-20 00:32:25 +00:00
npairs = toku_pma_n_entries ( origpma ) ;
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-11-20 00:32:25 +00:00
assert ( toku_pma_n_entries ( leftpma ) = = 0 ) ;
assert ( toku_pma_n_entries ( rightpma ) = = 0 ) ;
2007-08-09 18:54:58 +00:00
/* TODO move pairs to the stack */
2007-12-05 19:41:39 +00:00
pairs = pma_extract_pairs ( origpma , npairs , 0 , origpma - > N ) ;
2007-08-03 17:21:20 +00:00
assert ( pairs ) ;
2007-08-09 18:54:58 +00:00
origpma - > n_pairs_present = 0 ;
2007-07-30 16:32:46 +00:00
2007-08-09 18:54:58 +00:00
/* debug check the kv length sum */
2007-07-30 16:32:46 +00:00
sumlen = 0 ;
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
if ( origpma_size )
assert ( * ( int * ) origpma_size = = sumlen ) ;
2007-07-30 16:32:46 +00:00
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 ;
2007-08-09 18:54:58 +00:00
if ( leftpma_size )
* leftpma_size = runlen ;
if ( rightpma_size )
* rightpma_size = sumlen - runlen ;
2007-07-30 16:32:46 +00:00
2007-08-09 18:54:58 +00:00
/* set the cursor set to be all of the cursors from the original pma */
2007-08-06 19:43:27 +00:00
list_init ( & cursors ) ;
2007-08-09 18:54:58 +00:00
if ( ! list_empty ( & origpma - > cursors ) )
list_move ( & cursors , & origpma - > cursors ) ;
2007-08-06 19:43:27 +00:00
2007-11-14 17:58:38 +00:00
{
u_int32_t sum = 0 ;
for ( i = 0 ; i < spliti ; 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 ) ) ;
}
* leftfingerprint + = leftrand4fp * sum ;
}
{
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 ) ) ;
}
* rightfingerprint + = rightrand4fp * sum ;
}
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 ;
2007-11-19 20:22:56 +00:00
if ( origpma - > 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 first half of pairs into the left pma */
n = spliti ;
2007-12-04 10:02:59 +00:00
error = pma_resize_array ( txn , filenum , leftdiskoff , leftpma , n + n / 4 , 0 ) ;
2007-07-30 18:35:40 +00:00
assert ( error = = 0 ) ;
2007-11-20 00:32:25 +00:00
distribute_data ( leftpma - > pairs , toku_pma_index_limit ( leftpma ) , & pairs [ 0 ] , n , leftpma ) ;
2007-10-12 23:50:05 +00:00
# if PMA_USE_MEMPOOL
2007-10-10 19:33:31 +00:00
__pma_relocate_kvpairs ( leftpma ) ;
2007-10-12 23:50:05 +00:00
# endif
2007-08-30 15:15:14 +00:00
__pma_update_cursors ( leftpma , & cursors , & pairs [ 0 ] , spliti ) ;
2007-08-09 18:54:58 +00:00
leftpma - > n_pairs_present = spliti ;
2007-07-30 16:32:46 +00:00
2007-08-09 18:54:58 +00:00
/* put the second half of pairs into the right pma */
n = npairs - spliti ;
2007-12-04 10:02:59 +00:00
error = pma_resize_array ( txn , filenum , rightdiskoff , rightpma , n + n / 4 , 0 ) ;
2007-07-30 18:35:40 +00:00
assert ( error = = 0 ) ;
2007-11-20 00:32:25 +00:00
distribute_data ( rightpma - > pairs , toku_pma_index_limit ( rightpma ) , & pairs [ spliti ] , n , rightpma ) ;
2007-10-12 23:50:05 +00:00
# if PMA_USE_MEMPOOL
2007-10-10 19:33:31 +00:00
__pma_relocate_kvpairs ( rightpma ) ;
2007-10-12 23:50:05 +00:00
# endif
2007-08-30 15:15:14 +00:00
__pma_update_cursors ( rightpma , & cursors , & pairs [ spliti ] , n ) ;
2007-08-09 18:54:58 +00:00
rightpma - > n_pairs_present = n ;
2007-07-30 16:32:46 +00:00
toku_free ( pairs ) ;
2007-08-09 18:54:58 +00:00
/* bind the remaining cursors to the left pma*/
2007-08-06 19:43:27 +00:00
while ( ! list_empty ( & cursors ) ) {
struct list * list = list_head ( & cursors ) ;
list_remove ( list ) ;
2007-08-09 18:54:58 +00:00
list_push ( & leftpma - > cursors , list ) ;
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
}
2007-12-04 10:02:59 +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 ) {
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 ;
if ( ! list_empty ( & pma - > cursors ) )
return - 1 ;
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
}
}
2007-12-04 10:02:59 +00:00
error = pma_resize_array ( txn , filenum , diskoff , pma , n_newpairs + n_newpairs / 4 , 0 ) ;
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 ) ) {
kv = kv_pair_ptr ( 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 ) ) {
nextkv = kv_pair_ptr ( 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 ) ) {
kv = kv_pair_ptr ( 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 ;
}
2007-12-04 17:59:03 +00:00
// assume no cursors
int toku_pma_move_indices ( PMA pma , INTPAIRARRAY fromto ) {
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 ) {
assert ( pma - > pairs [ b ] = = 0 ) ;
pma - > pairs [ b ] = pma - > pairs [ a ] ;
pma - > pairs [ a ] = 0 ;
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 ) {
assert ( pma - > pairs [ b ] = = 0 ) ;
pma - > pairs [ b ] = pma - > pairs [ a ] ;
pma - > pairs [ a ] = 0 ;
}
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 ;
}
}
int toku_pma_move_indices_back ( PMA pma , INTPAIRARRAY fromto ) {
int r ;
reverse_fromto ( fromto ) ;
r = toku_pma_move_indices ( pma , fromto ) ;
reverse_fromto ( fromto ) ;
return r ;
}