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
		
			
				
	
	
		
			422 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			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
 |