CCH : From the Harbour Developers List
Date: Mon, 7 Sep 2009 13:29:16 -0700 (PDT)
Hello All
Here are the steps I took to convert my flagship application "Vouch" ( a mini ERP solutions for a variety of verticals ) to honor HBNETIO lib along-with normal execution as ususal.
BACKDROP
I use configuration file vouch.ini to set various parameters of the application, which beside setting extended protocols, sets the data paths too. So at any given point of execution every table/index/other file always contain fully qualified path.
This principal I adopted and implemented in my applications always made my efforts to switch to different RDD's which a minimum efforts and changes in the source code. Even mixing different RDDs for different parts of the application are made possible and been used successfully.
A table when used has this format:
c:\creative.ram\checks.dbf [ index: c:\creative.ram\checks.z01 ]
^^^^^^^^^^ ROOT FOLDER
^^^^^^^ TABLE
=>
net:checks.dbf
c:\creative.ram\cac00001\vpn453za.dbf
c:\creative.ram\caccomon\defaults.dbf , etc
^^^^^^^^^^ ROOT FOLDER
^^^^^^^ AREA OF OPERATION
^^^^^^^ TABLE NAME
=>
net:caccomon\defaults.dbf
For HBNETIO protocol I just changed the root data path of any
supported file [ .dbf | .z01 (CDX) ] [ which must reside on the
data server ] with "net:" and that's it.
I executed the netiosrv.exe as:
c:\creative.acp\netio\netiosrv.exe 63000 0.0.0.0 c:\creative.ram
And included in vouch.exe:
#if 1 /* Net IO Client-Server Protocol */
IF INIVLW( "NetIOEnabled" )
cNetIOServer := IniValue( 'NetIOServer' )
cNetIOPort := IniValue( 'NetIOPort' )
IF !empty( cNetIOServer ) .and. !empty( cNetIOPort )
lSuccess := netio_connect( cNetIOServer, val( cNetIOPort ) )
uiDebug( "netio_connect()", lSuccess, cNetIOServer, cNetIOPort )
uiDebug( " " )
ENDIF
ENDIF
#endif
IniValue() parses the vouch.ini and keeps in static variable and
supplies a value as requested.
The other functions which I adjusted to change the root
folder to "net:" looks like this:
Function VouExistTable( cAlias, cFile, cPath, cDriver, lTemp )
Local lRet := .f.
DEFAULT lTemp TO .f.
cFile := UPPER( trim( cFile ) )
if right( cFile,4 ) == '.DBF'
cFile := substr( cFile, 1, len( cFile )-4 )
endif
do case
case lTemp
lRet := file( cPath +'\'+ cFile + '.DBF' )
case cDriver == 'SQLRDD'
lRet := VouIsFile( cFile )
case cDriver == 'CACHERDD'
#ifdef __CACHE__
lRet := CacheExistTable( cFile )
#endif
otherwise
IF Vou_IsNetIO()
IF right( cPath, 1 ) == ":"
cFile := cPath + cFile + '.DBF'
ELSE
cFile := cPath +'\'+ cFile + '.DBF'
ENDIF
ELSE
cFile := cPath +'\'+ cFile + '.DBF'
ENDIF
lRet := DbExists( cFile )
endcase
Return lRet
//----------------------------------------------------------------------//
Function VouExistIndex( cAlias, cFile, cPath, cDriver, lTemp )
Local lRet := .f.
DEFAULT lTemp TO .f.
cFile := UPPER( trim( cFile ) )
if right( cFile,4 ) == '.Z01'
cFile := substr( cFile, 1, len( cFile )-4 )
endif
do case
case lTemp
lRet := file( cPath +'\'+ cFile + '.Z01' )
case cDriver == 'SQLRDD'
lRet := VouIsFile( cFile,.t. )
case cDriver == 'CACHERDD'
#ifdef __CACHE__
lRet := CacheExistIndex( cFile )
#endif
otherwise
IF Vou_IsNetIO()
IF right( cPath, 1 ) == ":"
cFile := cPath + cFile + '.Z01'
ELSE
cFile := cPath +'\'+ cFile + '.Z01'
ENDIF
ELSE
cFile := cPath +'\'+ cFile + '.Z01'
ENDIF
lRet := DbExists( cFile )
endcase
Return lRet
//----------------------------------------------------------------------//
FUNCTION Vou_IsNetIO()
IF INIVLW( 'NetIOEnabled' )
RETURN .t.
ENDIF
RETURN .f.
/*----------------------------------------------------------------------*/
FUNCTION Get_Path( cAlias )
LOCAL cPath, p
IF !empty( p := get_d_attr( cAlias,D_PATH ) )
cPath := eval( COMPILE( p ) )
ELSE
cPath := setWPath()
ENDIF
IF get_d_attr( cAlias, D_FILE_TYPE ) <> 9 /* Vouch Specific and on the
Client */
cPath := Vou_AdjustPathToNetIO( cPath )
ENDIF
RETURN cPath
/*----------------------------------------------------------------------*/
FUNCTION Vou_AdjustPathToNetIO( cPath )
LOCAL n, cPathL
IF Vou_IsNetIO()
cPathL := lower( cPath )
IF left( cPathL, 4 ) != "net:"
n := at( 'creative.', cPathL )
IF n > 0 // And it must be
cPath := "net:" + substr( cPath, n + 13 )
ENDIF
ENDIF
ENDIF
RETURN cPath
//----------------------------------------------------------------------//
NOTE: the above code is a case study only and should not
be used as is. However you may adopt the similar approach if
you want to.
OTHER CHANGES YOU MAY REQUIRE
==========================
You may also need to swich to following changes which work in both modes.
FILE() => DBEXISTS()
FERASE() => DBDROP()
THE OBSERVATION
==============
netiosrv.prg
//------------------------------//
proc main( cPort, cServer, cRoot )
local pListenSocket
if empty( cPort )
cPort := '63000'
endif
pListenSocket := netio_mtserver( val( cPort ), cServer, cRoot )
if empty( pListenSocket )
? "Cannot start server."
else
wait "Press any key to stop NETIO server."
netio_serverstop( pListenSocket )
pListenSocket := NIL
endif
return
//------------------------------//
netiosrv.prg => hbmk2 netiosrv.hbp => netiosrv.exe
* Consumes very little memory footprint : 2.5 MB
* Consumes very little CPU time even if many instances are logged : 3-5%
* With each instance increase in memory : 16 KB
* Reduces 16 kb with every instance if quits or is killed
* Record|File locks a released instantlt if an instance holding them is
killed.
THE EXPECTATIONS
===============
Would been nice if root path be automatically stripped
if "net:" is found a part of the table name, i.e.,
net:c:\creative.ram\cac00001\mytable.dbf
=>
net:cac00001\mytable.dbf
where
c:\creative.ram == netiosrv's root path
THE RESULTS
==========
Amazing.
Przemek, accept my hats off to this contribution.
BUT it will be really heartening if you decide to finish NETRDD.
The community is looking at NETRDD desperately.
Regards
Pritpal Bedi