📄 pblisam.c
字号:
DESCRIPTION: commit or rollback changes done during a transaction on a single ISAM file RESTRICTIONS: transactions can be nested, if so the commit only happens when the outermost transaction calls a commit. the commit only happens to process space buffer cache, call pblIsamFlush() after pblIsamCommitFile() if you want to flush to kernel space buffer cache. RETURNS: int rc == 0: the commit went ok int rc > 0: a rollback happened, either because the caller requested it or because an inner transaction resulted in a rollback int rc < 0: an error see pbl_errno------------------------------------------------------------------------------*/static int pblIsamCommitFile( PBLISAMFILE_t * isam, int rollback ){ int n; /* * remember if this is a rollback */ if( rollback ) { isam->rollback = 1; } else { /* * find out if any of the keyfiles needs a rollback * do this by starting another transaction on the ISAM file * if any of the index files have a rollback isam->rollback is set! */ pblIsamStartTransOnFile( isam ); /* * commit the main file transaction started above */ pblKfCommit( isam->mainfile, isam->rollback ); } /* * commit the outer transaction on the main file */ pblKfCommit( isam->mainfile, isam->rollback ); /* * do the rollback or commit on all key files */ for( n = 0; n < isam->nkeys; n++ ) { if( !rollback ) { /* * commit the transaction started above */ pblKfCommit( isam->keyfiles[ n ], isam->rollback ); } /* * commit the outer transaction */ pblKfCommit( isam->keyfiles[ n ], isam->rollback ); } if( !rollback ) { /* * count the transaction started above */ isam->transactions -= 1; } /* * we have one transaction less on the ISAM file */ isam->transactions -= 1; return( isam->rollback );}/** * commit or rollback changes done during a transaction * * transactions can be nested, if so the commit * only happens when the outermost transaction * calls a commit. * * the commit only happens to process space buffer cache, * call \Ref{pblIsamFlush}() after \Ref{pblIsamCommit}() if you want to * flush to kernel space buffer cache. * * @return int rc == 0: the commit went ok * @return int rc > 0: a rollback happened, either because the caller * requested it or because an inner transaction resulted * in a rollback * @return int rc < 0: some error, see pbl_errno */int pblIsamCommit(int nfiles, /** number of files in ISAM file list */pblIsamFile_t ** isamfiles, /** ISAM file list to commit changes of */int rollback /** != 0: roll back the changes, == 0: commit the changes */){ PBLISAMFILE_t ** files = ( PBLISAMFILE_t ** ) isamfiles; int n; int dorollback = rollback; if( !rollback ) { /* * find out if any of the files needs a rollback * do this by starting another transaction on the file set * if any of the ISAM files have a rollback dorollback is set! */ if( pblIsamStartTransaction( nfiles, isamfiles ) > 0 ) { dorollback = 1; } } /* * commit or rollback all files in the set */ for( n = 0; n < nfiles; n++ ) { if( !rollback ) { /* * commit the transaction done above */ pblIsamCommitFile( files[ n ], dorollback ); } /* * commit the outer transaction */ pblIsamCommitFile( files[ n ], dorollback ); } return( dorollback );}/** * open an ISAM file, creates the file if necessary * * if update is 0, the ISAM file is opened for read access only, * if update is not 0 the ISAM file is opened for reading and writing * * a file set tag can be attached to the ISAM file, * if a file having a non NULL file set tag is flushed * to disk all files having the same file set tag attached * are flushed as well. * * @return pblIsamFile_t * retptr == NULL: an error occured, see pbl_errno * @return pblIsamFile_t * retptr != NULL: a pointer to an ISAM file descriptor */pblIsamFile_t * pblIsamOpen(char * path, /** path of file to create */int update, /** flag: should file be opened for update? */void * filesettag, /** filesettag, for flushing multiple files consistently */int nkeys, /** number of key files to create */char **keyfilenames, /** list of names of key index files to create */int * keydup /** flaglist: is the i'th index key a duplicate key? */){ char * ptr; char * keyfile; PBLISAMFILE_t * isam; int i; /* * create the descriptor */ isam = pbl_malloc0( "pblIsamOpen ISAMFILE", sizeof( PBLISAMFILE_t )); if( !isam ) { return( 0 ); } /* * if the user did not specify an external file set tag * the isam file descriptor is used in order to make sure * all key files of the isam file are flushed at the same time */ if( update && !filesettag ) { filesettag = isam; } isam->nkeys = nkeys; if( isam->nkeys ) { /* * create space for pointers to key file descriptors */ isam->keyfiles = pbl_malloc0( "pblIsamOpen keyfiles", nkeys * sizeof( pblKeyFile_t * )); if( !isam->keyfiles ) { PBL_FREE( isam ); return( 0 ); } /* * save the duplicate key flags for all keys */ isam->keydup = pbl_memdup( "pblIsamOpen keydup", keydup, nkeys * sizeof( int * )); if( !isam->keydup ) { PBL_FREE( isam->keyfiles ); PBL_FREE( isam ); pbl_errno = PBL_ERROR_OUT_OF_MEMORY; return( 0 ); } /* * create the array of keycompare functions for all keys */ isam->keycompare = pbl_malloc0( "pblIsamOpen keycompare", nkeys * sizeof( void * )); if( !isam->keycompare ) { PBL_FREE( isam->keydup ); PBL_FREE( isam->keyfiles ); PBL_FREE( isam ); pbl_errno = PBL_ERROR_OUT_OF_MEMORY; return( 0 ); } } /* * open the main file */ if( update ) { /* * try to create */ isam->mainfile = pblKfCreate( path, filesettag ); } if( !isam->mainfile ) { /* * try to open */ isam->mainfile = pblKfOpen( path, update, filesettag ); /* * if the main file is not open */ if( !isam->mainfile ) { PBL_FREE( isam->keycompare ); PBL_FREE( isam->keydup ); PBL_FREE( isam->keyfiles ); PBL_FREE( isam ); return( 0 ); } } /* * if the name of the main file has a directory part * and the names of the index files do not * we prepend the directory part of the main file to * the names of the index files * * get a pointer to last / or \ in path */ ptr = strrchr( path, '/' ); keyfile = strrchr( path, '\\' ); if( ptr ) { if( keyfile > ptr ) { ptr = keyfile; } } else { ptr = keyfile; } if( ptr ) { /* * set pointer to the character after the slash */ ptr++; } /* * open all key files */ for( i = 0; i < nkeys; i++ ) { /* * if the path contains a directory part * and the name of the keyfile does not */ if( ptr && !strchr( keyfilenames[ i ], '/' ) && !strchr( keyfilenames[ i ], '\\' )) { /* * build the the path to the keyfile */ keyfile = pbl_mem2dup( "pblIsamOpen keyfile", path, ptr - path, keyfilenames[ i ], strlen( keyfilenames[ i ] ) + 1 ); } else { /* * use keyfile name as given */ keyfile = strdup( keyfilenames[ i ] ); } if( !keyfile ) { pblKfClose( isam->mainfile ); PBL_FREE( isam->keycompare ); PBL_FREE( isam->keydup ); PBL_FREE( isam->keyfiles ); PBL_FREE( isam ); pbl_errno = PBL_ERROR_OUT_OF_MEMORY; return( 0 ); } if( update ) { /* * try create */ isam->keyfiles[ i ] = pblKfCreate( keyfile, filesettag ); } if( !isam->keyfiles[ i ] ) { /* * try open */ isam->keyfiles[ i ] = pblKfOpen( keyfile, update, filesettag ); } if( !isam->keyfiles[ i ] ) { int j; for( j = 0; j < i; j++ ) { pblKfClose( isam->keyfiles[ j ] ); } pblKfClose( isam->mainfile ); PBL_FREE( keyfile ); PBL_FREE( isam->keycompare ); PBL_FREE( isam->keydup ); PBL_FREE( isam->keyfiles ); PBL_FREE( isam ); return( 0 ); } /* * set our custom compare function for keyfiles allowing * duplicate keys */ if( isam->keydup[ i ] ) { pblKfSetCompareFunction( isam->keyfiles[ i ], pblIsamDupKeyCompare); } /* * the key file is open, we don't need its name anymore */ PBL_FREE( keyfile ); } isam->magic = rcsid; return( ( pblIsamFile_t * )isam );}/** * close an ISAM file * * all changes are flushed to disk before, * all memory allocated for the file is released. * * @return int rc == 0: call went ok, file is closed * @return int rc != 0: some error, see pbl_errno */int pblIsamClose(pblIsamFile_t * isamfile /** ISAM file to close */){ PBLISAMFILE_t * isam = ( PBLISAMFILE_t * ) isamfile; int rc = 0; int i; int saveerrno = 0; /* * close all the keyfiles */ for( i = 0; i < isam->nkeys; i++ ) { if( pblKfClose( isam->keyfiles[ i ] )) { saveerrno = pbl_errno; rc = -1; } } /* * close the main file */ if( pblKfClose( isam->mainfile )) { saveerrno = pbl_errno; rc = -1; } PBL_FREE( isam->keycompare ); PBL_FREE( isam->keydup ); PBL_FREE( isam->keyfiles ); PBL_FREE( isam ); if( rc ) { pbl_errno = saveerrno; } return( rc );}/** * flush an ISAM file * * all changes are flushed to disk, * * @return int rc == 0: call went ok * @return int rc != 0: some error, see pbl_errno */int pblIsamFlush(pblIsamFile_t * isamfile /** ISAM file to flush */){ PBLISAMFILE_t * isam = ( PBLISAMFILE_t * ) isamfile; int rc = 0; int i; int saveerrno = 0; /* * flush all the keyfiles */ for( i = 0; i < isam->nkeys; i++ ) { if( pblKfFlush( isam->keyfiles[ i ] )) { saveerrno = pbl_errno; rc = -1; } } /* * flush the main file */ if( pblKfFlush( isam->mainfile )) { saveerrno = pbl_errno; rc = -1; } if( rc ) { pbl_errno = saveerrno; } return( rc );}/* * set the current record of the main file * used after deletes of records in the main file */static int pblIsamSetCurrentRecord( PBLISAMFILE_t * isam ){ long datalen; char okey[ PBLKEYLENGTH ]; int okeylen; int saveerrno = pbl_errno; /* * read the key of the current record in the main file */ datalen = pblKfThis( isam->mainfile, okey, &okeylen ); if( datalen >= 0 ) { if( okeylen == 9 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -