Can anyone recommend some material available on how to convert my present app (not networkable) to a network version.
Using clipper 5.2e Harbour and FWH
Thanks
Harvey
Can anyone recommend some material available on how to convert my present app (not networkable) to a network version.
Using clipper 5.2e Harbour and FWH
Thanks
Harvey,
just some hints:
databases must be opened in shared mode (SET EXLUSIVE OFF, USE...SHARED)
before any write access you must lock either the dbf or the record and unlock it when the write access is finished.
if you need to rebuild the index files you have to close the dbf and open it in exlusive mode
In clipper there is the file lock.prg where you can find usefull functions for opening and locking dbf´s in a network environment
/* LOGICAL NETUSE( CDATABASE, LOPENMODE, NSECONDS )
CHARACTER CDATABASE - NAME OF DATABASE
LOGICAL LOPENMODE - OPEN MODE .T. exclusive .F. shared
NUMERIC NSECONDS - NUMBER OF SECONDS TO WAIT 0 forever
RETURN .T. if successful, .F. if not
SAMPLE CALL IF NETUSE( "CALLS", .F., 5 )
*/
Func NETUSE( CDATABASE, LOPENMODE, NSECONDS )
LOCAL FOREVER, RESTART, WAIT_TIME, YESNO
RESTART := .T.
FOREVER := ( NSECONDS = 0 )
YESNO := {"Yes" , "No"}
DO WHILE RESTART
WAIT_TIME := NSECONDS
DO WHILE ( FOREVER .OR. WAIT_TIME > 0 )
IF LOPENMODE
USE ( CDATABASE ) via "DBFCDX" EXCLUSIVE
ELSE
USE ( CDATABASE ) via "DBFCDX" SHARED
ENDIF
IF .NOT. NETERR()
RETURN(.T.)
ENDIF
INKEY(1)
WAIT_TIME--
ENDDO
* lock failed, ask to continue
IF MsgYesNo( "Cannot lock " + CDATABASE + ", retry ?" )
ELSE
EXIT
ENDIF
ENDDO
RETURN(.F.)
//--------------------------
/*
LOGICAL ADDREC( NWAITSECONDS )
NUMERIC NWAITSECONDS
APPEND BLANK function with user interaction if failed
RETURN .T. if successful, .F. if not
SAMPLE CALL IF ADDREC( 5 )
SAMPLE TO UNSELECTED DATABASE IF ADDRESS->(ADDREC(5))
*/
Func ADDREC( NWAITSECONDS )
LOCAL LFOREVER, WAIT_TIME, RESTART, YESNO
APPEND BLANK
IF .NOT. NETERR()
RETURN(.T.)
ENDIF
RESTART := .T.
LFOREVER := ( NWAITSECONDS = 0 )
YESNO := {"Yes", "No"}
DO WHILE RESTART
WAIT_TIME := NWAITSECONDS
DO WHILE ( LFOREVER .OR. WAIT_TIME > 0 )
APPEND BLANK
IF .NOT. NETERR()
RETURN .T.
ENDIF
INKEY(.5) // wait 1/2 second to try again
WAIT_TIME := WAIT_TIME - .5
ENDDO
* if failed ask user to continue
IF MsgYesNo( "Cannot add Record, retry ?" )
ELSE
EXIT
ENDIF
ENDDO
RETURN(.F.)
//-----------------
/*
LOGICAL RECLOCK( WAIT )
NUMERIC WAIT
RETURN .T. if successful, .F. if not
RECORD LOCK ROUTINE WITH USER INTERACTION IF LOCK FAILES
SAMPLE CALL IF RECLOCK( 5 )
*/
Func RECLOCK( NSECONDS )
LOCAL LFOREVER, RESTART, WAIT_TIME, YESNO
IF RLOCK()
RETURN (.T.) // LOCKED
ENDIF
RESTART := .T.
LFOREVER := ( NSECONDS = 0 )
YESNO := {"Yes" , "No"}
DO WHILE RESTART
WAIT_TIME := NSECONDS
DO WHILE ( LFOREVER .OR. WAIT_TIME > 0 )
IF RLOCK()
RETURN(.T.)
ENDIF
INKEY(.5)
WAIT_TIME := WAIT_TIME - .5
ENDDO
* lock failed
IF MsgYesNo( "Cannot lock Record, retry ?" )
ELSE
EXIT
ENDIF
ENDDO
RETURN( .F.)Rick:
You wrote "Hope this helps.."
I'm such a novice anything will help.
Where do I put the functions you described.
I open 20 + data files at beginning of the program and others elsewhere.
Are the functions a one time call for each file or a many time call where are initialized?
Where do I put the functions you described.
I open 20 + data files at beginning of the program and others elsewhere.
select 1
if netuse( "Customer.dbf", .f.,5 ) // database, .t. for exclusive lock, .f. for shared, 5 for time-out
else
return(.f.)
endif
Select 2
if netuse( "Invoice.dbf", .f.,5 ) // database, .t. for exclusive lock, .f. for shared, 5 for time-out
else
return(.f.)
endifAre the functions a one time call for each file or a many time call where are initialized?
Thanks for the useful info.
How do I use an alias with netuse() ?
I open file
Use name.dbf alias name new
>I open 20 + data files at beginning of the program and others elsewhere.
INIT PROCEDURE PrgInit
SET CENTURY ON
SET EPOCH TO YEAR(DATE())-98
SET DELETED ON
SET EXCLUSIVE OFF
REQUEST HB_Lang_DE
REQUEST HB_CODEPAGE_DEWIN
HB_LangSelect("DE")
HB_SetCodePage("DEWIN")
SET DATE TO GERMAN
SetHandleCount(205)
rddsetdefault( "DBFCDX" )
RETURNuse &dbfname ALIAS &mAlias SHARED NEWAd exclusive)
I personally change always in a prgInit procedure the exclusive mode to off.
So all databases are automatically opened shared.
How do I use an alias with netuse() ?
IF LOPENMODE
if empty(cAlias)
USE ( CDATABASE ) via "DBFCDX" EXCLUSIVE
else
USE ( CDATABASE ) ALIAS &cAlias via "DBFCDX" EXCLUSIVE
Endif
ELSE
if empty(cAlias)
USE ( CDATABASE ) via "DBFCDX" SHARED
else
USE ( CDATABASE ) ALIAS &cAlias via "DBFCDX" SHARED
ENDIFhag wrote:Can anyone recommend some material available on how to convert my present app (not networkable) to a network version.
Using clipper 5.2e Harbour and FWH
Thanks
Thank you all for the help. Converting my app will not be easy and i'll spend sometime before I make my final decision to complete the task.
My preference would be to move the app to internet based. Any suggestions? ![]()
Thnks james all new stuff to me.
Harvey,
I know it is all scary since it is so different, but once you get over the intial learning curve, programming is so much easier, less error prone, and requires much less code. While converting some older programs I have reduced the code by as much as 50-90 percent.
When you are doing a conversion there are tricks. For instance, you can move entire functions into methods of a new class, then convert those functions into OOP as time permits. Think of it as wrapping legacy code into a class.
You can also use classes in some part of your application, and legacy code in others so you can convert a little at a time.
Read and re-read my articles, and then try some of the test programs. I think you will be amazed at how simple it is.
Regards,
James