af15e0698b
git-svn-id: svn://10.65.10.50/trunk@4679 c028cbd2-c16b-5b4b-a496-9718f37d4682
433 lines
11 KiB
C
Executable File
433 lines
11 KiB
C
Executable File
/* m4memo.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
|
|
|
|
|
|
#include "d4all.h"
|
|
#ifndef S4UNIX
|
|
#ifdef __TURBOC__
|
|
#pragma hdrstop
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef S4OFF_MEMO
|
|
|
|
#ifdef S4CLIENT
|
|
#ifndef S4OFF_WRITE
|
|
int S4FUNCTION d4memoCompress( DATA4 *data )
|
|
{
|
|
int rc ;
|
|
CONNECTION4 *connection ;
|
|
CODE4 *c4 ;
|
|
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( data, 2, E95201 ) )
|
|
return -1 ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 )
|
|
return error4( 0, e4parm_null, E95201 ) ;
|
|
#endif
|
|
|
|
c4 = data->codeBase ;
|
|
if ( error4code( c4 ) < 0 )
|
|
return e4codeBase ;
|
|
|
|
if ( data->readOnly == 1 )
|
|
return error4describe( c4, e4write, E80606, d4alias( data ), 0, 0 ) ;
|
|
|
|
if ( data->dataFile->nFieldsMemo == 0 )
|
|
return 0 ;
|
|
|
|
rc = d4update( data ) ;
|
|
if ( rc )
|
|
return rc ;
|
|
|
|
connection = data->dataFile->connection ;
|
|
if ( connection == 0 )
|
|
return error4stack( c4, e4connection, E95201 ) ;
|
|
|
|
data->count = -1 ;
|
|
data->dataFile->numRecs = -1 ;
|
|
connection4assign( connection, CON4MEMO_COMPRESS, data4clientId( data ), data4serverId( data ) ) ;
|
|
rc = connection4repeat( connection, -2, -1, -1, data ) ;
|
|
if ( rc < 0 )
|
|
connection4error( connection, c4, rc, E95201 ) ;
|
|
|
|
return rc ;
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
#endif /* S4CLIENT */
|
|
#endif /* S4OFF_MEMO */
|
|
|
|
#ifndef S4CLIENT
|
|
|
|
#ifndef S4OFF_MEMO
|
|
#ifdef S4MFOX
|
|
long memo4lenPart( MEMO4FILE *f4memo, long memoId )
|
|
{
|
|
long pos ;
|
|
int rc ;
|
|
MEMO4BLOCK memoBlock ;
|
|
|
|
if ( memoId <= 0L )
|
|
return 0 ;
|
|
|
|
pos = memoId * f4memo->blockSize ;
|
|
rc = file4readAll( &f4memo->file, pos, &memoBlock, sizeof( MEMO4BLOCK ) ) ;
|
|
if ( rc < 0 )
|
|
return error4stack( f4memo->file.codeBase, rc, E95204 ) ;
|
|
#ifdef S4BYTE_SWAP
|
|
memoBlock.type = x4reverseLong( (void *)&memoBlock.type ) ;
|
|
memoBlock.numChars = x4reverseLong( (void *)&memoBlock.numChars ) ;
|
|
#endif
|
|
|
|
return x4reverseLong( (void *)&memoBlock.numChars ) ;
|
|
}
|
|
#endif
|
|
|
|
#ifndef S4OFF_WRITE
|
|
int S4FUNCTION d4memoCompress( DATA4 *data )
|
|
{
|
|
CODE4 *c4 ;
|
|
int rc ;
|
|
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( data, 2, E95201 ) )
|
|
return -1 ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 )
|
|
return error4( 0, e4parm_null, E95201 ) ;
|
|
#endif
|
|
|
|
c4 = data->codeBase ;
|
|
if ( error4code( c4 ) < 0 )
|
|
return e4codeBase ;
|
|
|
|
if ( data->dataFile->nFieldsMemo == 0 )
|
|
return 0 ;
|
|
|
|
rc = d4update( data ) ;
|
|
if ( rc )
|
|
return rc ;
|
|
|
|
#ifndef S4OFF_MULTI
|
|
#ifdef S4SERVER
|
|
rc = dfile4lockFile( data->dataFile, data4clientId( data ), data4serverId( data ) ) ;
|
|
#else
|
|
rc = d4lockFile( data ) ;
|
|
#endif
|
|
if ( rc )
|
|
return rc ;
|
|
#endif
|
|
|
|
#ifndef S4OFF_TRAN
|
|
if ( code4transEnabled( c4 ) )
|
|
if ( tran4active( c4, data ) != 0 )
|
|
return error4( c4, e4transViolation, E81502 ) ;
|
|
#endif
|
|
|
|
return dfile4memoCompress( data->dataFile, data ) ;
|
|
}
|
|
|
|
int dfile4memoCompress( DATA4FILE *data, DATA4 *d4 )
|
|
{
|
|
char *rdBuf, *wrBuf, *ptr ;
|
|
FILE4SEQ_READ rd ;
|
|
FILE4SEQ_WRITE wr ;
|
|
MEMO4FILE newFile ;
|
|
CODE4 *c4 ;
|
|
unsigned int bufSize, ptrLen, ptrMax, saveFlag ;
|
|
long curCount, iRec, newId ;
|
|
int rc, i ;
|
|
FIELD4 *field ;
|
|
#ifdef S4MFOX
|
|
long memoLen, memoType ;
|
|
unsigned long pos ;
|
|
|
|
memoType = 1 ;
|
|
#endif
|
|
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( d4, 2, E95201 ) )
|
|
return -1 ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 )
|
|
return error4( 0, e4parm_null, E95201 ) ;
|
|
#endif
|
|
|
|
c4 = data->c4 ;
|
|
if ( error4code( c4 ) < 0 )
|
|
return e4codeBase ;
|
|
|
|
if ( data->memoFile.file.hand == -1 )
|
|
return 0 ;
|
|
|
|
#ifndef S4OFF_MULTI
|
|
#ifndef N4OTHER
|
|
#ifdef S4SERVER
|
|
rc = dfile4lockMemo( data ) ;
|
|
#else
|
|
rc = dfile4lockMemo( data ) ;
|
|
#endif
|
|
if ( rc )
|
|
return rc ;
|
|
#endif
|
|
#endif
|
|
|
|
saveFlag = c4->memSizeMemo ;
|
|
c4->memSizeMemo = (unsigned int)data->memoFile.blockSize ;
|
|
|
|
rc = memo4fileCreate( &newFile, c4, data, 0 ) ;
|
|
if ( rc < 0 )
|
|
return error4stack( c4, rc, E91102 ) ;
|
|
|
|
c4->memSizeMemo = saveFlag ;
|
|
newFile.blockSize = data->memoFile.blockSize ;
|
|
|
|
rdBuf = wrBuf = 0 ;
|
|
bufSize = c4->memSizeBuffer ;
|
|
|
|
for (; bufSize > data->recWidth; bufSize -= 0x800 )
|
|
{
|
|
rdBuf = (char *)u4allocFree( c4, (long)bufSize ) ;
|
|
if ( rdBuf == 0 )
|
|
continue ;
|
|
|
|
wrBuf = (char *)u4allocFree( c4, (long)bufSize ) ;
|
|
if ( wrBuf )
|
|
break ;
|
|
|
|
u4free( rdBuf ) ;
|
|
rdBuf = 0 ;
|
|
}
|
|
|
|
#ifdef S4ADVANCE_READ
|
|
file4seqReadInitDo( &rd, &data->file, dfile4recordPosition( data, 1L ), rdBuf, bufSize, 1 ) ;
|
|
#else
|
|
file4seqReadInit( &rd, &data->file, dfile4recordPosition( data, 1L ), rdBuf, bufSize ) ;
|
|
#endif
|
|
file4seqWriteInit( &wr, &data->file, dfile4recordPosition( data, 1L ), wrBuf, bufSize ) ;
|
|
|
|
curCount = dfile4recCount( data, data4serverId( d4 ) ) ;
|
|
|
|
ptr = 0 ;
|
|
ptrLen = ptrMax = 0 ;
|
|
|
|
for ( iRec= 1L ; iRec <= curCount && rc == 0 ; iRec++ )
|
|
{
|
|
if ( file4seqReadAll( &rd, d4->record, data->recWidth ) < 0 )
|
|
break ;
|
|
|
|
for ( i = 0 ; i < d4->dataFile->nFieldsMemo ; i++ )
|
|
{
|
|
field = d4->fieldsMemo[i].field ;
|
|
|
|
#ifdef S4FOX
|
|
pos = 0L ;
|
|
|
|
if ( f4null( field ) == 1 )
|
|
memoLen = 0 ;
|
|
else
|
|
memoLen = memo4lenPart( &data->memoFile, f4long( field ) ) ;
|
|
|
|
|
|
if ( memoLen > 0L )
|
|
{
|
|
newId = 0L ;
|
|
do
|
|
{
|
|
#ifdef E4ANALYZE
|
|
if ( pos > (unsigned long)memoLen )
|
|
{
|
|
rc = error4( c4, e4memoCorrupt, E91102 ) ;
|
|
break ;
|
|
}
|
|
#endif
|
|
|
|
ptrLen = ptrMax ;
|
|
|
|
if ( memo4fileReadPart( &data->memoFile, f4long( field ), &ptr, &ptrLen, pos, UINT_MAX - 100, &memoType ) < 0 )
|
|
{
|
|
rc = -1 ;
|
|
break ;
|
|
}
|
|
|
|
if ( ptrLen > ptrMax )
|
|
ptrMax = ptrLen ;
|
|
|
|
if ( memo4fileWritePart( &newFile, &newId, ptr, memoLen, pos, ptrLen, memoType ) < 0 )
|
|
{
|
|
rc = -1 ;
|
|
break ;
|
|
}
|
|
pos += ptrLen ;
|
|
} while( pos != (unsigned long)memoLen ) ;
|
|
c4ltoa45( newId, f4ptr(field), -( (int)field->len ) ) ;
|
|
}
|
|
else
|
|
c4ltoa45( 0L, f4ptr(field), -( (int)field->len) ) ;
|
|
#else
|
|
ptrLen = ptrMax ;
|
|
if ( memo4fileRead( &data->memoFile, f4long(field), &ptr, &ptrLen ) < 0 )
|
|
{
|
|
rc = -1 ;
|
|
break ;
|
|
}
|
|
|
|
if ( ptrLen > ptrMax )
|
|
ptrMax = ptrLen ;
|
|
|
|
newId = 0L ;
|
|
if ( memo4fileWrite( &newFile, &newId, ptr, ptrLen ) < 0 )
|
|
{
|
|
rc = -1 ;
|
|
break ;
|
|
}
|
|
|
|
c4ltoa45( newId, f4ptr(field), - ((int) field->len) ) ;
|
|
#endif
|
|
}
|
|
file4seqWrite( &wr, d4->record, data->recWidth ) ;
|
|
}
|
|
|
|
if ( rc < 0 )
|
|
file4close( &newFile.file ) ; /* error occurred */
|
|
else
|
|
file4seqWriteFlush(&wr) ;
|
|
|
|
#ifdef S4ADVANCE_READ
|
|
file4seqReadInitUndo( &rd ) ;
|
|
#endif
|
|
|
|
u4free( ptr ) ;
|
|
u4free( rdBuf ) ;
|
|
u4free( wrBuf ) ;
|
|
|
|
if ( rc == 0 )
|
|
{
|
|
rc = file4replace( &data->memoFile.file, &newFile.file ) ;
|
|
if ( rc == 0 )
|
|
#ifdef S4MMDX
|
|
if ( file4len( &data->memoFile.file ) < data->memoFile.blockSize )
|
|
rc = file4lenSet( &data->memoFile.file, data->memoFile.blockSize ) ;
|
|
#else
|
|
if ( file4len( &data->memoFile.file ) < 512 )
|
|
rc = file4lenSet( &data->memoFile.file, 512L ) ;
|
|
#endif
|
|
}
|
|
|
|
return rc ;
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
#ifndef S4MFOX
|
|
#ifndef S4MNDX
|
|
|
|
int memo4fileChainFlush( MEMO4FILE *f4memo, MEMO4CHAIN_ENTRY *chain )
|
|
{
|
|
#ifdef S4BYTE_SWAP
|
|
MEMO4CHAIN_ENTRY swap ;
|
|
#endif
|
|
|
|
if ( chain->toDisk )
|
|
{
|
|
chain->toDisk = 0 ;
|
|
#ifdef S4BYTE_SWAP
|
|
memcpy( (void *)&swap, (void *)chain, sizeof( MEMO4CHAIN_ENTRY ) ) ;
|
|
swap.next = x4reverseLong( (void *)&swap.next ) ;
|
|
swap.num = x4reverseLong( (void *)&swap.num ) ;
|
|
|
|
return file4write( &f4memo->file, chain->blockNo * f4memo->blockSize, &swap, 2*sizeof(S4LONG) ) ;
|
|
#else
|
|
return file4write( &f4memo->file, chain->blockNo * f4memo->blockSize, chain, 2*sizeof(S4LONG) ) ;
|
|
#endif
|
|
}
|
|
return 0 ;
|
|
}
|
|
|
|
int memo4fileChainSkip( MEMO4FILE *f4memo, MEMO4CHAIN_ENTRY *chain )
|
|
{
|
|
unsigned lenRead ;
|
|
|
|
chain->toDisk = 0 ;
|
|
chain->blockNo = chain->next ;
|
|
|
|
if ( chain->next < 0 )
|
|
lenRead = 0 ;
|
|
else
|
|
{
|
|
lenRead = file4read( &f4memo->file, chain->next * f4memo->blockSize, chain, sizeof(chain->next)+sizeof(chain->num) ) ;
|
|
#ifdef S4BYTE_SWAP
|
|
chain->next = x4reverseLong( (void *)&chain->next ) ;
|
|
chain->num = x4reverseLong( (void *)&chain->num ) ;
|
|
#endif
|
|
}
|
|
if ( f4memo->data->c4->errorCode < 0 )
|
|
return -1 ;
|
|
if ( lenRead == 0 )
|
|
{
|
|
chain->num = -1 ;
|
|
chain->next = -1 ;
|
|
return 0 ;
|
|
}
|
|
if ( lenRead != sizeof(chain->next)+sizeof(chain->num) )
|
|
return file4readError( &f4memo->file, chain->next * f4memo->blockSize, sizeof(chain->next)+sizeof(chain->num), "memo4fileChainSkip" ) ;
|
|
return 0 ;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#endif /* S4OFF_MEMO */
|
|
|
|
/* Make the memo file entries current */
|
|
#ifndef S4OFF_MEMO
|
|
#ifndef S4OFF_MULTI
|
|
int d4validateMemoIds( DATA4 *data )
|
|
{
|
|
int i, rc ;
|
|
char *fromPtr ;
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 )
|
|
return error4( 0, e4parm_null, E95203 ) ;
|
|
#endif
|
|
|
|
if ( data->memoValidated )
|
|
return 0 ;
|
|
|
|
if ( data->recNum > 0 )
|
|
{
|
|
#ifdef S4SERVER
|
|
rc = dfile4lock( data->dataFile, data4clientId( data ), data4serverId( data ), data->recNum ) ;
|
|
#else
|
|
rc = d4lock( data, data->recNum ) ;
|
|
#endif
|
|
if ( rc )
|
|
return rc ;
|
|
}
|
|
|
|
rc = d4readOld( data, data->recNum ) ;
|
|
if ( rc < 0 )
|
|
return error4stack( data->codeBase, rc, E95203 ) ;
|
|
|
|
if ( data->recordChanged == 0 ) /* if the record has changed, leave intact */
|
|
for ( i = 0 ; i < data->dataFile->nFieldsMemo ; i++ )
|
|
{
|
|
if ( data->fieldsMemo[i].isChanged == 0 )
|
|
{
|
|
fromPtr = data->recordOld + data->fieldsMemo[i].field->offset ;
|
|
memcpy( f4ptr( data->fieldsMemo[i].field ), fromPtr, f4len( data->fieldsMemo[i].field ) ) ; /* need f4len() because S4FOX 3.0 has 4 byte memos, not 10 byte */
|
|
}
|
|
}
|
|
|
|
data->memoValidated = 1 ;
|
|
return 0 ;
|
|
}
|
|
#endif /* S4OFF_MULTI */
|
|
#endif /* S4OFF_MEMO */
|
|
#endif /* S4CLIENT */
|