/* 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