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 m”glich: 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 Vorg„ngerseite kleiner wrde (zu grosser Reorganisationsaufwand). // // Ansonsten kann und sollte man die Keys beider Seiten gleichm„ssig // auf beide verteilen, so dass Splitten - der Einsatz einer neuen // physikalischen Seite also - mit etwas gr”áerer Wahrscheinlichkeit // nicht so bald n”tig 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, k”nnte man die leer // gewordene Seite auch physikalisch freigeben (was dann auch im Fall // m = 1 m”glich w„re): // // descr -> anz-- ; page[0]->dirty = 1 ; // da descr in page[0] // // Wie aber soll die freie Seite sp„ter 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
top . C++
Include-structure of
todir / btree.cpp

btree.c1
.   btree.h
.   .   for_spu.h
.   .   .   for_all.h
.   .   .   .   exec_ut.h
.   .   .   .   .   exec_ut.h3
.   .   .   .   .   macros_1.h
.   .   .   .   .   traceco.h
.   .   .   .   precomp.h
.   .   .   .   .   basis.h
.   .   .   .   .   .   compiler.h
.   .   .   .   .   .   dmlerr.h
.   .   .   .   .   en.h
.   .   .   .   .   .   en_lec.h
.   .   .   .   .   limits.h
.   .   .   .   .   mt.h
.   .   .   .   .   obsolete.h
.   .   .   .   .   ot.h
.   .   .   .   .   st.h
.   .   .   .   .   trace.h
.   .   .   .   standard.h
.   .   .   .   toscreen.h
.   .   .   spu.h
.   .   .   .   help_gen.h
.   .   .   .   .   help_gen.h3
.   .   .   .   rbuffer.h
.   .   .   .   .   rbuffer.h3
.   .   .   .   .   str_set.h
.   .   .   .   .   .   str_set.h3
.   .   .   .   safe_uts.h
.   .   .   .   .   safe_uts.h3
.   .   .   .   ut_repl.h
.   .   btree.h3

33 include files
top . is_inc_for . C++