2007-05-04 15:35 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/contrib/Makefile
* harbour/contrib/bmdbfcdx/Makefile
* harbour/source/rdd/Makefile
! fixed GNU make compilation
* harbour/include/hbapifs.h
* harbour/source/rtl/filesys.c
+ added support for DOS/Windows DENY_* flag emulation in POSIX
systems using BSD locks. So far such emulatin was done with
standard POSIX locks. The new emulation can be enabled by setting
HB_USE_BSDLOCKS and disabled by HB_USE_BSDLOCKS_OFF. By default
it's enabled in Linux and BSD* based systems.
Please not that it BSD locks work in differ way then POSIX ones.
They are bound with file handle and process ID not i-node and PID.
It will allow to synchronize even single process but it will not
work in NFS and some old BSD and Linux kernels. This synchronization
cannot be used also between different platforms. If someone needs
such synchronization then he should build Harbour on all platforms
with HB_USE_BSDLOCKS_OFF and HB_USE_SHARELOCKS with valid multi
platform lock offset
* harbour/source/rdd/dbcmd.c
* removed all explicit NETERR setting - now it can be set only
by NETERR() function (executed by default errorsys)
* changed ordListAdd()/dbSetIndex() - now they return logical value
with information about success
* harbour/source/rdd/wafunc.c
* changed hb_rddOpenTable()/hb_rddCreateTable() to make dbUseArea()/
dbCreate() more Clipper compatible - it's not exact Clipper behavior
but I intentionally do not want to replicate some strange for me
things, f.e. I do not know why Clipper ignores RDDNAME when it has
only one character
+ harbour/tests/tstuse.prg
+ test code for dbUseArea()
This commit is contained in:
@@ -8,6 +8,44 @@
|
||||
2002-12-01 13:30 UTC+0100 Foo Bar <foo.bar@foobar.org>
|
||||
*/
|
||||
|
||||
2007-05-04 15:35 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
|
||||
* harbour/contrib/Makefile
|
||||
* harbour/contrib/bmdbfcdx/Makefile
|
||||
* harbour/source/rdd/Makefile
|
||||
! fixed GNU make compilation
|
||||
|
||||
* harbour/include/hbapifs.h
|
||||
* harbour/source/rtl/filesys.c
|
||||
+ added support for DOS/Windows DENY_* flag emulation in POSIX
|
||||
systems using BSD locks. So far such emulatin was done with
|
||||
standard POSIX locks. The new emulation can be enabled by setting
|
||||
HB_USE_BSDLOCKS and disabled by HB_USE_BSDLOCKS_OFF. By default
|
||||
it's enabled in Linux and BSD* based systems.
|
||||
Please not that it BSD locks work in differ way then POSIX ones.
|
||||
They are bound with file handle and process ID not i-node and PID.
|
||||
It will allow to synchronize even single process but it will not
|
||||
work in NFS and some old BSD and Linux kernels. This synchronization
|
||||
cannot be used also between different platforms. If someone needs
|
||||
such synchronization then he should build Harbour on all platforms
|
||||
with HB_USE_BSDLOCKS_OFF and HB_USE_SHARELOCKS with valid multi
|
||||
platform lock offset
|
||||
|
||||
* harbour/source/rdd/dbcmd.c
|
||||
* removed all explicit NETERR setting - now it can be set only
|
||||
by NETERR() function (executed by default errorsys)
|
||||
* changed ordListAdd()/dbSetIndex() - now they return logical value
|
||||
with information about success
|
||||
|
||||
* harbour/source/rdd/wafunc.c
|
||||
* changed hb_rddOpenTable()/hb_rddCreateTable() to make dbUseArea()/
|
||||
dbCreate() more Clipper compatible - it's not exact Clipper behavior
|
||||
but I intentionally do not want to replicate some strange for me
|
||||
things, f.e. I do not know why Clipper ignores RDDNAME when it has
|
||||
only one character
|
||||
|
||||
+ harbour/tests/tstuse.prg
|
||||
+ test code for dbUseArea()
|
||||
|
||||
2007-05-04 11:06 UTC+0100 Miguel Angel Marchuet (miguelangel/at/marchuet.net)
|
||||
* source/rdd/wafunc.c
|
||||
* change of the behavior of DbUseArea opening, so that one behaves like made Clipper, when it fails the
|
||||
|
||||
@@ -12,7 +12,7 @@ DIRS=\
|
||||
libmisc \
|
||||
libnf \
|
||||
samples \
|
||||
bmdbfcdx \
|
||||
bmdbfcdx \
|
||||
|
||||
|
||||
ifeq ($(HB_ARCHITECTURE),w32)
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
# $Id$
|
||||
#
|
||||
|
||||
ROOT = ../../../
|
||||
ROOT = ../../
|
||||
|
||||
C_SOURCES=\
|
||||
bmdbfcdx1.c \
|
||||
bmsixcdx1.c
|
||||
bmsixcdx1.c
|
||||
|
||||
LIBNAME=bmdbfcdx
|
||||
|
||||
|
||||
@@ -152,6 +152,12 @@ extern HB_EXPORT FHANDLE hb_fsGetOsHandle( FHANDLE hFileHandle );
|
||||
# define HB_USE_SHARELOCKS
|
||||
# define HB_SHARELOCK_POS 0x7fffffffUL
|
||||
# define HB_SHARELOCK_SIZE 0x1UL
|
||||
# if defined( HB_USE_BSDLOCKS_OFF )
|
||||
# undef HB_USE_BSDLOCKS
|
||||
# elif ( defined( HB_OS_LINUX ) || defined( HB_OS_BSD ) ) && \
|
||||
!defined( __WATCOMC__ ) && !defined( HB_USE_BSDLOCKS )
|
||||
# define HB_USE_BSDLOCKS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define HB_MAX_DRIVE_LENGTH 10
|
||||
|
||||
@@ -37,7 +37,7 @@ LIBNAME=rdd
|
||||
|
||||
|
||||
# The list of all valid DB drivers is defined in config/global.cf.
|
||||
DIRS=$(HB_DB_DRIVERS)
|
||||
DIRS=nulsys $(HB_DB_DRIVERS)
|
||||
|
||||
include $(TOP)$(ROOT)config/lib.cf
|
||||
include $(TOP)$(ROOT)config/dir.cf
|
||||
|
||||
@@ -269,17 +269,10 @@ HB_FUNC( DBAPPEND )
|
||||
BOOL bUnLockAll = ISLOG( 1 ) ? hb_parl( 1 ) : TRUE;
|
||||
ERRCODE errCode;
|
||||
|
||||
/* Clipper clears NETERR flag when table is open */
|
||||
/* Clipper clears NETERR flag before APPEND */
|
||||
hb_rddSetNetErr( FALSE );
|
||||
errCode = SELF_APPEND( pArea, bUnLockAll );
|
||||
hb_retl( errCode == SUCCESS );
|
||||
|
||||
/*
|
||||
* Warning: this is not Clipper compatible. NETERR() should be set by
|
||||
* error handler not here
|
||||
*/
|
||||
if( errCode != SUCCESS )
|
||||
hb_rddSetNetErr( TRUE );
|
||||
}
|
||||
else
|
||||
hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "DBAPPEND" );
|
||||
@@ -361,7 +354,7 @@ HB_FUNC( DBCREATE )
|
||||
#ifdef HB_C52_STRICT
|
||||
hb_arrayLen( pStruct ) == 0 ||
|
||||
#endif
|
||||
!szFileName || !szFileName[ 0 ] )
|
||||
!szFileName )
|
||||
{
|
||||
hb_errRT_DBCMD( EG_ARG, EDBCMD_DBCMDBADPARAMETER, NULL, "DBCREATE" );
|
||||
return;
|
||||
@@ -1765,7 +1758,7 @@ HB_FUNC( ORDLISTADD )
|
||||
DBORDERINFO pOrderInfo;
|
||||
ERRCODE errCode;
|
||||
|
||||
/* Clipper clears NETERR flag when table is open */
|
||||
/* Clipper clears NETERR flag when index is open */
|
||||
hb_rddSetNetErr( FALSE );
|
||||
|
||||
memset( &pOrderInfo, 0, sizeof( DBORDERINFO ) );
|
||||
@@ -1783,14 +1776,12 @@ HB_FUNC( ORDLISTADD )
|
||||
|
||||
errCode = SELF_ORDLSTADD( pArea, &pOrderInfo );
|
||||
|
||||
/*
|
||||
* Warning: this is not Clipper compatible. NETERR() should be set by
|
||||
* error handler not here
|
||||
*/
|
||||
if( errCode != SUCCESS )
|
||||
hb_rddSetNetErr( TRUE );
|
||||
if( HB_IS_NIL( pOrderInfo.itmResult ) )
|
||||
hb_retl( errCode == SUCCESS );
|
||||
else
|
||||
hb_itemReturn( pOrderInfo.itmResult );
|
||||
|
||||
hb_itemRelease( hb_itemReturn( pOrderInfo.itmResult ) );
|
||||
hb_itemRelease( pOrderInfo.itmResult );
|
||||
}
|
||||
else
|
||||
hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "ORDLISTADD" );
|
||||
|
||||
@@ -578,47 +578,57 @@ ERRCODE hb_rddOpenTable( const char * szFileName, const char * szDriver,
|
||||
char szDriverBuffer[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH + 1 ];
|
||||
DBOPENINFO pInfo;
|
||||
ERRCODE errCode;
|
||||
//USHORT uiPrevArea;
|
||||
AREAP pArea;
|
||||
|
||||
/* Clipper clears NETERR flag before RT error below */
|
||||
/* uiArea = 0 in hb_rddInsertAreaNode() means chose first
|
||||
* available free area, otherwise we should close table in
|
||||
* current WA and it should be done before parameter validation
|
||||
* RT errors below. This breaks xHarbour like MT code which
|
||||
* shares WA between threads so dbUseArea() should be covered
|
||||
* by external mutex to make lNewArea MT safe, [druzus]
|
||||
*/
|
||||
if( uiArea )
|
||||
{
|
||||
hb_rddSelectWorkAreaNumber( uiArea );
|
||||
hb_rddReleaseCurrentArea();
|
||||
}
|
||||
else
|
||||
hb_rddSelectFirstAvailable();
|
||||
|
||||
/* Clipper clears NETERR flag before parameter validation, [druzus]
|
||||
*/
|
||||
hb_rddSetNetErr( FALSE );
|
||||
|
||||
if( !szFileName || !szFileName[ 0 ] )
|
||||
{
|
||||
hb_errRT_DBCMD( EG_ARG, EDBCMD_USE_BADPARAMETER, NULL, "DBUSEAREA" );
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Now check parameters, first RDD name.
|
||||
* Clipper seems to make sth like:
|
||||
* if( szDriver && strlen( szDriver ) > 1 )
|
||||
* but I do not think we should replicate it, [druzus]
|
||||
*/
|
||||
if( szDriver && szDriver[ 0 ] )
|
||||
{
|
||||
hb_strncpyUpper( szDriverBuffer, szDriver, HARBOUR_MAX_RDD_DRIVERNAME_LENGTH );
|
||||
szDriver = szDriverBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
szDriver = hb_rddDefaultDrv( NULL );
|
||||
}
|
||||
|
||||
//uiPrevArea = hb_rddGetCurrentWorkAreaNumber();
|
||||
|
||||
/*
|
||||
* 0 means chose first available in hb_rddInsertAreaNode()
|
||||
* This hack is necessary to avoid race condition in MT
|
||||
* if we don't want to lock whole RDD subsystem, Druzus
|
||||
*/
|
||||
hb_rddSelectWorkAreaNumber( uiArea );
|
||||
if( uiArea )
|
||||
{
|
||||
hb_rddReleaseCurrentArea();
|
||||
}
|
||||
|
||||
/* Create a new WorkArea node */
|
||||
/* First try to create new are node and validate RDD name */
|
||||
if( ! hb_rddInsertAreaNode( szDriver ) )
|
||||
{
|
||||
hb_errRT_DBCMD( EG_ARG, EDBCMD_BADPARAMETER, NULL, "DBUSEAREA" );
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Then check if valid file name was given - Clipper allows to use empty
|
||||
* ("") file name
|
||||
*/
|
||||
if( !szFileName )
|
||||
{
|
||||
hb_rddReleaseCurrentArea();
|
||||
hb_errRT_DBCMD( EG_ARG, EDBCMD_USE_BADPARAMETER, NULL, "DBUSEAREA" );
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();
|
||||
|
||||
/* Fill pInfo structure */
|
||||
@@ -631,42 +641,18 @@ ERRCODE hb_rddOpenTable( const char * szFileName, const char * szDriver,
|
||||
pInfo.ulConnection = ulConnection;
|
||||
pInfo.lpdbHeader = NULL;
|
||||
|
||||
if( pStruct )
|
||||
{
|
||||
errCode = SELF_CREATEFIELDS( pArea, pStruct );
|
||||
}
|
||||
else
|
||||
{
|
||||
errCode = SUCCESS;
|
||||
}
|
||||
|
||||
errCode = pStruct ? SELF_CREATEFIELDS( pArea, pStruct ) : SUCCESS;
|
||||
if( errCode == SUCCESS )
|
||||
{
|
||||
if( pDelim && !HB_IS_NIL( pDelim ) )
|
||||
errCode = SELF_INFO( pArea, DBI_SETDELIMITER, pDelim );
|
||||
|
||||
if( errCode == SUCCESS )
|
||||
{
|
||||
/* Open file */
|
||||
errCode = SELF_OPEN( pArea, &pInfo );
|
||||
/*-----------------04/05/2007 11:00-----------------
|
||||
* Clipper not restore the old workarea
|
||||
* --------------------------------------------------*/
|
||||
/*
|
||||
if( errCode != SUCCESS )
|
||||
{
|
||||
hb_rddReleaseCurrentArea();
|
||||
hb_rddSelectWorkAreaNumber( uiPrevArea );
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Warning: this is not Clipper compatible. NETERR() should be set by
|
||||
* error handler not here
|
||||
*/
|
||||
if( errCode != SUCCESS )
|
||||
hb_rddSetNetErr( TRUE );
|
||||
hb_rddReleaseCurrentArea();
|
||||
|
||||
return errCode;
|
||||
}
|
||||
@@ -683,7 +669,7 @@ ERRCODE hb_rddCreateTable( const char * szFileName, const char * szDriver,
|
||||
USHORT uiPrevArea;
|
||||
AREAP pArea;
|
||||
|
||||
if( !szFileName || !szFileName[ 0 ] )
|
||||
if( !szFileName )
|
||||
{
|
||||
hb_errRT_DBCMD( EG_ARG, EDBCMD_DBCMDBADPARAMETER, NULL, "DBCREATE" );
|
||||
return FAILURE;
|
||||
@@ -695,27 +681,25 @@ ERRCODE hb_rddCreateTable( const char * szFileName, const char * szDriver,
|
||||
szDriver = szDriverBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
szDriver = hb_rddDefaultDrv( NULL );
|
||||
}
|
||||
|
||||
uiPrevArea = hb_rddGetCurrentWorkAreaNumber();
|
||||
|
||||
/*
|
||||
* 0 means chose first available in hb_rddInsertAreaNode()
|
||||
* This hack is necessary to avoid race condition in MT
|
||||
* if we don't want to lock whole RDD subsystem, Druzus
|
||||
* mode where workareas are shared between threads and
|
||||
* we don't want to lock whole RDD subsystem, [druzus]
|
||||
*/
|
||||
hb_rddSelectWorkAreaNumber( uiArea );
|
||||
if( uiArea )
|
||||
{
|
||||
hb_rddReleaseCurrentArea();
|
||||
}
|
||||
|
||||
/* Create a new WorkArea node */
|
||||
if( ! hb_rddInsertAreaNode( szDriver ) )
|
||||
{
|
||||
hb_errRT_DBCMD( EG_CREATE, EDBCMD_BADPARAMETER, NULL, "DBCREATE" );
|
||||
hb_rddSelectWorkAreaNumber( uiPrevArea );
|
||||
hb_errRT_DBCMD( EG_ARG, EDBCMD_BADPARAMETER, NULL, "DBCREATE" );
|
||||
return FAILURE;
|
||||
}
|
||||
pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();
|
||||
|
||||
@@ -185,6 +185,9 @@
|
||||
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
||||
#endif
|
||||
#endif
|
||||
#if defined( HB_USE_SHARELOCKS ) && defined( HB_USE_BSDLOCKS )
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
|
||||
/* 27/08/2004 - <maurilio.longo@libero.it>
|
||||
HB_FS_GETDRIVE() should return a number in the range 0..25 ('A'..'Z')
|
||||
@@ -2230,6 +2233,15 @@ HB_EXPORT FHANDLE hb_fsExtOpen( BYTE * pFilename, BYTE * pDefExt,
|
||||
#if defined( HB_USE_SHARELOCKS )
|
||||
if( hFile != FS_ERROR && uiExFlags & FXO_SHARELOCK )
|
||||
{
|
||||
#if defined( HB_USE_BSDLOCKS )
|
||||
int iLock;
|
||||
if( ( uiFlags & ( FO_READ | FO_WRITE | FO_READWRITE ) ) == FO_READ ||
|
||||
( uiFlags & ( FO_DENYREAD | FO_DENYWRITE | FO_EXCLUSIVE ) ) == 0 )
|
||||
iLock = LOCK_SH | LOCK_NB;
|
||||
else
|
||||
iLock = LOCK_EX | LOCK_NB;
|
||||
if( flock( hFile, iLock ) != 0 )
|
||||
#else
|
||||
USHORT uiLock;
|
||||
if( ( uiFlags & ( FO_READ | FO_WRITE | FO_READWRITE ) ) == FO_READ ||
|
||||
( uiFlags & ( FO_DENYREAD | FO_DENYWRITE | FO_EXCLUSIVE ) ) == 0 )
|
||||
@@ -2238,6 +2250,7 @@ HB_EXPORT FHANDLE hb_fsExtOpen( BYTE * pFilename, BYTE * pDefExt,
|
||||
uiLock = FL_LOCK | FLX_EXCLUSIVE;
|
||||
|
||||
if( !hb_fsLockLarge( hFile, HB_SHARELOCK_POS, HB_SHARELOCK_SIZE, uiLock ) )
|
||||
#endif
|
||||
{
|
||||
hb_fsClose( hFile );
|
||||
hFile = FS_ERROR;
|
||||
|
||||
48
harbour/tests/tstuse.prg
Normal file
48
harbour/tests/tstuse.prg
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#define EOL chr(13)+chr(10)
|
||||
#command ? [<x,...>] => outstd(EOL)[;outstd(<x>)]
|
||||
proc main()
|
||||
? OS(), VERSION()
|
||||
if !file("_tst.dbf")
|
||||
dbCreate("_tst",{{"F1","C",1,0}})
|
||||
endif
|
||||
if !file("_tst2.dbf")
|
||||
dbCreate("_tst2",{{"F1","C",1,0}})
|
||||
endif
|
||||
|
||||
USE _tst NEW ALIAS "ONE" EXCLUSIVE
|
||||
? select(), alias(), netErr(), used()
|
||||
?
|
||||
|
||||
mkTest( .T., "NORDD",, "TWO", .T., .F. )
|
||||
mkTest( .T., "DBF",, "TWO", .T., .F. )
|
||||
mkTest( .T., "DBF", "", "TWO", .T., .F. )
|
||||
mkTest( .T., "DBF", "nofile", "TWO", .T., .F. )
|
||||
mkTest( .T., "DBF", "_tst2", "ONE", .T., .F. )
|
||||
mkTest( .T., "DBF", "_tst", "ONE", .T., .F. )
|
||||
mkTest( .T., "DBF", "_tst", "TWO", .T., .F. )
|
||||
?
|
||||
dbUseArea( .T., "DBF", "_tst", "ONE", .T., .F. )
|
||||
? select(), alias(), netErr(), used()
|
||||
dbUseArea( .T., "DBF", "_tst", "TWO", .T., .F. )
|
||||
? select(), alias(), netErr(), used()
|
||||
?
|
||||
dbSelectArea( 1 )
|
||||
mkTest( .F., "NORDD",, "TWO", .T., .F. )
|
||||
?
|
||||
return
|
||||
|
||||
proc mkTest( lNewArea, cRdd, cFile, cAlias, lShared, lReadOnly )
|
||||
local cbErr:=errorBlock({|oErr|break(oErr)}), oErr
|
||||
netErr(.f.)
|
||||
begin sequence
|
||||
dbUseArea( lNewArea, cRdd, cFile, cAlias, lShared, lReadOnly )
|
||||
recover using oErr
|
||||
? "Error:", oErr:subCode, oErr:description, oErr:operation, oErr:osCode
|
||||
end
|
||||
? select(), alias(), netErr(), used()
|
||||
errorBlock(cbErr)
|
||||
return
|
||||
Reference in New Issue
Block a user