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.
This commit is contained in:
Przemyslaw Czerpak
2011-12-06 10:42:41 +00:00
parent 6ac276d2f7
commit 8f7e9eda97
12 changed files with 381 additions and 165 deletions

View File

@@ -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

View File

@@ -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_ */

View File

@@ -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;

View File

@@ -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 );

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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:

View File

@@ -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 )
{

View File

@@ -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 );