alex af15e0698b Codebase
git-svn-id: svn://10.65.10.50/trunk@4679 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-06-16 13:01:08 +00:00

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, &sectorsPerCluster, &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 */