campo-sirio/cb5/d4opt.c
alex a0f5e0898b This commit was generated by cvs2svn to compensate for changes in r975,
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
1995-02-06 15:33:45 +00:00

422 lines
9.6 KiB
C
Executable File

/* d4opt.c (c)Copyright Sequiter Software Inc., 1990-1994. All rights reserved. */
#include "d4all.h"
#ifndef S4UNIX
#ifdef __TURBOC__
#pragma hdrstop
#endif
#endif
static void opt4free_alloc( OPT4 * ) ;
static int opt4init_alloc( CODE4 *, int ) ;
static void c4free_blocks( CODE4 *c4 )
{
DATA4 *data ;
data = 0 ;
for ( ;; )
{
data = (DATA4 *)l4next( &c4->data_list, data ) ;
if ( data == 0 )
break ;
d4free_blocks( data ) ;
}
}
int S4FUNCTION d4opt_start( CODE4 *code_base )
{
int rc ;
rc = d4opt_restart( code_base ) ;
if ( rc == 0 )
c4free_blocks( code_base ) ;
return rc ;
}
int S4FUNCTION d4opt_restart( CODE4 *code_base )
{
#ifndef S4OPTIMIZE_OFF
OPT4 *opt ;
unsigned alloc, num_buffers ;
int num_alloc ;
FILE4 *file_on ;
#ifdef S4VBASIC
if ( c4parm_check( code_base, 1, E4_D4OPT_START ) )
return -1 ;
#endif /* S4VBASIC */
if ( code_base == 0 )
#ifdef S4DEBUG
e4severe( e4parm, E4_D4OPT_START ) ;
#else
return -1 ;
#endif
#ifdef S4DEBUG
if ( code_base->debug_int != 0x5281 )
e4severe( e4result, E4_RESULT_D4I ) ;
#endif
if( code_base->error_code < 0 )
return -1 ;
opt = &code_base->opt ;
if ( opt->num_buffers || code_base->has_opt ) /* no initialization required */
return 0 ;
if ( code_base->mem_size_block == 0 || code_base->mem_size_buffer == 0 ||
code_base->mem_size_block > code_base->mem_size_buffer )
{
#ifdef S4DEBUG
e4( code_base, e4parm, E4_PARM_OPT ) ;
#endif
return -1 ;
}
opt->block_size = code_base->mem_size_block ;
if ( code_base->mem_size_block != 0 )
opt->buffer_size = code_base->mem_size_block * ( code_base->mem_size_buffer / code_base->mem_size_block ) ;
else
opt->buffer_size = 0 ;
opt->hash_trail = 0 ;
opt->prio[0] = &opt->dbf_lru ;
opt->prio[1] = &opt->index_lru ;
opt->prio[2] = &opt->other_lru ;
opt->do_update = 1 ;
code_base->mode = OPT4START_MODE ;
opt->check_count = OPT4CHECK_RATE ; /* set to do analysis when first block removed */
for( ; ( (num_buffers = (int)(code_base->mem_start_max / opt->buffer_size - 2 )) < 4) ; )
{
opt->buffer_size -= opt->block_size ;
if ( opt->buffer_size == 0 )
return -1 ;
}
for(;;)
{
code_base->has_opt = 1 ;
opt->min_link = opt->max_blocks = (int)( opt->buffer_size / opt->block_size ) ;
opt->block_power = (char) c4calc_type( opt->block_size ) ;
opt->num_shift = (char) (8*sizeof( long ) - (opt->block_power)) ;
opt->num_lists = OPT4BLOCK_DENSITY << c4calc_type( (long)num_buffers * opt->max_blocks ) ;
num_alloc = opt4init_alloc( code_base, num_buffers ) ;
if ( num_alloc <= 0 )
{
d4opt_suspend( code_base ) ;
return -1 ;
}
opt->num_buffers = num_alloc ;
if ( num_alloc < 4 ) /* couldn't do a minimum allocation, try again */
{
opt4free_alloc( opt ) ; /* free allocs */
if ( num_buffers > 4 )
num_buffers = 4 ;
opt->buffer_size /= 2 ;
opt->buffer_size = opt->buffer_size - opt->buffer_size % opt->block_size ; /* round it down to a block_size multiple */
if ( opt->buffer_size == 0 )
return -1 ;
continue ;
}
break ;
}
opt->num_blocks = (long)opt->num_buffers * opt->max_blocks ;
opt->num_lists = OPT4BLOCK_DENSITY << c4calc_type( opt->num_blocks ) ;
opt->mask = opt->num_lists - 1 ;
/* now actually optimize those files reqd */
for ( file_on = 0 ;; )
{
file_on = (FILE4 *)l4next( &opt->opt_files, file_on ) ;
if ( file_on == 0 )
break ;
file_on->len = -1 ; /* in case the file length changed during suspension */
file_on->do_buffer = 1 ; /* re-add the reference */
#ifndef S4SINGLE
if ( file_on->is_exclusive == 1 )
#endif
file4set_write_opt( file_on, 1 ) ;
if ( file_on->hash_init == -1 )
{
file_on->hash_init = opt->hash_trail * opt->block_size ;
#ifdef S4DEBUG
if ( file4len( file_on ) < 0 || opt->block_size == 0 )
e4severe( e4info, E4_D4OPT_START ) ;
#endif
opt->hash_trail = (opt->hash_trail + file4len( file_on ) / opt->block_size) % opt->num_blocks ;
}
}
#endif
return 0 ;
}
int S4FUNCTION d4opt_suspend( CODE4 *code_base )
{
#ifndef S4OPTIMIZE_OFF
OPT4 *opt ;
FILE4 *file_on ;
int rc ;
#ifdef S4VBASIC
if ( c4parm_check( code_base, 1, E4_D4OPT_SUSPEND ) )
return -1 ;
#endif /* S4VBASIC */
if ( code_base == 0 )
#ifdef S4DEBUG
e4severe( e4parm, E4_D4OPT_SUSPEND ) ;
#else
return -1 ;
#endif
opt = &code_base->opt ;
if ( opt->num_buffers == 0 || code_base->has_opt == 0 )
return 0 ;
rc = 0 ;
/* first remove any optimized files */
for ( file_on = 0 ;; )
{
file_on = (FILE4 *)l4next( &opt->opt_files, file_on ) ;
if ( file_on == 0 )
break ;
if ( ( rc = file4low_flush( file_on, 1 ) ) < 0 )
rc = -1 ;
file_on->do_buffer = 0 ; /* remove the reference */
file4set_write_opt( file_on, 0 ) ;
}
code_base->has_opt = 0 ;
opt4free_alloc( opt ) ;
opt->num_buffers = 0 ; /* mark as freed */
if ( rc < 0 )
return e4( code_base, e4opt_suspend, 0 ) ;
else
#endif
return 0 ;
}
int S4FUNCTION d4optimize( DATA4 *d4, int opt_flag )
{
#ifndef S4OPTIMIZE_OFF
#ifdef N4OTHER
TAG4 *tag_on ;
#else
INDEX4 *index_on ;
#endif
#ifdef S4VBASIC
if ( c4parm_check( d4, 2, E4_D4OPTIMIZE ) )
return -1 ;
#endif /* S4VBASIC */
if ( d4 == 0 || opt_flag < -1 || opt_flag > 1 )
#ifdef S4DEBUG
e4severe( e4parm, E4_D4OPTIMIZE ) ;
#else
return -1 ;
#endif
if ( file4optimize( &d4->file, opt_flag, OPT4DBF ) < 0 )
return -1 ;
#ifdef N4OTHER
for( tag_on = 0;;)
{
tag_on = d4tag_next( d4, tag_on ) ;
if ( tag_on == 0 )
break ;
if ( file4optimize( &tag_on->file, opt_flag, OPT4INDEX ) < 0 )
return -1 ;
}
#else
for ( index_on = 0 ;; )
{
index_on = (INDEX4 *)l4next( &d4->indexes, index_on ) ;
if ( index_on == 0 )
break ;
if ( file4optimize( &index_on->file, opt_flag, OPT4INDEX ) < 0 )
return -1 ;
}
#endif
if ( d4->n_fields_memo > 0 && d4->memo_file.file.hand != -1 )
return file4optimize( &d4->memo_file.file, opt_flag, OPT4OTHER ) ;
else
return 0 ;
#else
return 0 ;
#endif
}
int S4FUNCTION d4optimize_write( DATA4 *d4, int opt_flag )
{
#ifndef S4OFF_WRITE
#ifndef S4OPTIMIZE_OFF
#ifndef N4OTHER
INDEX4 *index_on ;
#else
TAG4 *tag_on ;
#endif
#ifdef S4VBASIC
if ( c4parm_check( d4, 2, E4_D4OPT_WRITE ) )
return -1 ;
#endif /* S4VBASIC */
if ( d4 == 0 || opt_flag < -1 || opt_flag > 1 )
#ifdef S4DEBUG
e4severe( e4parm, E4_D4OPT_WRITE ) ;
#else
return -1 ;
#endif
if ( file4optimize_write( &d4->file, opt_flag ) < 0 )
return -1 ;
if ( d4->n_fields_memo > 0 && d4->memo_file.file.hand != -1 )
if ( file4optimize_write( &d4->memo_file.file, opt_flag ) < 0 )
return -1 ;
#ifndef N4OTHER
index_on = (INDEX4 *) l4first( &d4->indexes ) ;
if ( index_on != 0 )
do
{
if ( file4optimize_write( &index_on->file, opt_flag ) < 0 )
return -1 ;
index_on = (INDEX4 *)l4next( &d4->indexes, index_on ) ;
} while ( index_on != 0 ) ;
#else
for( tag_on = 0;;)
{
tag_on = d4tag_next( d4, tag_on ) ;
if ( tag_on == 0 )
break ;
if ( file4optimize_write( &tag_on->file, opt_flag ) < 0 )
return -1 ;
}
#endif
#endif
#endif
return 0 ;
}
#ifndef S4OPTIMIZE_OFF
static void opt4free_alloc( OPT4 *opt )
{
OPT4BLOCK *cur_block ;
int i ;
#ifdef S4DEBUG
if ( opt == 0 )
e4severe( e4parm, E4_OPT4FREE ) ;
#endif
if ( opt->buffers )
{
for ( --opt->num_buffers; opt->num_buffers >= 0 ; opt->num_buffers-- )
{
for ( i = 0 ; i < (int)opt->max_blocks ; i++ )
{
cur_block = &opt->blocks[ opt->num_buffers * opt->max_blocks + i] ;
l4remove( &opt->avail, &cur_block->lru_link ) ;
}
if ( opt->buffers[opt->num_buffers] != 0 )
u4free( opt->buffers[opt->num_buffers] ) ;
}
u4free( opt->buffers ) ;
opt->buffers = 0 ;
}
u4free( opt->write_buffer ) ;
opt->write_buffer = 0 ;
u4free( opt->read_buffer ) ;
opt->read_buffer = 0 ;
u4free( opt->blocks ) ;
opt->blocks = 0 ;
u4free( opt->lists ) ;
opt->lists = 0 ;
u4free( opt->lists ) ;
opt->lists = 0 ;
}
static int opt4init_alloc( CODE4 *code_base, int num_buffers )
{
OPT4BLOCK *cur_block ;
OPT4 *opt ;
int num_alloc, i ;
#ifdef S4DEBUG
if ( code_base == 0 )
e4severe( e4parm, E4_OPT4INIT ) ;
#endif
opt = &code_base->opt ;
opt->buffers = (void **)u4alloc( ( (long)num_buffers + 2 ) * sizeof( void * ) ) ;
if ( opt->buffers == 0 )
{
d4opt_suspend( code_base ) ;
return -1 ;
}
opt->lists = (LIST4 *)u4alloc( opt->num_lists * sizeof (LIST4) ) ;
if ( opt->lists == 0 )
{
d4opt_suspend( code_base ) ;
return -1 ;
}
opt->blocks = (OPT4BLOCK *)u4alloc( (long)num_buffers * opt->max_blocks * sizeof( OPT4BLOCK ) ) ;
if ( opt->blocks == 0 )
{
d4opt_suspend( code_base ) ;
return -1 ;
}
opt->write_buffer = (char *)u4alloc( opt->buffer_size ) ;
if( opt->write_buffer == 0 )
return 0 ;
opt->write_block_count = 0 ;
opt->write_cur_pos = 0 ;
opt->write_start_pos = 0 ;
opt->write_file = 0 ;
opt->read_buffer = (char *)u4alloc( opt->buffer_size ) ;
if( opt->read_buffer == 0 )
return 0 ;
for ( num_alloc = 0 ; num_alloc < num_buffers ; num_alloc++ )
{
opt->buffers[num_alloc] = u4alloc( opt->buffer_size ) ;
if( opt->buffers[num_alloc] == 0 )
break ;
for ( i = 0 ; i < (int)opt->max_blocks ; i++ )
{
cur_block = &opt->blocks[ num_alloc * opt->max_blocks + i] ;
cur_block->data = (OPT4BLOCK *)( (char *)opt->buffers[num_alloc] + i * opt->block_size ) ;
l4add( &opt->avail, &cur_block->lru_link ) ;
}
}
return num_alloc ;
}
#endif