af15e0698b
git-svn-id: svn://10.65.10.50/trunk@4679 c028cbd2-c16b-5b4b-a496-9718f37d4682
813 lines
24 KiB
C
Executable File
813 lines
24 KiB
C
Executable File
/* d4opt.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
|
|
|
|
#include "d4all.h"
|
|
#ifndef S4UNIX
|
|
#ifdef __TURBOC__
|
|
#pragma hdrstop
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef S4OFF_OPTIMIZE
|
|
/* ensure we have at least 8 buffers -- 4 for special purpose, 4 for general purpose */
|
|
#define MEM4MIN_BUFFERS 8
|
|
static void opt4freeAlloc( OPT4 * ) ;
|
|
static int opt4initAlloc( CODE4 *, int ) ;
|
|
#ifdef E4ANALYZE_ALL
|
|
int file4copyx( CODE4 *, FILE4 *, char * ) ;
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef S4OFF_OPTIMIZE
|
|
/* if possible, it gets the physical amount of available memory and sets the
|
|
memStartMax to a percentage of that amount (the input percent)
|
|
It won't auto-start optimizatino if it was suspended physically */
|
|
void code4memStartMaxSet( CODE4 *c4, const int percent )
|
|
{
|
|
double availMem ;
|
|
#ifdef S4WIN32
|
|
MEMORYSTATUS memory;
|
|
#endif
|
|
|
|
if ( c4->hadOpt == 1 || c4->opt.numBuffers || c4->hasOpt ) /* don't enable if suspend was requested or is already initialized */
|
|
return ;
|
|
|
|
availMem = 0 ;
|
|
|
|
#ifdef S4WIN32
|
|
GlobalMemoryStatus( &memory ) ;
|
|
availMem = memory.dwAvailPhys ;
|
|
#endif
|
|
|
|
if ( availMem != 0 && percent <= 100 && percent >= 0 )
|
|
{
|
|
c4->memStartMax = (long) ( ((double)percent / 100) * availMem ) ;
|
|
code4optStart( c4 ) ;
|
|
}
|
|
else
|
|
c4->hadOpt = 1 ; /* had chance to enable optimization but it was denied */
|
|
|
|
return ;
|
|
}
|
|
#endif
|
|
|
|
#ifndef S4CLIENT
|
|
#ifdef S4CB51
|
|
int S4FUNCTION code4freeBlocks( CODE4 *c4 )
|
|
#else
|
|
static int code4freeBlocks( CODE4 *c4 )
|
|
#endif
|
|
{
|
|
#ifdef S4SERVER
|
|
SERVER4CLIENT *client ;
|
|
#endif
|
|
#ifndef S4CLIENT
|
|
DATA4 *data ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( c4 == 0 )
|
|
return error4( 0, e4parm_null, E92510 ) ;
|
|
#endif
|
|
|
|
#ifdef S4SERVER
|
|
for( client = 0 ;; )
|
|
{
|
|
client = (SERVER4CLIENT *)l4next( &c4->server->clients, client ) ;
|
|
if ( client == 0 )
|
|
break ;
|
|
for ( data = 0 ;; )
|
|
{
|
|
data = (DATA4 *)l4next( tran4dataList( &client->trans ), data ) ;
|
|
if ( data == 0 )
|
|
break ;
|
|
d4freeBlocks( data ) ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef S4STAND_ALONE
|
|
for ( data = 0 ;; )
|
|
{
|
|
data = (DATA4 *)l4next( tran4dataList( &c4->c4trans.trans ), data ) ;
|
|
if ( data == 0 )
|
|
break ;
|
|
d4freeBlocks( data ) ;
|
|
}
|
|
#endif
|
|
|
|
return 0 ;
|
|
}
|
|
#endif
|
|
|
|
#ifdef S4STAND_ALONE
|
|
#ifndef S4OFF_OPTIMIZE
|
|
int S4FUNCTION code4optAll( CODE4 *c4 )
|
|
{
|
|
LIST4 *list ;
|
|
int rc ;
|
|
DATA4FILE *dfile ;
|
|
DATA4 *data ;
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( c4 == 0 )
|
|
return error4( 0, e4parm_null, E92531 ) ;
|
|
#endif
|
|
|
|
list = tran4dataList( code4trans( c4 ) ) ;
|
|
for ( dfile = 0 ;; )
|
|
{
|
|
dfile = (DATA4FILE *)l4next( &c4->dataFileList, dfile ) ;
|
|
if ( dfile == 0 )
|
|
break ;
|
|
#ifdef S4OPTIMIZE_STATS
|
|
/* don't optimize the stat file or nested d4appends occur */
|
|
if ( c4->statusDbf != 0 )
|
|
if ( &dfile->file == &c4->statusDbf->dataFile->file ) /* don't do for the stat file! */
|
|
continue ;
|
|
#endif
|
|
for ( data = 0 ;; )
|
|
{
|
|
data = (DATA4 *)l4next( list, data ) ;
|
|
if ( data == 0 )
|
|
{
|
|
#ifdef E4ANALYZE
|
|
#ifndef S4OFF_MULTI
|
|
code4lockClear( c4 ) ;
|
|
#endif
|
|
return error4( c4, e4info, E92531 ) ;
|
|
#else
|
|
break ;
|
|
#endif
|
|
}
|
|
if ( data->dataFile == dfile )
|
|
{
|
|
#ifndef S4OFF_MULTI
|
|
rc = d4lockAddAll( data ) ;
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
#endif
|
|
rc = d4optimize( data, OPT4ALL ) ;
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
rc = d4optimizeWrite( data, OPT4ALL ) ;
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef S4OFF_MULTI
|
|
rc = code4lock( c4 ) ;
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
#endif
|
|
|
|
code4optStart( c4 ) ;
|
|
|
|
return 0 ;
|
|
}
|
|
#endif /* S4OFF_OPTIMIZE */
|
|
#endif /* S4STAND_ALONE */
|
|
|
|
int S4FUNCTION code4optStart( CODE4 *c4 )
|
|
{
|
|
#ifndef S4OFF_OPTIMIZE
|
|
int rc ;
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( c4 == 0 )
|
|
return error4( 0, e4parm_null, E92501 ) ;
|
|
#endif
|
|
|
|
rc = code4optRestart( c4 ) ;
|
|
#ifndef S4CLIENT
|
|
if ( rc == 0 )
|
|
code4freeBlocks( c4 ) ;
|
|
#endif
|
|
|
|
return rc ;
|
|
#else
|
|
return 0 ;
|
|
#endif /* S4OFF_OPTIMIZE */
|
|
}
|
|
|
|
int code4optRestart( CODE4 *c4 )
|
|
{
|
|
#ifndef S4OFF_OPTIMIZE
|
|
OPT4 *opt ;
|
|
unsigned numBuffers ;
|
|
int numAlloc ;
|
|
FILE4 *fileOn ;
|
|
double hitCountAdd ;
|
|
#ifdef S4WIN32
|
|
DWORD sectorsPerCluster, bytesPerSector, numberFreeClusters, totalNumberClusters ;
|
|
#endif
|
|
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( c4, 1, E92502 ) )
|
|
return -1 ;
|
|
#endif /* S4VBASIC */
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( c4 == 0 )
|
|
return error4( 0, e4parm_null, E92502 ) ;
|
|
#endif
|
|
|
|
#ifdef E4ANALYZE
|
|
if ( c4->debugInt != 0x5281 )
|
|
return error4( 0, e4struct, E81301 ) ;
|
|
#endif
|
|
|
|
if ( error4code( c4 ) < 0 )
|
|
return e4codeBase ;
|
|
|
|
opt = &c4->opt ;
|
|
|
|
if ( opt->numBuffers || c4->hasOpt ) /* no initialization required */
|
|
return 0 ;
|
|
|
|
#ifdef S4WIN32
|
|
/* set block sizes based on sector-size values */
|
|
/* if used, final version must address different drives for different
|
|
files */
|
|
/* use current directory for now */
|
|
if ( GetDiskFreeSpace( 0, §orsPerCluster, &bytesPerSector, &numberFreeClusters, &totalNumberClusters ) == TRUE )
|
|
{
|
|
if ( c4->memSizeBlock < bytesPerSector ) /* ok if larger than sector size */
|
|
c4->memSizeBlock = bytesPerSector ;
|
|
else
|
|
{
|
|
/* round down to nearest multiple sector size */
|
|
c4->memSizeBlock = bytesPerSector * (c4->memSizeBlock / bytesPerSector ) ;
|
|
/* round down to nearest multiple block size */
|
|
c4->memSizeBuffer = c4->memSizeBlock * ( c4->memSizeBuffer / c4->memSizeBlock ) ;
|
|
}
|
|
if ( c4->memSizeBlock > c4->memSizeBuffer )
|
|
c4->memSizeBuffer = c4->memSizeBlock ;
|
|
}
|
|
#endif
|
|
|
|
#ifdef E4ANALYZE
|
|
if ( c4->memSizeBlock == 0 || c4->memSizeBuffer == 0 || c4->memSizeBlock > c4->memSizeBuffer )
|
|
return error4( c4, e4struct, E82501 ) ;
|
|
#endif
|
|
|
|
opt->blockSize = c4->memSizeBlock ;
|
|
|
|
if ( c4->memSizeBlock != 0 )
|
|
opt->bufferSize = (unsigned long)(c4->memSizeBlock * ( (unsigned long)c4->memSizeBuffer / c4->memSizeBlock )) ;
|
|
else
|
|
opt->bufferSize = 0 ;
|
|
|
|
opt->hashTrail = 0 ;
|
|
opt->prio[0] = &opt->other ;
|
|
opt->prio[1] = &opt->dbfLo ;
|
|
opt->prio[2] = &opt->indexLo ;
|
|
opt->prio[3] = &opt->dbfHi ;
|
|
opt->prio[4] = &opt->indexHi ;
|
|
opt->doUpdate = 1 ;
|
|
opt->checkCount = OPT4CHECK_RATE ; /* set to do analysis when first block removed */
|
|
|
|
for( ; ( (numBuffers = (unsigned int)((unsigned long)c4->memStartMax / (unsigned long)(opt->bufferSize - 2UL) )) < MEM4MIN_BUFFERS) ; )
|
|
{
|
|
opt->bufferSize -= opt->blockSize ;
|
|
if ( opt->bufferSize == 0 )
|
|
return -1 ;
|
|
}
|
|
|
|
numBuffers -= 4 ; /* 4 special use buffers are taken into account elsewhere */
|
|
|
|
for( ;; )
|
|
{
|
|
c4->hasOpt = 1 ;
|
|
opt->minLink = opt->maxBlocks = (unsigned int)( opt->bufferSize / opt->blockSize ) ;
|
|
opt->blockPower = (char)c4calcType( opt->blockSize ) ;
|
|
opt->numShift = (char)(8*sizeof( long ) - (opt->blockPower)) ;
|
|
opt->numLists = OPT4BLOCK_DENSITY << c4calcType( (long)numBuffers * opt->maxBlocks ) ;
|
|
|
|
numAlloc = opt4initAlloc( c4, numBuffers ) ;
|
|
|
|
if ( numAlloc <= 0 )
|
|
{
|
|
code4optSuspend( c4 ) ;
|
|
return -1 ;
|
|
}
|
|
|
|
opt->numBuffers = numAlloc ;
|
|
|
|
if ( numAlloc < 4 ) /* couldn't do a minimum allocation, try again */
|
|
{
|
|
opt4freeAlloc( opt ) ; /* free allocs */
|
|
if ( numBuffers > 4 )
|
|
numBuffers = 4 ;
|
|
opt->bufferSize /= 2 ;
|
|
opt->bufferSize = opt->bufferSize - opt->bufferSize % opt->blockSize ; /* round it down to a blockSize multiple */
|
|
if ( opt->bufferSize == 0 )
|
|
return -1 ;
|
|
continue ;
|
|
}
|
|
break ;
|
|
}
|
|
|
|
opt->numBlocks = (unsigned long)opt->numBuffers * opt->maxBlocks ;
|
|
opt->numLists = OPT4BLOCK_DENSITY << c4calcType( opt->numBlocks ) ;
|
|
opt->mask = opt->numLists - 1 ;
|
|
|
|
/* now actually optimize those files reqd */
|
|
for ( fileOn = 0 ;; )
|
|
{
|
|
fileOn = (FILE4 *)l4next( &opt->optFiles, fileOn ) ;
|
|
if ( fileOn == 0 )
|
|
break ;
|
|
fileOn->len = -1 ; /* in case the file length changed during suspension */
|
|
fileOn->doBuffer = 1 ; /* re-add the reference */
|
|
#ifndef S4SINGLE
|
|
if ( fileOn->lowAccessMode == OPEN4DENY_RW )
|
|
#endif
|
|
file4setWriteOpt( fileOn, 1 ) ;
|
|
|
|
if ( fileOn->type == OPT4DBF )
|
|
{
|
|
hitCountAdd = (double)fileOn->expectedReadSize / (double)opt->blockSize ;
|
|
if ( hitCountAdd > 1.0 )
|
|
fileOn->hitCountAdd = 1.0 ;
|
|
else
|
|
fileOn->hitCountAdd = hitCountAdd ;
|
|
}
|
|
|
|
if ( fileOn->hashInit == -1 )
|
|
{
|
|
fileOn->hashInit = opt->hashTrail * opt->blockSize ;
|
|
#ifdef E4ANALYZE
|
|
if ( ( (long)file4len( fileOn ) < (long)0L ) || ( opt->blockSize == 0 ) )
|
|
return error4( c4, e4info, E92502 ) ;
|
|
#endif
|
|
opt->hashTrail = (opt->hashTrail + (unsigned)file4len( fileOn ) / opt->blockSize) % opt->numBlocks ;
|
|
}
|
|
#ifdef E4ANALYZE_ALL
|
|
file4copyx( c4, fileOn, fileOn->dupName ) ;
|
|
#endif
|
|
}
|
|
|
|
opt->minAccessTimeVariation = (unsigned int)opt->numBlocks / 100 ;
|
|
if ( opt->minAccessTimeVariation < 2 ) /* provide a basic minimum */
|
|
opt->minAccessTimeVariation = 2 ;
|
|
opt->dbfLo.minLink = (unsigned short int) ((double)opt->numBlocks * OPT4DBF_LO_MIN_LINK) ;
|
|
opt->dbfLo.maxTime = (unsigned long) ((double)opt->numBlocks * OPT4DBF_LO_MAX_TIME) ;
|
|
opt->dbfLo.minTime = (unsigned long) ((double)opt->numBlocks * OPT4DBF_LO_MIN_TIME) ;
|
|
opt->dbfHi.minLink = (unsigned short int) ((double)opt->numBlocks * OPT4DBF_HI_MIN_LINK) ;
|
|
opt->dbfHi.maxTime = (unsigned long) ((double)opt->numBlocks * OPT4DBF_HI_MAX_TIME) ;
|
|
opt->dbfHi.minTime = (unsigned long) ((double)opt->numBlocks * OPT4DBF_HI_MIN_TIME) ;
|
|
opt->indexLo.minLink = (unsigned short int) ((double)opt->numBlocks * OPT4INDEX_LO_MIN_LINK) ;
|
|
opt->indexLo.maxTime = (unsigned long) ((double)opt->numBlocks * OPT4INDEX_LO_MAX_TIME) ;
|
|
opt->indexLo.minTime = (unsigned long) ((double)opt->numBlocks * OPT4INDEX_LO_MIN_TIME) ;
|
|
opt->indexHi.minLink = (unsigned short int) ((double)opt->numBlocks * OPT4INDEX_HI_MIN_LINK) ;
|
|
opt->indexHi.maxTime = (unsigned long) ((double)opt->numBlocks * OPT4INDEX_HI_MAX_TIME) ;
|
|
opt->indexHi.minTime = (unsigned long) ((double)opt->numBlocks * OPT4INDEX_HI_MIN_TIME) ;
|
|
opt->other.minLink = (unsigned short int) ((double)opt->numBlocks * OPT4OTHER_MIN_LINK) ;
|
|
opt->other.maxTime = (unsigned long) ((double)opt->numBlocks * OPT4OTHER_MAX_TIME) ;
|
|
opt->other.minTime = (unsigned long) ((double)opt->numBlocks * OPT4OTHER_MIN_TIME) ;
|
|
|
|
#endif /* S4OFF_OPTIMIZE */
|
|
return 0 ;
|
|
}
|
|
|
|
int S4FUNCTION code4optSuspend( CODE4 *c4 )
|
|
{
|
|
#ifndef S4OFF_OPTIMIZE
|
|
OPT4 *opt ;
|
|
FILE4 *fileOn ;
|
|
int rc, saveRc ;
|
|
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( c4, 1, E92503 ) )
|
|
return -1 ;
|
|
#endif /* S4VBASIC */
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( c4 == 0 )
|
|
return error4( 0, e4parm_null, E92503 ) ;
|
|
#endif
|
|
|
|
opt = &c4->opt ;
|
|
if ( opt->numBuffers == 0 || c4->hasOpt == 0 )
|
|
return 0 ;
|
|
|
|
rc = 0 ;
|
|
saveRc = error4set( c4, 0 ) ;
|
|
|
|
/* first remove any optimized files */
|
|
for ( fileOn = 0 ;; )
|
|
{
|
|
fileOn = (FILE4 *)l4next( &opt->optFiles, fileOn ) ;
|
|
if ( fileOn == 0 )
|
|
break ;
|
|
rc = opt4fileFlush( fileOn, 1 ) ;
|
|
fileOn->doBuffer = 0 ; /* remove the reference */
|
|
file4setWriteOpt( fileOn, 0 ) ;
|
|
}
|
|
c4->hasOpt = 0 ;
|
|
c4->hadOpt = 1 ; /* indicate that at one time optimization was enabled */
|
|
|
|
opt4freeAlloc( opt ) ;
|
|
|
|
opt->numBuffers = 0 ; /* mark as freed */
|
|
|
|
if ( saveRc < 0 )
|
|
error4set( c4, saveRc ) ;
|
|
|
|
if ( rc < 0 )
|
|
return error4stack( c4, e4optSuspend, E92503 ) ;
|
|
else
|
|
#endif
|
|
return 0 ;
|
|
}
|
|
|
|
#ifndef S4SERVER
|
|
int S4FUNCTION d4optimize( DATA4 *d4, const int optFlag )
|
|
{
|
|
#ifdef S4CLIENT
|
|
return 0 ;
|
|
#else
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( d4, 2, E92504 ) )
|
|
return -1 ;
|
|
#endif /* S4VBASIC */
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( d4 == 0 || optFlag < -1 || optFlag > 1 )
|
|
return error4( 0, e4parm, E92504 ) ;
|
|
#endif
|
|
return dfile4optimize( d4->dataFile, optFlag ) ;
|
|
#endif
|
|
}
|
|
#endif /* S4SERVER */
|
|
|
|
#ifndef S4CLIENT
|
|
int dfile4optimize( DATA4FILE *d4, const int optFlag )
|
|
{
|
|
#ifndef S4OFF_OPTIMIZE
|
|
int rc ;
|
|
#ifndef S4OFF_INDEX
|
|
#ifdef N4OTHER
|
|
TAG4FILE *tagOn ;
|
|
#else
|
|
INDEX4FILE *indexOn ;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef E4PARM_LOW
|
|
if ( d4 == 0 || optFlag < -1 || optFlag > 1 )
|
|
return error4( 0, e4parm, E91102 ) ;
|
|
#endif
|
|
|
|
if ( dfile4recWidth( d4 ) > d4->c4->opt.bufferSize ) /* don't optimize records larger than the buffer size */
|
|
{
|
|
rc = file4optimizeLow( &d4->file, optFlag, OPT4DBF, dfile4recWidth( d4 ), d4 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
}
|
|
|
|
#ifndef S4OFF_INDEX
|
|
#ifdef N4OTHER
|
|
for( tagOn = 0;;)
|
|
{
|
|
tagOn = dfile4tagNext( d4, tagOn ) ;
|
|
if ( tagOn == 0 )
|
|
break ;
|
|
|
|
rc = file4optimizeLow( &tagOn->file, optFlag, OPT4INDEX, 0, tagOn ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
}
|
|
#else
|
|
for ( indexOn = 0 ;; )
|
|
{
|
|
indexOn = (INDEX4FILE *)l4next( &d4->indexes, indexOn ) ;
|
|
if ( indexOn == 0 )
|
|
break ;
|
|
rc = file4optimizeLow( &indexOn->file, optFlag, OPT4INDEX, 0, indexOn ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef S4OFF_MEMO
|
|
if ( d4->memoFile.file.hand != -1 )
|
|
return file4optimize( &d4->memoFile.file, optFlag, OPT4OTHER ) ;
|
|
#endif
|
|
|
|
return 0 ;
|
|
#else
|
|
return 0 ;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
int S4FUNCTION d4optimizeWrite( DATA4 *d4, const int optFlag )
|
|
{
|
|
#ifdef S4CLIENT
|
|
return 0 ;
|
|
#else
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( d4, 2, E92506 ) )
|
|
return -1 ;
|
|
#endif /* S4VBASIC */
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( d4 == 0 || optFlag < -1 || optFlag > 1 )
|
|
return error4( 0, e4parm, E92506 ) ;
|
|
#endif
|
|
return dfile4optimizeWrite( d4->dataFile, optFlag ) ;
|
|
#endif
|
|
}
|
|
|
|
#ifndef S4CLIENT
|
|
#ifdef P4ARGS_USED
|
|
#pragma argsused
|
|
#endif
|
|
int dfile4optimizeWrite( DATA4FILE *d4, const int optFlag )
|
|
{
|
|
#ifndef S4OFF_WRITE
|
|
#ifndef S4OFF_OPTIMIZE
|
|
int rc ;
|
|
#ifndef S4OFF_INDEX
|
|
#ifdef N4OTHER
|
|
TAG4FILE *tagOn ;
|
|
#else
|
|
INDEX4FILE *indexOn ;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef E4PARM_LOW
|
|
if ( d4 == 0 || optFlag < -1 || optFlag > 1 )
|
|
return error4( 0, e4parm, E91102 ) ;
|
|
#endif
|
|
|
|
rc = file4optimizeWrite( &d4->file, optFlag ) ;
|
|
if ( rc < 0 )
|
|
return error4stack( d4->c4, rc, E91102 ) ;
|
|
|
|
#ifndef S4OFF_MEMO
|
|
if ( d4->memoFile.file.hand != -1 )
|
|
{
|
|
|
|
rc = file4optimizeWrite( &d4->memoFile.file, optFlag ) ;
|
|
if ( rc < 0 )
|
|
return error4stack( d4->c4, rc, E91102 ) ;
|
|
}
|
|
#endif
|
|
|
|
#ifndef S4OFF_INDEX
|
|
#ifndef N4OTHER
|
|
indexOn = (INDEX4FILE *) l4first( &d4->indexes ) ;
|
|
if ( indexOn != 0 )
|
|
do
|
|
{
|
|
rc = file4optimizeWrite( &indexOn->file, optFlag ) ;
|
|
if ( rc < 0 )
|
|
return error4stack( d4->c4, rc, E91102 ) ;
|
|
indexOn = (INDEX4FILE *)l4next( &d4->indexes, indexOn ) ;
|
|
} while ( indexOn != 0 ) ;
|
|
#else
|
|
for( tagOn = 0;;)
|
|
{
|
|
tagOn = dfile4tagNext( d4, tagOn ) ;
|
|
if ( tagOn == 0 )
|
|
break ;
|
|
rc = file4optimizeWrite( &tagOn->file, optFlag ) ;
|
|
if ( rc < 0 )
|
|
return error4stack( d4->c4, rc, E91102 ) ;
|
|
}
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
return 0 ;
|
|
}
|
|
#endif
|
|
|
|
#ifndef S4OFF_OPTIMIZE
|
|
static void opt4freeAlloc( OPT4 *opt )
|
|
{
|
|
OPT4BLOCK *curBlock ;
|
|
int i ;
|
|
#ifdef S4ADVANCE_READ
|
|
FILE4ADVANCE_READ *advanceRead ;
|
|
LINK4 *advanceLink ;
|
|
FILE4 *f4 ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_LOW
|
|
if ( opt == 0 )
|
|
{
|
|
error4( 0, e4parm_null, E92508 ) ;
|
|
return ;
|
|
}
|
|
#endif
|
|
|
|
#ifdef S4WRITE_DELAY
|
|
if ( opt->delayWriteBuffer != 0 )
|
|
{
|
|
while ( l4numNodes( &opt->delayAvail ) != opt->maxBlocks ) /* wait for delay-write to finish on blocks */
|
|
Sleep( 0 ) ;
|
|
|
|
for ( i = 0 ; i < (int)opt->maxBlocks ; i++ )
|
|
{
|
|
curBlock = &opt->blocks[ opt->numBuffers * opt->maxBlocks + i] ;
|
|
l4remove( &opt->delayAvail, &curBlock->lruLink ) ;
|
|
}
|
|
|
|
DeleteCriticalSection( &opt->critical4optWrite ) ;
|
|
u4free( opt->delayWriteBuffer ) ;
|
|
opt->delayWriteBuffer = 0 ;
|
|
}
|
|
#endif
|
|
|
|
#ifdef S4ADVANCE_READ
|
|
if ( opt->advanceLargeBuffer != 0 )
|
|
{
|
|
/* just cancel it */
|
|
EnterCriticalSection( &opt->critical4optRead ) ;
|
|
f4 = opt->advanceReadFile ;
|
|
if ( f4 != 0 )
|
|
if ( l4numNodes( &f4->advanceReadFileList ) != 0 )
|
|
{
|
|
EnterCriticalSection( &f4->critical4file ) ;
|
|
for ( advanceLink = (LINK4 *)l4first( &f4->advanceReadFileList ) ;; )
|
|
{
|
|
if ( advanceLink == 0 )
|
|
break ;
|
|
advanceRead = (FILE4ADVANCE_READ *)(advanceLink - 1 ) ;
|
|
advanceLink = (LINK4 *)l4next( &f4->advanceReadFileList, advanceLink ) ;
|
|
|
|
if ( advanceRead->data == opt->advanceLargeBuffer ) /* found the one we want */
|
|
break ;
|
|
}
|
|
|
|
if ( advanceRead != 0 ) /* have the advance-read, just remove it */
|
|
{
|
|
while ( advanceRead->usageFlag == r4inUse ) /* is being read, so wait */
|
|
Sleep( 0 ) ;
|
|
if ( advanceRead->usageFlag == r4queued ) /* remove ourselves */
|
|
{
|
|
EnterCriticalSection( &advanceRead->file->codeBase->critical4advanceReadList ) ;
|
|
l4remove( &advanceRead->file->codeBase->advanceReadList, advanceRead ) ;
|
|
l4remove( &advanceRead->file->advanceReadFileList, &advanceRead->fileLink ) ;
|
|
LeaveCriticalSection( &advanceRead->file->codeBase->critical4advanceReadList ) ;
|
|
}
|
|
}
|
|
LeaveCriticalSection( &f4->critical4file ) ;
|
|
}
|
|
|
|
LeaveCriticalSection( &opt->critical4optRead ) ;
|
|
DeleteCriticalSection( &opt->critical4optRead ) ;
|
|
u4free( opt->advanceLargeBuffer ) ;
|
|
opt->advanceLargeBuffer = 0 ;
|
|
}
|
|
#endif
|
|
|
|
opt4flushAll( opt, 1 ) ; /* move all blocks over to avail list */
|
|
|
|
if ( opt->buffers )
|
|
{
|
|
for ( --opt->numBuffers; opt->numBuffers >= 0 ; opt->numBuffers-- )
|
|
{
|
|
for ( i = 0 ; i < (int)opt->maxBlocks ; i++ )
|
|
{
|
|
curBlock = &opt->blocks[ opt->numBuffers * opt->maxBlocks + i] ;
|
|
l4remove( &opt->avail, &curBlock->lruLink ) ;
|
|
}
|
|
if ( opt->buffers[opt->numBuffers] != 0 )
|
|
u4free( opt->buffers[opt->numBuffers] ) ;
|
|
}
|
|
u4free( opt->buffers ) ;
|
|
opt->buffers = 0 ;
|
|
}
|
|
|
|
opt->writeBuffer = 0 ;
|
|
#ifdef S4WRITE_DELAY
|
|
u4free( opt->delayLargeBuffer ) ;
|
|
opt->delayLargeBuffer = 0 ;
|
|
#endif
|
|
u4free( opt->writeBufferActual ) ;
|
|
opt->writeBufferActual = 0 ;
|
|
u4free( opt->readBuffer ) ;
|
|
opt->readBuffer = 0 ;
|
|
u4free( opt->blocks ) ;
|
|
opt->blocks = 0 ;
|
|
u4free( opt->lists ) ;
|
|
opt->lists = 0 ;
|
|
u4free( opt->lists ) ;
|
|
opt->lists = 0 ;
|
|
}
|
|
|
|
static int opt4initAlloc( CODE4 *c4, int numBuffers )
|
|
{
|
|
OPT4BLOCK *curBlock ;
|
|
OPT4 *opt ;
|
|
int numAlloc, i ;
|
|
|
|
#ifdef E4PARM_LOW
|
|
if ( c4 == 0 || numBuffers < 0 )
|
|
return error4( c4, e4parm, E92508 ) ;
|
|
#endif
|
|
|
|
opt = &c4->opt ;
|
|
|
|
opt->buffers = (void **)u4alloc( ( (long)numBuffers ) * sizeof( void * ) ) ;
|
|
if ( opt->buffers == 0 )
|
|
{
|
|
code4optSuspend( c4 ) ;
|
|
return error4stack( c4, e4memory, E92508 ) ;
|
|
}
|
|
|
|
opt->lists = (LIST4 *)u4alloc( opt->numLists * sizeof (LIST4) ) ;
|
|
if ( opt->lists == 0 )
|
|
{
|
|
code4optSuspend( c4 ) ;
|
|
return error4stack( c4, e4memory, E92508 ) ;
|
|
}
|
|
|
|
#ifdef S4WRITE_DELAY
|
|
#ifdef S4ADVANCE_READ
|
|
opt->blocks = (OPT4BLOCK *)u4alloc( (long)(numBuffers + 2) * opt->maxBlocks * sizeof( OPT4BLOCK ) ) ;
|
|
#else
|
|
opt->blocks = (OPT4BLOCK *)u4alloc( (long)(numBuffers + 1) * opt->maxBlocks * sizeof( OPT4BLOCK ) ) ;
|
|
#endif
|
|
#else
|
|
#ifdef S4ADVANCE_READ
|
|
opt->blocks = (OPT4BLOCK *)u4alloc( (long)(numBuffers + 1) * opt->maxBlocks * sizeof( OPT4BLOCK ) ) ;
|
|
#else
|
|
opt->blocks = (OPT4BLOCK *)u4alloc( (long)numBuffers * opt->maxBlocks * sizeof( OPT4BLOCK ) ) ;
|
|
#endif
|
|
#endif
|
|
if ( opt->blocks == 0 )
|
|
{
|
|
code4optSuspend( c4 ) ;
|
|
return error4stack( c4, e4memory, E92508 ) ;
|
|
}
|
|
|
|
opt->writeBufferActual = (char *)u4alloc( opt->bufferSize ) ;
|
|
if( opt->writeBufferActual == 0 )
|
|
return 0 ;
|
|
opt->writeBuffer = opt->writeBufferActual ;
|
|
|
|
opt->writeBlockCount = 0 ;
|
|
opt->writeCurPos = 0 ;
|
|
opt->writeStartPos = 0 ;
|
|
opt->writeFile = 0 ;
|
|
|
|
opt->readBuffer = (char *)u4alloc( opt->bufferSize ) ;
|
|
if( opt->readBuffer == 0 )
|
|
return 0 ;
|
|
|
|
#ifdef S4WRITE_DELAY
|
|
opt->delayWriteBuffer = (char *)u4alloc( opt->bufferSize ) ;
|
|
if( opt->delayWriteBuffer == 0 )
|
|
return 0 ;
|
|
opt->delayLargeBuffer = (char *)u4alloc( opt->bufferSize ) ;
|
|
if( opt->delayLargeBuffer == 0 )
|
|
return 0 ;
|
|
InitializeCriticalSection( &opt->critical4optWrite ) ;
|
|
opt->delayLargeBufferAvail = 1 ;
|
|
opt->writeBufferActualAvail = 1 ;
|
|
#endif
|
|
#ifdef S4ADVANCE_READ
|
|
opt->advanceLargeBuffer = (char *)u4alloc( opt->bufferSize ) ;
|
|
if( opt->advanceLargeBuffer == 0 )
|
|
return 0 ;
|
|
InitializeCriticalSection( &opt->critical4optRead ) ;
|
|
opt->advanceLargeBufferAvail = 1 ;
|
|
#endif
|
|
|
|
for ( numAlloc = 0 ; numAlloc < numBuffers ; numAlloc++ )
|
|
{
|
|
opt->buffers[numAlloc] = (void *)u4alloc( opt->bufferSize ) ;
|
|
if( opt->buffers[numAlloc] == 0 )
|
|
break ;
|
|
for ( i = 0 ; i < (int)opt->maxBlocks ; i++ )
|
|
{
|
|
curBlock = &opt->blocks[ numAlloc * opt->maxBlocks + i] ;
|
|
curBlock->data = (OPT4BLOCK *)( (char *)opt->buffers[numAlloc] + i * opt->blockSize ) ;
|
|
l4add( &opt->avail, &curBlock->lruLink ) ;
|
|
}
|
|
}
|
|
|
|
#ifdef S4WRITE_DELAY
|
|
/* now set up the delay write buffer. numAlloc already 1 greater than max, so just use */
|
|
for ( i = 0 ; i < (int)opt->maxBlocks ; i++ )
|
|
{
|
|
curBlock = &opt->blocks[ numAlloc * opt->maxBlocks + i] ;
|
|
curBlock->data = (OPT4BLOCK *)( (char *)opt->delayWriteBuffer + i * opt->blockSize ) ;
|
|
l4add( &opt->delayAvail, &curBlock->lruLink ) ;
|
|
}
|
|
#endif
|
|
|
|
return numAlloc ;
|
|
}
|
|
|
|
#endif /* S4OFF_OPTIMIZE */
|