which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@976 c028cbd2-c16b-5b4b-a496-9718f37d4682
880 lines
26 KiB
C
Executable File
880 lines
26 KiB
C
Executable File
/* i4addtag.c (c)Copyright Sequiter Software Inc., 1990-1994. All rights reserved. */
|
|
|
|
#include "d4all.h"
|
|
#ifndef S4UNIX
|
|
#ifdef __TURBOC__
|
|
#pragma hdrstop
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef S4INDEX_OFF
|
|
|
|
#ifndef S4OFF_WRITE
|
|
|
|
#ifdef S4NDX
|
|
int S4FUNCTION i4get_last_key( TAG4 *t4, char *key_data, long for_block )
|
|
{
|
|
int rc = 0 ;
|
|
B4BLOCK *temp_block ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( for_block <= 0 || t4 == 0 || key_data == 0 )
|
|
e4severe( e4parm, E4_I4GET_LAST_KEY ) ;
|
|
#endif
|
|
|
|
/* must get block for_block, then find the last key */
|
|
temp_block = b4alloc( t4, for_block ) ;
|
|
if ( temp_block == 0 )
|
|
return -1 ;
|
|
|
|
if ( file4read_all( &t4->file, I4MULTIPLY * for_block, &temp_block->n_keys, B4BLOCK_SIZE ) < 0 )
|
|
return -1 ;
|
|
|
|
b4go_eof( temp_block ) ;
|
|
if ( b4leaf( temp_block ) )
|
|
rc = 2 ;
|
|
else
|
|
rc = b4get_last_key( temp_block, key_data ) ;
|
|
|
|
b4free( temp_block ) ;
|
|
|
|
return rc ;
|
|
}
|
|
#endif
|
|
|
|
#ifndef N4OTHER
|
|
|
|
#ifdef S4FOX
|
|
/* (temporary) fix for FoxPro multi-user compatibility
|
|
swaps parent and right blocks */
|
|
#ifndef S4SINGLE
|
|
static long t4swap( B4BLOCK *parent, B4BLOCK *left )
|
|
{
|
|
long temp_fb ;
|
|
#ifdef S4BYTE_SWAP
|
|
S4LONG long_val ;
|
|
#endif
|
|
|
|
temp_fb = left->file_block ;
|
|
left->file_block = parent->file_block ;
|
|
parent->file_block = temp_fb ;
|
|
|
|
/* now update neighbours */
|
|
if ( left->header.right_node != -1 )
|
|
{
|
|
#ifdef S4BYTE_SWAP
|
|
long_val = x4reverse_long( (void *)&left->file_block ) ;
|
|
file4write( &parent->tag->index->file, left->header.right_node + 2*sizeof(short),
|
|
&long_val, sizeof( left->header.left_node ) ) ;
|
|
#else
|
|
file4write( &parent->tag->index->file, left->header.right_node + 2*sizeof(short),
|
|
&left->file_block, sizeof( left->header.left_node ) ) ;
|
|
#endif
|
|
}
|
|
|
|
if ( left->header.left_node != -1 )
|
|
{
|
|
#ifdef S4BYTE_SWAP
|
|
long_val = x4reverse_long( (void *)&left->file_block ) ;
|
|
file4write( &parent->tag->index->file, left->header.left_node + 2*sizeof(short),
|
|
&long_val, sizeof( left->header.right_node ) ) ;
|
|
#else
|
|
file4write( &parent->tag->index->file, left->header.left_node + 2*sizeof(short),
|
|
&left->file_block, sizeof( left->header.right_node ) ) ;
|
|
#endif
|
|
}
|
|
|
|
if ( parent->header.right_node != -1 )
|
|
{
|
|
#ifdef S4BYTE_SWAP
|
|
long_val = x4reverse_long( (void *)&parent->file_block ) ;
|
|
file4write( &parent->tag->index->file, parent->header.right_node + 2*sizeof(short),
|
|
&long_val, sizeof( parent->header.left_node ) ) ;
|
|
#else
|
|
file4write( &parent->tag->index->file, parent->header.right_node + 2*sizeof(short),
|
|
&parent->file_block, sizeof( parent->header.left_node ) ) ;
|
|
#endif
|
|
}
|
|
|
|
if ( parent->header.left_node != -1 )
|
|
{
|
|
#ifdef S4BYTE_SWAP
|
|
long_val = x4reverse_long( (void *)&parent->file_block ) ;
|
|
file4write( &parent->tag->index->file, parent->header.left_node + 2*sizeof(short),
|
|
&long_val, sizeof( parent->header.right_node ) ) ;
|
|
#else
|
|
file4write( &parent->tag->index->file, parent->header.left_node + 2*sizeof(short),
|
|
&parent->file_block, sizeof( parent->header.right_node ) ) ;
|
|
#endif
|
|
}
|
|
|
|
return left->file_block ;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
int S4FUNCTION t4add( TAG4 *t4, unsigned char *key_info, long rec )
|
|
{
|
|
CODE4 *c4 ;
|
|
INDEX4 *i4 ;
|
|
B4BLOCK *old_block, *root_block, *new_block ;
|
|
int rc ;
|
|
long old_file_block, extend_block ;
|
|
#ifdef S4FOX
|
|
int key_on ;
|
|
long rec1 = 0L ;
|
|
long rec2 = 0L ;
|
|
unsigned char *temp_key ;
|
|
int do_insert, update_reqd ;
|
|
#else
|
|
int is_branch ;
|
|
#endif
|
|
|
|
#ifdef S4DEBUG
|
|
if ( t4 == 0 || key_info == 0 || rec < 1 )
|
|
e4severe( e4parm, E4_T4ADD ) ;
|
|
#endif
|
|
|
|
c4 = t4->code_base ;
|
|
i4 = t4->index ;
|
|
|
|
if ( c4->error_code < 0 )
|
|
return -1 ;
|
|
|
|
#ifdef S4FOX
|
|
rc = t4go( t4, (char *)key_info, rec ) ;
|
|
#else
|
|
rc = t4seek( t4, (char *)key_info, t4->header.key_len ) ;
|
|
#endif
|
|
if ( rc < 0 )
|
|
return -1 ;
|
|
|
|
#ifdef S4FOX
|
|
if ( rc == 0 && t4->unique_error == e4unique )
|
|
{
|
|
e4( c4, e4unique, i4->file.name ) ;
|
|
return e4unique ;
|
|
}
|
|
#endif
|
|
|
|
#ifdef S4FOX
|
|
if ( (t4->header.type_code & 0x01) && rc == r4found )
|
|
#else
|
|
if ( t4->header.unique && rc == 0 )
|
|
#endif
|
|
{
|
|
switch ( t4->unique_error )
|
|
{
|
|
case e4unique:
|
|
return e4( c4, e4unique, i4->file.name ) ;
|
|
case r4unique:
|
|
return r4unique ;
|
|
case r4unique_continue:
|
|
return r4unique_continue ;
|
|
default:
|
|
break ;
|
|
}
|
|
}
|
|
|
|
if ( t4->filter && !t4->has_keys )
|
|
{
|
|
file4write(&t4->index->file, t4->header_offset+sizeof(t4->header)+222, (char *) "\0", (int) 1 ) ;
|
|
t4->has_keys = (char)1 ;
|
|
#ifdef S4MDX
|
|
t4->had_keys = (char)0 ;
|
|
#endif
|
|
}
|
|
|
|
old_block = t4block(t4) ;
|
|
old_file_block = 0 ;
|
|
|
|
#ifdef S4FOX
|
|
do_insert = 1 ;
|
|
update_reqd = 0 ;
|
|
|
|
for( ;; )
|
|
{
|
|
if ( do_insert == 1 )
|
|
{
|
|
i4->tag_index->header.version = i4->version_old+1 ;
|
|
if ( old_block == 0 )
|
|
{
|
|
/* Must create a new root block */
|
|
extend_block = i4extend(i4) ;
|
|
if ( extend_block < 0 )
|
|
return (int)extend_block ;
|
|
|
|
root_block = b4alloc( t4, extend_block) ;
|
|
if ( root_block == 0 )
|
|
return -1 ;
|
|
|
|
root_block->header.left_node = -1 ;
|
|
root_block->header.right_node = -1 ;
|
|
root_block->header.node_attribute = 1 ;
|
|
|
|
l4add( &t4->blocks, root_block ) ;
|
|
|
|
#ifndef S4SINGLE
|
|
if ( t4->index->file.is_exclusive == 0 )
|
|
{
|
|
old_file_block = t4swap( root_block, (B4BLOCK *)l4last( &t4->saved ) ) ;
|
|
if ( old_file_block < 0 )
|
|
return -1 ;
|
|
}
|
|
|
|
#endif
|
|
|
|
b4top( root_block ) ;
|
|
b4insert( root_block, temp_key, rec, rec2, 1 ) ;
|
|
b4insert( root_block, key_info, old_file_block, rec1, 1 ) ;
|
|
rec1 = 0L ;
|
|
rec2 = 0L ;
|
|
t4->header.root = root_block->file_block ;
|
|
t4->root_write = 1 ;
|
|
return 0 ;
|
|
}
|
|
|
|
if ( (rc = b4insert( old_block, key_info, rec, rec1, 0 )) != 1 )
|
|
{
|
|
if ( rc == 0 )
|
|
{
|
|
if ( b4leaf( old_block ) )
|
|
{
|
|
temp_key = key_info ;
|
|
rec2 = rec ;
|
|
}
|
|
if ( old_block->key_on == old_block->header.n_keys - 1 )
|
|
update_reqd = 1 ;
|
|
do_insert = 0 ;
|
|
continue ;
|
|
}
|
|
else
|
|
return rc ;
|
|
}
|
|
else
|
|
{
|
|
l4pop( &t4->blocks ) ;
|
|
key_on = old_block->key_on ;
|
|
|
|
/* The new block's end key gets added to the block just up */
|
|
new_block= t4split( t4, old_block ) ;
|
|
if ( new_block == 0 )
|
|
return -1 ;
|
|
|
|
l4add( &t4->saved, old_block ) ;
|
|
|
|
if ( key_on < old_block->header.n_keys )
|
|
{
|
|
b4go( old_block, key_on ) ;
|
|
b4insert( old_block, key_info, rec, rec1, 0 ) ;
|
|
}
|
|
else
|
|
{
|
|
b4go( new_block, key_on - old_block->header.n_keys ) ;
|
|
b4insert( new_block, key_info, rec, rec1, 0 ) ;
|
|
if ( new_block->key_on == new_block->header.n_keys - 1 )
|
|
update_reqd = 1 ;
|
|
}
|
|
|
|
#ifdef S4INDEX_VERIFY
|
|
if ( b4verify( old_block ) == -1 )
|
|
e4describe( t4->code_base, e4index, t4->alias, "t4split()-old after split", "" ) ;
|
|
if ( b4verify( new_block ) == -1 )
|
|
e4describe( t4->code_base, e4index, t4->alias, "t4split()-new after split", "" ) ;
|
|
#endif
|
|
|
|
/* Now add to the block just up */
|
|
b4go_eof( old_block ) ;
|
|
old_block->key_on-- ;
|
|
|
|
key_info = b4key_key( old_block, old_block->key_on ) ;
|
|
old_file_block = old_block->file_block ;
|
|
rec1 = b4recno( old_block, old_block->key_on ) ;
|
|
|
|
rec = new_block->file_block ;
|
|
if ( b4flush(new_block) < 0 )
|
|
return -1 ;
|
|
|
|
b4go_eof( new_block ) ;
|
|
new_block->key_on-- ;
|
|
|
|
temp_key = (unsigned char *)c4->saved_key ;
|
|
memcpy( (void *)temp_key, (void *)b4key_key( new_block, new_block->key_on ), t4->header.key_len ) ;
|
|
rec2 = b4recno( new_block, new_block->key_on ) ;
|
|
if( new_block->key_on == new_block->header.n_keys - 1 )
|
|
update_reqd = 1 ;
|
|
b4free( new_block ) ;
|
|
}
|
|
}
|
|
else
|
|
l4add( &t4->saved, l4pop( &t4->blocks ) ) ;
|
|
|
|
old_block = (B4BLOCK *)t4->blocks.last_node ;
|
|
|
|
if ( old_block == 0 )
|
|
{
|
|
if ( do_insert == 0 )
|
|
return 0 ;
|
|
}
|
|
else
|
|
if ( update_reqd ) /* may have to update a parent block */
|
|
{
|
|
b4br_replace( old_block, (char *)temp_key, rec2 ) ;
|
|
if ( old_block->key_on != old_block->header.n_keys - 1 ) /* done reqd updates */
|
|
update_reqd = 0 ;
|
|
}
|
|
}
|
|
#else /* if not S4FOX */
|
|
i4->changed = 1 ;
|
|
t4->changed = 1 ;
|
|
t4->header.version++ ;
|
|
|
|
for(;;)
|
|
{
|
|
if ( old_block == 0 )
|
|
{
|
|
/* Must create a new root block */
|
|
extend_block = i4extend(i4) ;
|
|
if ( extend_block < 0 )
|
|
return (int) extend_block ;
|
|
|
|
root_block = b4alloc( t4, extend_block) ;
|
|
if ( root_block == 0 )
|
|
return -1 ;
|
|
|
|
l4add( &t4->blocks, root_block ) ;
|
|
|
|
b4insert( root_block, key_info, old_file_block ) ;
|
|
b4insert( root_block, key_info, rec ) ;
|
|
root_block->n_keys-- ;
|
|
t4->header.root = root_block->file_block ;
|
|
t4->root_write = 1 ;
|
|
return 0 ;
|
|
}
|
|
|
|
if ( old_block->n_keys < old_block->tag->header.keys_max )
|
|
{
|
|
b4insert( old_block, key_info, rec ) ;
|
|
return 0 ;
|
|
}
|
|
|
|
l4pop( &t4->blocks ) ;
|
|
|
|
is_branch = b4leaf( old_block ) ? 0 : 1 ;
|
|
|
|
/* NNNNOOOO N - New, O - Old */
|
|
/* The new block's end key gets added to the block just up */
|
|
new_block= t4split( t4, old_block ) ;
|
|
if ( new_block == 0 )
|
|
return -1 ;
|
|
|
|
l4add( &t4->saved, new_block ) ;
|
|
|
|
new_block->n_keys -= (short)is_branch ;
|
|
if ( new_block->key_on < (new_block->n_keys+is_branch) )
|
|
b4insert( new_block, key_info, rec ) ;
|
|
else
|
|
b4insert( old_block, key_info, rec ) ;
|
|
|
|
#ifdef S4INDEX_VERIFY
|
|
if ( b4verify( old_block ) == -1 )
|
|
e4describe( t4->code_base, e4index, t4->alias, "t4split()-old after split", "" ) ;
|
|
if ( b4verify( new_block ) == -1 )
|
|
e4describe( t4->code_base, e4index, t4->alias, "t4split()-new after split", "" ) ;
|
|
#endif
|
|
|
|
/* Now add to the block just up */
|
|
new_block->key_on = b4lastpos(new_block) ;
|
|
|
|
key_info = b4key_key( new_block, new_block->key_on ) ;
|
|
rec = new_block->file_block ;
|
|
|
|
old_file_block = old_block->file_block ;
|
|
if ( b4flush(old_block) < 0 )
|
|
return -1 ;
|
|
|
|
b4free( old_block ) ;
|
|
old_block = (B4BLOCK *) t4->blocks.last_node ;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int S4FUNCTION t4add_calc( TAG4 *t4, long rec )
|
|
{
|
|
int len ;
|
|
char *ptr ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( t4 == 0 || rec < 1 )
|
|
e4severe( e4parm, E4_T4ADD_CALC ) ;
|
|
#endif
|
|
|
|
if ( t4->code_base->error_code < 0 )
|
|
return -1 ;
|
|
|
|
if ( t4->filter )
|
|
if ( !expr4true( t4->filter ) )
|
|
return 0;
|
|
|
|
len = t4expr_key( t4, &ptr ) ;
|
|
if ( len < 0 )
|
|
return -1 ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( len != t4->header.key_len )
|
|
e4severe( e4result, E4_T4ADD_CALC ) ;
|
|
#endif
|
|
|
|
return t4add( t4, (unsigned char *)ptr, rec ) ;
|
|
}
|
|
|
|
#endif /* ifndef N4OTHER */
|
|
|
|
|
|
#ifdef N4OTHER
|
|
|
|
#ifdef S4NDX
|
|
int S4FUNCTION t4add( TAG4 *t4, unsigned char *key_info, long rec )
|
|
{
|
|
CODE4 *c4 ;
|
|
INDEX4 *i4 ;
|
|
B4BLOCK *old_block, *root_block, *new_block, *wch_block ;
|
|
int rc, is_branch ;
|
|
long old_file_block, extend_block ;
|
|
char key_data[I4MAX_KEY_SIZE+1] ; /* temporary storage for the key data (max size 100) */
|
|
char key2_data[I4MAX_KEY_SIZE+1] ;
|
|
B4KEY_DATA *at_new ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( t4 == 0 || key_info == 0 || rec < 1 )
|
|
e4severe( e4parm, E4_T4ADD ) ;
|
|
#endif
|
|
|
|
c4 = t4->code_base ;
|
|
i4 = t4->index ;
|
|
|
|
if ( c4->error_code < 0 )
|
|
return -1 ;
|
|
|
|
rc = t4go( t4, (char *)key_info, rec ) ;
|
|
if ( rc < 0 )
|
|
return -1 ;
|
|
|
|
if ( rc == 0 && t4->unique_error == e4unique )
|
|
{
|
|
e4( c4, e4unique, i4->file.name ) ;
|
|
return e4unique ;
|
|
}
|
|
|
|
if ( rc == r4found || rc == 0 )
|
|
{
|
|
switch ( t4->unique_error )
|
|
{
|
|
case e4unique:
|
|
return e4( c4, e4unique, i4->file.name ) ;
|
|
case r4unique:
|
|
return r4unique ;
|
|
case r4unique_continue:
|
|
return r4unique_continue ;
|
|
default:
|
|
break ;
|
|
}
|
|
}
|
|
|
|
old_block = t4block( t4 ) ;
|
|
old_file_block = 0 ;
|
|
|
|
t4->header.version = t4->header.old_version + 1 ;
|
|
|
|
for(;;)
|
|
{
|
|
if ( old_block == 0 )
|
|
{
|
|
/* Must create a new root block */
|
|
extend_block = t4extend( t4 ) ;
|
|
if ( extend_block < 0 )
|
|
return (int)extend_block ;
|
|
|
|
root_block = b4alloc( t4, extend_block ) ;
|
|
if ( root_block == 0 )
|
|
return -1 ;
|
|
|
|
l4add( &t4->blocks, root_block ) ;
|
|
|
|
i4get_last_key( t4, key_data, old_file_block ) ;
|
|
|
|
b4insert( root_block, key_data, 0L, old_file_block ) ;
|
|
b4append( root_block, rec ) ;
|
|
t4->header.root = root_block->file_block ;
|
|
t4->root_write = 1 ;
|
|
return 0 ;
|
|
}
|
|
|
|
if ( b4room( old_block ) )
|
|
{
|
|
if ( b4leaf( old_block ) )
|
|
b4insert( old_block, key_info, rec, 0L ) ;
|
|
else
|
|
{
|
|
b4get_last_key( old_block, key_data ) ;
|
|
if ( old_block->key_on >= old_block->n_keys ) /*insert at end done different */
|
|
{
|
|
b4insert( old_block, key_data, 0L, old_file_block ) ;
|
|
b4append( old_block, rec ) ;
|
|
}
|
|
else
|
|
{
|
|
at_new = b4key( old_block, old_block->key_on ) ;
|
|
at_new->pointer = rec ;
|
|
b4insert( old_block, key_data, 0L, old_file_block ) ;
|
|
}
|
|
}
|
|
return 0 ;
|
|
}
|
|
|
|
l4pop( &t4->blocks ) ;
|
|
is_branch = b4leaf( old_block ) ? 0 : 1 ;
|
|
|
|
/* NNNNOOOO N - New, O - Old */
|
|
/* The new block's end key gets added to the block just up */
|
|
new_block= t4split( t4, old_block ) ;
|
|
if ( new_block == 0 )
|
|
return -1 ;
|
|
|
|
l4add( &t4->saved, new_block ) ;
|
|
|
|
/* which block should do the insertion ? */
|
|
if ( old_block->key_on < (old_block->n_keys + is_branch) )
|
|
wch_block = old_block ;
|
|
else wch_block = new_block ;
|
|
|
|
if ( b4leaf( wch_block ) )
|
|
b4insert( wch_block, key_info, rec, 0L ) ;
|
|
else
|
|
{
|
|
b4get_last_key( wch_block, key_data ) ;
|
|
if ( wch_block->key_on >= wch_block->n_keys ) /* insert at end done different */
|
|
{
|
|
b4insert( wch_block, key_data, 0L, old_file_block ) ;
|
|
b4append( wch_block, rec ) ;
|
|
}
|
|
else
|
|
{
|
|
at_new = b4key( wch_block, wch_block->key_on ) ;
|
|
at_new->pointer = rec ;
|
|
b4insert( wch_block, key_data, 0L, old_file_block ) ;
|
|
}
|
|
}
|
|
|
|
#ifdef S4INDEX_VERIFY
|
|
if ( b4verify( old_block ) == -1 )
|
|
e4describe( t4->code_base, e4index, t4->alias, "t4split()-old after split", "" ) ;
|
|
if ( b4verify( new_block ) == -1 )
|
|
e4describe( t4->code_base, e4index, t4->alias, "t4split()-new after split", "" ) ;
|
|
#endif
|
|
|
|
/* Now add to the block just up */
|
|
new_block->key_on = b4lastpos(new_block) ;
|
|
|
|
key_info = b4key_key( new_block, new_block->key_on ) ;
|
|
rec = new_block->file_block ;
|
|
|
|
if( !b4leaf( new_block ) )
|
|
if ( b4get_last_key( new_block, key2_data ) != 4)
|
|
key_info = (unsigned char *)key2_data ;
|
|
|
|
old_block->key_on = b4lastpos( old_block ) ;
|
|
memcpy( key_data, b4key_key( old_block, old_block->key_on ), t4->header.key_len ) ;
|
|
|
|
old_file_block = old_block->file_block ;
|
|
if ( b4flush( old_block ) < 0 )
|
|
return -1 ;
|
|
b4free( old_block ) ;
|
|
old_block = (B4BLOCK *) t4->blocks.last_node ;
|
|
}
|
|
}
|
|
#else
|
|
#ifdef S4CLIPPER
|
|
int S4FUNCTION t4add( TAG4 *t4, unsigned char *key_info, long rec )
|
|
{
|
|
CODE4 *c4 ;
|
|
INDEX4 *i4 ;
|
|
B4BLOCK *old_block, *root_block, *new_block, *wch_block ;
|
|
int rc, is_branch ;
|
|
long old_file_block, extend_block, new_file_block ;
|
|
B4KEY_DATA *at_new ;
|
|
unsigned char old_key_ptr[ I4MAX_KEY_SIZE ] ;
|
|
unsigned char key_data[I4MAX_KEY_SIZE+1] ; /* temporary storage for the key data (max size 100) */
|
|
int old_desc, inc_pos ;
|
|
#ifndef S4SINGLE
|
|
int d_set ;
|
|
#ifdef S4DEBUG_DEV
|
|
long findVal ;
|
|
int trc ;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef S4DEBUG
|
|
if ( t4 == 0 || key_info == 0 || rec < 1 )
|
|
e4severe( e4parm, E4_T4ADD ) ;
|
|
#endif
|
|
|
|
c4 = t4->code_base ;
|
|
i4 = t4->index ;
|
|
if ( c4->error_code < 0 )
|
|
return -1 ;
|
|
|
|
old_desc = t4->header.descending ;
|
|
t4descending( t4, 0 ) ;
|
|
|
|
rc = t4seek( t4, (char *)key_info, t4->header.key_len ) ;
|
|
|
|
#ifndef S4SINGLE
|
|
if ( rc == 0 && t4->unique_error == 0 )
|
|
{
|
|
for( d_set = 0, inc_pos = t4->header.key_len - 1 ; d_set == 0 && inc_pos >=0 ; inc_pos-- )
|
|
if ( key_info[inc_pos] != 0xFF )
|
|
{
|
|
key_info[inc_pos]++ ;
|
|
d_set = 1 ;
|
|
if ( t4seek( t4, (char *)key_info, t4->header.key_len ) < 0 )
|
|
return -1 ;
|
|
key_info[inc_pos]-- ;
|
|
#ifdef S4DEBUG_DEV
|
|
findVal = t4recno( t4 ) ;
|
|
#endif
|
|
}
|
|
#ifdef S4DEBUG_DEV
|
|
rc = t4seek( t4, (char *)key_info, t4->header.key_len ) ;
|
|
if ( rc != 0 || t4->unique_error != 0 )
|
|
findVal = -2L ;
|
|
for(;;)
|
|
{
|
|
if ( (*t4->cmp)( t4key_data( t4 )->value, key_info, t4->header.key_len ) == 0 )
|
|
{
|
|
trc = t4skip( t4, 1L ) ;
|
|
if ( trc == 0L )
|
|
{
|
|
b4go_eof( t4block( t4 ) ) ;
|
|
break ;
|
|
}
|
|
}
|
|
else
|
|
break ;
|
|
}
|
|
if ( t4recno( t4 ) != findVal )
|
|
e4severe( e4index, "i4addtag() - record number mismatch" ) ;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
t4descending( t4, old_desc ) ;
|
|
|
|
if ( rc < 0 )
|
|
return -1 ;
|
|
|
|
if ( rc == 0 )
|
|
{
|
|
switch ( t4->unique_error )
|
|
{
|
|
case e4unique:
|
|
return e4( c4, e4unique, i4->file.name ) ;
|
|
case r4unique:
|
|
return r4unique ;
|
|
case r4unique_continue:
|
|
return r4unique_continue ;
|
|
default:
|
|
break ;
|
|
}
|
|
}
|
|
|
|
old_block = t4block(t4) ;
|
|
old_file_block = 0 ;
|
|
new_file_block = 0 ;
|
|
|
|
t4->header.version = (short)(t4->header.old_version + 1L) ;
|
|
|
|
while( !b4leaf( old_block ) )
|
|
{
|
|
rc = t4down( t4 ) ;
|
|
if ( rc < 0 || rc == 2 )
|
|
return -1 ;
|
|
old_block = t4block( t4 ) ;
|
|
if ( b4leaf( old_block ) )
|
|
old_block->key_on = b4lastpos( old_block ) + 1 ;
|
|
else
|
|
old_block->key_on = b4lastpos( old_block ) ;
|
|
}
|
|
|
|
for(;;)
|
|
{
|
|
if ( old_block == 0 )
|
|
{
|
|
/* Must create a new root block */
|
|
extend_block = t4extend( t4 ) ;
|
|
if ( extend_block < 0 )
|
|
return (int) extend_block ;
|
|
|
|
root_block = b4alloc( t4, extend_block) ;
|
|
if ( root_block == 0 )
|
|
return -1 ;
|
|
|
|
l4add( &t4->blocks, root_block ) ;
|
|
|
|
b4insert( root_block, key_info, rec, old_file_block ) ;
|
|
t4->header.root = root_block->file_block * 512 ; /* line order here so that the index validation works */
|
|
b4append( root_block, new_file_block ) ;
|
|
|
|
t4->root_write = 1 ;
|
|
return 0 ;
|
|
}
|
|
|
|
if ( b4room( old_block ) )
|
|
{
|
|
if ( b4leaf( old_block ) )
|
|
b4insert( old_block, key_info, rec, 0L ) ;
|
|
else /* update the current pointer, add the new branch */
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( old_block->n_keys == 0 )
|
|
e4severe( e4info, E4_T4ADD ) ;
|
|
/*
|
|
{
|
|
b4insert( old_block, key_info, rec, old_file_block ) ;
|
|
at_new = b4key( old_block, 1 ) ;
|
|
at_new->pointer = new_file_block * 512 ;
|
|
}
|
|
else
|
|
{
|
|
...
|
|
}
|
|
*/
|
|
#endif
|
|
at_new = b4key( old_block, old_block->key_on ) ;
|
|
at_new->pointer = new_file_block * 512 ;
|
|
b4insert( old_block, key_info, rec, old_file_block ) ;
|
|
}
|
|
return 0 ;
|
|
}
|
|
|
|
l4pop( &t4->blocks ) ;
|
|
is_branch = b4leaf( old_block ) ? 0 : 1 ;
|
|
|
|
/* NNNNOOOO N - New, O - Old */
|
|
/* The new block's end key gets added to the block just up */
|
|
if ( old_block->key_on < (t4->header.keys_half + is_branch) )
|
|
{
|
|
new_block= t4split( t4, old_block, 0 ) ;
|
|
if ( new_block == 0 )
|
|
return -1 ;
|
|
wch_block = old_block ;
|
|
}
|
|
else
|
|
{
|
|
new_block= t4split( t4, old_block, 1 ) ;
|
|
if ( new_block == 0 )
|
|
return -1 ;
|
|
wch_block = new_block ;
|
|
}
|
|
|
|
if ( b4leaf( wch_block ) )
|
|
{
|
|
b4insert( wch_block, key_info, rec, 0L ) ;
|
|
if ( new_block->n_keys <= t4->header.keys_half ) /* add a key from the old block!, must have info in new_block because old_block gets deleted below */
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( old_block->n_keys <= t4->header.keys_half ) /* impossible */
|
|
e4severe( e4info, E4_INFO_CIF ) ;
|
|
#endif
|
|
old_block->key_on = old_block->n_keys - 1 ;
|
|
memcpy( key_data, b4key_key( old_block, old_block->key_on ), t4->header.key_len ) ;
|
|
key_info = key_data ;
|
|
rec = b4key( old_block, old_block->key_on )->num ;
|
|
b4remove( old_block ) ;
|
|
new_block->key_on = 0 ;
|
|
b4insert( new_block, key_info, rec, 0 ) ;
|
|
}
|
|
new_block->key_on = 0 ;
|
|
memcpy( key_data, b4key_key( new_block, new_block->key_on ), t4->header.key_len ) ;
|
|
key_info = key_data ;
|
|
rec = b4key( new_block, new_block->key_on )->num ;
|
|
b4remove( new_block ) ;
|
|
}
|
|
else
|
|
{
|
|
/* now get the key to place upwards */
|
|
if ( wch_block->n_keys == 0 ) /* treat like a root block */
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( wch_block == old_block )
|
|
e4severe( e4info, "t4add - split distribution incorrect" ) ;
|
|
#endif
|
|
b4insert( wch_block, key_info, rec, old_file_block ) ;
|
|
b4append( wch_block, new_file_block ) ;
|
|
}
|
|
else
|
|
{
|
|
if ( wch_block->key_on > wch_block->n_keys && wch_block == old_block )
|
|
{
|
|
at_new = b4key( new_block, 0 ) ;
|
|
at_new->pointer = new_file_block * 512 ;
|
|
}
|
|
else
|
|
{
|
|
at_new = b4key( wch_block, wch_block->key_on ) ;
|
|
at_new->pointer = new_file_block * 512 ;
|
|
}
|
|
b4insert( wch_block, key_info, rec, old_file_block ) ;
|
|
}
|
|
memcpy( old_key_ptr, b4key_key( old_block, b4lastpos( old_block )), t4->header.key_len ) ;
|
|
key_info = old_key_ptr ;
|
|
rec = b4key( old_block, b4lastpos( old_block ) )->num ;
|
|
}
|
|
|
|
#ifdef S4INDEX_VERIFY
|
|
if ( b4verify( old_block ) == -1 )
|
|
e4describe( t4->code_base, e4index, t4->alias, "t4split()-old after split", "" ) ;
|
|
if ( b4verify( new_block ) == -1 )
|
|
e4describe( t4->code_base, e4index, t4->alias, "t4split()-new after split", "" ) ;
|
|
#endif
|
|
|
|
l4add( &t4->saved, new_block ) ;
|
|
new_file_block = new_block->file_block ;
|
|
old_file_block = old_block->file_block ;
|
|
if ( b4flush( old_block ) < 0 )
|
|
return -1 ;
|
|
b4free( old_block ) ;
|
|
old_block = (B4BLOCK *) t4->blocks.last_node ;
|
|
}
|
|
}
|
|
#endif /* ifdef S4CLIPPER */
|
|
#endif /* ifdef S4NDX */
|
|
|
|
int S4FUNCTION t4add_calc( TAG4 *t4, long rec )
|
|
{
|
|
char *ptr ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( t4 == 0 || rec < 1 )
|
|
e4severe( e4parm, E4_T4ADD_CALC ) ;
|
|
#endif
|
|
|
|
if ( t4->code_base->error_code < 0 )
|
|
return -1 ;
|
|
|
|
#ifdef S4CLIPPER
|
|
if ( t4->filter )
|
|
if ( !expr4true( t4->filter ) )
|
|
return 0;
|
|
#endif
|
|
|
|
if ( t4expr_key( t4, &ptr ) < 0 )
|
|
return -1 ;
|
|
|
|
return t4add( t4, (unsigned char *)ptr, rec ) ;
|
|
}
|
|
|
|
#endif /* ifdef N4OTHER */
|
|
#endif /* S4OFF_WRITE */
|
|
#endif /* S4INDEX_OFF */
|