meta,
C++
224 Methoden:
/* private: */ BOOL Btree :: NoUpd
/* private: */ BOOL Btree :: locate_First
/* private: */ BOOL Btree :: locate_Last
/* private: */ BOOL Btree :: locate_Next
/* private: */ BOOL Btree :: locate_Prev
/* private: */ BOOL Btree :: locate_ipos
/* private: */ BOOL Btree :: locate_pos
/* private: */ BOOL Btree :: reduce_spare
/* private: */ BOOL Btree :: str_ok
/* private: */ Btree_page * Btree :: into_root
/* private: */ Btree_page * Btree :: new_page
/* private: */ Surr Btree :: located_key_and_data
/* private: */ char * Btree :: spare_At
/* private: */ char * Btree :: to_s260
/* private: */ int Btree :: relate
/* private: */ uchar Btree :: our_uspar
/* private: */ uint Btree :: become_deep_trans
/* private: */ uint Btree :: become_trans
/* private: */ void Btree :: check_page
/* private: */ void Btree :: check_path
/* private: */ void Btree :: data_to_file
/* private: */ void Btree :: ensure_cache
/* private: */ void Btree :: get_page
/* private: */ void Btree :: into_father
/* private: */ void Btree :: new_cache
/* private: */ void Btree :: reorganize
/* private: */ void Btree :: split_data
/* private: */ void Btree :: split_index
/* private: */ void Btree :: split_root
/* private: */ void Btree :: to_Disk
/* private: */ void Btree :: to_extra
/* private: */ void Btree :: trace_in_cache
/* private: */ void Btree :: trace_pos_m
/* private: */ void Btree :: zeige
|
/* public: */ BOOL Btree :: cache_ok
/* public: */ Btree * Btree :: invers
/* public: */ Btree :: Btree
/* public: */ Btree :: Btree
/* public: */ Btree :: ~Btree
/* public: */ Surr Btree :: Get
/* public: */ Surr Btree :: Get
/* public: */ Surr Btree :: Get
/* public: */ Surr Btree :: GetFirst
/* public: */ Surr Btree :: GetLast
/* public: */ Surr Btree :: GetNext
/* public: */ Surr Btree :: GetNext
/* public: */ Surr Btree :: GetNext
/* public: */ Surr Btree :: GetPath
/* public: */ Surr Btree :: GetPath
/* public: */ Surr Btree :: GetPrev
/* public: */ Surr Btree :: GetPrev
/* public: */ Surr Btree :: GetPrev
/* public: */ Surr Btree :: Getmax_At
/* public: */ Surr Btree :: Getmax_LE
/* public: */ Surr Btree :: Getmax_LE
/* public: */ Surr Btree :: Getmax_LS
/* public: */ Surr Btree :: Getmax_LS
/* public: */ Surr Btree :: Getmax_prefix
/* public: */ Surr Btree :: Getmin_At
/* public: */ Surr Btree :: Getmin_GE
/* public: */ Surr Btree :: Getmin_GE
/* public: */ Surr Btree :: Getmin_GR
/* public: */ Surr Btree :: Getmin_GR
/* public: */ Surr Btree :: Next
/* public: */ Surr Btree :: Prev
/* public: */ Surr Btree :: Rem
/* public: */ Surr Btree :: Rem
/* public: */ Surr Btree :: Rem
/* public: */ Surr Btree :: Rem
/* public: */ Surr Btree :: RemPath
/* public: */ Surr Btree :: RemPath
/* public: */ Surr Btree :: contains
/* public: */ Surr Btree :: contains
/* public: */ Surr Btree :: contains
/* public: */ Surr Btree :: containsPath
/* public: */ Surr Btree :: containsPath
/* public: */ Surr Btree :: ensure
/* public: */ Surr Btree :: postfix
/* public: */ Surr Btree :: retNr
/* public: */ char Btree :: Ins
/* public: */ char Btree :: Ins
/* public: */ char Btree :: InsAtSurr
/* public: */ char Btree :: InsPath
/* public: */ char Btree :: InsPath
/* public: */ char Btree :: StrIns
/* public: */ char Btree :: StrIns
/* public: */ char Btree :: StrIns
/* public: */ char Btree :: StrIns
/* public: */ char Btree :: StrIns
/* public: */ char Btree :: StrIns
/* public: */ char Btree :: Update
/* public: */ char * Btree :: retAlias
/* public: */ int Btree :: Rem_GE_LE
/* public: */ int Btree :: number_of_elements
/* public: */ uint Btree :: become_deep_transitive
/* public: */ uint Btree :: become_transitive
/* public: */ uint Btree :: Ins
/* public: */ uint Btree :: anz_pages
/* public: */ void Btree :: become_end_to_end_transitive
/* public: */ void Btree :: check_Btree
/* public: */ void Btree :: commit
/* public: */ void Btree :: count
/* public: */ void Btree :: init
/* public: */ void Btree :: show
/* public: */ void Btree :: to_file
/* public: */ void Btree :: trace
/* public: */ void Btree :: traceAbs
/* public: */ void Btree :: traceAbs
/* public: */ void Btree :: traceAt
/* public: */ void Btree :: trace_data
/* public: */ void Btree :: trace_deepest
/* public: */ void Btree :: trace_index
#define static
#include btree.h : cpp
#include btree.c1 : cpp
#undef BB
#undef BBStr
#undef bb
#undef bbStr
#define BB
#define BBStr( x,y,z ) ;
#define bb
#define bbStr( x,y,z ) ;
#ifndef procNestOn
#undef BB
#undef BBStr
#undef bb
#undef bbStr
#undef LB_
#undef LE_
#undef LE_ret
#undef ret
#undef ret_
#undef __
#undef ___
#define BB if ( 1 < call_nr || errno )
#define bb if ( 1 < call_nr || errno )
#define BBStr( x,y,z ) { BB traceStr( x,y,z ); }
#define bbStr( x,y,z ) { bb traceStr( x,y,z ); }
#define __ { bb { printf( "\nLine %i", __LINE__ ); }}
#define ___
#define ret_ { __ return ; }
#define LE_ __ return ; }
#define LE_ret( x ) __ return( x ); }
#define ret( x ) { __ return( x ); }
#define LB_( x ) { bb printf( "\n-> %s", x ); safe_ut.showSysCalls = 1 ;
#endif
// #define __TESTING__
#undef BB
#undef bb
#undef __
#define BB if ( call_nr == 0 )
// #define bb
#define bb if ( 0 )
// #define bb if ( call_nr >= 4982850 )
// #define bb if ( call_nr >= 4982654 && abs(treeID) == 1 )
// #define bb if ( errTrace || ! noTrace )
// #define bb if ( call_nr >= 4983064 && abs(treeID) == 2 )
#define __
// #define __ { bb { printf( "\nLine %i", __LINE__ ); fflush(stdout); }}
#define check_pp { if ( pp ) check_page( *pp ); }
// # define get_page( i,n ) Get_page( i,n, __LINE__ )
#define Located_key_and_data(s) located_key_and_data( s,__LINE__ )
#define min_anz_data 3
// Each data node is large enough to contain
#define L_255 255
#define L_249 249
#define L_heap L_Btree_heap
// Btree_page.c[ eoheap ] == length of // common prefix extracted from all keys // in this page. Find it at position
#define L_page sizeof( Btree_page )
#define L_descr sizeof( Btree_descr )
#define L_data sizeof( Btree_data )
#define L_index sizeof( Btree_index )
/* public: */ Btree :: Btree(
/* -----------------------------------------------------------------------------
create Btree in memory
-----------------------------------------------------------------------------
*/ )
LB_("Btree.Btree")
fflush( stderr ); fflush( stdout );
BtreeName = checkPoint ;
LData = 0 ;
LDataNr = 0 ;
Bf = 0 ; cache[0] = 0 ; kurz = 0 ;
init( 0, 0 ); // Niemals Constructor in anderem Constructor aufrufen!
LE_
/* public: */ Btree :: Btree
/* -----------------------------------------------------------------------------
Create or open Btree file and cache page[ 0 ]
Deconstructor is to delete the tree on disk iff do_what < 0.
-----------------------------------------------------------------------------
*/ (
char * at // path to the new Btree Directory
// or 0 if do_what == 0
, int do_what // 0 = create tree in memory
// -1 or 1 = create or re-create
// -2 or 2 = create
// -3 or 3 = open for reading
// -4 or 4 = open for update
// -5 or 5 = create or open for update
)
LB_("Btree.Btree")
BtreeName = checkPoint ;
Bf = 0 ;
int i = -1 ; while ( ++i < L_Cp ) cache[i] = 0 ;
Volatile = ( do_what <= 0 ); init( at, abs( do_what ) );
accessNo = 0 ;
LE_
/* public: */ Btree :: ~Btree(
// -----------------------------------------------------------------------------
)
LB_("Btree.~Btree")
// trace( "END_Btree", stdout );
//
// if ( accessNo )
/* Test for GetFirst(), GetNext(), GetLast(), GetPrev()
// ----------------------------------------------------
{
char * x = Bfn ; while not_in_str( *x, "/\\" ) x++ ;
char merke = *x ; *x = 0 ;
path x1 ; sprintf( x1, "x1_%s", Bfn );
path x2 ; sprintf( x2, "x2_%s", Bfn );
path x3 ; sprintf( x3, "x3_%s", Bfn );
*x = merke ;
FILE * f = create( x1 ); store_256 st ; Surr s = GetFirst( st );
while( s ) { fprintf( f, "\n%s", st.k ); s = GetNext( st ); } close( f );
f = create( x2 ); s = GetLast( st );
while( s ) { fprintf( f, "\n%s", st.k ); s = GetPrev( st ); }
close( f );
if ( file_len( x2 ) != file_len( x1 ) )
{
trace( "BBB", stdout ); fErr
}
}
*/
//
int i = -1 ; cache[0] -> dirty = true ;
// while ( ++i < e_cache )
while ( ++i < L_Cp )
{
Btree_page * p = cache[i] ;
if ( Volatile || e_cache <= i ) p = 0 ;
if ( p && ! read_only && p->dirty && Bf )
{
putfw( Bf, 0, p->nr, L_page, p ); // commit is default !!
}
delete( cache[i] );
}
// if ( 0 < Bf ) { close( Bf ); Bf = 0 ; } // warum fehler
if ( Volatile )
{
if ( *Bfn && is_file( Bfn ) ) Unlink( Bfn );
}
if ( LData || LDataNr )
{
_1( LDataNr )
if ( ! LDataNr ) fErr
if ( ! LData ) fErr
if ( ! Volatile )
{
m_errMess "System: LData is not persistent, but we use it !!!" m_
ret_error
}
Delete( LData )
}
LE_
/* public: */ void Btree :: init
/* -----------------------------------------------------------------------------
open Btree file and cache page[ 0 ]
-----------------------------------------------------------------------------
*/ (
char * at // path to the new Btree Directory
// or 0 if do_what == 0
, int do_what // 0 = create tree in memory
// 1 = create or re-create
// 2 = create
// 3 = open for reading
// 4 = open for update
// 5 = create or open for update
)
LB_("Btree.init")
if ( L_Cp < 3 * L_Bp ) fErr2( L_Cp, L_Bp )
strPairs = 0 ; // Nur der Testtreiber zu class StrPairs macht das zu 1
anzfalsch = 0 ;
stopTrace = 0 ;
LocNr = 0 ;
root_e = 0 ;
treeID = 0 ;
ourtree = 0 ;
traceIndex = 0 ;
traceAb = 1 ;
noTrace = 1 ;
max_k_L = 252 ;
int i = -1 ; while ( ++i < L_Cp ) cache[i] = 0 ;
i = -1 ; while ( ++i < L_Bp ) page[i] = 0 ;
if ( do_what < 0 || 5 < do_what ) fErr1( do_what )
maxDepth = kuerzer = 0 ; pp = 0 ; silent = 1 ;
eoheap = L_heap - 1 ;
if ( Bf ) { close( Bf ); Bf = 0 ; }
do_what = abs( do_what ); // damit cache auf Platte kann
if ( cache[0] )
{
int i = -1 ; while ( ++i < e_cache ) Delete( cache[i] );
}
deepest = 0 ;
read_only = ( do_what == 3 );
do_at = alles = errno_if_get_fails = 0 ;
e_cache = 0 ; if ( L_Cp < 3 * L_Bp ) fErr // too few Cache Pages
# ifdef __TESTING__
if ( sizeof( Btree_page ) != L_page ||
sizeof( Btree_data ) != L_data ||
sizeof( Btree_index ) != L_index ||
sizeof( Btree_descr ) != L_descr ||
sizeof( uint2 ) != 2 ||
sizeof( Surr ) != 4 || ( L_page % 256 )
)
{
printf( "%4i = L_page \n", L_page );
printf( "%4i = L_data \n", L_data );
printf( "%4i = L_index \n", L_index );
printf( "%4i = L_descr \n", L_descr );
printf( "%4i = size Btree_page \n", sizeof( Btree_page ));
printf( "%4i = size Btree_data \n", sizeof( Btree_data ));
printf( "%4i = size Btree_index \n", sizeof( Btree_index ));
printf( "%4i = size Btree_descr \n", sizeof( Btree_descr ));
printf( "%4i = size uint2 \n", sizeof( uint2 ));
printf( "%4i = size Surr \n", sizeof( Surr ));
fErr
}
# endif
pos_descr = ( L_heap - 2 ) - L_descr ;
if ( ! do_what )
then {
at = "c:/tmp" ;
//
// Muss absoluter Pfad sein, da sonst rm -rf ... fehlschlagen kann.
if ( *at == 'c' && tmp_DRIVE ) *at = tmp_DRIVE ;
dir_exist( at );
s_( Bfn, "%s/%u_%u", at, tmpName( at ), _getpid() );
dos_me( Bfn );
}
if ( do_what == 2 )
then {
if path_exists( Bfn ) S_ "AppError: %s exists\n", Bfn _fErr
do_what = 1 ;
}
if ( do_what == 5 )
then {
if ( path_exists( Bfn ) )
then {
if ( L_page <= file_len( Bfn ) ) then do_what = 4 ;
else do_what = 1 ;
}
else do_what = 1 ;
}
#undef open
if ( do_what == 4 )
then {
Bf = open( Bfn, 'u', 'B' );
}
esif ( do_what == 3 )
{
Bf = open( Bfn, 'r', 'B' );
}
#define open safe_ut.ok_open
else Bf = 0 ;
if ( Bf == 0 )
then {
if ( do_what )
then {
if ( do_what == 1 ) { unlink( Bfn ); ok }
esif ( do_what != 2 ) { fErr }
if ( ! path_exists( at ) ) S_ "mkdir %s", at _Do
Bf = open( Bfn, 'c', 'B' ); // cache on disk
// Bf = _open( Bfn, O_BINARY | O_RDWR | O_CREAT
// , S_IREAD | S_IWRITE ); EE
printf( "\nBf = %i = %s", Bf, Bfn );
}
Btree_page * p = page[1] = cache[1] = new Btree_page ;
p -> nr = 1 ;
p -> dirty = 1 ;
p -> e = 1 ;
p -> h = L_heap - 5 ;
p -> t = 0 ; // this page is a data page
(( Btree_data * ) p ) -> ak = L_heap - 3 ;
(( Btree_data * ) p ) -> ad = L_heap - 5 ;
(( Btree_data * ) p ) -> surr = 0 ;
p -> c[ eoheap ] =
p -> c[ L_heap - 2 ] =
p -> c[ L_heap - 3 ] =
p -> c[ L_heap - 4 ] =
p -> c[ L_heap - 5 ] = 0 ;
p = page[0] = cache[0] = new Btree_page ;
descr = tA( Btree_descr, p, pos_descr );
if ( tA( char, p, 1 ) - ( char * )p != 1 ) fErr
descr -> last = 1 ; // root index and 1st data page are present
descr -> next = 1 ; // which means: the page following page 1
descr -> surr = 0 ;
descr -> anz = 0 ;
descr -> maxkeylen = 0 ;
descr -> l_index = sizeof( Btree_index ) ;
descr -> l_data = sizeof( Btree_data ) ;
descr -> l_page = sizeof( Btree_page ) ;
descr -> h_descr = pos_descr ;
p -> nr = 0 ;
p -> dirty = 1 ;
p -> e = 1 ;
p -> h = pos_descr - 1 ;
p -> t = 1 ; // this page is index
(( Btree_index * ) p ) -> ak = p -> h ;
(( Btree_index * ) p ) -> son = 1 ;
p -> c[ eoheap ] = 0 ;
p -> c[ p->h ] = 0 ;
e_cache = 2 ; // trace_page( *p ); __ fErr
}
else {
cache[0] = page[ 0 ] = new Btree_page ;
_1( file_len(Bf) )
getfw( Bf, 0, 0, L_page, page[ 0 ] );
e_cache = 1 ;
}
int j = e_cache ; while ( j < L_Bp ) page [ j++ ] = 0 ;
j = e_cache ; while ( j < L_Cp ) cache[ j++ ] = 0 ;
descr = tA( Btree_descr, page[ 0 ], pos_descr );
if ( descr -> l_index != sizeof( Btree_index )
|| descr -> l_data != sizeof( Btree_data )
|| descr -> l_page != sizeof( Btree_page )
|| descr -> h_descr != pos_descr
)
then fErr
if ( 1 ) // do some test
{
// if ( relate( "name_2172", 10, "name_217", 9, 5, 0 ) <= 0 ) fErr
store_256 st ; if ( GetFirst( st ) ) fErr
if ( GetLast ( st ) ) fErr
if ( contains( "" ) ) fErr
}
if ( Bf ) BtreeName = Bfn ;
LE_
/* private: */ void Btree :: check_page
// -----------------------------------------------------------------------------
(
Btree_page & p
)
LB_("Btree.check_page")
if ( p.t )
then {
// Index page:
int supr = eoheap ; if ( ! p.nr ) supr -= L_descr ;
char * aa1 = 0 ; uchar nn1 ;
for ( int e = 0 ; e < p.e ; e++ )
{
Btree_index * n = tA( Btree_index, &p, e * L_index );
to_s260( p.c + n->ak, 0 );
}
}
else {
// Data page:
char predec[ 1000 ]; *predec = 0 ;
char * aa1 = 0 ; uchar nn1, spare ;
for ( int e = 0 ; e < p.e ; e++ )
{
Btree_data * n = tA( Btree_data, &p, e * L_data );
if ( L_heap <= max( n->ak, n->ad ) ) fErr4( e, p.e, n->ak, n->ad )
if ( e == 0 )
{
spare = p.c[ eoheap ];
if ( spare ) memcpy( s260, p.c + n->ak - spare, spare );
s260[ spare ] = 0 ;
}
to_s260( p.c + n->ak, spare );
if ( *s260 != '!' )
then {
if sm_( s260, predec )
{
printf( "\nstrlen( predec ) = %i ", strlen( predec ) );
printf( "\nstrlen( s260 ) = %i\n", strlen( s260 ) );
printf( "\npredec + spare = %s\n ", predec + spare );
printf( "\n s260 + spare = %s\n\n", s260 + spare );
fErr1( spare )
}
strcpy( predec, s260 );
}
uchar Lk = p.c[ n->ak ];
if ( Lk != strlen( s260 + spare ) )
{
fErr4( Lk, spare, strlen(s260), s260 )
}
}
}
/*
// Nur wenn alle keys aus druckbaren Zeichen bestehen:
char * x = s260 - 1 ;
while ( *( ++x ) ) if (( uchar ) *x < 45 ) trac1_page( p, stdout );
*/
LE_
/* private: */ char * Btree :: to_s260
// -----------------------------------------------------------------------------
(
char * ak
, uchar pos
)
{
uchar L = *ak ; // stets kleiner als 256 - schon dem Typ nach !!
char * x = s260 + pos + L ;
memcpy( s260 + pos, ak+1, L ); *x = 0 ; ret( x )
}
/* private: */ void Btree :: show_krMin
/* -----------------------------------------------------------------------------
aufzurufen als: show key range minimum
-----------------------------------------------------------------------------
*/ (
Btree_page * p
, path & sanf
)
LB_("Btree.show_krMin")
if ( ! p ) fErr
char * ak ; uchar spare = 0 ; char * pc = p -> c ;
if ( p -> t ) // Index page
then {
Btree_index * n = tA( Btree_index, p, 0 );
ak = pc + n->ak ;
}
else {
Btree_data * n = tA( Btree_data , p, 0 );
ak = pc + n->ak ; spare = pc[ eoheap ];
if ( spare ) memcpy( sanf, pc + n->ak - spare, spare );
}
uchar L = *ak ; // stets kleiner als 256 - schon dem Typ nach !!
memcpy( sanf + spare, ak+1, L ); sanf[ L + spare ] = 0 ;
LE_
// #define trace_page if ( atComm(__LINE__) ) trac1_page
#define trace_page trac1_page
/* private: */ BOOL Btree :: str_ok( char * s
// -----------------------------------------------------------------------------
)
{
while ( *s ) if not_in_str( *s++, "(0123456789,+-)" ) ret( false )
ret( true );
}
/* private: */ void Btree :: trac1_page
// -----------------------------------------------------------------------------
(
Btree_page & p
)
{
trac1_page( p, stdout );
}
/* private: */ void Btree :: trac1_page
/* -----------------------------------------------------------------------------
trace page and check its content for consistency
-----------------------------------------------------------------------------
*/ (
Btree_page & p // page
, FILE * f // soll geschrieben werden nach
)
LB_("Btree.trac1_page")
# define max_pageNr descr -> last
// ret_
// noTrace = ( abs( treeID ) != 1 || max_pageNr < 4362 );
// noTrace = ( call_nr < 873614 );
bb noTrace = false ;
if ( noTrace )
{
errTrace = -( noTrace = ( call_nr < 159273 ) );
if ( errTrace ) ret_
}
#ifdef __TESTING__
int treffer = 0 ;
int e = 0 ; while ( e < e_cache ) if ( &p == cache[e++] ) treffer++ ;
if ( treffer != 1 )
then {
trace_on
for ( e = 0 ; e < e_cache ; e++ )
fprintf( f, " cache( %4i ).nr = %4i \n", e, cache[e]->nr );
for ( e = 0 ; e < deepest ; e++ )
fprintf( f, " page( %4i ).nr = %4i \n", e, page[e]->nr );
fErr3( e_cache, treffer, &p )
}
#endif
// if ( ! alles ) ret_
BOOL fehler = 0 ;
if ( p.t )
then {
int supr = eoheap ; if ( ! p.nr ) supr -= L_descr ;
uchar nn1, spare = p.c[ eoheap ] ;
if ( ! p.nr && spare ) fErr2( p.nr, spare )
if ( spare <= ( uchar ) 250 )
{
if ( spare ) memcpy( s260, p.c + eoheap - spare, spare );
s260[ spare ] = 0 ;
printf( "\n%i = I/spare( %i ) = [%s]", spare, p.nr, s260 );
if (strPairs) if ( ! str_ok( s260 ) ) fErr3( treeID, s260, descr->last )
}
fprintf( f, "\n\n treeID %i: Index page( %i ):"
" e = %i, h = %i, dirty = %i, call_nr = %u\n |"
"\n I/spare = %u = '%s'\n |"
"\n pos: ak son "
, treeID, p.nr, p.e, p.h, p.dirty, call_nr
, p.c[ eoheap ], s260 );
char * aa1 = 0 ;
for ( int e = 0 ; e < p.e ; e++ )
{
Btree_index * n = tA( Btree_index, &p, e * L_index );
// Beachte: n->ak ist (als funktion von i) nicht notwendig monoton,
// da die Werte im page heap nicht sortiert liegen, sondern in der
// Reihenfolge, in der sie entstanden.
char * ee = to_s260( p.c + n->ak, spare );
uchar Lk = p.c[ n->ak ];
char * aa2 = p.c + n->ak + 1 ;
fprintf( f, "\n%4i: %5i(%3u) %7i ( ", e, n->ak, Lk, n->son );
char * y = eos(s260)-1 ; char m = *y ; *y = 0 ;
if ( strPairs && ! str_ok(s260) ) fErr2( s260, max_pageNr )
*y = m ;
char * x = (( *s260 == '!' )? s260+6 : s260 ) - 1 ;
while ( ++x < ee ) if ( ! *x ) *x = '?' ; // um NULL zu sehen
*x = 0 ;
char * XY = (e)? "" : " = XY" ;
if ( *s260 == '!' )
then {
fprintf( f, "%u : %s%s )\n", *( Surr * )( s260+2 ), s260+6, XY );
}
else fprintf( f, "%s%s )\n", s260, XY );
aa1 = aa2 ; nn1 = Lk ;
if ( ! spare ) {{
if ( strlen( s260 ) > Lk || descr->maxkeylen < Lk )
{
printf( "\nstrlen( 260 ) = %i, Lk = %u \n", strlen(s260), Lk );
fErr
}
if ( supr <= n->ak || descr->last < n->son )
{
fErr4( supr, n->ak, descr->last, n->son )
}
}
}}
fprintf( f, "\n\n" );
}
else {
if ( traceIndex ) ret_
fprintf( f, "\n\n treeID = %i: Data page( %i ):\n|"
"\n pos: ad ak surr "
" e = %i, h = %i, dirty = %i, call_nr = %i"
, treeID, p.nr, p.e, p.h, p.dirty, call_nr );
char predec[ 1000 ]; *predec = 0 ;
char * aa1 = 0 ;
uchar nn1, spare = ( p.nr )? p.c[ eoheap ] : 0 ;
if ( spare ) // memcpy( s260, p.c + eoheap - spare, spare ); falsch
{
// Sample "(72,5" in GetNext zeigt, dass es so richtig ist:
Btree_data * n = tA( Btree_data, &p, 0 );
memcpy( s260, p.c + n->ak-spare, spare ); // nur DATA pages so !!!
}
char300 V ; *V = 0 ;
for ( int e = 0 ; e < p.e ; e++ )
{
Btree_data * n = tA( Btree_data, &p, e * L_data );
if ( L_heap <= max( n->ak, n->ad ) ) fErr3( n->ak, n->ad, L_heap )
if ( e == 0 )
{
s260[ spare ] = 0 ;
fprintf( f, "\n D/spare %u = '%s'\n\n", spare, s260 );
e = traceAb-1 ; // muss sein
}
if ( 0 < p.c[ n->ad ] )
{
memcpy( V, p.c + n->ad+2, ( uchar ) p.c[ n->ad ] ); // our Value
V[ p.c[ n->ad ] ] = 0 ;
}
else * V = 0 ;
char * ee = to_s260( p.c + n->ak, spare );
uchar Lk = p.c[ n->ak ]; char * aa2 = p.c + n->ak + 1 ;
uchar Ld = p.c[ n->ad ];
fprintf( f, "%4i: %5i(%3u) %5i(%3u) %7u, |"
, e, n->ad, Ld, n->ak, Lk, n->surr );
char * y = eos(s260)-1 ; char m = *y ; if ( !e ) *y = 0 ;
if ( strPairs && ! str_ok(s260) ) fErr1( s260 )
*y = m ;
char * x = (( *s260 == '!' )? s260+6 : s260 ) - 1 ;
while ( ++x < ee ) if ( ! *x ) *x = '?' ; // um NULL zu sehen
*x = 0 ;
char * XY = (e)? "" : " = XY" ;
if ( *s260 == '!' )
then {
fprintf( f, "%u : %s|\n", *( Surr * )( s260+2 ), s260+6 );
}
else {
uchar tV = p.c[ n->ad+1 ] ; // type of Value
fprintf( f, "%s%s\n%*s%i |%s|\n\n", s260, XY, 34, "", tV, V );
if ( e && strPairs) if (
in_str('+',s260) && in_str('-',s260) ) fErr3( treeID, s260, descr->last )
/*
// Nur wenn alle keys aus druckbaren Zeichen bestehen:
char * x = s260 - 1 ;
while ( *( ++x ) ) if (( uchar ) *x < 45 ) fErr
*/
if ( sm_( s260, predec ) )
{
printf( "\n--> f a l s c h : Knoten inkonsistent !!!\n\n" );
if ( 2 <= ++anzfalsch )
then {
printf( " See preceeding trace_deepest()." );
printf( "\n max_pageNr = %i\n\n", max_pageNr );
{
m_errMess "System: Error in Btree code, treeID = %i" m_
treeID, ret_error
}
exit(1);
}
else {
stopTrace = -( noTrace = false );
trace_deepest( stdout );
}
}
memcpy( predec, s260, ee-s260 + 1 );
}
if ( Lk != strlen( s260 + spare ) )
{
_4( Lk, spare, strlen(s260), s260 ) ret_ // fErr
}
aa1 = aa2 ; nn1 = Lk ;
}
}
traceAb = 1 ;
if ( fehler )
{
m_errMess "System: FEHLER in Btree( treeID=%i )" m_
treeID, ret_error
}
fflush( f );
LE_
/* private: */ char * Btree :: spare_At ( Btree_page * p
// -----------------------------------------------------------------------------
// return pointer to common prefix
// -----------------------------------------------------------------------------
)
LB_("Btree.spare_At")
uchar spare = ( p->nr )? p -> c[ eoheap ] : 0 ;
if ( p -> t )
then {
// INDEX page:
ret( p->c + eoheap - spare )
}
else {
// DATA page:
Btree_data * n = tA( Btree_data, p, 0 );
ret( p->c + n->ak - spare )
}
LE_ret( 0 )
/* private: */ void Btree :: trace_pos_m
// -----------------------------------------------------------------------------
(
FILE * f
)
LB_("Btree.trace_pos_m")
for ( int i = 0 ; i <= deepest ; i++ )
{
int m = pos_m[ i ].m ;
int r = pos_m[ i ].r ;
fprintf( f, " p = %3i, pos_m(%3i ).( m,r ) = %3i %i\n"
, page[i] -> nr, i, m, r );
}
fprintf( f, " at_surr: %i\n\n", at_surr );
LE_
/* public: */ void Btree :: show
/* -----------------------------------------------------------------------------
trace Btree in a black box view
-----------------------------------------------------------------------------
*/ (
char * name // Btree
, FILE * f // soll geschrieben werden nach
)
LB_("Btree.show")
fprintf( f, "\n%s - This is Btree %s: \n{", name, Bfn );
store_256 st ; Surr s = GetFirst( st );
while ( s )
{
fprintf( f, "\n%s - %s(%s)", name, st.k, st.c );
s = Next( st );
}
fprintf( f, "\n}\nend of Btree %s\n\n", name );
LE_
/* public: */ void Btree :: traceAbs( char * name
/* -----------------------------------------------------------------------------
Show on stdout all elements ( key, value ) in the Btree
-----------------------------------------------------------------------------
*/ )
LB_("Btree.traceAbs(")
printf( "\ntraceAbs: %s", name );
traceAbs( name, stdout );
LE_
/* public: */ void Btree :: traceAbs
/* -----------------------------------------------------------------------------
Show all elements ( key, value ) in the Btree
-----------------------------------------------------------------------------
*/ (
char * name // Btree
, FILE * f // soll geschrieben werden nach
)
LB_("Btree.traceAbs")
long anz = 0 ;
fprintf( f, "\n\nBtree %s:", name );
__
KVStore st ; Surr s = GetFirst( st );
_1(s) __
while ( s )
{
__ anz++ ;
fprintf( f, "\n%s:[ %s ][%s]", name, st.k, st.c );
s = Next( st );
}
fprintf( f, "\nend Btree %s, %ld elements\n\n", name, anz );
LE_
/* public: */ void Btree :: traceAt
/* -----------------------------------------------------------------------------
Show all elements ( key, value ) in the Btree such that At( key, pre )
-----------------------------------------------------------------------------
*/ (
char * name // Btree
, char * pre // prefix
, FILE * f // soll geschrieben werden nach
)
LB_("Btree.traceAt")
if ( ! pre ) fErr
fprintf( f, "\n\nBtree %s, prefix = %s:", name, pre );
KVStore st ; Surr s = Getmin_GE( st, pre );
if not_At( st.k, pre )
then {
traceAbs( "name", f ); ret_
}
while ( s && At( st.k, pre ) )
{
fprintf( f, "\n[ %s ][%s]", st.k, st.c ); s = Next( st );
}
fprintf( f, "\nend Btree %s, prefix = %s, treeID= %i\n\n", name, pre, treeID );
LE_
/* public: */ void Btree :: trace_index ( FILE * f
// -----------------------------------------------------------------------------
)
LB_("Btree.trace_index")
traceIndex = 1 ; trace( "INDEX", f );
traceIndex = 0 ;
LE_
/* public: */ void Btree :: trace_data ( Btree_page & p
// -----------------------------------------------------------------------------
)
LB_("Btree.trace_data")
if (1)
then {
traceIndex = 1 ; trace( "INDEX", stdout );
traceIndex = 0 ;
}
else {
trace_deepest( stdout ); // wirklich nur notwendige Index Nodes
if ( page[ deepest ]->nr != p.nr ) trace_page( p );
}
// trace_page( p ); _2(umwe,Loc)
LE_
/* public: */ void Btree :: trace_deepest (
// -----------------------------------------------------------------------------
)
{
trace_deepest( stdout );
}
/* public: */ void Btree :: trace_deepest ( FILE * f
// -----------------------------------------------------------------------------
)
LB_("Btree.trace_deepest")
// if ( noTrace ) ret_
fprintf( f, "\n\ndeepest = %i\n\n", deepest );
noTrace = false ;
for ( int i = 0 ; i <= deepest ; i++ )
{
int m = pos_m[ i ].m ;
int r = pos_m[ i ].r ;
fprintf( f, "\n--> pos_m(%3i ).( m,r ) = %3i %i \n", i, m, r );
trace_page( *( page[ i ] ), f );
}
printf( "\n--> END trace_deepest, treeID = %i\n", treeID );
LE_
/* public: */ void Btree :: trace
// -----------------------------------------------------------------------------
(
char * name // Objekt
, FILE * f // soll geschrieben werden nach
)
LB_("Btree.trace")
if ( noTrace || abs( treeID ) != 1 ) ret_
fprintf( f, "\ntreeID %i, %s - This is Btree %s: \n\n", treeID, name, Bfn );
fprintf( f, "pos_descr = %i \n"
"Bf = %i \n"
"Bfn = %s \n"
"maxkeylen = %u \n"
"surr = %u \n"
"anz = %u \n"
"last = %u \n"
"next = %u \n"
"deepest = %i <= %i = e_cache \n\n"
, pos_descr
, Bf
, Bfn
, descr -> maxkeylen
, descr -> surr
, descr -> anz
, descr -> last
, descr -> next
, deepest, e_cache ); trace_pos_m( f );
trace_deepest( f );
fprintf( f, "\n--- end Btree, last surr = %u \n", descr->surr );
// if ( alles < 2 ) ret_
int i, a = L_Bp - 1 ; if ( a <= deepest ) fErr
// for ( i = 1 ; i <= 1 ; i++ ) // nur eine Seite
for ( i = 1 ; i <= descr->last ; i++ )
{
get_page( a, i );
trace_page( *( page[a] ), f );
}
if (0) if ( treeID < 0 )
{
traceAbs( name );
{
m_errMess "System: FEHLER im Btree ???" m_
ret_error
}
;
}
_1( noTrace+1-1 )
LE_
/* private: */ int Btree :: relate
/* -----------------------------------------------------------------------------
return -1 iff ( k1 < k2 )
0 iff ( k1 = k2 )
1 iff ( k1 > k2 )
-----------------------------------------------------------------------------
*/ (
char * k1 // key
, uchar n1 // number of bytes in k1
, char * k2 // key
, uchar n2 // number of bytes in k2
, uchar same
, uchar spa
)
{
kuerzer += same ;
k1 += spa ;
n1 -= spa ;
if ( n1 == 0 ) return( -n2 ); esif ( n2 == 0 ) return( 1 );
int m = min( n1, n2 );
if ( m < same )
{
trace( "XXX", stdout ); showStr( "K1", k1, n1 );
showStr( "K2", k2, n2 );
fErr3( n1, n2, same )
}
int j = same ;
while ( j < m ) { if ( k1[j] != k2[j] ) m = 0 ; else j++ ; }
if ( m )
{
if ( j == n1 ) return( ( n2 == n1 )? 0 : -1 ); else return( 1 );
}
return( ( k1[j] < k2[j] )? -1 : 1 );
}
/* private: */ BOOL Btree :: locate
/* -----------------------------------------------------------------------------
Make pos_m[] the path to the page containing (or to contain) k.
Beachte: pos_m[ deepest ].m zeigt auf die gesuchte Position g e r u n d e t
auf ein direkt benachbartes Element (ein existierendes bei m > 0, ansonsten
auf den Anfang der Datenseite, was 0 < r zur Folge hat).
pos_m[ deepest ].r sagt ob die gesuchte Position durch m exakt gegeben ist,
d.h. als Element schon existiert ( r == 0 ), oder ob sie sich - als erst noch
zu erzeugende Position - direkt davor ( r < 0 ) oder direkt danach ( 0 < r )
einordnet.
-----------------------------------------------------------------------------
*/ (
char * k // key
, uchar n1 // number of bytes in key
)
LB_("Btree.locate")
accessNo++ ; int r, i, m ; uint2 a, e ; pageNr son ;
Btree_page * p = page[ i = deepest = 0 ] ;
while ( p -> t ) // page is index page on path to data page
{
uchar ispar = p->c[ eoheap ] ;
uchar epf = ( deepest )? p->c[ eoheap ] : 0 ;
m = a = 0 ; e = p->e ; r = -1 ;
if ( e <= 0 ) { trace_page( *p, stdout ); fErr }
while ( a < e )
{
m = ( a + e )/2 ;
Btree_index * n = tA( Btree_index, p, m * L_index );
r = relate( k, n1, p->c + n->ak + 1, p->c[ n->ak ], 0, ispar );
/*
L4_( a, m, e, r ); L2_( n1, (uchar)p->c[ n->ak ] )
show_str( "SS1", k, n1 );
show_str( "SS2", p->c + n->ak + 1, (uchar)p->c[n->ak] );
*/
if ( r == 0 ) a = e = m ; esif ( r < 0 ) e = m ;
else { a = m ; if ( a+1 == e ) e = a ; }
}
pos_m[ i ].m = m ;
pos_m[ i ].r = r ;
if ( r < 0 )
then {
if ( m ) { L1_( *this ); fErr }
if ( i ) // so lassen !!!
{
m = pos_m[ --i ].m -= 1 ;
if ( m < 0 )
{
trace( "LLL", stdout ); k[n1] = 0 ; fErr1( k )
}
p = page[ i ] ;
}
}
esif ( m + r == 0 ) r = 1 ;
son = tA( Btree_index, p, m * L_index ) -> son ;
if ( ! son ) son = 1 ; // the always existing 1st data page
if ( descr->last < son )
{
_4( son, descr->last, p, m )
trace_page( *p, stdout ); fErr3( son, descr->last, m )
}
if ( L_Bp <= ++i ) fErr2( L_Bp, i )
if ( ! page[i] ) get_page( i, son ); else
if ( page[i]->nr != son ) get_page( i, son );
p = page[ deepest = i ] ;
}
if ( maxDepth < deepest ) maxDepth = deepest ;
BOOL res = locate_pos( k, n1, pos_m[ deepest ].m, pos_m[ deepest ].r, *p );
LE_ret( res )
/* private: */ BOOL Btree :: locate_ipos
/* -----------------------------------------------------------------------------
for index pages only !!!!
-----------------------------------------------------------------------------
*/ (
char * k // key
, uchar n1 // number of bytes in key
, int & m
, int & r
, Btree_page & p
)
LB_("Btree.locate_ipos")
uint2 a, e ; uchar ispar = p.c[ eoheap ] ;
m = a = 1 ; e = p.e ; r = -1 ; if ( e == 1 ) m = a = 0 ;
if ( e <= 0 ) { trace_page( p, stdout ); fErr }
while ( a < e )
{
m = ( a + e )/2 ;
Btree_index * n = tA( Btree_index, &p, m * L_index );
r = relate( k, n1, p.c + n->ak + 1, p.c[ n->ak ], 0, ispar );
if ( treeID < 0 )
{
char300 cok ; memcpy( cok, k, n1 );
char * ex = cok + n1 ;
char * x = cok - 1 ;
while ( ++x < ex ) if ( ! *x ) *x = '?' ; *x = 0 ;
printf( "\nr = %i, node %i, Locate k=[%s]", r, p.nr, cok );
printf( "\nr = %i, a = %i, e = %i, m = %i : %i...", r, a, e, m
, ( uchar ) p.c[ n->ak ] );
int ee = min( m+1, e ) + 1 ;
while ( max( 0, m-1 ) <= --ee ) if ( ee < p.e )
{
_1(p.nr)
char * zAt = ( ee == m )? "I:-->" : "I:zzz" ;
Btree_index * n = tA( Btree_index, &p, ee * L_index );
traceStr( zAt, p.c + n->ak + 1, (uchar)p.c[ n->ak ] );
}
}
if ( r == 0 ) a = e = m ; esif ( r < 0 ) e = m ;
else { a = m ; if ( a+1 == e ) e = a ; }
}
// if ( r && treeID < 0 ) trace_page( p, stdout );
LE_ret( ! r )
/* private: */ BOOL Btree :: locate_pos
/* -----------------------------------------------------------------------------
for data pages only !!!!
-----------------------------------------------------------------------------
*/ (
char * k // key
, uchar n1 // number of bytes in key
, int & m
, int & r
, Btree_page & p
)
LB_("Btree.locate_pos")
LocNr++ ;
int a, e ; uchar spare = ( uchar )( p.c[ eoheap ] );
n1 -= spare ;
k += spare ;
m = a = 1 ; e = p.e ; r = -1 ; if ( e == 1 ) m = a = 0 ;
while ( a < e )
{
m = ( a + e )/2 ; if ( m == p.e ) fErr
Btree_data * n = tA( Btree_data, &p, m * L_data );
if ( L_heap <= n->ak ) { L3_( p.nr, p.e, m )
trace_page( p, stdout ); L1_(m) fErr }
r = relate( k, n1, p.c + n->ak + 1, p.c[ n->ak ], 0, 0 );
if ( treeID < 0 )
{
char300 cok ; memcpy( cok, k, n1 );
char * ex = cok + n1 ;
char * x = cok - 1 ;
while ( ++x < ex ) if ( ! *x ) *x = '?' ; *x = 0 ;
printf( "\nr = %i, node %i, Locate k=[%s]", r, p.nr, cok );
printf( "\nr = %i, a = %i, e = %i, m = %i : %i...", r, a, e, m
, ( uchar ) p.c[ n->ak ] );
int ee = min( m+1, e ) + 1 ;
while ( max( 0, m-1 ) <= --ee ) if ( ee < p.e )
{
_1(p.nr)
char * zAt = ( ee == m )? "D:-->" : "I:zzz" ;
Btree_data * n = tA( Btree_data, &p, ee-- * L_data );
traceStr( zAt, p.c + n->ak + 1, (uchar)p.c[ n->ak ] );
}
}
if ( r == 0 ) { ; at_surr = n->surr ; break ; }
esif ( r < 0 ) { e = m ; }
else { a = m ; if ( a+1 == e ) e = a ; }
}
// if ( treeID < 0 ) trace_page( p, stdout );
if ( r < 0 )
{
if ( m == 1 ) m = 0 ; else fErr1( *this )
}
if ( m == 0 )
{
// so und NICHT anders:
r = 1 ; if ( 1 < p.e )
{
Btree_data * n = tA( Btree_data, &p, L_data );
if ( ! relate( k, n1, p.c + n->ak + 1, p.c[ n->ak ], 0, 0 ) )
{
m = 1 ;
r = 0 ;
}
}
}
LE_ret( ! r )
/* private: */ BOOL Btree :: locate_First(
/* -----------------------------------------------------------------------------
Return Wahrheitswert "gesuchtes Element gefunden"
-----------------------------------------------------------------------------
*/ )
LB_("Btree.locate_First")
locate( "", 0 );
if ( ! pos_m[ deepest ].r ) ret( 1 )
LE_ret( locate_Next( "", 0 ) )
/* private: */ BOOL Btree :: locate_Last (
/* -----------------------------------------------------------------------------
Return Wahrheitswert "gesuchtes Element gefunden"
-----------------------------------------------------------------------------
*/ )
LB_("Btree.locate_Last")
Btree_page * p = page[ deepest = 0 ] ;
pos_m[ deepest ].m = p -> e-1 ;
pos_m[ deepest ].r = 1 ;
while ( p -> t ) // p is index page
{
pageNr son = tA( Btree_index, p
, pos_m[ deepest ].m * L_index ) -> son ;
if ( ! son ) son = 1 ; // the always existing 1st data page
get_page( ++deepest, son ); p = page[ deepest ] ;
pos_m[ deepest ].m = p -> e-1 ;
pos_m[ deepest ].r = 1 ;
}
if ( pos_m[ deepest ].m == 0 ) ret( 0 )
pos_m[ deepest ].r = 0 ;
LE_ret( 1 )
/* private: */ BOOL Btree :: locate_Next
// -----------------------------------------------------------------------------
(
char * k // key
, uchar kL // number of bytes in key
)
LB_("Btree.locate_Next")
// _2("DXDXDX",k) locate( k,kL );
// if ( 48000 < atLB ) fErr
if ( deepest < 1 || L_Bp <= deepest )
{
// trace( "Btree locate_Next", stdout );
// showStr( "k", k, kL ); fErr3( deepest, L_Bp, *this )
ret( 0 )
}
Btree_page * p = page[ deepest ] ;
/*
if At( k, "make.html" )
{ printf( "\npage %3i deepest %2i m,r,e = ( %2i, %2i, %2i )"
, p -> nr, deepest, pos_m[ deepest ].m, pos_m[ deepest ].r, p -> e );
printf( "\nlocate_Next" );}
*/
// _1("DDD") trace_deepest();
if ( pos_m[ deepest ].r < 0 ) fErr
if ( pos_m[ deepest ].m + 1 < p -> e )
then {
__ if ( pos_m[ deepest ].r < 0 ) pos_m[ deepest ].m -= 1 ;
pos_m[ deepest ].m++ ;
pos_m[ deepest ].r = 0 ;
}
esif ( pos_m[ deepest ].m + 1 == p -> e )
{
__ if ( pos_m[ deepest ].r < 0 )
then {
if ( p->e <= 1 )
{
showStr( "error in locate_Next of", k, kL );
trace( "XX", stdout ); fErr
}
pos_m[ deepest ].r = 0 ;
__ __ ret( 1 )
}
p = page[ --deepest ] ;
while ( deepest && pos_m[ deepest ].m + 1 == p -> e )
{
p = page[ --deepest ] ;
}
pos_m[ deepest ].m++ ;
if ( deepest == 0 && pos_m[ deepest ].m == p -> e ) ret( 0 )
while ( p -> t ) // page is index page
{
if ( p -> e <= pos_m[ deepest ].m ) fErr
pageNr son = tA( Btree_index, p
, pos_m[ deepest ].m * L_index ) -> son ;
if ( ! son ) son = 1 ; // the always existing 1st data page
int i = deepest + 1 ;
if ( L_Bp <= i ) fErr2( L_Bp, i )
if ( ! page[i] ) get_page( i, son ); else
if ( page[i]->nr != son ) get_page( i, son );
p = page[ deepest = i ] ;
pos_m[ deepest ].m = 0 ;
pos_m[ deepest ].r = 1 ;
}
__ if ( p -> e <= 1 ) ret( locate_Next( k, kL ) )
__
pos_m[ deepest ].m = 1 ;
pos_m[ deepest ].r = 0 ;
ret( 1 )
}
else {
trace( "Btree locate_Next", stdout );
printf( "\nPlease make sure that the Btree was not updated immediately"
"\nbefore this call of Next():" );
k[ kL ] = 0 ; fErr2( kL, k )
}
if ( deepest < 1 || L_Bp <= deepest ) fErr2( deepest, L_Bp )
if ( pos_m[ deepest ].m == 0 )
{
if ( 1 < p -> e )
then {
pos_m[ deepest ].m = 1 ;
pos_m[ deepest ].r = 0 ;
}
else fErr
}
if ( pos_m[ deepest ].r )
{
showStr( "Next of", k, kL ); trace( "", stdout ); fErr
}
LE_ret( 1 )
/* private: */ BOOL Btree :: locate_Prev
// -----------------------------------------------------------------------------
(
char * k // key
, uchar kL // number of bytes in key
)
LB_("Btree.locate_Prev")
// if ( deepest < 1 || L_Bp <= deepest ) fErr2( deepest, L_Bp )
Btree_page * p = page[ deepest ] ; if ( p -> t ) fErr
//
// , pos_m[ deepest ].m, pos_m[ deepest ].r );
int count = 0 ;
while ( deepest && pos_m[ deepest ].m <= 1 && pos_m[ deepest ].r < 1 )
{
if ( 0 < pos_m[ deepest - 1 ].m )
then {
count += 1 ;
pos_m[ --deepest ].m-- ; p = page[ deepest ] ;
pageNr son = tA( Btree_index, p
, pos_m[ deepest ].m * L_index ) -> son ;
if ( ! son ) son = 1 ; // the always existing 1st data page
get_page( ++deepest, son ); p = page[ deepest ] ;
pos_m[ deepest ].m = p -> e-1 ;
pos_m[ deepest ].r = 0 ;
if ( pos_m[ deepest ].m > 0 ) ret( 1 )
if ( 300 < count ) fErr1( *this )
}
esif ( deepest == 1 ) ret( 0 ) else break ;
}
if ( pos_m[ deepest ].r ) fErr
if ( 1 < pos_m[ deepest ].m )
then {
if ( pos_m[ deepest ].r > 0 ) pos_m[ deepest ].m += 1 ;
pos_m[ deepest ].m-- ;
pos_m[ deepest ].r = 0 ;
}
else {
if ( pos_m[ deepest ].m == 1 && pos_m[ deepest ].r > 0 )
{
pos_m[ deepest ].r = 0 ;
ret( 1 )
}
p = page[ --deepest ] ;
while ( deepest && ! pos_m[ deepest ].m ) p = page[ --deepest ] ;
if ( deepest == 0 && pos_m[ deepest ].m == 0 ) ret( 0 )
if ( pos_m[ deepest ].m > 0 ) pos_m[ deepest ].m-- ;
pos_m[ deepest ].r = 1 ;
while ( p -> t ) // page is index page
{
pageNr son = tA( Btree_index, p
, pos_m[ deepest ].m * L_index ) -> son ;
if ( ! son )
{
if ( deepest == 0 && pos_m[ deepest ].m == 0 ) ret( 0 )
son = 1 ; // the always existing 1st data page
}
int i = deepest + 1 ;
if ( L_Bp <= i ) fErr2( L_Bp, i )
if ( ! page[i] ) get_page( i, son ); else
if ( page[i]->nr != son ) get_page( i, son );
p = page[ deepest = i ] ;
pos_m[ deepest ].m = p -> e-1 ;
pos_m[ deepest ].r = 1 ;
}
if ( pos_m[ deepest ].m == 0 ) ret( locate_Prev( k, kL ) )
pos_m[ deepest ].r = 0 ;
if ( pos_m[ deepest ].m <= 0 ) ret( 0 ) else ret( 1 )
//
// , pos_m[ deepest ].m, pos_m[ deepest ].r );
}
if ( pos_m[ deepest ].r )
{
showStr( "Prev of", k, kL ); trace( "XXX", stdout ); fErr
}
LE_ret( 1 )
/* private: */ void Btree :: data_to_file
/* -----------------------------------------------------------------------------
Der Aufrufer sagt:
Store data d in a file associated to the Btree and make ( d, d_L, t )
the local path to this file.
Die Funktion garantiert: fErr || ok
-----------------------------------------------------------------------------
*/ (
char * & d // data
, int & d_L // number of bytes in data
, uchar & t // set t = t_file
)
LB_("Btree.data_to_file")
d[ d_L ] = 0 ; printf( "\nBtree: Data truncated: %s", d );
fErr1(d)
d_L = 252 ; ret_
fErr2( d_L, d ) // not yet supported
LE_
/* public: */ char Btree :: StrIns
/* -----------------------------------------------------------------------------
Der Aufrufer sagt: Ins( do_this, k, strlen( k ), d, n2, t )
-----------------------------------------------------------------------------
*/ (
char * k
)
LB_("Btree.StrIns")
LE_ret( StrIns( 'i', k ) )
/* public: */ char Btree :: StrIns
/* -----------------------------------------------------------------------------
Der Aufrufer sagt: Ins( do_this, k, strlen( k ), d, n2, t )
-----------------------------------------------------------------------------
*/ (
char do_this // 'i' insert, 'e' ensure
, char * k // key
)
LB_("Btree.StrIns")
if ( ! k || ! *k ) fErr1( k )
if ( L_255 <= strlen( k ) ) fErr1( k )
if not_in_str( do_this, "ie?" ) fErr1( do_this )
if ( do_this != 'i' && do_this != 'e' ) fErr
__
Surr res = Ins( do_this, k, strlen( k ), "", 0, t_undef );
__
LE_ret( res )
// LE_ret( Ins( do_this, k, strlen( k ), "", 0, t_undef ) )
/* public: */ char Btree :: Update
// -----------------------------------------------------------------------------
(
store_256 & st
)
LB_("Btree.Update")
LE_ret( StrIns( 'u', st.k, st.c, st.L, st.t ) )
/* public: */ char Btree :: StrIns
// -----------------------------------------------------------------------------
(
char do_this // 'i' insert, 'e' ensure, '
, int k // key
, char * d // t_data that is a string
)
LB_("Btree.StrIns")
char20 strk ; s_( strk, "%i", k );
// char r = StrIns( do_this, strk, d ); if ( ! cache_ok() ) fErr else ret(r)
LE_ret( StrIns( do_this, strk, d ) )
/* public: */ char Btree :: StrIns
// -----------------------------------------------------------------------------
(
char do_this // 'i' insert, 'e' ensure, '
, char * k // key
, char * d // t_data that is a string
)
LB_("Btree.StrIns")
// _1("INSINS") _2(k,d)
if ( ! k ) fErr
if ( ! d ) fErr
int L = strlen( d );
if ( 252 < strlen( d ) )
{
if ( 1022 < L ) fErr2( L, d )
char * e = d + L ;
char * w = d ;
char300 pstr ;
uint n1 = LDataNr ;
__ if ( n1 == 0 )
{
if ( LData ) fErr
LData = new Btree();
}
while ( 220 < L )
{
__ memcpy( pstr, w, 252 ); pstr[252] = 0 ;
L -= 252 ;
w += 252 ;
char20 xx ; s_( xx, "%i", ++LDataNr );
LData -> StrIns( 'i', xx, pstr );
}
s_( pstr, "%s:%i/%i:", ( w < 0 )? w : e, n1, LDataNr );
d = pstr ;
}
//
LE_ret( Ins( do_this, k, strlen( k ), d, strlen( d ), t_data ) )
/* public: */ char Btree :: StrIns
/* -----------------------------------------------------------------------------
Der Aufrufer sagt: Ins( do_this, k, strlen( k ), d, n2, t )
-----------------------------------------------------------------------------
*/ (
char do_this // 'i' insert, 'u' update, 'e' ensure
, char * k // key
, void * d // data
, int n2 // number of bytes in data
, uchar t // type of data
)
LB_("Btree.StrIns")
if ( ! k ) fErr1( do_this )
LE_ret( Ins( do_this, k, strlen( k ), ( char * )d, n2, t ) )
/* public: */ char Btree :: StrIns
/* -----------------------------------------------------------------------------
= Ins( do_this, k, strlen( k )+1, d, strlen( d ), t )
-----------------------------------------------------------------------------
*/ (
char do_this // 'i' insert, 'u' update, 'e' ensure
, char * k // key
, void * d // data
, uchar t // type of data
)
LB_("Btree.StrIns")
if ( ! k ) fErr
LE_ret( Ins( do_this, k, strlen( k ), (char *)d, strlen((char *) d ), t ) )
/* private: */ BOOL Btree :: NoUpd
/* -----------------------------------------------------------------------------
Der Aufrufer sagt:
Return( true ) iff ( d, d_L ) is the value for the key at
pos_m[ deepest ].m .
Die Funktion garantiert: fErr || ok
-----------------------------------------------------------------------------
*/ (
char * d // data
, int d_L // number of bytes in data
)
LB_("Btree.NoUpd")
if ( ! d ) fErr
if ( 252 < d_L ) ret( false )
int m = pos_m[ deepest ].m ;
Btree_page * p = page[ deepest ] ; if ( p->t ) fErr
Btree_data * da = tA( Btree_data, p, m * L_data );
if ( ! da->surr || da->surr != at_surr )
{
L2_( da->surr, descr->surr ) fErr
}
if ( p->c[ da -> ad ] != d_L ) ret( false )
LE_ret( is( d, p->c + da->ad + 2, d_L ) )
/* public: */ char Btree :: InsAtSurr
/* -----------------------------------------------------------------------------
Der Aufrufer sagt: f a l s c h !!!!!
Wie Ins( 'u', k, k_L, d, d_L, t ), wo die Zielstelle k nun aber
per Surrogat genannt ist.
Die Funktion garantiert: fErr || ok || return 'n' &&
EN_not_found:
You gave ( do_this == 'u' ), but the key is not in the tree.
-----------------------------------------------------------------------------
*/ (
Surr k //
, char * d // data
, int d_L // number of bytes in data
, uchar t // type of data
)
LB_("Btree.InsAtSurr")
if ( ! d ) fErr
if ( 252 < d_L ) data_to_file( d, d_L, t );
char kk[ 256 ] ; memcpy( kk, "!!", 2 ); memcpy( kk+2, &k, 4 );
// at_surr = *(( Surr * ) &k );
LE_ret( Ins( 'u', kk, 6, d, d_L, t ) )
/* public: */ Surr Btree :: ensure
// -----------------------------------------------------------------------------
(
void * k // key
, int k_L // number of bytes in key
)
LB_("Btree.ensure")
Ins( 'e', ( char * )k, k_L, 0, 0, t_undef );
LE_ret( at_surr )
/* public: */ char Btree :: InsPath
/* -----------------------------------------------------------------------------
Ein ''path in diesem Sinn hat die Form /n1/n2/... , wobei jeder
der Namen n1, n2, ... auch leer sein darf (aber keine NULL ent-
halten darf).
-----------------------------------------------------------------------------
*/ (
char do_this // 'i' insert, 'u' update, 'e' ensure
, char * k // key
, char * d // data
, int d_L // number of bytes in data
, uchar t // type of data
, Surr k_father // path ''k is to start from this father
)
LB_("Btree.InsPath")
if ( ! k ) fErr
LE_ret( InsPath( do_this, k, strlen( k ), d, d_L, t, k_father ) )
/* public: */ char Btree :: InsPath
/* -----------------------------------------------------------------------------
Write into Btree (i.e. insert, update, or ensure)
Here 'ensure' means 'update if entry exists, else insert'.
Return 'i' or 'u' characterizing the action taken
Die Funktion garantiert: fErr || ok || return 'n' &&
EN_exists:
You gave ( do_this == 'i' ), but the key cannot be inserted
because it is already in the tree.
EN_not_found:
You gave ( do_this == 'u' ), but the key is not in the tree.
-----------------------------------------------------------------------------
*/ (
char do_this // 'i' insert, 'u' update, 'e' ensure
, char * k // key
, int k_L // number of bytes in key
, char * d // data
, int d_L // number of bytes in data
, uchar t // type of data
, Surr k_father // path ''k is to start from this father
)
LB_("Btree.InsPath")
check_path( k, k_L, k_father );
if ( t == t_undef ) { d_L = 0 ; d = k ; }
if ( ! d ) fErr
show_str( "Key = ", k, k_L ); L1_( d_L )
if ( 252 < d_L ) data_to_file( d, d_L, t );
// show_str( "KKK", k, k_L ); show_str( "KKD", d, d_L );
char * s ;
char * a ; char * ek = k + k_L ;
a = s = k ; char action = 'n' ; // no action
char kk[ 256 ] ; memcpy( kk, "!/", 2 ); at_surr = k_father ;
while ( a < ek )
{
s++ ; while ( s < ek && *s != '/' ) s++ ;
int k_L = s-a ;
memcpy( kk+2, &at_surr, 4 );
memcpy( kk+6, a , k_L );
if ( s < ek )
then action = Ins( 'e' , kk, 6 + k_L, d, 0 , t_keep );
else action = Ins( do_this, kk, 6 + k_L, d, d_L, t );
a = s ;
}
LE_Ret( errno, action )
/* public: */ uint Btree :: Ins
/* -----------------------------------------------------------------------------
Add Btree 'also to this Btree
-----------------------------------------------------------------------------
*/ (
Btree & also
, char do_this // i, e, u, ?
)
LB_("Btree.Ins")
KVStore st ; Surr s = also.GetFirst( st ); uint anz = 0 ;
while ( s )
{
anz++ ; Ins( do_this, st.k, st.k_L, st.c, st.L, st.t );
s = also.Next( st );
}
LE_ret( anz )
/* public: */ char Btree :: Ins
/* -----------------------------------------------------------------------------
Write into Btree (i.e. insert, update, or ensure)
Here 'ensure' means 'update if entry exists, else insert'.
Return 'i' or 'u' characterizing the action taken
Die Funktion garantiert: fErr || ok || return 'n' &&
EN_exists:
You gave ( do_this == 'i' ), but the key cannot be inserted
because it is already in the tree.
EN_not_found:
You gave ( do_this == 'u' ), but the key is not in the tree.
-----------------------------------------------------------------------------
*/ (
char do_this // 'i' insert, 'u' update, 'e' ensure
, char * k // key
, char * d // data
, int d_L // number of bytes in data
, uchar t // type of data
)
LB_("Btree.Ins")
if ( ! k ) fErr
LE_ret( Ins( do_this, k, strlen( k ), d, d_L, t ) )
/* public: */ char Btree :: Ins
/* -----------------------------------------------------------------------------
Write into Btree (i.e. insert, update, or ensure)
Here 'ensure' means 'update if entry exists, else insert'.
Return 'i' or 'u' characterizing the action taken
Die Funktion garantiert: fErr || ok || return 'n' &&
EN_exists:
You gave ( do_this == 'i' ), but the key cannot be inserted
because it is already in the tree.
EN_not_found:
You gave ( do_this == 'u' ), but the key is not in the tree.
-----------------------------------------------------------------------------
*/ (
char do_this // 'i' insert, 'u' update, 'e' ensure
, char * k // key
, int k_L // number of bytes in key
, char * d // data
, int d_L // number of bytes in data
, uchar t // type of data
)
LB_("Btree.Ins")
uint mxpNr = max_pageNr ;
call_nr++ ;
bb if ( ! cache_ok() ) fErr // _1("INSERT.1") _1(k)
if ( 252 < k_L ) fErr2( k_L, k )
if ( 252 < d_L ) fErr2( d_L, d )
e_extra = 0 ;
if ( max_k_L != 252 ) fErr1( max_k_L )
if ( k_L <= 0 )
{
if ( k_L == 0 )
then {
printf( "\nW a r n i n g : Btree ignored empty key - d_L = %i,"
" do_this = %c, Btree = %s\n", d_L, do_this, BtreeName );
ret(0)
traceStr( "st.c", d, d_L );
printf( "\nAn empty key usually causes problems in split_data().\n" );
fErr ret( 0 )
}
else fErr
// #define __ { printf( "\nLine %i", __LINE__ ); fflush(stdout); }
if ( contains( k, k_L ) )
then {
__ if ( do_this == 'i' )
{
showStr( "in Btree already:", k, k_L ); Ret( EN_exists, 0 )
}
if ( do_this == '?' )
{
showStr( "in Btree already:", k, k_L );
}
}
else if ( do_this == 'u' )
{
showStr( "not yet in Btree:", k, k_L ); Ret( EN_not_found, 0 )
}
}
__
if ( max_k_L < k_L )
{
traceStr( "xxx", k, k_L ); _2( k_L, max_k_L )
{
m_errMess "System: key (see above) too long" m_
ret_error
}
;
}
if ( t == t_undef ) { d_L = 0 ; d = k ; } esif ( d_L < 0 ) fErr
if ( ! k ) fErr
if ( ! d ) fErr
char * ek = k + k_L ;
// _1(k_L)
if ( 252 < d_L ) data_to_file( d, d_L, t );
// _1(k_L+0)
__
if ( L_255 < k_L )
then {
Surr sr = 0 ; char kk[ 256 ] ; memcpy( kk, "!?", 2 );
while ( L_249 < k_L )
{
memcpy( kk+2, &sr, 4 );
memcpy( kk+6, k, L_249 ); k_L -= L_249 ; k += L_249 ;
Ins( 'e', kk, L_255, 0, 0, t_undef );
sr = at_surr ; if ( !sr ) fErr
}
memcpy( kk+2, &sr, 4 ); memcpy( kk+6, k, k_L );
ret( Ins( do_this, kk, k_L+6, d, d_L, t ) )
}
if ( 256 <= max( k_L, d_L ) ) fErr
uchar n1 = k_L % 256 ;
uchar n2 = d_L % 256 ;
Btree_data * dn ;
__
deepest = 0 ;
BOOL found = locate( k, n1 ); // _2( deepest, found )
if ( found && ( do_this == 'e' || do_this == 'u' ) )
{
if ( NoUpd( d, d_L ) ) ret( 'u' )
}
if ( descr->maxkeylen < n1 )
{
descr->maxkeylen = n1 ; cache[0] -> dirty = 1 ;
}
Btree_page * p = page[ deepest ]; if ( p->t ) fErr
int stop = 0 ;
int split = 0 ;
if ( do_this == 'e' || do_this == '?' )
{
if ( pos_m[ deepest ].r ) do_this = 'i' ; else do_this = 'u' ;
}
if ( do_this == 'u' )
{
if ( pos_m[ deepest ].r ) Ret( EN_not_found, 0 );
}
esif ( do_this != 'i' ) fErr
// _3( stop, pos_m[ deepest ].r, do_this ) fflush( stdout );
if ( do_this == 'u' && t == t_keep ) ret( 'u' )
BOOL splitted = false ;
bb _1(stop)
while ( stop < 2 )
{
__ stop++ ;
if ( do_this == 'i' )
then {
if ( pos_m[ deepest ].r == 0 )
{
if ( ! silent )
traceStr( "exists in Btree", k, k_L );
Ret( EN_exists, 0 );
}
bb _4( p->h, n1, n2, p->e )
__ split = ( p->h < 3 + n1 + n2 + ( p->e+1 ) * L_data ) ;
}
else {
if ( pos_m[ deepest ].r )
{
traceStr( "not found: k=", k, k_L );
Ret( EN_not_found, 0 );
}
__ split = ( p->h < 2 + n2 + ( p->e+1 ) * L_data ) ;
}
if ( split )
then {
__ splitted = true ;
// _3( stop, split, k_L ) traceStr( "SSS", k, k_L );
// _5( stop, p->h, n2, ( p -> e+1 ) * L_data, *this )
if ( stop == 2 ) // reorganize schon gelaufen
then {
__ if ( ! deepest ) fErr
__ split_data( page[ deepest ], new_page() ); bb _1("www1")
bb _1(k-4+4) ret( Ins( do_this, k, n1, d, n2, t ) )
}
else {
__ // reorganize, zuerst berechne uspar:
Btree_page * s = page[ deepest - 1 ];
int m = pos_m[ deepest - 1 ].m + 1 ;
uchar ispar = s->c[ eoheap ] ;
uchar uspar = 0 ;
if ( m < s -> e )
{
Btree_data * A = tA( Btree_data , p, 0 );
Btree_index * B = tA( Btree_index, s, m * L_index );
uchar spareA = p -> c[ eoheap ];
uchar spareB = s -> c[ eoheap ];
char kA[ L_heap ]; uchar nA = p -> c[ A -> ak ];
char kB[ L_heap ]; uchar nB = s -> c[ B -> ak ];
memcpy( kA, p->c + A->ak - spareA, spareA );
memcpy( kA + spareA, p->c + A->ak + 1
, ( uchar ) p->c[ A->ak ] );
__ memcpy( kB, s->c + eoheap - spareB, spareB );
__ __ memcpy( kB + spareB, s->c + B->ak + 1
, ( uchar ) s->c[ B->ak ] );
// Correct casting makes a difference here !!!!!!
__
char * xA = kA ;
char * xB = kB ;
nA = spareA + ( uchar ) p->c[ A->ak ] ;
nB = spareB + ( uchar ) s->c[ B->ak ] ;
uint M = min( nA, nB );
__ while ( uspar < M && *xA++ == *xB++ ) uspar++ ;
// traceStr( "kA", kA, nA );
// traceStr( "kB", kB, nB ); _2(uspar,spareA)
if ( uspar < spareA )
{
__ trace_page( *s ); // *page[ deepest - 1 ]
trace_page( *p ); // *page[ deepest ]
traceStr( "kA", kA, nA );
traceStr( "kB", kB, nB );
fErr5( treeID, m, uspar, spareA, spareB )
}
uspar -= spareA ;
}
__ reorganize( p, p->e, uspar );
}
}
else stop = 2 ;
}
if ( do_this == 'i' )
{
if ( p->t ) fErr // Index page
}
// -----------------------------------------------------------------------------
__
int m = pos_m[ deepest ].m ;
if ( 0 < pos_m[ deepest ].r )
then {
__ dn = tA( Btree_data, p->c, (m+1) * L_data );
memshift( A(dn) + L_data, dn, ( p->e - (m+1) ) * L_data ) ;
}
else {
__ dn = ( Btree_data * )( p->c + m * L_data );
if ( pos_m[ deepest ].r < 0 )
memshift( A(dn) + L_data, dn, ( p->e - m ) * L_data ) ;
}
if ( p->nr != page[ deepest]->nr ) fErr
__ __ __
BOOL alloc_data = 1 ;
if ( do_this == 'i' )
then {
if ( t == t_keep ) t = t_undef ;
__ uchar spare = p->c[ eoheap ]; n1 -= spare ;
dn->ak = p->h = p->h - n1 - 1 ;
p -> c[ dn->ak ] = n1 ;
memcpy( p->c + dn->ak + 1, k + spare, n1 );
at_surr = dn->surr = ++ descr -> surr ;
descr -> anz++ ;
p -> e++ ; // _1(p->e)
page[0] -> dirty = p -> dirty = 1 ;
}
else {
// if ( L_heap < dn->ad ) fErr
__ if ( n2 <= p->c[ dn->ad ] ) alloc_data = 0 ;
}
p -> dirty = 1 ; // _2( t, t_keep )
if ( t != t_keep )
then {
if ( alloc_data ) dn->ad = p->h = p->h - n2 - 2 ;
__ if ( p->h < p->e * L_data ) { trace_page( *p, sterr ); fErr }
p -> c[ dn->ad ] = n2 ;
p -> c[ dn->ad + 1 ] = t ; memcpy( p->c + dn->ad + 2, d, n2 );
// c[ dn->ad ] = length of data
// c[ dn->ad + 1 ] = type of data
// c[ dn->ad + 2 ] = first byte of data
}
__ if ( ! cache_ok() ) fErr __
ret( do_this )
// -----------------------------------------------------------------------------
// if ( p -> nr == 1 && p -> e > 100 ) pp = p ; check_pp
#ifdef __TESTING__
if is( k, "name_", 5 )
{
if ( t <= 1 ) fErr
store_256 st ;
if ( ! Get( k, n1, st ) ) { this->trace( k, stdout ); fErr }
if not_is ( d, st.c, n2 ) { trace_on L1_( *this ) fErr }
}
#endif
// if( treeID == 2 ) trace_page( *p );
if (0) if ( treeID == 1 && descr -> surr >= 10 )
{
printf( "\ncall_nr %i, INS: {%s}", call_nr, k );
}
LE_ret( do_this )
/* private: */ BOOL Btree :: reduce_spare
/* -----------------------------------------------------------------------------
If we want to insert a key larger than all current keys, we may
find the node's current spare too large.
However:
Reduction of spare implies that we will need more space in the node's
heap - more space than may be available. So, quite often, we need to
split the node.
-----------------------------------------------------------------------------
*/ (
Btree_page * p
, char * k // key
, char * V // Value
, uchar kL // Len of key
, uchar VL // Len of Value
)
LB_("Btree.reduce_spare")
char * k1 = k ;
char * s1 ;
char * s = s1 = spare_At( p );
uchar spare = p -> c[ eoheap ] ;
uchar same = 0 ;
uchar M = ( spare < kL )? spare : kL ;
while ( same < M ) if ( *s++ == *k++ ) same++ ; else break ;
if ( treeID == 1 && p->nr == 4361 )
{
_2( same, spare ); traceStr( "KEY_R", k1, kL )
traceStr( "SPARE", s1, spare )
}
if ( spare <= same ) ret( 0 ) else k = k1 ;
if (1)
{
Btree_page * neu = new_page();
uint e = eoheap ; // _2(e,eoheap) // uint statt uchar !!!
neu->t = p -> t ;
neu->c[ eoheap ] = 0 ;
if ( p->t )
then {
// INDEX page
Btree_index * x0 = tA( Btree_index, neu, 0 );
e -= kL ;
neu -> c[ x0->ak = e ] = kL ;
memcpy( neu->c + e+1, k, kL );
neu->e = 1 ;
}
else {
// DATA page
Btree_data * x0 = tA( Btree_data, neu, 0 );
Btree_data * x1 = tA( Btree_data, neu, L_data );
uchar skL = same + 1 ;
e -= ( 1 + skL );
neu -> c[ x0->ak = e ] = skL ;
memcpy( neu->c + e+1, k, skL );
e -= 1 ;
neu -> c[ x0->ad = e ] = 0 ;
x0->surr = 0 ;
e -= ( 1 + kL );
neu -> c[ x1->ak = e ] = kL ;
memcpy( neu->c + e+1, k, kL );
x1->surr = ++ descr -> surr ;
descr -> anz++ ;
traceStr("kkk",k,kL);
e -= ( 2 + VL ); traceStr("VVV",V,VL);
neu -> c[ x1->ad = e ] = VL ;
neu -> c[ e+1 ] = t_data ;
memcpy( neu->c + e+2, V, VL );
neu->e = 2 ;
}
neu -> dirty = 1 ;
neu -> h = e ;
char300 sk ; *sk = same+1 ; memcpy( sk+1, k, same+1 );
__ if ( deepest == 1 )
then into_root ( sk, neu -> nr );
else into_father ( sk, 0, neu -> nr );
if ( ! locate( k, kL ) )
{
treeID = -abs( treeID ); _1("RRRRRRRRRR")
deepest = 0 ; _3( locate( k, kL ), k, kL )
trace_deepest( stdout ); traceStr( "KEY_k", k, kL ); fErr
}
ret(1)
}
LE_ret( 0 )
/* private: */ void Btree :: check_path
// -----------------------------------------------------------------------------
(
char * k
, int k_L
, Surr k_father
)
LB_("Btree.check_path")
if ( k_L < 1 ) fErr
if ( *k != '/' ) fErr
char * ek = k + k_L ; while ( k < ek ) if ( ! *( k++ ) ) fErr
if ( k_father < 0 || descr -> surr < k_father ) fErr
LE_
/* private: */ void Btree :: into_father
/* -----------------------------------------------------------------------------
Der Aufrufer sagt:
Insert ( k, son ) into index page[ --deepest ] .
Die Funktion garantiert: fErr || ok && Return( re-localize )
-----------------------------------------------------------------------------
*/ (
char * k // the key, k[0] its length
, uchar spare // of son
, pageNr son // Btree_index.son
)
LB_("Btree.into_father")
// if ( strPairs && treeID == 1 ) if not_in_str( k[1], "(1" ) fErr2( *k, k+1 )
Btree_page * pp ;
if ( descr->last < son ) { L2_( son, descr->last ) fErr }
__ if ( deepest )
then {
__ // we are not in the root
Btree_page * p = page[ --deepest ] ; if ( ! p->t ) fErr
Btree_index * n ;
uchar keylen = *k ;
locate_ipos( k+1, *k, pos_m[ deepest ].m, pos_m[ deepest ].r, *p );
__ int m = pos_m[ deepest ].m ;
if ( p->e <= m ) { L2_( p->e, m ) trace_page( *p ); fErr }
if ( 0 < pos_m[ deepest ].r )
then {
__ if ( pos_m[ 0 ].r <= 0 ) fErr else m++ ;
}
esif ( pos_m[ deepest ].r == 0 )
{
__ printf( "\nEintrag existiert schon - arbeiten wir mit der alten"
"\nVersion einer per split_data() reduzierten Seite? Wenn"
"\nja, muss es jene sein, die in der folgenden Index Page"
"\nunmittelbar vor diesem Eintrag genannt ist:\n\n" );
_2( pos_m[ deepest ].m, k[0] )
traceStr( "key to insert int page[deepest]", k+1, k[0] );
get_page( deepest + 2, son );
trace_page( * page[ deepest ] );
trace_page( * page[ deepest + 2 ] );
}
if ( p->h - p->e * L_index < 1 + keylen + L_index )
then {
__ // noTrace = false ; trace_page( *p );
__ split_index( k, son, m, p );
__
}
else {
uchar spare = ( p->nr )? p->c[ eoheap ] : 0 ;
if ( keylen < spare )
{
trace_deepest( stdout ); fErr3( keylen, spare, p->nr )
}
uchar s = 1 + keylen - spare ;
p->h -= s ;
*( A(p) + p->h ) = keylen - spare ;
__ memcpy( A(p) + p->h+1, k+1 + spare, keylen - spare );
__
n = tA( Btree_index, p, m * L_index );
if ( p->e < m ) // hier wirklich < m ( nicht wie oben <= )
{
L3_( *this, m, p->nr ) fErr
}
int shift = p->e++ - m ; if ( shift < 0 ) fErr
if ( shift ) memshift( A(n) + L_index, n, shift * L_index );
n->ak = p->h ;
n->son = son ;
p->dirty = 1 ;
__ }
__ pp = p ;
// p hier nicht notwendig dirty !!
}
else pp = into_root( k, son );
ret_
// if ( abs( treeID ) == 2 && son == 10006 ) // show the new father version:
if ( abs( treeID ) == 1 && son == 4098 ) // show the new father version:
{
noTrace = false ;
uchar L = k[0] ; if ( 252 < L ) fErr1( L )
char300 xx ; memcpy( xx, k+1, L ); // _1("WWW")
char * ee = xx + L ;
char * x = xx-1 ; while( ++x < ee ) if ( !*x ) *x = 0 ; *x = 0 ;
printf( "\nFATHER - SON: k=%s\n", xx );
__ trace_page( *pp );
printf( "\nFATHER - SON: k=%s\n", xx );
// fErr
}
LE_
/* private: */ Btree_page * Btree :: into_root
/* -----------------------------------------------------------------------------
Der Aufrufer sagt:
Insert ( k, son ) into root (= page[0] ).
Die Funktion garantiert: fErr || ok && Return( re-localize )
-----------------------------------------------------------------------------
*/ (
char * k // the key, k[0] its length
, pageNr son // Btree_index.son ////alt: int
)
LB_("Btree.into_root")
printf( "\nINTO_Root: son = %u", son );
if ( treeID == 1 ) if not_in_str( k[1], "(1" ) fErr2( *k, k+1 )
if ( descr->last < son ) { L2_( son, descr->last ) fErr }
deepest = 0 ;
Btree_page * p = page[0] ; if ( ! p->t ) fErr
Btree_index * n ;
uchar keylen = *k ;
locate_ipos( k+1, *k, pos_m[ deepest ].m, pos_m[ deepest ].r, *p );
int m = pos_m[ deepest ].m ;
if ( p->e <= m ) { L2_( p->e, m ) trace_page( *p ); fErr }
__
if ( 0 < pos_m[ deepest ].r )
then {
if ( pos_m[ 0 ].r <= 0 ) fErr else m++ ;
}
esif ( pos_m[ deepest ].r == 0 )
{
printf( "\nEintrag existiert schon - arbeiten wir mit der alten"
"\nVersion einer per split_data() reduzierten Seite? Wenn"
"\nja, muss es jene sein, die in der folgenden Index Page"
"\nunmittelbar vor diesem Eintrag genannt ist:\n\n" );
_2( pos_m[ deepest ].m, k[0] )
traceStr( "key to insert int page[deepest]", k+1, k[0] );
get_page( deepest + 2, son );
trace_page( * page[ deepest ] );
trace_page( * page[ deepest + 2 ] );
}
__
if ( p->h - p->e * L_index < 1 + keylen + L_index )
then {
__ split_root( k, son );
__ if ( ! cache_ok() ) fErr2( son, p->nr )
}
else {
uchar spare = ( p->nr )? p->c[ eoheap ] : 0 ;
uchar s = 1 + keylen - spare ;
p->h -= s ; memcpy( A(p) + p->h, k + spare, s );
n = tA( Btree_index, p, m * L_index );
if ( p->e < m ) // hier wirklich < ( nicht wie oben <= )
{
L3_( *this, m, p->nr ) fErr
}
int shift = p->e++ - m ; if ( shift < 0 ) fErr
if ( shift ) memshift( A(n) + L_index, n, shift * L_index );
n->ak = p->h ;
n->son = son ;
p->dirty = 1 ;
__ }
ret( p )
// trace_page( *p ); _1("END of INSERT into ROOT")
LE_ret( p )
/* private: */ void Btree :: split_data
/* -----------------------------------------------------------------------------
Node neu is empty. Move alt.e/2 nodes from alt to neu.
-----------------------------------------------------------------------------
*/ (
Btree_page * alt
, Btree_page * neu
)
LB_("Btree.split_data")
__
if ( alt->t ) fErr // not data page
to_extra( alt );
to_extra( neu );
uchar spare_alt = alt->c[ eoheap ];
int na = 0 ; // number of data bytes to remain in node 'alt'
int ta = 0 ; // to node 'alt'
int half = alt->e/2 ;
while ( ta < half )
{
Btree_data * n = tA( Btree_data, alt, ta++ * L_data );
na += 3 + ( uchar )alt->c[ n->ak ] + ( uchar )alt->c[ n->ad ] ;
}
// ------------------------------------------- write contents of node 'neu':
neu -> t = alt -> t ;
neu -> h = eoheap ;
memcpy( neu, A(alt) + ta * L_data, neu->e * L_data );
int tr ; // transfer
int i = ta ;
int w = 0 ;
int e = 1 ;
__
if ( alt->e <= i ) { trace_page( *alt ); fErr }
Btree_data * s = tA( Btree_data, alt, 0 );
Btree_data * a = tA( Btree_data, alt, ta * L_data );
Btree_data * n = tA( Btree_data, neu, 0 );
uchar spare = spare_alt ;
neu->h -= tr = 1 + ( uchar ) alt->c[ a->ak ] + spare ; w += tr ;
if ( spare )
memcpy( neu->c + neu->h , alt->c + s->ak - spare, spare );
memcpy( neu->c + neu->h + spare, alt->c + a->ak , tr - spare );
n->ak = neu->h + spare ;
neu->h -= 2 ; w += 2 ;
neu->c[ neu->h ] = 0 ;
neu->c[ neu->h+1 ] = t_undef ;
neu->c[ eoheap ] = spare ; // L2_( spare, spare_alt )
n->surr = 0 ;
n->ad = neu->h ;
if ( i <= 0 || e != 1 ) fErr2( i, e )
BOOL mkuspar = 1 ; uchar uspar = 0 ;
uchar zspar = 0 ;
while ( i < alt->e )
{
Btree_data * a = tA( Btree_data, alt, i++ * L_data );
Btree_data * n = tA( Btree_data, neu, e++ * L_data );
neu->h -= tr = 1 + ( uchar ) alt->c[ a->ak ] ; w += tr ;
memcpy( neu->c + neu->h, alt->c + a->ak, tr ); n->ak = neu->h ;
neu->h -= tr = 2 + ( uchar ) alt->c[ a->ad ] ; w += tr ;
//
memcpy( neu->c + neu->h, alt->c + a->ad, tr ); n->ad = neu->h ;
n->surr = a->surr ;
if(1) if ( mkuspar )
{
char * neu_0 = alt->c + a->ak+1 ; uchar n0 = alt->c[ a->ak ] ;
Btree_data * x = tA( Btree_data, alt, 0 );
char * alt_0 = alt->c + x->ak+1 ; uchar a0 = alt->c[ a->ak ] ;
while ( *neu_0++ == *alt_0++ && uspar < min( n0, a0 ) )
{
uspar += 1 ;
}
// if not_is( alt->c + x->ak+1, alt->c + a->ak+1, uspar ) fErr
mkuspar = 0 ;
}
if(1) {
uint xspar = 0 ;
Btree_index * a = tA( Btree_index, alt, ta * L_index );
Btree_index * n = tA( Btree_index, alt, (alt->e-1) * L_index );
uchar n1 = alt->c[ a->ak ] ; char * c1 = alt->c + a->ak + 1 ;
uchar n2 = alt->c[ n->ak ] ; char * c2 = alt->c + n->ak + 1 ;
uchar m = min( n1, n2 ) ;
while ( xspar < m && *c1++ == *c2++ ) xspar += 1 ;
uspar = min( xspar, uspar ); // muss sein, macht 700000 ok
}
if(0) if ( alt->e <= i ) // berechnet zspar for neu:
{ // warum funktioniert das nicht
int d = deepest - 1 ;
while ( 0 <= d && page[ d ]->e-1 <= pos_m[ d ].m ) d-- ;
if ( 0 <= d )
{
uint nb = pos_m[ d ].m + 1 ;
Btree_page * nxt = page[ d ] ;
Btree_index * a = tA( Btree_index, alt, ( 0 ) * L_index );
Btree_index * n = tA( Btree_index, nxt, ( nb ) * L_index );
uchar n1 = alt->c[ a->ak ] ; char * c1 = alt->c + a->ak + 1 ;
uchar n2 = nxt->c[ n->ak ] ; char * c2 = nxt->c + n->ak + 1 ;
uchar m = min( n1, n2 ) ;
while ( zspar < m && *c1++ == *c2++ ) zspar += 1 ;
}
}
}
if ( ! neu ) fErr
if ( ! e ) fErr
neu->e = e ;
// reorganize( neu, e , zspar ); __ // notwendig, da heap nicht sortiert
__ reorganize( alt, ta, uspar ); __ // notwendig, da heap nicht sortiert
// ---------------------------------- update father page of 'alt' and 'neu':
if ( deepest )
then {
char * a = alt->c + (( Btree_data * )( alt ))[ alt->e-1 ].ak ;
char * n = neu->c + (( Btree_data * )( neu ))[ 0 ].ak ;
// Mache Index Key so kurz wie mglich:
char * A = a ;
char * N = n ;
uchar aL = *a++ ;
uchar nL = *n++ ;
uchar kL = 0 ;
char k[ L_heap ];
char u[ L_heap ];
if ( uspar )
{
char * x = alt->c + (( Btree_data * )( alt ))[ 0 ].ak ;
memcpy( u , x - uspar, uspar );
memcpy( u + uspar, A+1 , aL );
aL += uspar ; a = u ;
}
memcpy( k+1, n-1 - spare, spare ); // "n-1" ist richtig !!!
// showStr( "a:" , a , aL );
// showStr( "n:" , n , nL );
// showStr( "n-1-spare", n-1-spare, spare);
while ( *a++ == *n++ && kL < aL && kL < nL ) kL += 1 ;
memcpy( k+1 + spare, N+1, kL );
if ( aL == kL++ ) then k[ kL + spare ] = N[ kL ] ;
else k[ kL + spare ] = N[ kL ] = *(--a) + 1 ;
*k = kL + spare ; *N = kL ;
// _ trace_page( *neu );
__ into_father( k, spare, neu -> nr ); __ // _ trace_page( *neu );
}
else fErr // the root is never a data page
// Weder alt noch neu brauchen hier dirty zu sein!
__ if ( ! cache_ok() ) fErr
__
LE_
/* private: */ void Btree :: split_index
/* -----------------------------------------------------------------------------
Der Aufrufer sagt:
Make the second half of this index page a new index page. Then
insert the pair ( k, son ) into the union of these two pages.
Die Funktion garantiert: fErr || ok && Return( re-localize )
-----------------------------------------------------------------------------
*/ (
char * k //
, pageNr son // node.nr //alt: uint2
, int & m //
, Btree_page * & p //
)
LB_("Btree.split_index")
__ if ( ! cache_ok() ) fErr
//
if ( deepest == 0 )
{
if ( ! cache_ok() ) fErr
__ split_root( k, son );
if ( ! cache_ok() ) fErr2( son, p->nr )
ret_
}
__
uchar keylen = ( uchar )k[ 0 ] ;
Btree_page * alt = page[ deepest ] ; if ( ! alt->t ) fErr
Btree_page * neu = new_page() ;
to_extra( alt );
to_extra( neu );
// trace_page( *alt );
path kr ; show_krMin( alt, kr );
/* printf( "----> m = %i \n", pos_m[ deepest ].m );
printf( "----> r = %i \n", pos_m[ deepest ].r );
printf( "split %i ---> %i \n", alt->nr, neu->nr );
// trace_page( *alt );
*/
int na = 0 ; // number of data bytes to remain in node 'alt'
int ta = 0 ; // to node 'alt'
int half = alt -> e/2 ;
while ( ta < half )
{
Btree_index * n = tA( Btree_index, alt, ta++ * L_index );
na += 1 + ( uchar )alt->c[ n->ak ] ;
}
// write contents of node 'neu':
neu->t = alt -> t ;
uchar spare = neu->c[ eoheap ] = alt->c[ eoheap ] ;
int tr ;// transfer
int i = ta ;
int e = eoheap - 1 - spare ;
memcpy( neu->c + e, alt->c + e, spare + 1 ); // ok so !!!!!
neu->e = 0 ;
// _1("www4") trace_page( *alt );
// _1("www8") trace_page( *neu );
while ( i < alt->e )
{
Btree_index * a = tA( Btree_index, alt, i++ * L_index );
Btree_index * n = tA( Btree_index, neu, neu -> e++ * L_index );
neu->h = ( e -= tr = 1 + ( uchar ) alt->c[ a->ak ] );
n->ak = neu->h ;
neu->c[ e ] = ( uint ) alt->c[ a->ak ] ; // Len
memcpy( neu->c + e+1, alt->c + a->ak+1, tr-1 );
n->son = a->son ;
if ( descr->last < n->son ) fErr
}
__ if ( ! cache_ok() ) fErr
uchar uspar = 0 ;
{
Btree_index * a = tA( Btree_index, alt, 0 );
Btree_index * n = tA( Btree_index, neu, 0 );
uchar n1 = alt->c[ a->ak ] ; char * c1 = alt->c + a->ak + 1 ;
uchar n2 = neu->c[ n->ak ] ; char * c2 = neu->c + n->ak + 1 ;
uchar m = min( n1, n2 ) ;
while ( uspar < m && *c1++ == *c2++ ) uspar += 1 ;
}
if ( alt->e - ta != neu->e ) { L2_( alt->e - ta , neu->e ); fErr }
path kr1 ; show_krMin( alt, kr1 );
__ reorganize( alt, ta, uspar ); // notwendig, da heap nicht sortiert
__ if ( ! cache_ok() ) fErr1( alt->nr )
__
path kr2 ; show_krMin( alt, kr2 );
int depth = deepest ;
m = pos_m[ deepest ].m ;
if ( pos_m[ deepest ].r < 0 ) m-- ;
// Now insert ( k, son ) at ( alt conc neu )[ m ] :
// -------------------------------------------------------------------------
if ( alt->e <= m ) { m -= alt->e ; p = neu ; }
if ( ! p->t ) fErr
m++ ;
Btree_index * n = tA( Btree_index, p, m * L_index );
if ( p->h - p->e * L_index < 1 + keylen + L_index )
then {
deepest-- ;
__ Btree_index * n = tA( Btree_index, neu, 0 * L_index );
char * k = neu->c + n->ak ;
if ( ! cache_ok() ) fErr2( neu->nr, p->nr )
_1(deepest)
__ if ( 0 < deepest )
then split_index( k, neu->nr, m, p );
else split_root ( k, neu->nr );
__ if ( ! cache_ok() ) fErr2( neu->nr, p->nr )
}
else {
uchar spare = ( p->nr )? p->c[ eoheap ] : 0 ; // zeige(4675,5);
if ( m < p->e )
then {
memshift( A(n) + L_index, n, ( p->e - m ) * L_index );
}
if ( keylen < spare ) fErr2( keylen, spare )
n -> ak = p->h -= ( keylen - spare + 1 );
n -> son = son ;
*( A(p) + p->h ) = ( uchar )( keylen - spare );
__ memcpy( A(p) + p->h+1, k+1 + spare, keylen - spare );
__
p->e++ ;
// -----------------------------------------------------------------------
}
n = tA( Btree_index, neu, 0 );
if ( neu->c[ eoheap ] )
then {
char300 u ;
uchar s1 = neu->c[ eoheap ] ;
uchar s2 = neu->c[ n->ak ] ;
__ memcpy( u+1, spare_At( neu ) , s1 );
__ memcpy( u+1+ s1, neu->c + n->ak+1, s2 );
__
*u = s1 + s2 ;
into_father( u, 0, neu->nr ); __
}
else into_father( neu->c + n->ak, 0, neu->nr ); __
ret_
// Weder alt noch neu brauchen hier dirty zu sein!
path kr3 ; show_krMin( alt, kr3 );
path kr4 ; show_krMin( neu, kr4 );
__ if ( ! cache_ok() ) fErr
LE_
/* private: */ void Btree :: split_root
/* -----------------------------------------------------------------------------
the Btree is growing at its root
-----------------------------------------------------------------------------
*/ (
char * k // the key, k[0] its length
, pageNr son // Btree_index.son
)
LB_("Btree.split_root")
if ( ! cache_ok() ) fErr1( son )
root_e = 0 ;
if ( deepest ) fErr
int j = L_Bp ; while ( ! page[ --j ] ) ; j++ ;
if ( L_Bp <= j )
{ _2(L_Bp,j)
int i = -1 ; while ( ++i < L_Bp ) { _1( page[i] -> nr ) }
_2( descr -> last, L_Cp )
S_ "Btree too deep - augment L_Bp (1) = %i", L_Bp _fErr
}
do {
pos_m[ j ] = pos_m[ j-1 ] ;
page [ j ] = page [ j-1 ] ;
}
while ( --j );
// if ( ! cache_ok() ) fErr1( son )
page[ 1 ] = new_page(); pageNr N1 = page[ 1 ]->nr ;
*( page[1] ) = *( page[0] ); page[1]->nr = N1 ;
Btree_page * p = page[0] ;
if ( ! cache_ok() ) fErr2( son, N1 )
to_extra( page[0] );
to_extra( page[1] );
p->h = pos_descr - 1 ;
p->e = 1 ;
p->dirty = 1 ;
Btree_index * n = tA( Btree_index, p, L_index );
pos_m[ 0 ].r = 1 ;
pos_m[ 0 ].m = 0 ;
(( Btree_index * ) p ) -> son = N1 ;
// noTrace = false ; trace_page( *page[1] );
// if ( ! cache_ok() ) fErr
deepest = 1 ; split_index( k, son, pos_m[1].m, page[1] );
// if ( ! cache_ok() ) fErr
LE_
/* private: */ uchar Btree :: our_uspar
// -----------------------------------------------------------------------------
(
char * xu
, char * xo
)
LB_("Btree.our_uspar")
uchar m1 = *xu++ ;
uchar m2 = *xo++ ;
uint M = min( m1, m2 ); uchar uspar = 0 ;
while ( uspar < M && *xu++ == *xo++ ) uspar++ ;
// Es muss hier wirklich uspar < M sein ( da ja *xu = Len(xu) )
// ( da ja *xo = Len(xo) )
LE_ret( uspar )
/* private: */ void Btree :: reorganize
/* -----------------------------------------------------------------------------
Der Aufrufer sagt:
Set p->e = e_neu , then reorganize the page for pruning all garbage.
Die Funktion garantiert: fErr || ok && ( p->dirty )
-----------------------------------------------------------------------------
*/ (
Btree_page * p
, int e_neu // define p->e = e_neu
, uchar usparP // neues spare = altes spare + uspar
)
LB_("Btree.reorganize")
//
// _1(uspar)
if ( !p ) fErr // __ trace_page( *p ); _2( e_neu, p->e )
if ( p->e < e_neu ) S_ "p->e = %i < %i = e_neu \n", p->e, e_neu _fErr
if ( ! p->e ) fErr
p->e = e_neu ;
Btree_page co = *p ;
char comm[ L_Btree_heap ] ;
int2 n, e = eoheap ;
uchar spare = ( co.nr )? co.c[ eoheap ] : 0 ;
if ( p->t )
then {
__ // p is an INDEX page
Btree_index * xu = tA( Btree_index, &co, 0 * L_index );
Btree_index * xo = tA( Btree_index, &co, ( co.e-1 ) * L_index );
uchar uspar = our_uspar( co.c + xu->ak, co.c + xo->ak );
if ( usparP < uspar ) uspar = usparP ;
if ( uspar != usparP )
{
noTrace = false ; trace_deepest();
_2(uspar,usparP)
trace_page( co ); fErr2( uspar, usparP )
}
uchar spar = p->c[ eoheap ] = spare + uspar ; // = neues spare ///IDX
if ( p->nr == 0 )
{
e -= L_descr ;
if ( spar ) fErr
}
for ( int i = 0 ; i < p->e ; i++ )
{
Btree_index * at1 = tA( Btree_index, &co, i * L_index );
Btree_index * at2 = tA( Btree_index, p, i * L_index );
if ( i == 0 )
then {
memcpy( comm , co.c + eoheap - spare, spare );
memcpy( comm + spare, co.c + at1->ak + 1 , uspar );
comm[ spar ] = 0 ;
p->c[ eoheap ] = spar ;
memcpy( p->c + ( e -= spar ), comm, spar );
}
n = ( uchar )( co.c[ at1->ak ] ) - uspar ;
p->c[ e = e-1 - n ] = n ;
memcpy( p->c + e+1, co.c + at1->ak + 1 + uspar, n );
at2->ak = e ;
} // _2(p->e,p->nr) // zeige(4675,4);
char * ee = ( char * ) tA( Btree_index, p, co.e * L_index );
if ( p->c + e < ee ) fErr1( ee - ( p->c + e ) )
__ }
else { // p is a DATA page
char * ee = tA( char, p, co.e * L_data );
__ Btree_data * xu = tA( Btree_data, &co, 0 * L_index );
Btree_data * xo = tA( Btree_data, &co, ( co.e-1 ) * L_index );
uchar uspar = our_uspar( co.c + xu->ak, co.c + xo->ak );
if ( usparP < uspar ) uspar = usparP ;
if (1) if ( uspar != usparP && *( co.c + xu->ak ) )
{
noTrace = 0 ;
trace_data( co );
printf( "\nEs sollte *( co.c + xu->ak ) == Len(XY)-spare sein:" );
// fErr4( uspar, usparP, *( co.c + xu->ak ), co.nr )
}
uchar spar = p->c[ eoheap ] = spare + uspar ; // = neues spare
for ( int i = 0 ; i < co.e ; i++ )
{
p -> e = i+1 ;
__ Btree_data * at1 = tA( Btree_data, &co, i * L_data );
Btree_data * at2 = tA( Btree_data, p, i * L_data );
// -------------------------------------------------------------------
if ( i == 0 )
{
memcpy( comm , co.c + at1->ak - spare, spare );
memcpy( comm + spare, co.c + at1->ak + 1 , uspar );
comm[ spar ] = 0 ;
}
n = 1 + ( uchar )( co.c[ at1->ak ] ) - uspar ;
at2->ak = e -= n ;
if ( n <= 0 || p->c+e < ee )
{
// Not enough space in this node - warum
noTrace = false ; trace_page( co );
fErr5( i, e, n, uspar, ee - p->c+e )
}
memcpy( p->c + e+1, co.c + at1->ak + 1 + uspar, n-1 );
p -> c[e] = co.c[ at1->ak ] - uspar ;
if ( i == 0 && spar ) // dies wirklich erst hier zuletzt
{
memcpy( p->c + ( e -= spar ), comm, spar );
}
__ // -------------------------------------------------------------------
n = 2 + ( uchar )( co.c[ at1->ad ] );
at2->ad = e -= n ;
memcpy( p->c + e, co.c + at1->ad, n );
if ( L_heap <= max( at2->ak, at2->ad ) ) fErr
__ }
if ( p->c + e < ee ) fErr1( ee - ( p->c+e ) )
}
p -> dirty = 1 ;
p -> h = e ;
__
// ret_
//
if ( p->nr == 4358 && treeID == 1 )
{
noTrace = false ; trace_page( *p ); noTrace = true ;
}
//
LE_
/* private: */ Btree_page * Btree :: new_page(
/* -----------------------------------------------------------------------------
Create a new page in the tree and cache it.
-----------------------------------------------------------------------------
*/ )
LB_("Btree.new_page")
if ( L_Cp <= e_cache ) new_cache(-1);
if ( L_Cp <= e_cache ) fErr1( e_cache );
if ( ! cache[ e_cache ] ) cache[ e_cache ] = new Btree_page ;
Btree_page * p = cache[ e_cache ++ ] ;
p -> nr = ++ descr->last ; // Btree storage is non-shrinking so far
if ( p->nr < 0 ) fErr1( p->nr )
p -> h = eoheap ; p->c[ eoheap ] = 0 ;
p -> e = 0 ;
p -> dirty = 1 ;
if ( cache[0] -> nr ) fErr
if ( A( descr ) != A( cache[0] ) + pos_descr ) fErr
LE_ret( p )
/* public: */ uint Btree :: anz_pages(
/* -----------------------------------------------------------------------------
return current number of pages
-----------------------------------------------------------------------------
*/ )
LB_("Btree.anz_pages")
LE_ret( descr->last + 1 )
/* private: */ void Btree :: trace_in_cache( pageNr nr
/* -----------------------------------------------------------------------------
trace the cached version of page
-----------------------------------------------------------------------------
*/ )
LB_("Btree.trace_in_cache(")
if ( noTrace ) ret_
if ( 0 < e_cache ) printf( "\ncache[ 0]: p.nr = %i", cache[0] -> nr );
// if ( 1 < e_cache )
// if ( 2 < e_cache )
// if ( 3 < e_cache )
for ( int i = 0 ; i < e_cache ; i++ )
{
if ( cache[i] -> nr == nr )
then {
printf( "\npage %i found as cache[%i]:", nr, i );
printf( "\ntrace_in_cache page %i, call_NR = %u", nr, call_nr );
trace_page( *cache[i] );
ret_
}
else printf( "\ncache[%5i]: p.nr = %i", i, cache[i] -> nr );
}
LE_
/* private: */ void Btree :: zeige
/* -----------------------------------------------------------------------------
trace page[ i ].nr == pnr
-----------------------------------------------------------------------------
*/ (
long pnr
, uint steNr
)
LB_("Btree.zeige")
printf( "\n+++++++++++++++++++ ZEIGE %i,%i:", pnr, steNr );
int s = -1 ;
while ( ++s < e_cache ) if ( cache[s]->nr == pnr )
{
traceAb = 55 ;
trace_page( *cache[s] ); ret_
}
LE_
/* private: */ void Btree :: get_page
/* -----------------------------------------------------------------------------
establisch page[ i ].nr == nr with page[i] pointing into the cache
-----------------------------------------------------------------------------
*/ (
int i
, long nr
)
LB_("Btree.get_page")
if ( nr < 0 || descr -> last < nr ) fErr2( descr -> last, nr )
if ( L_Bp <= i )
{
S_ "Btree too deep - augment L_Bp (2) = %i", L_Bp _fErr
}
if ( i == 0 || nr == 0 ) fErr // root always in the cache
int s = 0 ;
if ( Bf )
then {
while ( s < e_cache )
{
if ( cache[s]->nr == nr ) break ; else s++ ;
}
if ( s == e_cache )
then {
if ( L_Cp <= e_cache )
{
new_cache(i);
if ( L_Cp <= e_cache ) fErr2( e_cache, i );
}
if ( ! cache[ e_cache ] ) cache[ e_cache ] = new Btree_page ;
if(0) if ( nr > file_len( Bf )/L_page )
{
_2( nr, nr - file_len( Bf )/L_page )
}
getfw( Bf, 0, nr, L_page, cache[ e_cache ] );
page[ i ] = cache[ e_cache++ ] ;
}
else page[ i ] = cache[ s ] ;
}
else page[ i ] = cache[ nr ] ;
if ( page[ i ] -> nr != nr ) fErr5( Bf, i, e_cache, page[ i ] -> nr, nr )
LE_
/* private: */ void Btree :: to_Disk( int s
// -----------------------------------------------------------------------------
)
LB_("Btree.to_Disk(")
Btree_page * p = cache[s] ; if ( ! p -> dirty ) ret_
if ( p->nr < 0 ) fErr
putfw( Bf, 0, p -> nr, L_page, p );
p -> dirty = 0 ;
LE_
/* private: */ void Btree :: to_extra( Btree_page * p
// -----------------------------------------------------------------------------
)
LB_("Btree.to_extra(")
if ( ! p ) fErr
int s = 0 ; while ( s < e_cache ) if ( p == cache[ s++ ] ) ret_
if ( e_extra >= L_Bp * 3 ) fErr
extra[ e_extra++ ] = p ;
LE_
/* public: */ BOOL Btree :: cache_ok (
// -----------------------------------------------------------------------------
)
LB_("Btree.cache_ok")
ret(1) // nur zum Test auskommentieren
if (1)
{
uchar spare = cache[0] -> c[ eoheap ] ;
if ( spare ) ret( 0 )
if ( spare )
{
m_errMess "System: Btree(%i).root.spare is NOT NULL !!!" m_
treeID, ret_error
}
;
}
for ( int s = 1 ; s < e_cache ; s++ )
{
if ( cache[s]->nr <= 0 || cache[s]->e <= 0 )
{
noTrace = false ; trace_page( *cache[s] ); noTrace = true ;
fErr3( s, cache[s]->nr, cache[s]->e )
}
if ( cache[ s++ ] -> nr < 0 ) ret( 0 )
}
LE_ret( 1 )
/* private: */ void Btree :: ensure_cache( Btree_page * p
// -----------------------------------------------------------------------------
)
LB_("Btree.ensure_cache(")
if ( ! p ) ret_
int s = 0 ; while ( s < e_cache ) if ( p == cache[ s++ ] ) ret_
if ( e_cache >= L_Cp )
{
m_errMess "System: no more space in the Cache" m_
ret_error
}
if ( p->nr < 0 ) fErr
cache[ e_cache++ ] = p ;
LE_
/* private: */ void Btree :: new_cache( int notAt
// -----------------------------------------------------------------------------
)
LB_("Btree.new_cache(")
int s ; Btree_page * xx[ L_Cp ];
bb printf( "\nnew_cache() for Btree %i, notAt = %i, e_cache = %i"
, treeID, notAt, e_cache );
if ( L_Cp < e_cache ) fErr2( L_Cp, e_cache )
if ( Bf == 0 )
then {
// Btree so far in memory only - now L_Cp too small, go to disk:
__ if (0) for ( s = 0 ; s < e_cache ; s++ )
{
printf( "\ncache[ %4i ] -> nr = %4i", s, cache[s] -> nr );
}
printf( "\n\ncreate cache for Btree %s", BtreeName );
char * x = eos( Bfn ) - 1 ;
while in_name( *x ) x-- ; char m = *x ; *x = 0 ;
dir_exist( Bfn ); *x = m ;
Bf = open( Bfn, 'c', 'B' ); // cache on disk
// _2( Bf, Bfn )
for ( s = 1 ; s < e_cache ; s++ )
{
Btree_page * p = xx[s] = cache[s] ; if ( ! p -> dirty ) fErr
if ( p->nr < 0 ) fErr2( s, p->nr )
putfw( Bf, 0, p->nr, L_page, p );
}
Volatile = true ;
}
esif ( e_cache == L_Cp ) // i.e. no more space in the Cache
{
__ for ( s = 1 ; s < e_cache ; s++ )
{
Btree_page * p = xx[s] = cache[s] ;
if ( p->nr < 0 ) fErr3( e_cache, s, p->nr )
if ( p -> dirty ) putfw( Bf, 0, p->nr, L_page, p );
p -> dirty = 1 ; // muss so sein
}
for ( s = 0 ; s < e_extra ; s++ ) extra[s] -> dirty = 1 ;
}
else S_ "L_Cp = %i <= %i = e_cache \n", L_Cp, e_cache _fErr
e_cache = 1 ;
for ( s = 1 ; s <= deepest ; s++ ) if ( s != notAt )
{
if ( page[s]->nr < 0 ) fErr2( s, page[s]->nr )
cache[ e_cache++ ] = page[s] ;
page[s] -> dirty = 0 ;
}
// if ( page[ 0 ]->nr != 0 ) fErr1( call_nr ) else _2( page[0], cache[0] )
int e = e_cache ;
for ( s = 1 ; s < L_Cp ; s++ ) if ( xx[s] -> dirty )
{
xx[s] -> nr = -1 ;
if ( e < L_Cp ) cache[ e++ ] = xx[ s ] ; else fErr2( e, L_Cp )
}
if ( page[ 0 ]->nr != 0 ) fErr3( call_nr, page[0], cache[0] )
LE_
/* public: */ char * Btree :: retAlias ( char * nam
// -----------------------------------------------------------------------------
)
LB_("Btree.retAlias")
if ( Get( nam, AL ) ) ret( AL.c )
printf( "\nno Alias for [%s]\n", nam );
LE_ret( nam )
/* public: */ Surr Btree :: retNr
/* -----------------------------------------------------------------------------
ordnet jedem String eine unique Number zu
-----------------------------------------------------------------------------
*/ (
BOOL existiert
, char * str
)
LB_("Btree.retNr")
if ( ! str ) fErr
if ( ! *str ) ret( 0 )
KVStore st ; Surr s = Get( str, st );
if ( ! s )
{
if ( existiert ) fErr1( str )
StrIns( 'e', str ); // returns a char, not a Surr !!!
s = contains( str );
}
LE_ret( s )
/* public: */ Btree * Btree :: invers (
/* -----------------------------------------------------------------------------
Mache alle Paare ( st.k, st.c ) zu Paaren ( st.c, st.k )
-----------------------------------------------------------------------------
*/ )
LB_("Btree.invers")
Btree * um = new Btree ;
KVStore st ; Surr s = GetFirst( st );
while ( s )
{
um -> StrIns( 'e', st.c, st.k );
s = Next( st );
}
LE_ret( um )
/* public: */ void Btree :: become_end_to_end_transitive ( Btree * invers
/* -----------------------------------------------------------------------------
Create the transitive closure of a binary relation ~ given by
records str1~str2 in this tree
Then delete all pairs y~z for which there is a pair x~y.
-----------------------------------------------------------------------------
*/ )
LB_("Btree.become_end_to_end_transitive")
become_transitive();
Btree Links, Rechts ;
KVStore st ; Surr s = GetFirst( st );
while ( s )
{
char * x = in_str( '~', st.k );
if ( !x || in_str( '~', x+1 ) ) fErr1( st.k )
*x = 0 ;
Links .StrIns( 'e', st.k );
Rechts.StrIns( 'e', x+1 );
*x = '~' ;
s = Next( st );
}
s = GetFirst( st );
while ( s )
{
char * x = in_str( '~', st.k ); *x = 0 ;
if ( Links.contains( st.k ) && Rechts.contains( st.k ) )
then {
*x = '~' ;
Rem( st.k );
}
esif ( invers )
{
char300 xx ; s_( xx, "%s~%s", x+1, st.k );
invers -> StrIns( 'e', xx );
}
*x = '~' ;
s = Getmin_GR( st, st.k );
}
LE_
/* public: */ void Btree :: check_Btree
/* -----------------------------------------------------------------------------
needed for j2h.ic
-----------------------------------------------------------------------------
*/ (
uint Line
, char * File
)
LB_("Btree.check_Btree")
ret_
KVStore st ; Surr s = GetFirst( st );
while ( s )
{
int i = st.k_L ;
while ( i ) if ( ! st.k[ --i ] )
{
if ( ! st.k[ --i ] ) fErr4( st.k, st.k_L, Line, File )
}
s = Next( st );
}
LE_
/* public: */ uint Btree :: become_transitive (
/* -----------------------------------------------------------------------------
Create the transitive closure of a binary relation ~ given by
records str1~str2 in this tree
-----------------------------------------------------------------------------
*/ )
LB_("Btree.become_transitive")
uint anz = 0 ;
while ( 1 )
{
uint anz1 = anz ;
KVStore st ; Surr s = GetFirst( st );
while ( s )
{
char * x = in_str( '~', st.k );
if ( !x )
{
{
m_errMess "User: Btree is not a str1~str2 relation: st.k = %s" m_
st.k, ret_error
}
}
*x = 0 ; anz += become_trans( st.k, x+1 );
*x = '~' ;
s = GetNext( st );
}
if ( anz == anz1 ) ret( anz )
}
LE_ret( anz )
/* public: */ uint Btree :: become_deep_transitive (
/* -----------------------------------------------------------------------------
Create the transitive closure of a binary relation ~ given by
records str1~str2 in this tree
Record also the depth of the transitive closure
-----------------------------------------------------------------------------
*/ )
LB_("Btree.become_deep_transitive")
uint anz = 0 ; check_Btree( __LF__ );
while ( 1 )
{
uint anz1 = anz ;
KVStore st ; Surr s = GetFirst( st );
while ( s )
{
char * x = in_str( '~', st.k );
if ( !x )
{
{
m_errMess "User: Btree is not a str1~str2 relation: st.k = %s" m_
st.k, ret_error
}
}
*x = 0 ; anz += become_deep_trans( st.k, x+1 );
*x = '~' ;
s = GetNext( st );
}
_1( anz-anz1 )
if ( anz == anz1 ) ret( anz )
}
check_Btree( __LF__ );
LE_ret( anz )
/* private: */ uint Btree :: become_trans
/* -----------------------------------------------------------------------------
Create the transitive closure of a binary relation ~
-----------------------------------------------------------------------------
*/ (
char * x1
, char * x2
)
LB_("Btree.become_trans")
uint anz = 0 ;
char300 NN ; s_( NN, "%s~", x1 );
char300 xx ; s_( xx, "%s~", x2 );
char * e = eos( NN );
KVStore st ; Surr s = Getmin_GE( st, xx );
while ( s && At( st.k, xx ) )
{
char * x = in_str( '~', st.k );
if ( !x )
{
{
m_errMess "User: Btree is not a str1~str2 relation: st.k = %s" m_
st.k, ret_error
}
}
strcpy( e, x+1 );
if ( ! contains( NN ) ) { anz++ ; StrIns( 'e', NN ); }
s = GetNext( st );
}
LE_ret( anz )
/* private: */ uint Btree :: become_deep_trans
/* -----------------------------------------------------------------------------
Create the transitive closure of a binary relation ~
-----------------------------------------------------------------------------
*/ (
char * x1
, char * x2
)
LB_("Btree.become_deep_trans")
uint anz = 0 ;
char300 NN ; s_( NN, "%s~", x1 );
char300 xx ; s_( xx, "%s~", x2 );
char * e = eos( NN );
KVStore st ; Surr s = Getmin_GE( st, xx );
while ( s && At( st.k, xx ) )
{
char * x = in_str( '~', st.k );
if ( !x )
{
{
m_errMess "User: Btree is not a str1~str2 relation: st.k = %s" m_
st.k, ret_error
}
}
strcpy( e, x+1 );
if ( ! contains( NN ) )
{
x = in_str( '~', st.c );
if ( !x ) x = st.c-1 ; // um robust zu sein
if ( x )
then {
anz++ ;
char300 zz ; s_( zz, "%i~%s", decNr( st.c ) + 1, x+1 );
StrIns( 'e', NN, zz );
/*
if substr( "hierarch", NN )
if substr( "criteria", NN )
printf( "\nFFF: x1=%s, x2=%s, st.c=%s, NN=%s, st.k=%s", x1, x2, st.c, NN, st.k );
*/
}
else fErr2( st.k, st.c )
}
s = GetNext( st );
}
LE_ret( anz )
/* public: */ void Btree :: count ( char * k
// -----------------------------------------------------------------------------
)
LB_("Btree.count")
KVStore st ;
if ( Get( k, st ) )
then {
char20 anz ; s_( anz, "%i", decNr( st.c ) + 1 );
StrIns( 'e', k, anz );
}
else StrIns( 'i', k, "1" );
LE_
/* public: */ void Btree :: to_file ( char * fn
/* -----------------------------------------------------------------------------
write Btree to file in form of lines \n~Key~Value~
Btree_ut :: to_tree() can recash the tree.
-----------------------------------------------------------------------------
*/ )
LB_("Btree.to_file")
FILE * f = create( fn );
KVStore st ; Surr s = GetFirst( st );
while ( s )
{
fprintf( f, "\n~%s~%s~", st.k, st.c );
s = Next( st );
}
close( f );
LE_
/* public: */ void Btree :: commit(
/* -----------------------------------------------------------------------------
write all changes to disk
-----------------------------------------------------------------------------
*/ )
LB_("Btree.commit")
cache[0] -> dirty = true ;
if ( Bf ) // not just a memory database
{
for ( int s = 0 ; s < e_cache ; s++ )
{
if ( cache[s] -> dirty ) to_Disk( s );
}
}
LE_
/* public: */ Surr Btree :: GetPath
// -----------------------------------------------------------------------------
(
char * k // key
, store_256 & d // data
, Surr k_father // starting point of path ''k
)
LB_("Btree.GetPath")
if ( ! k ) fErr
LE_ret( GetPath( k, strlen( k ), d, k_father ) )
/* public: */ Surr Btree :: GetPath
/* -----------------------------------------------------------------------------
Read into 'd the data assigned to the key 'k by the Btree
and assure d.c[ d.L ] == 0 .
Return BOOL( key in tree )
-----------------------------------------------------------------------------
*/ (
char * k // key
, int k_L // number of bytes in key
, store_256 & d // data
, Surr k_father // starting point of path ''k
)
LB_("Btree.GetPath")
check_path( k, k_L, k_father );
*( d.c ) = 0 ;
char * s ;
char * a ; char * ek = k + k_L ;
a = s = k ; char kk[ 256 ] ; memcpy( kk, "!/", 2 );
Surr suche = 1 ; at_surr = k_father ;
while ( suche && a < ek )
{
s++ ; while ( s < ek && *s != '/' ) s++ ;
int k_L = s-a ;
memcpy( kk+2, &at_surr, 4 );
memcpy( kk+6, a , k_L );
suche = Get( kk, k_L+6, d );
a = s ;
}
LE_ret( suche )
/* public: */ Surr Btree :: Get
// -----------------------------------------------------------------------------
(
int k // key
, store_256 & d // data
)
LB_("Btree.Get")
char20 kstr ; s_( kstr, "%i", k );
LE_ret( Get( kstr, strlen( kstr ), d ) )
/* public: */ Surr Btree :: Get
// -----------------------------------------------------------------------------
(
char * k // key
, store_256 & d // data
)
LB_("Btree.Get")
if ( ! k || ! *k ) fErr
_1(k)
LE_ret( Get( k, strlen( k ), d ) )
/* public: */ Surr Btree :: Get
/* -----------------------------------------------------------------------------
Read into 'd the data assigned to the key 'k by the Btree
and assure d.c[ d.L ] == 0 .
Return BOOL( key in tree )
-----------------------------------------------------------------------------
*/ (
char * k // key
, int k_L // number of bytes in key
, store_256 & d // data
)
LB_("Btree.Get")
// if ( ! this ) fErr
__ __
if ( ! LastSurr() ) ret( 0 )
// if ( ! k || k_L < 0 ) fErr1( k_L )
if ( ! k || k_L <= 0 ) fErr1( k_L )
*( d.c ) = 0 ;
if ( L_255 < k_L )
{
if ( max_k_L < k_L )
{
char300 xx ; memcpy( xx, k, 280 ); strcpy( xx + 280, " ..." );
_1(k_L)
{
m_errMess "System: Btree.Get(): no such long keys in Btree: %s" m_
xx, ret_error
}
;
}
Surr sr = 0 ; char kk[ 256 ] ; memcpy( kk, "!?", 2 );
while ( L_249 < k_L )
{
memcpy( kk+2, &sr, 4 );
memcpy( kk+6, k, L_249 ); k_L -= L_249 ; k += L_249 ;
sr = Get( kk, L_255, d );
if ( !sr ) fErr2( *this, kk )
}
memcpy( kk+2, &sr, 4 ); memcpy( kk+6, k, k_L );
ret( Get( kk, k_L+6, d ) )
}
uchar n1 = k_L % 256 ;
deepest = 0 ; locate( k, n1 );
if ( pos_m[ deepest ].r )
{
__ if ( treeID == -2 )
{
int i = -1 ; while ( ++i <= deepest ) trace_data( *page[i] );
}
ret( 0 )
}
LE_ret( Located_key_and_data( d ) )
/* private: */ Surr Btree :: located_key_and_data
/* -----------------------------------------------------------------------------
Read into 'd the data assigned to the located key in the Btree
and assure d.c[ d.L ] == 0 .
Return the key's surrogate.
-----------------------------------------------------------------------------
*/ (
store_256 & d
, int line
)
LB_("Btree.located_key_and_data")
int m = pos_m[ deepest ].m ;
Btree_page * p = page[ deepest ] ;
if ( m <= 0 || p -> e <= m )
{
trace( "BBB", stdout ); fErr3( m, p -> e, line )
}
if ( ! m )
{
// hierzu kommt es - aber warum nur
Btree_data * n0 = tA( Btree_data, p, 0 * L_data );
Btree_data * n1 = tA( Btree_data, p, 1 * L_data );
char * k0 = p -> c + ( n0 -> ak );
char * k1 = p -> c + ( n1 -> ak );
if is( k0, k1, ( uchar )( *k0 ) )
then {
if ( p -> e <= 1 ) fErr
pos_m[ deepest ].m = m = 1 ;
pos_m[ deepest ].r = 0 ;
}
esif ( pos_m[ deepest ].r > 0 )
{
if ( p -> e <= 1 ) fErr
pos_m[ deepest ].m = m = 1 ;
pos_m[ deepest ].r = 0 ;
}
else {
trace( "EEE", stdout ); fErr
}
}
if ( p -> t ) // p is an index page
{
int i = 0 ; alles = 1 ;
while ( i <= deepest ) trace_page( * page[ i++ ] );
fErr
}
if ( pos_m[ deepest ].r ) fErr1( *this )
// if ( d.k_L == 0 || 31300 < atLB ) trace( "Btree", stdout );
//
Btree_data * da = tA( Btree_data, p, m * L_data );
char * pc = p -> c ; uchar spare = pc[ eoheap ];
if ( spare )
{
Btree_data * n = tA( Btree_data, p, 0 );
memcpy( d.k, pc + n -> ak-spare, spare );
}
d.k_L = pc[ da -> ak ] ;
d.L = pc[ da -> ad ] ;
d.t = pc[ da -> ad + 1 ] ;
//
memcpy( d.k + spare, pc + da->ak + 1, d.k_L ); d.k[ d.k_L += spare ] = 0 ;
memcpy( d.c , pc + da->ad + 2, d.L ); d.c[ d.L ] = 0 ;
if (0) if At( d.k, "(72,5" ) // test zu StrBtree
{
// Um zu sehen wie spare im Node aussieht:
trace_page( *p ); fErr5( d.k, d.c, d.k_L, d.L, spare )
}
if ( ! da -> surr )
{
if ( ! descr -> surr ) ret( 0 ) // tree is still empty
trace( "BBB", stout );
S_ "deepest.m = %i.%i\n", deepest, m _fErr
}
//
// , Bfn, spare, da, d.c, da -> surr, line );
if ( LData && At( d.c + d.L - 2, ":" ) )
{
// Value is a string longer than max( d.L, 252 ), hence:
char * x = substr( ":", d.c );
if ( ! x ) fErr1( d.c )
int n1 = decNr( x ); char * e = x ; to_( e, '/' ) e++ ;
int n2 = decNr( e );
while ( n1 < n2 )
{
KVStore st ; s_( st.k, "%i", ++n1 );
if ( LData -> Get( st.k, st ) )
then {
strcpy( x, st.c );
x = eos( x );
}
else fErr2( n1, n2 )
}
}
// _1(d.c)
LE_ret( d.at = at_surr = da -> surr )
/* public: */ Surr Btree :: GetFirst
/* -----------------------------------------------------------------------------
Return 0 if the Btree is empty, else return the surrogate of
the smallest key ''k in this tree and describe in ''e the
located pair ( key, data ).
Assure e.c[ d.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
)
LB_("Btree.GetFirst")
if ( ! locate_First() ) ret( 0 )
LE_ret( Located_key_and_data( e ) )
/* public: */ Surr Btree :: GetLast
/* -----------------------------------------------------------------------------
Return 0 if the Btree is empty, else return the surrogate of
the highest key ''k in this tree and describe in ''e the
located pair ( key, data ).
Assure d.c[ d.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
)
LB_("Btree.GetLast")
if ( ! locate_Last() ) ret( 0 )
LE_ret( Located_key_and_data( e ) )
/* public: */ Surr Btree :: GetNext
/* -----------------------------------------------------------------------------
This requires 'e to exist in the Btree - if 'e might not exist,
use Getmin_GE() instead of GetNext().
Return the surrogate ''s of the successor of key ''e.k in this tree,
and describe in ''e this successor and the associated data.
Return 0 if there is no successor.
Assure d.c[ d.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e // PRECondition: e.k_L zutreffend gesetzt
)
LB_("Btree.GetNext")
LE_ret( GetNext( e, e.k, e.k_L ) )
/* public: */ int Btree :: number_of_elements (
/* -----------------------------------------------------------------------------
Return number of elements in the tree
-----------------------------------------------------------------------------
*/ )
LB_("Btree.number_of_elements")
KVStore st ; Surr s = GetFirst( st ); int anz = 0 ;
while ( s ) { ++anz ; s = Next( st ); }
LE_ret( anz )
/* public: */ Surr Btree :: Next
/* -----------------------------------------------------------------------------
This requires 'e to exist in the Btree - if 'e might not exist,
use Getmin_GE() instead of GetNext().
Return the surrogate ''s of the successor of key ''e.k in this tree,
and describe in ''e this successor and the associated data.
Return 0 if there is no successor.
Assure d.c[ d.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e // PRECondition: e.k_L zutreffend gesetzt
// und letzter Aufruf war GetFirst oder Next
)
LB_("Btree.Next")
if ( pos_m[ deepest ].r || page[ deepest ] -> t )
{
ret( GetNext( e ) )
_2( pos_m[ deepest ].r, page[ deepest ] -> t )
{
m_errMess "System: precodition for Next() not established by the Btree App" m_
ret_error
}
}
LD: if ( pos_m[ deepest ].m < page[ deepest ] -> e-1 )
{
pos_m[ deepest ].m += 1 ;
pos_m[ deepest ].r = 0 ;
// trace_deepest();
ret( Located_key_and_data( e ) )
}
while ( page[ deepest ] -> e-1 <= pos_m[ deepest ].m )
{
if ( deepest )
then {
deepest-- ;
}
else ret( 0 )
}
while ( page[ deepest ] -> t ) // an Index page
{
pos_m[ deepest ].m += 1 ;
pos_m[ deepest ].r = 1 ;
Btree_page * p = page[ deepest ] ;
int m = pos_m[ deepest ].m ;
pageNr son = tA( Btree_index, p, m * L_index ) -> son ;
if ( ! son ) son = 1 ; // the always existing 1st data page
get_page( ++deepest, son );
pos_m[ deepest ].m = -1 ;
pos_m[ deepest ].r = 1 ;
}
pos_m[ deepest ].m = 0 ;
pos_m[ deepest ].r = 1 ;
// _1("DEEP") trace_deepest();
goto LD ;
// Solution before Dez 15, 2009:
kurz = 1 ; if ( atLB && strlen( e.k ) != e.k_L ) fErr
LE_ret( GetNext( e, e.k, e.k_L ) )
/* public: */ Surr Btree :: GetNext
/* -----------------------------------------------------------------------------
This requires 'e to exist in the Btree - if 'e might not exist,
use Getmin_GE() instead of GetNext().
Return the surrogate ''s of the successor of key ''k in this tree,
and describe in ''e this successor and the associated data.
Return 0 if there is no successor.
Assure d.c[ d.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
)
LB_("Btree.GetNext")
LE_ret( GetNext( e, k, strlen( k ) ) )
/* public: */ Surr Btree :: GetNext
/* -----------------------------------------------------------------------------
This requires 'e to exist in the Btree - if 'e might not exist,
use Getmin_GE() instead of GetNext().
Return the surrogate ''s of the successor of key ''k in this tree,
and describe in ''e this successor and the associated data.
Return 0 if there is no successor.
Assure d.c[ d.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
, int kL
)
LB_("Btree.GetNext")
if ( ! k || kL <= 0 ) fErr1( kL ) else contains( k, kL );
// path xx ; memcpy( xx, k, kL ); xx[kL] = 0 ;
kurz = 0 ; if ( ! locate_Next( k, kL ) ) ret( 0 )
if ( deepest < 1 || L_Bp <= deepest ) fErr2( deepest, L_Bp )
LE_ret( Located_key_and_data( e ) )
/* public: */ Surr Btree :: GetPrev
/* -----------------------------------------------------------------------------
This requires 'e to exist in the Btree - if 'e might not exist,
use Getmax_LE() instead of GetPrev().
Return the surrogate ''s of the predeccessor of key ''e.k in this tree,
and describe in ''e this predeccessor and the associated data.
Return 0 if there is no successor.
Assure d.c[ d.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e // PRECondition: e.k_L zutreffend gesetzt
)
LB_("Btree.GetPrev")
if ( atLB && strlen( e.k ) != e.k_L ) fErr
LE_ret( GetPrev( e, e.k, e.k_L ) )
/* public: */ Surr Btree :: Prev
/* -----------------------------------------------------------------------------
This requires 'e to exist in the Btree - if 'e might not exist,
use Getmax_LE() instead of GetPrev().
Return the surrogate ''s of the predeccessor of key ''e.k in this tree,
and describe in ''e this predeccessor and the associated data.
Return 0 if there is no successor.
Assure d.c[ d.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e // PRECondition: e.k_L zutreffend gesetzt
// und letzter Aufruf war GetLast oder Prev
)
LB_("Btree.Prev")
call_nr++ ;
if ( pos_m[ deepest ].r || page[ deepest ] -> t )
{
{
m_errMess "System: precodition for Prev() not established by the Btree App" m_
ret_error
}
}
LD: if ( 1 < pos_m[ deepest ].m )
{
pos_m[ deepest ].m -= 1 ;
pos_m[ deepest ].r = 0 ;
// trace_deepest();
ret( Located_key_and_data( e ) )
}
uint u = 1 ;
while ( pos_m[ deepest ].m <= u )
{
u = 0 ;
if ( deepest ) deepest-- ; else ret( 0 )
}
while ( page[ deepest ] -> t ) // an Index page
{
pos_m[ deepest ].m -= 1 ;
pos_m[ deepest ].r = 1 ;
Btree_page * p = page[ deepest ] ;
int m = pos_m[ deepest ].m ;
pageNr son = tA( Btree_index, p, m * L_index ) -> son ;
if ( ! son ) son = 1 ; // the always existing 1st data page
get_page( ++deepest, son );
pos_m[ deepest ].m = page[ deepest ] -> e ;
pos_m[ deepest ].r = -1 ;
}
pos_m[ deepest ].m = page[ deepest ] -> e ;
pos_m[ deepest ].r = -1 ;
// _1("DEEP") trace_deepest();
goto LD ;
// Solution before Dez 15, 2009 (Test zu StrPairs entdeckt Fehler):
kurz = 1 ; if ( atLB && strlen( e.k ) != e.k_L ) fErr
LE_ret( GetPrev( e, e.k, e.k_L ) )
/* public: */ Surr Btree :: GetPrev
/* -----------------------------------------------------------------------------
This requires 'e to exist in the Btree - if 'e might not exist,
use Getmax_LE() instead of GetPrev().
Return the surrogate ''s of the predeccessor of key ''k in this tree,
and describe in ''e this predeccessor and the associated data.
Return 0 if there is no successor.
Assure d.c[ d.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
)
LB_("Btree.GetPrev")
LE_ret( GetPrev( e, k, strlen( k ) ) )
/* public: */ Surr Btree :: GetPrev
/* -----------------------------------------------------------------------------
This requires 'e to exist in the Btree - if 'e might not exist,
use Getmax_LE() instead of GetPrev().
Return the surrogate ''s of the predeccessor of key ''k in this tree,
and describe in ''e this predeccessor and the associated data.
Return 0 if there is no successor.
Assure d.c[ d.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
, int kL
)
LB_("Btree.GetPrev")
//
if ( ! k || kL <= 0 ) fErr1( kL ) else contains( k, kL );
if ( ! kurz && ! locate( k, kL ) )
{
k[ kL ] = 0 ;
printf( "\nGetPREV of x, not found: x = %s", k ); //fErr2( k, *this )
ret( 0 )
}
kurz = 0 ;
if ( ! locate_Prev( k, kL ) ) ret( 0 )
LE_ret( Located_key_and_data( e ) )
/* public: */ Surr Btree :: Getmax_prefix
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the largest key in this tree that is a
prefix of the given key k.
Return 0 if there is no such element, otherwise copy it to ''e.
Assure e.c[ e.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
)
LB_("Btree.Getmax_prefix")
int i = strlen( k ); Surr s = Get( k, i, e );
while ( !s && 0 <= --i ) s = Get( k, i, e );
LE_ret( s )
/* public: */ Surr Btree :: Getmax_LE
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the largest key in this tree that is
LESS or EQUAL the given key.
Return 0 if there is no such element, otherwise copy it to ''e.
Assure e.c[ e.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
)
LB_("Btree.Getmax_LE")
Surr s = Getmax_LE( e, k, strlen( k ) ); if ( !s ) ret( 0 )
if sm_( k, e.k )
{
//
trace( "Btree", stdout ); fErr
}
LE_ret( s )
/* public: */ Surr Btree :: Getmax_LE
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the largest key in this tree that is
LESS or EQUAL the given key.
Return 0 if there is no such element, otherwise copy it to ''e.
Assure e.c[ e.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
, int kL
)
LB_("Btree.Getmax_LE")
if ( locate( k, kL ) ) ret( Located_key_and_data( e ) )
/* {
Surr s = Located_key_and_data( e ); printf( "\ns = %ld", s );
ret( s )
} */
if ( pos_m[ deepest ].m == 0 )
{
if ( pos_m[ deepest ].r == 1 ) pos_m[ deepest ].r = 0 ; else fErr
if ( ! locate_Prev( k, kL ) ) ret( 0 )
if ( pos_m[ deepest ].r ) fErr
}
if ( pos_m[ deepest ].r )
{
// showStr( "Getmax_LE", k, kL );
if ( page[ deepest ] -> e <= pos_m[ deepest ].m ) fErr
if ( 0 >= pos_m[ deepest ].m ) fErr
pos_m[ deepest ].r = 0 ;
}
LE_ret( Located_key_and_data( e ) )
/* public: */ Surr Btree :: Getmax_LS
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the largest key in this tree that is
LESS than the given key.
Return 0 if there is no such element, otherwise copy it to ''e.
Assure e.c[ e.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
, int kL
)
LB_("Btree.Getmax_LS")
if ( contains( k, kL ) ) then ret( GetPrev ( e, k, kL ) )
else ret( Getmax_LE( e, k, kL ) )
LE_ret( 0 )
/* public: */ Surr Btree :: Getmax_LS
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the smallest key in this tree that is
LESS than the given key.
Return 0 if there is no such element, otherwise copy it to ''e.
Assure e.c[ e.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
)
LB_("Btree.Getmax_LS")
if ( contains( k ) ) then ret( GetPrev ( e, k ) )
else ret( Getmax_LE( e, k ) )
LE_ret( 0 )
/* public: */ Surr Btree :: Getmin_At
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the smallest key in this tree that has
k for a prefix.
Return 0 if there is no such element, otherwise copy it to ''e.
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
)
LB_("Btree.Getmin_At")
Surr s = Getmin_GE( e, k );
if ( s && At( e.k, k ) ) ret( s )
LE_ret( 0 )
/* public: */ Surr Btree :: Getmax_At
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the largest key in this tree that has
k for a prefix.
Return 0 if there is no such element, otherwise copy it to ''e.
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
)
LB_("Btree.Getmax_At")
KVStore xx ; Surr s, s1 ; s = s1 = Getmin_At( xx, k );
while ( s1 && At( xx.k, k ) )
{
e = xx ;
s = s1 ;
s1 = Next( xx );
}
LE_ret( s )
/* public: */ Surr Btree :: Getmin_GE
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the smallest key in this tree that is
GREATER or EQUAL the given key.
Return 0 if there is no such element, otherwise copy it to ''e.
Assure e.c[ e.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
)
LB_("Btree.Getmin_GE")
path k1 ; strcpy( k1, k );
__ Surr s = Getmin_GE( e, k, strlen( k ) ); if ( !s ) ret( 0 )
__
if sm_( e.k, k1 )
{
//
while ( s ) s = Next( e );
if ( !s ) ret( 0 )
}
LE_ret( s )
/* public: */ Surr Btree :: Getmin_GE
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the smallest key in this tree that is
GREATER or EQUAL the given key.
Return 0 if there is no such element, otherwise copy it to ''e.
Assure e.c[ e.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
, int kL
)
LB_("Btree.Getmin_GE")
showStr( "Locate_GE_", k, kL );
__
Surr s = locate( k, kL ); Btree_page * p = page[ deepest ] ;
__
if ( !s && pos_m[ deepest ].m < p -> e-1 )
then {
__ if ( pos_m[ deepest ].r <= 0 ) fErr
pos_m[ deepest ].m++ ;
pos_m[ deepest ].r = 0 ;
}
esif ( !s && pos_m[ deepest ].m + 1 == p -> e )
{
__ if ( pos_m[ deepest ].r <= 0 ) fErr
if ( ! locate_Next( k, kL ) ) ret( 0 )
p = page[ deepest ];
}
esif ( !s && pos_m[ deepest ].m == p -> e ) ret( 0 )
// trace( "XXX", stdout ); fErr
Surr res = Located_key_and_data( e ); ret( res )
LE_ret( Located_key_and_data( e ) )
/* public: */ Surr Btree :: Getmin_GR
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the smallest key in this tree that is
GREATER than the given key.
Return 0 if there is no such element, otherwise copy it to ''e.
Assure e.c[ e.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
)
LB_("Btree.Getmin_GR")
if ( contains( k ) ) then ret( GetNext ( e, k ) )
else ret( Getmin_GE( e, k ) )
LE_ret( 0 )
/* public: */ Surr Btree :: Getmin_GR
/* -----------------------------------------------------------------------------
Return the surrogate ''s of the smallest key in this tree that is
GREATER than the given key.
Return 0 if there is no such element, otherwise copy it to ''e.
Assure e.c[ e.L ] == 0 .
-----------------------------------------------------------------------------
*/ (
store_256 & e
, char * k
, int kL
)
LB_("Btree.Getmin_GR")
if ( contains( k, kL ) ) then ret( GetNext ( e, k, kL ) )
else ret( Getmin_GE( e, k, kL ) )
LE_ret( 0 )
/* public: */ Surr Btree :: contains( char * k
// -----------------------------------------------------------------------------
)
LB_("Btree.contains(")
if ( ! k ) fErr
LE_ret( contains( k, strlen( k ) ) )
/* public: */ Surr Btree :: contains ( KVStore & st
// -----------------------------------------------------------------------------
)
LB_("Btree.contains")
LE_ret( contains( st.k, st.k_L ) )
/* public: */ Surr Btree :: contains
/* -----------------------------------------------------------------------------
Return Surrogate of key ''k as an element in the BTree (or 0 if
this key is n o t in the Tree).
-----------------------------------------------------------------------------
*/ (
char * k
, int k_L
)
LB_("Btree.contains")
if ( ! k ) fErr
if ( L_255 < k_L )
then {
store_256 d ;
Surr sr = 0 ; char kk[ 256 ] ; memcpy( kk, "!?", 2 );
while ( L_249 < k_L )
{
memcpy( kk+2, &sr, 4 );
memcpy( kk+6, k, L_249 ); k_L -= L_249 ; k += L_249 ;
sr = Get( kk, L_255, d ); if ( !sr ) ret( 0 )
}
memcpy( kk+2, &sr, 4 ); memcpy( kk+6, k, k_L );
ret( Get( kk, k_L+6, d ) )
}
esif ( k_L < 0 ) fErr
uchar n1 = k_L % 256 ;
deepest = 0 ; locate( k, n1 );
// if ( ! locate( k, n1 ) ) ret( 0L )
if ( pos_m[ deepest ].r ) ret( 0 )
LE_ret( at_surr )
/* public: */ Surr Btree :: containsPath
// -----------------------------------------------------------------------------
(
char * k
, Surr k_father // starting point of path ''k
)
LB_("Btree.containsPath")
if ( ! k ) fErr
LE_ret( containsPath( k, strlen( k ), k_father ) )
/* public: */ Surr Btree :: containsPath
/* -----------------------------------------------------------------------------
Return Surrogate of Path ''k as an element in the BTree (or 0 if
this path is n o t in the Tree).
-----------------------------------------------------------------------------
*/ (
char * k
, int k_L
, Surr k_father // starting point of path ''k
)
LB_("Btree.containsPath")
check_path( k, k_L, k_father );
char * a ;
char * s ; char * ek = k + k_L ;
a = s = k ; char kk[ 256 ] ; memcpy( kk, "!/", 2 );
Surr suche = 1 ; at_surr = k_father ;
while ( suche && a < ek )
{
s++ ; while ( s < ek && *s != '/' ) s++ ;
int k_L = s-a ;
memcpy( kk+2, &at_surr, 4 );
memcpy( kk+6, a , k_L );
store_256 st ; suche = Get( kk, k_L+6, st );
a = s ;
}
LE_ret( suche )
/* public: */ Surr Btree :: RemPath
// -----------------------------------------------------------------------------
(
char * k
, Surr k_father
)
LB_("Btree.RemPath")
if ( ! *k ) fErr
LE_ret( RemPath( k, strlen( k ), k_father ) )
/* public: */ Surr Btree :: RemPath
/* -----------------------------------------------------------------------------
Der Aufrufer sagt: Delete entry k from the tree.
Die Funktion garantiert: fErr || ok && return Surrogate of entry
-----------------------------------------------------------------------------
*/ (
char * k // key
, int k_L // number of bytes in key
, Surr k_father // starting point of path ''k
)
LB_("Btree.RemPath")
check_path( k, k_L, k_father );
char * a ;
char * s ; char * ek = k + k_L ;
a = s = k ; char kk[ 256 ] ; memcpy( kk, "!/", 2 );
Surr suche = 1 ; at_surr = k_father ;
while ( suche && a < ek )
{
s++ ; while ( s < ek && *s != '/' ) s++ ;
int k_L = s-a ;
memcpy( kk+2, &at_surr, 4 );
memcpy( kk+6, a , k_L );
if ( s < ek )
then {
store_256 st ;
suche = Get( kk, k_L+6, st );
}
else suche = Rem( kk, k_L+6 );
a = s ;
}
LE_ret( suche )
/* public: */ int Btree :: Rem_GE_LE
/* -----------------------------------------------------------------------------
Delete all keys k satisfying u <= k <= o ,
Return number of deleted items.
-----------------------------------------------------------------------------
*/ (
char * u
, char * o
)
LB_("Btree.Rem_GE_LE")
if ( ! *u ) fErr
if ( ! *o ) fErr
//
store_256 st ; Surr s = Getmin_GE( st, u ); int anz = 0 ;
// if (s)
while ( s && ! sm_( o, st.k ) )
{
char x[300] ; strcpy( x, st.k ); s = GetNext( st );
if ( ! Rem( x ) ) fErr
anz += 1 ;
}
LE_ret( anz )
/* public: */ Surr Btree :: Rem ( int n
// -----------------------------------------------------------------------------
)
LB_("Btree.Rem")
char20 k ; s_( k, "%i", n );
LE_ret( Rem( k, strlen( k ) ) )
/* public: */ Surr Btree :: Rem ( char * k
// -----------------------------------------------------------------------------
)
LB_("Btree.Rem")
LE_ret( Rem( k, strlen( k ) ) )
/* public: */ Surr Btree :: Rem ( KVStore & st
// -----------------------------------------------------------------------------
)
LB_("Btree.Rem")
LE_ret( Rem( st.k, st.k_L ) )
/* public: */ Surr Btree :: postfix
// -----------------------------------------------------------------------------
// augment the key's value by the given postfix
// -----------------------------------------------------------------------------
(
char * k
, char * postfix
)
LB_("Btree.postfix")
if ( ! k || ! postfix ) fErr2( k, postfix )
KVStore st ; Surr s = Get( k, st );
if ( s && not_substr( postfix, st.c ) )
{
if ( 250 < st.L + strlen( postfix ) ) then fErr2( st.c, postfix )
strcpy( st.c + st.L, postfix );
StrIns( 'e', k, st.c );
}
LE_ret( s )
/* public: */ Surr Btree :: Rem
/* -----------------------------------------------------------------------------
Der Aufrufer sagt: Delete entry k from the tree.
Die Funktion garantiert: fErr || ok && return Surrogate of entry
-----------------------------------------------------------------------------
*/ (
char * k // key
, int k_L // number of bytes in key
)
LB_("Btree.Rem")
if ( !k ) fErr
if ( L_255 < k_L )
then {
Surr sr = 0 ; char kk[ 256 ] ; memcpy( kk, "!?", 2 );
while ( L_249 < k_L )
{
memcpy( kk+2, &sr, 4 );
memcpy( kk+6, k, L_249 ); k_L -= L_249 ; k += L_249 ;
store_256 st ;
sr = Get( kk, L_255, st ); if ( !sr ) ret( 0 )
}
memcpy( kk+2, &sr, 4 ); memcpy( kk+6, k, k_L );
ret( Rem( kk, k_L+6 ) )
}
esif ( k_L < 0 ) fErr
uchar n1 = k_L % 256 ;
deepest = 0 ; locate( k, n1 ); if ( pos_m[ deepest ].r ) ret( 0 )
int m = pos_m[ deepest ].m ;
Btree_page * p = page[ deepest ] ;
char * to = tA( char, p, m * L_data );
if ( m < p->e ) memshift( to, to + L_data, ( p->e - m ) * L_data );
p -> e -= 1 ;
p -> dirty = 1 ;
// -----------------------------------------------------------------------------
if ( 1 ) // kann auch unterbleiben
if ( p->e == 1 && 1 < deepest )
{
// Freigeben einer Data Page sollte unterbleiben, wenn dadurch das spare
// der Vorgngerseite kleiner wrde (zu grosser Reorganisationsaufwand).
//
// Ansonsten kann und sollte man die Keys beider Seiten gleichmssig
// auf beide verteilen, so dass Splitten - der Einsatz einer neuen
// physikalischen Seite also - mit etwas gráerer Wahrscheinlichkeit
// nicht so bald ntig wird.
Btree_page * pm = p ;
p = page[ --deepest ]; if ( p->e <= 0 ) fErr
if ( 1 < m )
{
int M = pos_m[ deepest ].m-1 ;
int m = pos_m[ deepest ].m ;
get_page( L_Bp, tA( Btree_index
, page[ deepest - 1 ], M * L_index ) -> son );
Btree_page * pM = page[ L_Bp ];
uchar m_spare = pm -> c[ eoheap ];
uchar M_spare = pM -> c[ eoheap ];
if ( M_spare <= m_spare )
{
char * x = tA( char, p, m * L_index ); p->e-- ; p->dirty = 1 ;
while ( m < p->e )
{
char * x1 ;
memcpy( x, x1 = x + L_index, L_index ); x = x1 ;
}
split_data( pm, pM ); __
}
}
// Statt keys aus der vorangehenden Seite zu holen, knnte man die leer
// gewordene Seite auch physikalisch freigeben (was dann auch im Fall
// m = 1 mglich wre):
//
// descr -> anz-- ; page[0]->dirty = 1 ; // da descr in page[0]
//
// Wie aber soll die freie Seite spter neu verwendbar werden
}
LE_ret( at_surr )
#undef L_Bp
#undef L_Cp
#undef L_255
#undef L_249
#undef min_anz_data
#undef L_heap
#undef L_page
#undef L_descr
#undef L_data
#undef L_index
#undef static
#endif