diff --git a/harbour/ChangeLog b/harbour/ChangeLog index a7422cb21d..e7cf7e7603 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,77 @@ The license applies to all entries newer than 2009-04-28. */ +2011-12-06 11:42 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbrdddbf.h + * modified DB_DBFLOCK_HB64 locking scheme + - extended RLOCK/FLOCK area from 2^31-2 to 2^32-2 + it effectively changes maximum number of records in this + locking scheme to 4'294'967'294 + - use COMIX like hyper locking mode + it should increase performance + Warning: INCOMPATIBLE! + all applications using DB_DBFLOCK_HB64 locking mode should + be updated - it is not safe to concurrently access the + same files using programs compiled with older Harbour + versions and current one. + * renamed the following DB_DBFLOCK_* macros: + DB_DBFLOCK_CLIP to DB_DBFLOCK_CLIPPER + DB_DBFLOCK_CL53 to DB_DBFLOCK_COMIX + DB_DBFLOCK_CL53EXT to DB_DBFLOCK_HB32 + * added new locking scheme: DB_DBFLOCK_CLIPPER2 + This locking scheme is designed to replicate _real_ locking scheme + used by Cl*pper applications linked with NTXLOCK2.OBJ + It's different then the documented one. + ; Now Harbour supports the following locking schemes: + DB_DBFLOCK_CLIPPER 1 default Clipper locking scheme + DB_DBFLOCK_COMIX 2 COMIX and CL53 DBFCDX hyper locking scheme + DB_DBFLOCK_VFP 3 [V]FP, CL52 DBFCDX, SIx3 SIXCDX, CDXLOCK.OBJ + DB_DBFLOCK_HB32 4 Harbour hyper locking scheme for 32bit file API + DB_DBFLOCK_HB64 5 Harbour hyper locking scheme for 64bit file API + DB_DBFLOCK_CLIPPER2 6 extended Clipper locking scheme NTXLOCK2.OBJ + + * harbour/include/hbrdddbf.h + * harbour/include/hbrddntx.h + * harbour/include/hbrddnsx.h + * harbour/include/hbrddcdx.h + * harbour/src/rdd/dbf1.c + * harbour/src/rdd/dbfntx/dbfntx1.c + * harbour/src/rdd/dbfnsx/dbfnsx1.c + * harbour/src/rdd/dbfcdx/dbfcdx1.c + + finished support for COMIX like hyper locking. + This modification enables periodical switch to write locks + by readers to eliminate starvation effect on some systems + where many readers can completely block writer. + By default readers use exclusive lock once per each 16 operations. + + added optional support for delayed index write locks (flush locks) + in hyper locking modes. + If index RDD can use such locks then write lock can be divided into + two parts: + 1) block writers and new readers (write lock) + [prepare index modifications in memory] + 2) wait for old readers still active (flush lock) + [write modifications to index file] + [release locks] + This mode reduces time when index is locked exclusively increasing + reader performance and also increase writer performance because + waiting for active readers it can prepare index modifications in + memory. + + * harbour/src/rdd/dbfcdx/dbfcdx1.c + + added support for delayed index write locks (flush locks) in DBFCDX + + * harbour/src/rtl/filebuf.c + * automatically change write file locks to read locks when file is + open in readonly mode in POSIX systems. + + * harbour/src/vm/classes.c + * disabled inheriting of class variables values from ancestor classes + when new class is dynamically created. + Warning: INCOMPATIBLE! + This modification is not backward compatible and can + interact with some existing code which has to be updated + for new behavior. + 2011-11-25 14:23 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com) * contrib/hbqt/qtgui/qth/QClipboard.qth * contrib/hbqt/qtgui/qth/QDirModel.qth diff --git a/harbour/include/dbinfo.ch b/harbour/include/dbinfo.ch index 0e117136a0..5d4e6484ca 100644 --- a/harbour/include/dbinfo.ch +++ b/harbour/include/dbinfo.ch @@ -366,10 +366,18 @@ /* LOCK SCHEMES */ #define DB_DBFLOCK_DEFAULT 0 -#define DB_DBFLOCK_CLIP 1 -#define DB_DBFLOCK_CL53 2 -#define DB_DBFLOCK_VFP 3 -#define DB_DBFLOCK_CL53EXT 4 -#define DB_DBFLOCK_HB64 5 +#define DB_DBFLOCK_CLIPPER 1 /* default Clipper locking scheme */ +#define DB_DBFLOCK_COMIX 2 /* COMIX and CL53 DBFCDX hyper locking scheme */ +#define DB_DBFLOCK_VFP 3 /* [V]FP, CL52 DBFCDX, SIx3 SIXCDX, CDXLOCK.OBJ */ +#define DB_DBFLOCK_HB32 4 /* Harbour hyper locking scheme for 32bit file API */ +#define DB_DBFLOCK_HB64 5 /* Harbour hyper locking scheme for 64bit file API */ +#define DB_DBFLOCK_CLIPPER2 6 /* extended Clipper locking scheme NTXLOCK2.OBJ */ + +/* for backward compatibility */ +#ifdef HB_LEGACY_LEVEL5 + #define DB_DBFLOCK_CLIP DB_DBFLOCK_CLIPPER + #define DB_DBFLOCK_CL53 DB_DBFLOCK_COMIX + #define DB_DBFLOCK_CL53EXT DB_DBFLOCK_HB32 +#endif #endif /* HB_DBINFO_CH_ */ diff --git a/harbour/include/hbrddcdx.h b/harbour/include/hbrddcdx.h index af56d1c9ff..aa0afdb818 100644 --- a/harbour/include/hbrddcdx.h +++ b/harbour/include/hbrddcdx.h @@ -388,7 +388,7 @@ typedef struct _CDXINDEX LPCDXLIST freeLst; /* list of free pages in index file */ int lockWrite; /* number of write lock set */ int lockRead; /* number of read lock set */ - HB_FOFFSET ulLockPos; /* readlock position for CL53 lock scheme */ + HB_DBFLOCKDATA lockData; /* index lock data */ #ifdef HB_CDX_DBGCODE HB_BOOL RdLck; HB_BOOL WrLck; diff --git a/harbour/include/hbrdddbf.h b/harbour/include/hbrdddbf.h index 9c19078a83..712f3480d5 100644 --- a/harbour/include/hbrdddbf.h +++ b/harbour/include/hbrdddbf.h @@ -63,45 +63,51 @@ HB_EXTERN_BEGIN #define DBF_TABLEEXT ".dbf" /* DBF locking schemes */ -#define DBF_LOCKPOS_CLIP 1000000000UL -#define DBF_LOCKPOS_CL53 1000000000UL +#define DBF_LOCKPOS_CLIPPER 1000000000UL +#define DBF_LOCKPOS_CLIPPER2 4000000000UL +#define DBF_LOCKPOS_COMIX 1000000000UL #define DBF_LOCKPOS_VFP 0x40000000UL #define DBF_LOCKPOS_VFPX 0x7ffffffeUL -#define DBF_LOCKPOS_CL53EXT 4000000000UL +#define DBF_LOCKPOS_HB32 4000000000UL #define DBF_LOCKPOS_HB64 HB_LL( 0x7FFFFFFF00000001 ) -#define DBF_LOCKDIR_CLIP 1 -#define DBF_LOCKDIR_CL53 1 +#define DBF_LOCKDIR_CLIPPER 1 +#define DBF_LOCKDIR_CLIPPER2 1 +#define DBF_LOCKDIR_COMIX 1 #define DBF_LOCKDIR_VFP 2 /* lock forward at at record offset */ #define DBF_LOCKDIR_VFPX -1 -#define DBF_LOCKDIR_CL53EXT 1 +#define DBF_LOCKDIR_HB32 1 #define DBF_LOCKDIR_HB64 1 -#define DBF_FLCKSIZE_CLIP 1000000000UL -#define DBF_FLCKSIZE_CL53 1000000000UL +#define DBF_FLCKSIZE_CLIPPER 1000000000UL +#define DBF_FLCKSIZE_CLIPPER2 294967295UL +#define DBF_FLCKSIZE_COMIX 1000000000UL #define DBF_FLCKSIZE_VFP 0x3ffffffdUL #define DBF_FLCKSIZE_VFPX 0x07ffffffUL -#define DBF_FLCKSIZE_CL53EXT 294967295UL -#define DBF_FLCKSIZE_HB64 0x7ffffffeUL +#define DBF_FLCKSIZE_HB32 294967295UL +#define DBF_FLCKSIZE_HB64 0xfffffffeUL -#define DBF_RLCKSIZE_CLIP 1UL -#define DBF_RLCKSIZE_CL53 1UL +#define DBF_RLCKSIZE_CLIPPER 1UL +#define DBF_RLCKSIZE_CLIPPER2 1UL +#define DBF_RLCKSIZE_COMIX 1UL #define DBF_RLCKSIZE_VFP 1UL #define DBF_RLCKSIZE_VFPX 1UL -#define DBF_RLCKSIZE_CL53EXT 1UL +#define DBF_RLCKSIZE_HB32 1UL #define DBF_RLCKSIZE_HB64 1UL -#define IDX_LOCKPOS_CLIP 1000000000UL -#define IDX_LOCKPOS_CL53 0xfffeffffUL +#define IDX_LOCKPOS_CLIPPER 1000000000UL +#define IDX_LOCKPOS_CLIPPER2 1000000000UL +#define IDX_LOCKPOS_COMIX 0xfffeffffUL #define IDX_LOCKPOS_VFP 0x7ffffffeUL -#define IDX_LOCKPOS_CL53EXT 0xfffeffffUL +#define IDX_LOCKPOS_HB32 0xfffeffffUL #define IDX_LOCKPOS_HB64 HB_LL( 0x7FFFFFFF00000001 ) -#define IDX_LOCKPOOL_CLIP 0UL -#define IDX_LOCKPOOL_CL53 0x00010000UL +#define IDX_LOCKPOOL_CLIPPER 0UL +#define IDX_LOCKPOOL_CLIPPER2 0UL +#define IDX_LOCKPOOL_COMIX 0x00010000UL #define IDX_LOCKPOOL_VFP 0UL -#define IDX_LOCKPOOL_CL53EXT 0x00010000UL -#define IDX_LOCKPOOL_HB64 0UL +#define IDX_LOCKPOOL_HB32 0x00010000UL +#define IDX_LOCKPOOL_HB64 0x00010000UL /* Index dirty read flags */ @@ -156,6 +162,16 @@ typedef struct _HB_DBFFIELDBITS HB_USHORT uiLengthBit; } HB_DBFFIELDBITS, * PHB_DBFFIELDBITS; +typedef struct _HB_DBFLOCKDATA +{ + HB_FOFFSET offset; + HB_FOFFSET size; + HB_FOFFSET next; + HB_FOFFSET tolock; + int type; + int count; +} HB_DBFLOCKDATA, * PHB_DBFLOCKDATA; + /* * DBF WORKAREA @@ -246,8 +262,12 @@ extern HB_EXPORT HB_ERRCODE hb_dbfSetMemoData( DBFAREAP pArea, HB_USHORT uiIndex HB_ULONG ulBlock, HB_ULONG ulSize, HB_ULONG ulType ); extern HB_EXPORT HB_ERRCODE hb_dbfGetEGcode( HB_ERRCODE errCode ); -extern HB_EXPORT HB_BOOL hb_dbfLockIdxFile( PHB_FILE pFile, HB_BYTE bScheme, HB_USHORT usMode, HB_FOFFSET *pPoolPos ); -extern HB_EXPORT HB_BOOL hb_dbfLockIdxGetData( HB_BYTE bScheme, HB_FOFFSET *ulPos, HB_FOFFSET *ulPool ); +extern HB_EXPORT HB_BOOL hb_dbfLockIdxGetData( HB_BYTE bScheme, PHB_DBFLOCKDATA pLockData ); +extern HB_EXPORT HB_BOOL hb_dbfLockIdxFile( DBFAREAP pArea, PHB_FILE pFile, + int iType, HB_BOOL fLateWrlck, + PHB_DBFLOCKDATA pLockData ); +extern HB_EXPORT HB_BOOL hb_dbfLockIdxWrite( DBFAREAP pArea, PHB_FILE pFile, + PHB_DBFLOCKDATA pLockData ); extern HB_EXPORT void hb_dbfTranslateRec( DBFAREAP pArea, HB_BYTE * pBuffer, PHB_CODEPAGE cdp_src, PHB_CODEPAGE cdp_dest ); diff --git a/harbour/include/hbrddnsx.h b/harbour/include/hbrddnsx.h index ab5cd6b50e..7a64114e8d 100644 --- a/harbour/include/hbrddnsx.h +++ b/harbour/include/hbrddnsx.h @@ -490,7 +490,7 @@ typedef struct _NSXINDEX HB_BOOL Changed; HB_BOOL Update; HB_BOOL Production; /* Production index */ - HB_FOFFSET ulLockPos; /* readlock position for CL53 lock scheme */ + HB_DBFLOCKDATA lockData; /* index lock data */ int lockWrite; /* number of write lock set */ int lockRead; /* number of read lock set */ diff --git a/harbour/include/hbrddntx.h b/harbour/include/hbrddntx.h index faeb0aa0fe..2c9a3ac58b 100644 --- a/harbour/include/hbrddntx.h +++ b/harbour/include/hbrddntx.h @@ -272,7 +272,7 @@ typedef struct _NTXINDEX HB_BOOL Update; HB_BOOL Compound; HB_BOOL Production; /* Production index */ - HB_FOFFSET ulLockPos; /* readlock position for CL53 lock scheme */ + HB_DBFLOCKDATA lockData; /* index lock data */ int lockWrite; /* number of write lock set */ int lockRead; /* number of read lock set */ diff --git a/harbour/src/rdd/dbf1.c b/harbour/src/rdd/dbf1.c index 07424a0a1e..c233bb595e 100644 --- a/harbour/src/rdd/dbf1.c +++ b/harbour/src/rdd/dbf1.c @@ -1152,104 +1152,172 @@ HB_ERRCODE hb_dbfSetMemoData( DBFAREAP pArea, HB_USHORT uiIndex, * This function is common for different MEMO implementation * so I left it in DBF. */ -HB_BOOL hb_dbfLockIdxGetData( HB_BYTE bScheme, - HB_FOFFSET * pnPos, HB_FOFFSET * pnPool ) +HB_BOOL hb_dbfLockIdxGetData( HB_BYTE bScheme, PHB_DBFLOCKDATA pLockData ) { + pLockData->next = pLockData->tolock = 0; + pLockData->type = 0; + switch( bScheme ) { - case DB_DBFLOCK_CLIP: - *pnPos = IDX_LOCKPOS_CLIP; - *pnPool = IDX_LOCKPOOL_CLIP; + case DB_DBFLOCK_CLIPPER: + pLockData->offset = IDX_LOCKPOS_CLIPPER; + pLockData->size = IDX_LOCKPOOL_CLIPPER; break; - case DB_DBFLOCK_CL53: - *pnPos = IDX_LOCKPOS_CL53; - *pnPool = IDX_LOCKPOOL_CL53; + case DB_DBFLOCK_CLIPPER2: + pLockData->offset = IDX_LOCKPOS_CLIPPER2; + pLockData->size = IDX_LOCKPOOL_CLIPPER2; break; - case DB_DBFLOCK_CL53EXT: - *pnPos = IDX_LOCKPOS_CL53EXT; - *pnPool = IDX_LOCKPOOL_CL53EXT; + case DB_DBFLOCK_COMIX: + pLockData->offset = IDX_LOCKPOS_COMIX; + pLockData->size = IDX_LOCKPOOL_COMIX; break; case DB_DBFLOCK_VFP: - *pnPos = IDX_LOCKPOS_VFP; - *pnPool = IDX_LOCKPOOL_VFP; + pLockData->offset = IDX_LOCKPOS_VFP; + pLockData->size = IDX_LOCKPOOL_VFP; + break; + + case DB_DBFLOCK_HB32: + pLockData->offset = IDX_LOCKPOS_HB32; + pLockData->size = IDX_LOCKPOOL_HB32; break; #ifndef HB_LONG_LONG_OFF case DB_DBFLOCK_HB64: - *pnPos = IDX_LOCKPOS_HB64; - *pnPool = IDX_LOCKPOOL_HB64; + pLockData->offset = IDX_LOCKPOS_HB64; + pLockData->size = IDX_LOCKPOOL_HB64; break; #endif default: + pLockData->offset = pLockData->size = 0; return HB_FALSE; } return HB_TRUE; } +static HB_BOOL hb_dbfLockIdxRepeatFail( DBFAREAP pArea, PHB_DBFLOCKDATA pLockData ) +{ + HB_SYMBOL_UNUSED( pArea ); + HB_SYMBOL_UNUSED( pLockData ); + + /* TODO: call special error handler (LOCKHANDLER) here */ + + return HB_TRUE; +} + /* * Set lock using current locking schemes in additional files (MEMO, INDEX) * This function is common for different MEMO implementation * so I left it in DBF. */ -HB_BOOL hb_dbfLockIdxFile( PHB_FILE pFile, HB_BYTE bScheme, HB_USHORT usMode, - HB_FOFFSET * pnPoolPos ) +HB_BOOL hb_dbfLockIdxFile( DBFAREAP pArea, PHB_FILE pFile, + int iType, HB_BOOL fLateWrlck, + PHB_DBFLOCKDATA pLockData ) { - HB_FOFFSET nPos, nPool, nSize = 1; - HB_BOOL fRet = HB_FALSE; + HB_FOFFSET offset, size, tolock; + HB_BOOL fOK; - if( !hb_dbfLockIdxGetData( bScheme, &nPos, &nPool ) ) + switch( iType & FL_MASK ) { - return fRet; - } - - for( ;; ) - { - switch( usMode & FL_MASK ) - { - case FL_LOCK: - if( nPool ) - { - if( ( usMode & FLX_SHARED ) != 0 ) - *pnPoolPos = ( HB_FOFFSET ) ( hb_random_num() * nPool ) + 1; - else - { - *pnPoolPos = 0; - nSize = nPool + 1; - } - } - else - { - *pnPoolPos = 0; - } - break; - - case FL_UNLOCK: - if( nPool ) - { - if( ! *pnPoolPos ) - nSize = nPool + 1; - } - else - { - *pnPoolPos = 0; - } - break; - - default: + case FL_LOCK: + if( !hb_dbfLockIdxGetData( pArea->bLockType, pLockData ) ) return HB_FALSE; - } - fRet = hb_fileLock( pFile, nPos + *pnPoolPos, nSize, usMode ); - if( fRet || ( usMode & FLX_WAIT ) == 0 || ( usMode & FL_MASK ) != FL_LOCK ) - break; - /* TODO: call special error handler (LOCKHANDLER) here if fWait */ - hb_releaseCPU(); - } - return fRet; + if( pLockData->size && ( iType & FLX_SHARED ) != 0 ) + { + if( ++pLockData->count >= 16 ) + { + pLockData->size = 0; + pLockData->count = 0; + iType &= ~FLX_SHARED; + } + } + else + pLockData->count = 0; + + tolock = 0; + for( ;; ) + { + size = 1; + offset = pLockData->offset; + if( pLockData->count != 0 ) + offset += ( HB_FOFFSET ) ( hb_random_num() * pLockData->size ) + 1; + else if( pLockData->size != 0 ) + size = pLockData->size + 1; + if( hb_fileLock( pFile, offset, size, + size > 1 ? iType & ~FLX_WAIT : iType ) ) + { + pLockData->offset = offset; + pLockData->size = size; + pLockData->tolock = tolock; + pLockData->type = iType; + if( !fLateWrlck && tolock != 0 ) + { + if( ! hb_dbfLockIdxWrite( pArea, pFile, pLockData ) ) + { + hb_fileLock( pFile, offset, size, FL_UNLOCK ); + break; + } + } + return HB_TRUE; + } + if( ( iType & FLX_WAIT ) == 0 ) + break; + else if( size > 1 ) + { + tolock = size - 1; + pLockData->size = 0; + } + else if( !hb_dbfLockIdxRepeatFail( pArea, pLockData ) ) + break; + else + hb_releaseCPU(); + } + pLockData->offset = pLockData->size = + pLockData->next = pLockData->tolock = 0; + pLockData->type = 0; + break; + + case FL_UNLOCK: + fOK = hb_fileLock( pFile, pLockData->offset, pLockData->size, iType ); + if( pLockData->next ) + { + if( !hb_fileLock( pFile, pLockData->offset + pLockData->size, + pLockData->next, iType ) ) + fOK = HB_FALSE; + } + if( fOK ) + { + pLockData->offset = pLockData->size = + pLockData->next = pLockData->tolock = 0; + pLockData->type = 0; + return HB_TRUE; + } + } + return HB_FALSE; +} + +HB_BOOL hb_dbfLockIdxWrite( DBFAREAP pArea, PHB_FILE pFile, + PHB_DBFLOCKDATA pLockData ) +{ + if( pLockData->tolock ) + { + /* FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT */ + while( ! hb_fileLock( pFile, pLockData->offset + pLockData->size, + pLockData->tolock, pLockData->type ) ) + { + if( ! hb_dbfLockIdxRepeatFail( pArea, pLockData ) ) + return HB_FALSE; + hb_releaseCPU(); + } + pLockData->next = pLockData->tolock; + pLockData->tolock = 0; + } + return HB_TRUE; + } /* @@ -1261,25 +1329,25 @@ static HB_ERRCODE hb_dbfLockData( DBFAREAP pArea, { switch( pArea->bLockType ) { - case DB_DBFLOCK_CLIP: - *pnPos = DBF_LOCKPOS_CLIP; - *iDir = DBF_LOCKDIR_CLIP; - *pnFlSize = DBF_FLCKSIZE_CLIP; - *pnRlSize = DBF_RLCKSIZE_CLIP; + case DB_DBFLOCK_CLIPPER: + *pnPos = DBF_LOCKPOS_CLIPPER; + *iDir = DBF_LOCKDIR_CLIPPER; + *pnFlSize = DBF_FLCKSIZE_CLIPPER; + *pnRlSize = DBF_RLCKSIZE_CLIPPER; break; - case DB_DBFLOCK_CL53: - *pnPos = DBF_LOCKPOS_CL53; - *iDir = DBF_LOCKDIR_CL53; - *pnFlSize = DBF_FLCKSIZE_CL53; - *pnRlSize = DBF_RLCKSIZE_CL53; + case DB_DBFLOCK_CLIPPER2: + *pnPos = DBF_LOCKPOS_CLIPPER2; + *iDir = DBF_LOCKDIR_CLIPPER2; + *pnFlSize = DBF_FLCKSIZE_CLIPPER2; + *pnRlSize = DBF_RLCKSIZE_CLIPPER2; break; - case DB_DBFLOCK_CL53EXT: - *pnPos = DBF_LOCKPOS_CL53EXT; - *iDir = DBF_LOCKDIR_CL53EXT; - *pnFlSize = DBF_FLCKSIZE_CL53EXT; - *pnRlSize = DBF_RLCKSIZE_CL53EXT; + case DB_DBFLOCK_COMIX: + *pnPos = DBF_LOCKPOS_COMIX; + *iDir = DBF_LOCKDIR_COMIX; + *pnFlSize = DBF_FLCKSIZE_COMIX; + *pnRlSize = DBF_RLCKSIZE_COMIX; break; case DB_DBFLOCK_VFP: @@ -1299,6 +1367,13 @@ static HB_ERRCODE hb_dbfLockData( DBFAREAP pArea, } break; + case DB_DBFLOCK_HB32: + *pnPos = DBF_LOCKPOS_HB32; + *iDir = DBF_LOCKDIR_HB32; + *pnFlSize = DBF_FLCKSIZE_HB32; + *pnRlSize = DBF_RLCKSIZE_HB32; + break; + #ifndef HB_LONG_LONG_OFF case DB_DBFLOCK_HB64: *pnPos = DBF_LOCKPOS_HB64; @@ -2895,7 +2970,7 @@ static HB_ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) pArea->bLockType = ( HB_BYTE ) hb_itemGetNI( pItem ); if( pArea->bLockType == 0 ) { - pArea->bLockType = DB_DBFLOCK_CLIP; + pArea->bLockType = DB_DBFLOCK_CLIPPER; } } @@ -3472,10 +3547,11 @@ static HB_ERRCODE hb_dbfInfo( DBFAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem } switch( iScheme ) { - case DB_DBFLOCK_CLIP: - case DB_DBFLOCK_CL53: - case DB_DBFLOCK_CL53EXT: + case DB_DBFLOCK_CLIPPER: + case DB_DBFLOCK_CLIPPER2: + case DB_DBFLOCK_COMIX: case DB_DBFLOCK_VFP: + case DB_DBFLOCK_HB32: #ifndef HB_LONG_LONG_OFF case DB_DBFLOCK_HB64: #endif @@ -3808,7 +3884,7 @@ static HB_ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) } pArea->bLockType = ( HB_BYTE ) hb_itemGetNI( pItem ); if( !pArea->bLockType ) - pArea->bLockType = DB_DBFLOCK_CLIP; + pArea->bLockType = DB_DBFLOCK_CLIPPER; } if( pOpenInfo->cdpId ) @@ -5716,10 +5792,11 @@ static HB_ERRCODE hb_dbfRddInfo( LPRDDNODE pRDD, HB_USHORT uiIndex, HB_ULONG ulC hb_setGetDBFLockScheme() ); switch( iScheme ) { - case DB_DBFLOCK_CLIP: - case DB_DBFLOCK_CL53: - case DB_DBFLOCK_CL53EXT: + case DB_DBFLOCK_CLIPPER: + case DB_DBFLOCK_CLIPPER2: + case DB_DBFLOCK_COMIX: case DB_DBFLOCK_VFP: + case DB_DBFLOCK_HB32: #ifndef HB_LONG_LONG_OFF case DB_DBFLOCK_HB64: #endif diff --git a/harbour/src/rdd/dbfcdx/dbfcdx1.c b/harbour/src/rdd/dbfcdx/dbfcdx1.c index f67ea0abd2..abc769826b 100644 --- a/harbour/src/rdd/dbfcdx/dbfcdx1.c +++ b/harbour/src/rdd/dbfcdx/dbfcdx1.c @@ -966,6 +966,18 @@ static void hb_cdxIndexCheckBuffers( LPCDXINDEX pIndex ) } #endif +/* + * lock index for flushing data after (exclusive lock) + */ +static void hb_cdxIndexLockFlush( LPCDXINDEX pIndex ) +{ + if( !hb_dbfLockIdxWrite( &pIndex->pArea->dbfarea, pIndex->pFile, + &pIndex->lockData ) ) + { + hb_errInternal( 9109, "hb_cdxIndexLockFlush: flush lock failed.", NULL, NULL ); + } +} + /* * get free index page */ @@ -1019,6 +1031,8 @@ static HB_ULONG hb_cdxIndexGetAvailPage( LPCDXINDEX pIndex, HB_BOOL bHeader ) { HB_BYTE byPageBuf[CDX_PAGELEN]; HB_FOFFSET fOffset = ulPos; + + hb_cdxIndexLockFlush( pIndex ); memset( byPageBuf, 0, CDX_PAGELEN ); do { @@ -1075,6 +1089,7 @@ static void hb_cdxIndexFlushAvailPage( LPCDXINDEX pIndex ) hb_errInternal( 9101, "hb_cdxIndexPutAvailPage on readonly database.", NULL, NULL ); if( pIndex->fShared && !pIndex->lockWrite ) hb_errInternal( 9102, "hb_cdxIndexPutAvailPage on not locked index file.", NULL, NULL ); + hb_cdxIndexLockFlush( pIndex ); ulPos = pIndex->freePage; while( pLst && pLst->fStat ) @@ -1124,6 +1139,7 @@ static void hb_cdxIndexPageWrite( LPCDXINDEX pIndex, HB_ULONG ulPos, HB_BYTE * p hb_errInternal( 9101, "hb_cdxIndexPageWrite on readonly database.", NULL, NULL ); if( pIndex->fShared && !pIndex->lockWrite ) hb_errInternal( 9102, "hb_cdxIndexPageWrite on not locked index file.", NULL, NULL ); + hb_cdxIndexLockFlush( pIndex ); if( hb_fileWriteAt( pIndex->pFile, pBuffer, uiSize, ulPos ) != ( HB_SIZE ) uiSize ) hb_errInternal( EDBF_WRITE, "Write in index page failed.", NULL, NULL ); @@ -1205,8 +1221,9 @@ static HB_BOOL hb_cdxIndexLockRead( LPCDXINDEX pIndex ) pIndex->RdLck = HB_TRUE; #endif - ret = hb_dbfLockIdxFile( pIndex->pFile, pIndex->pArea->dbfarea.bLockType, - FL_LOCK | FLX_SHARED | FLX_WAIT, &pIndex->ulLockPos ); + ret = hb_dbfLockIdxFile( &pIndex->pArea->dbfarea, pIndex->pFile, + FL_LOCK | FLX_SHARED | FLX_WAIT, HB_TRUE, + &pIndex->lockData ); if( !ret ) hb_cdxErrorRT( pIndex->pArea, EG_LOCK, EDBF_LOCK, pIndex->szFileName, hb_fsError(), 0, NULL ); @@ -1246,8 +1263,9 @@ static HB_BOOL hb_cdxIndexLockWrite( LPCDXINDEX pIndex ) hb_errInternal( 9107, "hb_cdxIndexLockWrite: lock failure (*)", NULL, NULL ); pIndex->WrLck = HB_TRUE; #endif - ret = hb_dbfLockIdxFile( pIndex->pFile, pIndex->pArea->dbfarea.bLockType, - FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT, &pIndex->ulLockPos ); + ret = hb_dbfLockIdxFile( &pIndex->pArea->dbfarea, pIndex->pFile, + FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT, HB_TRUE, + &pIndex->lockData ); } if( !ret ) hb_cdxErrorRT( pIndex->pArea, EG_LOCK, EDBF_LOCK, pIndex->szFileName, hb_fsError(), 0, NULL ); @@ -1289,7 +1307,8 @@ static HB_BOOL hb_cdxIndexUnLockRead( LPCDXINDEX pIndex ) hb_errInternal( 9108, "hb_cdxIndexUnLockRead: unlock error (*)", NULL, NULL ); pIndex->RdLck = HB_FALSE; #endif - if( !hb_dbfLockIdxFile( pIndex->pFile, pIndex->pArea->dbfarea.bLockType, FL_UNLOCK, &pIndex->ulLockPos ) ) + if( !hb_dbfLockIdxFile( &pIndex->pArea->dbfarea, pIndex->pFile, FL_UNLOCK, + HB_TRUE, &pIndex->lockData ) ) { hb_errInternal( 9108, "hb_cdxIndexUnLockRead: unlock error.", NULL, NULL ); } @@ -1342,7 +1361,8 @@ static HB_BOOL hb_cdxIndexUnLockWrite( LPCDXINDEX pIndex ) hb_errInternal( 9108, "hb_cdxIndexUnLockWrite: unlock error (*)", NULL, NULL ); pIndex->WrLck = HB_FALSE; #endif - if( !hb_dbfLockIdxFile( pIndex->pFile, pIndex->pArea->dbfarea.bLockType, FL_UNLOCK, &pIndex->ulLockPos ) ) + if( !hb_dbfLockIdxFile( &pIndex->pArea->dbfarea, pIndex->pFile, FL_UNLOCK, + HB_TRUE, &pIndex->lockData ) ) { hb_errInternal( 9108, "hb_cdxIndexUnLockWrite: unlock error.", NULL, NULL ); } @@ -4675,6 +4695,7 @@ static void hb_cdxIndexReindex( LPCDXINDEX pIndex ) LPCDXTAG pCompound, pTagList, pTag; hb_cdxIndexLockWrite( pIndex ); + hb_cdxIndexLockFlush( pIndex ); hb_cdxIndexDiscardBuffers( pIndex ); pCompound = pIndex->pCompound; @@ -7696,6 +7717,7 @@ static HB_ERRCODE hb_cdxOrderCreate( CDXAREAP pArea, LPDBORDERCREATEINFO pOrderI } hb_cdxIndexLockWrite( pIndex ); + hb_cdxIndexLockFlush( pIndex ); if( !fNewFile ) { pTag = hb_cdxGetTagByNumber( pArea, pArea->uiTag ); @@ -7916,13 +7938,13 @@ static HB_ERRCODE hb_cdxOrderInfo( CDXAREAP pArea, HB_USHORT uiIndex, LPDBORDERI case DBOI_LOCKOFFSET: case DBOI_HPLOCKING: { - HB_FOFFSET ulPos, ulPool; + HB_DBFLOCKDATA lockData; - hb_dbfLockIdxGetData( pArea->dbfarea.bLockType, &ulPos, &ulPool ); + hb_dbfLockIdxGetData( pArea->dbfarea.bLockType, &lockData ); if( uiIndex == DBOI_LOCKOFFSET ) - pInfo->itmResult = hb_itemPutNInt( pInfo->itmResult, ulPos ); + pInfo->itmResult = hb_itemPutNInt( pInfo->itmResult, lockData.offset ); else - pInfo->itmResult = hb_itemPutL( pInfo->itmResult, ulPool > 0 ); + pInfo->itmResult = hb_itemPutL( pInfo->itmResult, lockData.size > 0 ); return HB_SUCCESS; } diff --git a/harbour/src/rdd/dbfnsx/dbfnsx1.c b/harbour/src/rdd/dbfnsx/dbfnsx1.c index fea677d447..fefab437a0 100644 --- a/harbour/src/rdd/dbfnsx/dbfnsx1.c +++ b/harbour/src/rdd/dbfnsx/dbfnsx1.c @@ -2167,8 +2167,9 @@ static HB_BOOL hb_nsxIndexLockRead( LPNSXINDEX pIndex ) } else { - fOK = hb_dbfLockIdxFile( pIndex->pFile, pIndex->pArea->dbfarea.bLockType, - FL_LOCK | FLX_SHARED | FLX_WAIT, &pIndex->ulLockPos ); + fOK = hb_dbfLockIdxFile( &pIndex->pArea->dbfarea, pIndex->pFile, + FL_LOCK | FLX_SHARED | FLX_WAIT, HB_FALSE, + &pIndex->lockData ); /* if fOK then check VERSION field in NSXHEADER and * if it has been changed then discard all page buffers */ @@ -2178,8 +2179,8 @@ static HB_BOOL hb_nsxIndexLockRead( LPNSXINDEX pIndex ) if( hb_nsxIndexHeaderRead( pIndex ) != HB_SUCCESS ) { pIndex->lockRead--; - hb_dbfLockIdxFile( pIndex->pFile, pIndex->pArea->dbfarea.bLockType, - FL_UNLOCK, &pIndex->ulLockPos ); + hb_dbfLockIdxFile( &pIndex->pArea->dbfarea, pIndex->pFile, + FL_UNLOCK, HB_FALSE, &pIndex->lockData ); return HB_FALSE; } } @@ -2210,8 +2211,9 @@ static HB_BOOL hb_nsxIndexLockWrite( LPNSXINDEX pIndex, HB_BOOL fCheck ) } else { - fOK = hb_dbfLockIdxFile( pIndex->pFile, pIndex->pArea->dbfarea.bLockType, - FL_LOCK | FLX_WAIT, &pIndex->ulLockPos ); + fOK = hb_dbfLockIdxFile( &pIndex->pArea->dbfarea, pIndex->pFile, + FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT, HB_FALSE, + &pIndex->lockData ); /* if fOK then check VERSION field in NSXHEADER and * if it has been changed then discard all page buffers */ @@ -2221,8 +2223,8 @@ static HB_BOOL hb_nsxIndexLockWrite( LPNSXINDEX pIndex, HB_BOOL fCheck ) if( fCheck && hb_nsxIndexHeaderRead( pIndex ) != HB_SUCCESS ) { pIndex->lockWrite--; - hb_dbfLockIdxFile( pIndex->pFile, pIndex->pArea->dbfarea.bLockType, - FL_UNLOCK, &pIndex->ulLockPos ); + hb_dbfLockIdxFile( &pIndex->pArea->dbfarea, pIndex->pFile, + FL_UNLOCK, HB_FALSE, &pIndex->lockData ); return HB_FALSE; } } @@ -2258,8 +2260,8 @@ static HB_BOOL hb_nsxIndexUnLockRead( LPNSXINDEX pIndex ) else { pIndex->fValidHeader = HB_FALSE; - fOK = hb_dbfLockIdxFile( pIndex->pFile, pIndex->pArea->dbfarea.bLockType, - FL_UNLOCK, &pIndex->ulLockPos ); + fOK = hb_dbfLockIdxFile( &pIndex->pArea->dbfarea, pIndex->pFile, + FL_UNLOCK, HB_FALSE, &pIndex->lockData ); } if( !fOK ) hb_errInternal( 9108, "hb_nsxIndexUnLockRead: unlock error.", NULL, NULL ); @@ -2296,8 +2298,8 @@ static HB_BOOL hb_nsxIndexUnLockWrite( LPNSXINDEX pIndex ) { hb_fileFlush( pIndex->pFile, HB_TRUE ); pIndex->fValidHeader = HB_FALSE; - fOK = hb_dbfLockIdxFile( pIndex->pFile, pIndex->pArea->dbfarea.bLockType, - FL_UNLOCK, &pIndex->ulLockPos ); + fOK = hb_dbfLockIdxFile( &pIndex->pArea->dbfarea, pIndex->pFile, + FL_UNLOCK, HB_FALSE, &pIndex->lockData ); } if( !fOK ) hb_errInternal( 9108, "hb_nsxIndexUnLockWrite: unlock error.", NULL, NULL ); @@ -6579,7 +6581,7 @@ static HB_ERRCODE hb_nsxOpen( NSXAREAP pArea, LPDBOPENINFO pOpenInfo ) pArea->dbfarea.bLockType = ( HB_BYTE ) hb_itemGetNI( pItem ); hb_itemRelease( pItem ); if( pArea->dbfarea.bLockType == 0 ) - pArea->dbfarea.bLockType = DB_DBFLOCK_CLIP; + pArea->dbfarea.bLockType = DB_DBFLOCK_CLIPPER; } errCode = SUPER_OPEN( ( AREAP ) pArea, pOpenInfo ); @@ -7150,12 +7152,13 @@ static HB_ERRCODE hb_nsxOrderInfo( NSXAREAP pArea, HB_USHORT uiIndex, LPDBORDERI case DBOI_LOCKOFFSET: case DBOI_HPLOCKING: { - HB_FOFFSET ulPos, ulPool; - hb_dbfLockIdxGetData( pArea->dbfarea.bLockType, &ulPos, &ulPool ); + HB_DBFLOCKDATA lockData; + + hb_dbfLockIdxGetData( pArea->dbfarea.bLockType, &lockData ); if( uiIndex == DBOI_LOCKOFFSET ) - pInfo->itmResult = hb_itemPutNInt( pInfo->itmResult, ulPos ); + pInfo->itmResult = hb_itemPutNInt( pInfo->itmResult, lockData.offset ); else - pInfo->itmResult = hb_itemPutL( pInfo->itmResult, ulPool > 0 ); + pInfo->itmResult = hb_itemPutL( pInfo->itmResult, lockData.size > 0 ); return HB_SUCCESS; } case DBOI_ORDERCOUNT: diff --git a/harbour/src/rdd/dbfntx/dbfntx1.c b/harbour/src/rdd/dbfntx/dbfntx1.c index 3286bb1b63..89eb0c542e 100644 --- a/harbour/src/rdd/dbfntx/dbfntx1.c +++ b/harbour/src/rdd/dbfntx/dbfntx1.c @@ -1605,12 +1605,12 @@ static LPTAGINFO hb_ntxTagLoad( LPNTXINDEX pIndex, HB_ULONG ulBlock, } else if( usType & NTX_FLAG_EXTLOCK ) { - pIndex->Owner->dbfarea.bLockType = DB_DBFLOCK_CL53EXT; + pIndex->Owner->dbfarea.bLockType = DB_DBFLOCK_CLIPPER2; } else if( ! pIndex->Owner->dbfarea.bLockType ) { pIndex->Owner->dbfarea.bLockType = usType & NTX_FLAG_EXTLOCK ? - DB_DBFLOCK_CL53EXT : DB_DBFLOCK_CLIP; + DB_DBFLOCK_CLIPPER2 : DB_DBFLOCK_CLIPPER; } } return pTag; @@ -1719,7 +1719,7 @@ static HB_ERRCODE hb_ntxTagHeaderSave( LPTAGINFO pTag ) type = NTX_FLAG_DEFALUT | ( pTag->ForExpr ? NTX_FLAG_FORITEM : 0 ) | ( pTag->Partial ? NTX_FLAG_PARTIAL | NTX_FLAG_FORITEM : 0 ) | - ( pIndex->Owner->dbfarea.bLockType == DB_DBFLOCK_CL53EXT ? NTX_FLAG_EXTLOCK : 0 ) | + ( pIndex->Owner->dbfarea.bLockType == DB_DBFLOCK_CLIPPER2 ? NTX_FLAG_EXTLOCK : 0 ) | ( pTag->Partial ? NTX_FLAG_PARTIAL | NTX_FLAG_FORITEM : 0 ) | /* non CLipper flags */ ( pTag->Custom ? NTX_FLAG_CUSTOM : 0 ) | @@ -2042,8 +2042,9 @@ static HB_BOOL hb_ntxIndexLockRead( LPNTXINDEX pIndex ) } else { - fOK = hb_dbfLockIdxFile( pIndex->DiskFile, pIndex->Owner->dbfarea.bLockType, - FL_LOCK | FLX_SHARED | FLX_WAIT, &pIndex->ulLockPos ); + fOK = hb_dbfLockIdxFile( &pIndex->Owner->dbfarea, pIndex->DiskFile, + FL_LOCK | FLX_SHARED | FLX_WAIT, HB_FALSE, + &pIndex->lockData ); /* if fOK then check VERSION field in NTXHEADER and * if it has been changed then discard all page buffers */ @@ -2053,8 +2054,8 @@ static HB_BOOL hb_ntxIndexLockRead( LPNTXINDEX pIndex ) if( hb_ntxIndexHeaderRead( pIndex ) != HB_SUCCESS ) { pIndex->lockRead--; - hb_dbfLockIdxFile( pIndex->DiskFile, pIndex->Owner->dbfarea.bLockType, - FL_UNLOCK, &pIndex->ulLockPos ); + hb_dbfLockIdxFile( &pIndex->Owner->dbfarea, pIndex->DiskFile, + FL_UNLOCK, HB_FALSE, &pIndex->lockData ); return HB_FALSE; } } @@ -2086,8 +2087,9 @@ static HB_BOOL hb_ntxIndexLockWrite( LPNTXINDEX pIndex, HB_BOOL fCheck ) } else { - fOK = hb_dbfLockIdxFile( pIndex->DiskFile, pIndex->Owner->dbfarea.bLockType, - FL_LOCK | FLX_WAIT, &pIndex->ulLockPos ); + fOK = hb_dbfLockIdxFile( &pIndex->Owner->dbfarea, pIndex->DiskFile, + FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT, HB_FALSE, + &pIndex->lockData ); /* if fOK then check VERSION field in NTXHEADER and * if it has been changed then discard all page buffers */ @@ -2097,8 +2099,8 @@ static HB_BOOL hb_ntxIndexLockWrite( LPNTXINDEX pIndex, HB_BOOL fCheck ) if( fCheck && hb_ntxIndexHeaderRead( pIndex ) != HB_SUCCESS ) { pIndex->lockWrite--; - hb_dbfLockIdxFile( pIndex->DiskFile, pIndex->Owner->dbfarea.bLockType, - FL_UNLOCK, &pIndex->ulLockPos ); + hb_dbfLockIdxFile( &pIndex->Owner->dbfarea, pIndex->DiskFile, + FL_UNLOCK, HB_FALSE, &pIndex->lockData ); return HB_FALSE; } } @@ -2135,8 +2137,8 @@ static HB_BOOL hb_ntxIndexUnLockRead( LPNTXINDEX pIndex ) else { pIndex->fValidHeader = HB_FALSE; - fOK = hb_dbfLockIdxFile( pIndex->DiskFile, pIndex->Owner->dbfarea.bLockType, - FL_UNLOCK, &pIndex->ulLockPos ); + fOK = hb_dbfLockIdxFile( &pIndex->Owner->dbfarea, pIndex->DiskFile, + FL_UNLOCK, HB_FALSE, &pIndex->lockData ); } if( !fOK ) hb_errInternal( 9108, "hb_ntxIndexUnLockRead: unlock error.", NULL, NULL ); @@ -2173,8 +2175,8 @@ static HB_BOOL hb_ntxIndexUnLockWrite( LPNTXINDEX pIndex ) { hb_fileFlush( pIndex->DiskFile, HB_TRUE ); pIndex->fValidHeader = HB_FALSE; - fOK = hb_dbfLockIdxFile( pIndex->DiskFile, pIndex->Owner->dbfarea.bLockType, - FL_UNLOCK, &pIndex->ulLockPos ); + fOK = hb_dbfLockIdxFile( &pIndex->Owner->dbfarea, pIndex->DiskFile, + FL_UNLOCK, HB_FALSE, &pIndex->lockData ); } if( !fOK ) hb_errInternal( 9108, "hb_ntxIndexUnLockWrite: unlock error.", NULL, NULL ); @@ -6742,12 +6744,13 @@ static HB_ERRCODE hb_ntxOrderInfo( NTXAREAP pArea, HB_USHORT uiIndex, LPDBORDERI case DBOI_LOCKOFFSET: case DBOI_HPLOCKING: { - HB_FOFFSET ulPos, ulPool; - hb_dbfLockIdxGetData( pArea->dbfarea.bLockType, &ulPos, &ulPool ); + HB_DBFLOCKDATA lockData; + + hb_dbfLockIdxGetData( pArea->dbfarea.bLockType, &lockData ); if( uiIndex == DBOI_LOCKOFFSET ) - hb_itemPutNInt( pInfo->itmResult, ulPos ); + hb_itemPutNInt( pInfo->itmResult, lockData.offset ); else - hb_itemPutL( pInfo->itmResult, ulPool > 0 ); + hb_itemPutL( pInfo->itmResult, lockData.size > 0 ); return HB_SUCCESS; } case DBOI_ORDERCOUNT: diff --git a/harbour/src/rtl/filebuf.c b/harbour/src/rtl/filebuf.c index 959b16e78e..ee63186694 100644 --- a/harbour/src/rtl/filebuf.c +++ b/harbour/src/rtl/filebuf.c @@ -526,6 +526,10 @@ static HB_BOOL s_fileLock( PHB_FILE pFile, HB_FOFFSET nStart, HB_FOFFSET nLen, hb_threadLeaveCriticalSection( &s_fileMtx ); if( fLockFS ) { +#if defined( HB_OS_UNIX ) + if( pFile->readonly ) + iType |= FLX_SHARED; +#endif fResult = hb_fsLockLarge( pFile->hFile, nStart, nLen, ( HB_USHORT ) iType ); if( !fResult ) { diff --git a/harbour/src/vm/classes.c b/harbour/src/vm/classes.c index f9213fb2ce..9cff98c281 100644 --- a/harbour/src/vm/classes.c +++ b/harbour/src/vm/classes.c @@ -920,7 +920,15 @@ static void hb_clsCopyClass( PCLASS pClsDst, PCLASS pClsSrc ) pClsDst->fHasDestructor = pClsSrc->fHasDestructor; /* CLASS DATA Not Shared ( new array, new value ) */ - pClsDst->pClassDatas = hb_arrayClone( pClsSrc->pClassDatas ); +#if 0 + /* enable this code if you want to inherit class variables values + * from ancestor classes when new class is dynamically created. + * (compatibility with older [x]Harbour versions) + */ + pClsDst->pClassDatas = hb_arrayClone( pClsSrc->pClassDatas ); +#else + pClsDst->pClassDatas = hb_itemArrayNew( hb_arrayLen( pClsSrc->pClassDatas ) ); +#endif /* do not copy shared data array - just simply create new one */ pClsDst->pSharedDatas = hb_itemArrayNew( 0 ); pClsDst->pInlines = hb_arrayClone( pClsSrc->pInlines );