First, please forgive me if this is a well known issue, I feel sure it should be given the significance of its effects, but I have been unable to find any prior reference to the issue under Tec Tips or otherwise. I am rather hoping that I have I've done something stupid, or that the issue is fixed in subsequent versions of VFP - any thoughts, suggestions, or results from different versions / platforms would be welcomed.
I am running VFP7.0 on an NT4sp6a and XPPro sp2 workstations of various hardware specifications.
I have a form in an application that is designed to update a flag on a file once a process has been completed.
The environment is multi-user, and the flag exists to prevent the process inadvertently occurring more than once by more than one user. I have found that in some circumstances the update of the flag is apparently not visible to the a second user for a period of time (or indefinitely without additional action - see test 3 below) once it has been updated by another.
To test the issue, I have tried to incrementally eliminate possible influences on a table being updated: ie. network issues, buffering issues, operating system issues, & hardware issues.
A 'SelectTest' form was created that runs a SQL SELECT to return a SECONDS() value stored in a local free table. This value is tested within a loop against an old value, and if different, the difference in update time and current time is recorded. This is repeated ten times and the average recorded.
An 'update' form was created to run an SQL UPDATE to update the time field of the table with SECONDS(). The Update button is hit each time the SelectTest form detects a data change.
By running these two forms in separate VFP sessions on the same workstation, I hoped to measure the time taken for an update to be visible to a select.
Results indicate that where the file is immediately closed following the select, the change can be detected almost instantaneously - as I would have expected (Test 1). However, where the file is allowed to remain open after the select, a significant delay of up to 4 seconds or so is experienced (Test 2). Worse still, if the selecttest form's datasession is set to private, and the vfptest1 file is open in the default session, the changes are not detected at all! (Test 3)
Note that Issuing 'FLUSH' following the update, or Closing the file following the update makes little difference to the times recorded.
I have also run this test on a server networked file from two workstations, having first synchronised workstation times (and restarted VFP, as seconds() appears to rely on the system time at startup). This resulted in similar results to the non-networked version.
Regards,
Mike.
RESULTS:
Test 1 - Default data session, close file each select
Detected Applied Difference
45910.964 45910.964 0.000
45911.839 45911.839 0.000
45912.480 45912.479 0.001
45913.011 45913.011 0.000
45913.464 45913.464 0.000
45914.058 45914.057 0.001
45914.527 45914.526 0.001
45915.042 45915.042 0.000
45915.495 45915.495 0.000
45916.042 45916.042 0.000
Tests: 10
Total Delay: 0.003
Average Delay: 0.000
Test 2 - Default data session, file remains open after each select
Detected Applied Difference
45944.558 45942.214 2.344
45949.558 45945.557 4.001
45954.558 45950.042 4.516
45959.558 45957.229 2.329
45964.558 45960.229 4.329
45969.558 45968.057 1.501
45974.558 45970.292 4.266
45979.558 45975.089 4.469
45984.558 45980.636 3.922
45989.558 45986.261 3.297
Tests: 10
Total Delay: 34.974
Average Delay: 3.179
Test 3 - Private data session, close file each select -test file opened in default session
- Total Failure to detect change - loops until interupted by 'esc'
The test file was created as follows:
CREATE TABLE c:\mptest1 free (ID c(1), time n(9,3))
INSERT INTO c:\mptest1 values ('1', SECONDS())
My test forms are as follows:
**************************************************
*-- Form: frmselecttest
*-- ParentClass: form
*-- BaseClass: form
*-- Time Stamp: 04/03/06 12:51:13 PM
*
DEFINE CLASS frmselecttest AS form
Top = 0
Left = 0
Height = 104
Width = 189
DoCreate = .T.
Caption = "Form1"
Name = "frmSelectTest"
ADD OBJECT cmdtest1 AS commandbutton WITH ;
Top = 36, ;
Left = 48, ;
Height = 27, ;
Width = 84, ;
Caption = "Start Test 1", ;
Name = "cmdTest1"
ADD OBJECT lbltestsdone AS label WITH ;
Caption = "Label1", ;
Height = 17, ;
Left = 84, ;
Top = 12, ;
Width = 40, ;
Name = "lblTestsDone"
ADD OBJECT cmdtest2 AS commandbutton WITH ;
Top = 72, ;
Left = 48, ;
Height = 27, ;
Width = 84, ;
Caption = "Start Test 2", ;
Name = "cmdTest2"
PROCEDURE runtest
LPARAMETERS tnTestID
LOCAL ARRAY latemp(1)
LOCAL lnOldTime, lnTotalDelay, lnTotalTests
lnTotalDelay=0
lnTotalTests = 10
thisform.Caption = 'Running test ' + ALLTRIM(STR(tnTestID))
lcRestext = 'Test ' + ALLTRIM(STR(tnTestID)) + ' - Default data session, ' + ;
IIF(tnTestID=1, 'close file each select', 'file remains open after each select') + CHR(13)+CHR(10)
lcRestext = lcRestext + 'Detected Applied Difference' + CHR(13)+CHR(10)
&& get the initial time value from the file:
SELECT time FROM c:\vfptest1;
where id = '1';
INTO ARRAY latemp
lnOldTime = laTemp(1)
USE IN vfptest1
&& Begin tests...
FOR lnTest = 1 TO lnTotalTests
DO WHILE .T.
SELECT time FROM c:\vfptest1;
where id = '1';
INTO ARRAY latemp
lnPostTestTime = SECONDS()
IF latemp(1) != lnOldTime
lnOldTime = latemp(1)
EXIT
ENDIF
&& Small loop delay to prevent cpu from going too high...
&& note that removing this makes little difference to the result on my pc
&&=INKEY(0.01)
&& test 1 - Close the test file within the test loop...
IF tnTestID = 1
USE IN vfptest1
ENDIF
ENDDO
&& fallen out of our loop, so record the discovery time
lcRestext = lcRestext + STR(lnPostTestTime,9,3) + ' ' + ;
STR(laTemp(1),9,3) + ' ' + ;
STR(lnPostTestTime-laTemp(1),9,3)+CHR(13)+CHR(10)
lnTotalDelay = lnTotalDelay + lnPostTestTime-laTemp(1)
&& Show the number of tests completed...
thisform.lblTestsDone.caption = ALLTRIM(STR(lnTest))
ENDFOR
lcRestext = lcRestext + 'Tests: ' + ALLTRIM(STR(lnTotalTests)) + CHR(13)+CHR(10)
lcRestext = lcRestext + 'Total Delay: ' + ALLTRIM(STR(lnTotalDelay,9,3)) + CHR(13)+CHR(10)
lcRestext = lcRestext + 'Average Delay: ' + ALLTRIM(STR(lnTotalDelay/lnTest,9,3))
_cliptext=lcRestext
thisform.release
ENDPROC
PROCEDURE cmdtest1.Click
thisform.runtest(1)
ENDPROC
PROCEDURE cmdtest2.Click
thisform.runtest(2)
ENDPROC
ENDDEFINE
*
*-- EndDefine: frmselecttest
**************************************************
**************************************************
*-- Form: frmupdatetest
*-- ParentClass: form
*-- BaseClass: form
*-- Time Stamp: 04/03/06 12:52:05 PM
*
DEFINE CLASS frmupdatetest AS form
Top = 0
Left = 0
Height = 59
Width = 155
DoCreate = .T.
Caption = "UpdateTest"
Name = "frmUpdateTest"
ADD OBJECT cmdupdate AS commandbutton WITH ;
Top = 12, ;
Left = 36, ;
Height = 27, ;
Width = 84, ;
Caption = "Update", ;
Name = "cmdUpdate"
PROCEDURE cmdupdate.Click
UPDATE c:\vfptest1 set time = SECONDS() WHERE id = '1'
&& flush
&& use in vfptest1
ENDPROC
ENDDEFINE
*
*-- EndDefine: frmupdatetest
**************************************************
I am running VFP7.0 on an NT4sp6a and XPPro sp2 workstations of various hardware specifications.
I have a form in an application that is designed to update a flag on a file once a process has been completed.
The environment is multi-user, and the flag exists to prevent the process inadvertently occurring more than once by more than one user. I have found that in some circumstances the update of the flag is apparently not visible to the a second user for a period of time (or indefinitely without additional action - see test 3 below) once it has been updated by another.
To test the issue, I have tried to incrementally eliminate possible influences on a table being updated: ie. network issues, buffering issues, operating system issues, & hardware issues.
A 'SelectTest' form was created that runs a SQL SELECT to return a SECONDS() value stored in a local free table. This value is tested within a loop against an old value, and if different, the difference in update time and current time is recorded. This is repeated ten times and the average recorded.
An 'update' form was created to run an SQL UPDATE to update the time field of the table with SECONDS(). The Update button is hit each time the SelectTest form detects a data change.
By running these two forms in separate VFP sessions on the same workstation, I hoped to measure the time taken for an update to be visible to a select.
Results indicate that where the file is immediately closed following the select, the change can be detected almost instantaneously - as I would have expected (Test 1). However, where the file is allowed to remain open after the select, a significant delay of up to 4 seconds or so is experienced (Test 2). Worse still, if the selecttest form's datasession is set to private, and the vfptest1 file is open in the default session, the changes are not detected at all! (Test 3)
Note that Issuing 'FLUSH' following the update, or Closing the file following the update makes little difference to the times recorded.
I have also run this test on a server networked file from two workstations, having first synchronised workstation times (and restarted VFP, as seconds() appears to rely on the system time at startup). This resulted in similar results to the non-networked version.
Regards,
Mike.
RESULTS:
Test 1 - Default data session, close file each select
Detected Applied Difference
45910.964 45910.964 0.000
45911.839 45911.839 0.000
45912.480 45912.479 0.001
45913.011 45913.011 0.000
45913.464 45913.464 0.000
45914.058 45914.057 0.001
45914.527 45914.526 0.001
45915.042 45915.042 0.000
45915.495 45915.495 0.000
45916.042 45916.042 0.000
Tests: 10
Total Delay: 0.003
Average Delay: 0.000
Test 2 - Default data session, file remains open after each select
Detected Applied Difference
45944.558 45942.214 2.344
45949.558 45945.557 4.001
45954.558 45950.042 4.516
45959.558 45957.229 2.329
45964.558 45960.229 4.329
45969.558 45968.057 1.501
45974.558 45970.292 4.266
45979.558 45975.089 4.469
45984.558 45980.636 3.922
45989.558 45986.261 3.297
Tests: 10
Total Delay: 34.974
Average Delay: 3.179
Test 3 - Private data session, close file each select -test file opened in default session
- Total Failure to detect change - loops until interupted by 'esc'
The test file was created as follows:
CREATE TABLE c:\mptest1 free (ID c(1), time n(9,3))
INSERT INTO c:\mptest1 values ('1', SECONDS())
My test forms are as follows:
**************************************************
*-- Form: frmselecttest
*-- ParentClass: form
*-- BaseClass: form
*-- Time Stamp: 04/03/06 12:51:13 PM
*
DEFINE CLASS frmselecttest AS form
Top = 0
Left = 0
Height = 104
Width = 189
DoCreate = .T.
Caption = "Form1"
Name = "frmSelectTest"
ADD OBJECT cmdtest1 AS commandbutton WITH ;
Top = 36, ;
Left = 48, ;
Height = 27, ;
Width = 84, ;
Caption = "Start Test 1", ;
Name = "cmdTest1"
ADD OBJECT lbltestsdone AS label WITH ;
Caption = "Label1", ;
Height = 17, ;
Left = 84, ;
Top = 12, ;
Width = 40, ;
Name = "lblTestsDone"
ADD OBJECT cmdtest2 AS commandbutton WITH ;
Top = 72, ;
Left = 48, ;
Height = 27, ;
Width = 84, ;
Caption = "Start Test 2", ;
Name = "cmdTest2"
PROCEDURE runtest
LPARAMETERS tnTestID
LOCAL ARRAY latemp(1)
LOCAL lnOldTime, lnTotalDelay, lnTotalTests
lnTotalDelay=0
lnTotalTests = 10
thisform.Caption = 'Running test ' + ALLTRIM(STR(tnTestID))
lcRestext = 'Test ' + ALLTRIM(STR(tnTestID)) + ' - Default data session, ' + ;
IIF(tnTestID=1, 'close file each select', 'file remains open after each select') + CHR(13)+CHR(10)
lcRestext = lcRestext + 'Detected Applied Difference' + CHR(13)+CHR(10)
&& get the initial time value from the file:
SELECT time FROM c:\vfptest1;
where id = '1';
INTO ARRAY latemp
lnOldTime = laTemp(1)
USE IN vfptest1
&& Begin tests...
FOR lnTest = 1 TO lnTotalTests
DO WHILE .T.
SELECT time FROM c:\vfptest1;
where id = '1';
INTO ARRAY latemp
lnPostTestTime = SECONDS()
IF latemp(1) != lnOldTime
lnOldTime = latemp(1)
EXIT
ENDIF
&& Small loop delay to prevent cpu from going too high...
&& note that removing this makes little difference to the result on my pc
&&=INKEY(0.01)
&& test 1 - Close the test file within the test loop...
IF tnTestID = 1
USE IN vfptest1
ENDIF
ENDDO
&& fallen out of our loop, so record the discovery time
lcRestext = lcRestext + STR(lnPostTestTime,9,3) + ' ' + ;
STR(laTemp(1),9,3) + ' ' + ;
STR(lnPostTestTime-laTemp(1),9,3)+CHR(13)+CHR(10)
lnTotalDelay = lnTotalDelay + lnPostTestTime-laTemp(1)
&& Show the number of tests completed...
thisform.lblTestsDone.caption = ALLTRIM(STR(lnTest))
ENDFOR
lcRestext = lcRestext + 'Tests: ' + ALLTRIM(STR(lnTotalTests)) + CHR(13)+CHR(10)
lcRestext = lcRestext + 'Total Delay: ' + ALLTRIM(STR(lnTotalDelay,9,3)) + CHR(13)+CHR(10)
lcRestext = lcRestext + 'Average Delay: ' + ALLTRIM(STR(lnTotalDelay/lnTest,9,3))
_cliptext=lcRestext
thisform.release
ENDPROC
PROCEDURE cmdtest1.Click
thisform.runtest(1)
ENDPROC
PROCEDURE cmdtest2.Click
thisform.runtest(2)
ENDPROC
ENDDEFINE
*
*-- EndDefine: frmselecttest
**************************************************
**************************************************
*-- Form: frmupdatetest
*-- ParentClass: form
*-- BaseClass: form
*-- Time Stamp: 04/03/06 12:52:05 PM
*
DEFINE CLASS frmupdatetest AS form
Top = 0
Left = 0
Height = 59
Width = 155
DoCreate = .T.
Caption = "UpdateTest"
Name = "frmUpdateTest"
ADD OBJECT cmdupdate AS commandbutton WITH ;
Top = 12, ;
Left = 36, ;
Height = 27, ;
Width = 84, ;
Caption = "Update", ;
Name = "cmdUpdate"
PROCEDURE cmdupdate.Click
UPDATE c:\vfptest1 set time = SECONDS() WHERE id = '1'
&& flush
&& use in vfptest1
ENDPROC
ENDDEFINE
*
*-- EndDefine: frmupdatetest
**************************************************