LOCK and UNLOCK in the Wiki/Manuals
LOCK and UNLOCK in the Wiki/Manuals
I've been "playing with" the LOCK/UNLOCK commands (under Windows, 0.21.1), and could never get them to actually LOCK anything! Tried Binary/Random files, etc... LOCK always set ERR=1 (illegal function call). (I didn't try the LOCK option on the OPEN commands - I think other threads here state that these options are currently not supported).
Unless others have had better results with LOCK/UNLOCK, should we insert some comments in the Wiki so that folks don't waste time on these commands?
- Mike
Unless others have had better results with LOCK/UNLOCK, should we insert some comments in the Wiki so that folks don't waste time on these commands?
- Mike
As far as I can tell from the sources, the LOCK/UNLOCK statements are implemented on all systems and should work fine. But some testing shows that the implementations are at best incomplete on Windows and DOS, and on Linux I couldn't get it to work at all.
I'll add a note to those wiki pages, along the lines of "this command is currently a bit broken".
I'll add a note to those wiki pages, along the lines of "this command is currently a bit broken".
I think the LOCK statement is more than a bit broken, Under Windows and using 0.21.1 (08-11-2010) I can’t get it to work either. And I also can’t get the lock_type parameter for OPEN # to work (and the documentation is not quite clear on the syntax and there is no example).
Code: Select all
'==============================================================================
#include "windows.bi"
'==============================================================================
function LastErrorStr() as string
dim as string * 1024 buffer
dim as integer p
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,_
0,_
GetLastError(),_
0,_
strptr( buffer ),_
1024,_
0 )
buffer = rtrim( buffer )
p = instr( buffer, chr(13) )
if p then buffer = left( buffer, p - 1 )
return buffer
end function
'==============================================================================
sub GetProc( pParam as any ptr )
dim as integer x
for i as integer = 0 to 100
if get( #1 , , x ) then
print "get #1 error @ "; i
exit for
else
print i,
end if
next
print
print
for i as integer = 0 to 100
if get( #2 , , x ) then
print "get #2 error @ "; i
exit for
else
print i,
end if
next
print
print
end sub
'==============================================================================
sub InputProc( pParam as any ptr )
dim as string s
dim as integer e
SetLastError(0)
line input #3, s
e = err
if e <> 0 then
print "LINE INPUT, ERR = "; e
print LastErrorStr()
else
print s
end if
end sub
'==============================================================================
dim pThread as any ptr
dim as integer e,r
kill "test.bin"
kill "test.ran"
kill "test.txt"
open "test.bin" for binary as 1
open "test.ran" for random as 2 len = 4
open "test.txt" for output as 3
for i as integer = 0 to 100
put #1,,i
put #2,,i
print #3,i-100
next
close
sleep 1000
'==============================================================================
open "test.bin" for binary as 1
open "test.ran" for random as 2 len = 4
print "These should succeed:"
pThread = threadcreate( @GetProc, 0 )
ThreadWait( pThread )
print "Press any key to continue..."
sleep
print
print "These should succeed:"
SetLastError(0)
lock #1, 0 to 100
e = err
if e then
print "LOCK, ERR = "; e
print "Windows Last Error: ",LastErrorStr()
end if
print
SetLastError(0)
lock #2, 99
e = err
if e then
print "LOCK, ERR = "; e
print "Windows Last Error: ",LastErrorStr()
end if
print
print "These should fail:"
print
pThread = threadcreate( @GetProc, 0 )
ThreadWait( pThread )
close
print "Press any key to continue..."
sleep
print
'r = open( "test.bin" for binary lock read write as 1 )
r = open( "test.bin" for binary lock read as 1 )
'r = open( "test.bin" for binary lock as 1 )
if r then
print "OPEN FOR BINARY LOCK error "; r
end if
'r = open( "test.ran" for random lock read write as 2 len = 4 )
r = open( "test.ran" for random lock read as 2 len = 4 )
'r = open( "test.ran" for random lock as 2 len = 4 )
if r then
print "OPEN FOR BINARY RANDOM LOCK error "; r
end if
print "These should fail:"
pThread = threadcreate( @GetProc, 0 )
ThreadWait( pThread )
print "Press any key to continue..."
sleep
print
print "This should succeed:"
r = open( "test.txt" for input as 3 )
if r then
print "OPEN FOR INPUT INPUT error "; r
end if
pThread = threadcreate( @InputProc, 0 )
ThreadWait( pThread )
close
'r = open( "test.txt" for input lock read write as 3 )
r = open( "test.txt" for input lock read as 3 )
'r = open( "test.txt" for input lock as 3 )
if r then
print "OPEN FOR INPUT RANDOM LOCK error "; r
end if
print "This should fail:"
pThread = threadcreate( @InputProc, 0 )
ThreadWait( pThread )
print
print "done"
sleep
I found that I can LOCK something, and then another process can't LOCK it again. But the other process can still write to the file. Something in the FB runtime or the C runtime seems to cause the lock to be released, somehow, prematurely.
As stated, last news on OPEN ... LOCK says it's still unimplemented.
As stated, last news on OPEN ... LOCK says it's still unimplemented.
MichaelW,
Actually, I ran a lot of tests/combos, and, AFAIR, I NEVER got LOCK to execute and return with ERR=0! Then, when I ignored the ERR setting, I never got any LOCK to work properly.
I can upload bits of test code, if needed - but they're very similar to yours.
I then wrote some code using LockFileEx() and UnLockFileEx(), and it's working just fine in the tests (under Windows only). I've not yet tested this code with the LOCK file(s) accessed through SAMBA into a Linux box.
I hoped to end up with some code that would work under Windows AND Linux, AND, furthermore, that would SHARE the same Locks/Lock-files (through SAMBA). So, then I started looking up Linux options (OPEN(), FCNTKL(), etc). Now, it looks like the LockFileEx() approach under Windows is not compatible with the FCNTL() approaches, and it looks like I'll have to re-do the Windows approach from scratch. Dang!!
- Mike
Same here...MichaelW wrote:I think the LOCK statement is more than a bit broken, Under Windows and using 0.21.1 (08-11-2010) I can’t get it to work either.
Actually, I ran a lot of tests/combos, and, AFAIR, I NEVER got LOCK to execute and return with ERR=0! Then, when I ignored the ERR setting, I never got any LOCK to work properly.
I can upload bits of test code, if needed - but they're very similar to yours.
I then wrote some code using LockFileEx() and UnLockFileEx(), and it's working just fine in the tests (under Windows only). I've not yet tested this code with the LOCK file(s) accessed through SAMBA into a Linux box.
I hoped to end up with some code that would work under Windows AND Linux, AND, furthermore, that would SHARE the same Locks/Lock-files (through SAMBA). So, then I started looking up Linux options (OPEN(), FCNTKL(), etc). Now, it looks like the LockFileEx() approach under Windows is not compatible with the FCNTL() approaches, and it looks like I'll have to re-do the Windows approach from scratch. Dang!!
- Mike
DKL,
- Mike
Gee, that's MUCH better than I experienced!dkl wrote:I found that I can LOCK something, and then another process can't LOCK it again.
IMO, that's not TOO serious, if all the locking code is under the control of the same app(s). The programmer can issue the LOCK, and then issue the other IOs only if "acceptable". Not perfect, but workable.But the other process can still write to the file.
- Mike
Re: LOCK and UNLOCK in the Wiki/Manuals
Can we revisit this issue? I think it is important to be able to lock files for safe writing.
I am using files in RANDOM mode and would like to be able to lock entire files.
I am using files in RANDOM mode and would like to be able to lock entire files.
-
- Posts: 139
- Joined: Feb 04, 2011 20:34
- Location: Ontario, Canada
Re: LOCK and UNLOCK in the Wiki/Manuals
If you control all the applications that use a shared file, then you can simulate file locking by using a special lock file in conjunction with the "Name" statement.
Start with a lock file name such as "lockfile.off". When an application needs to lock a file it should attempt to rename the lock file to something else. If the rename fails then another program has control of the lock. In this case the application should sit in a wait loop, retrying the rename until it has control of the lock file. Once it finishes its file I/O it can rename the file back to "lockfile.off". This will then allow other programs to take control of the lock.
We use this method to share files between our DOS, Windows and Linux applications. It's a flexible technique that can be applied in different ways. A single lock file can be used for a pool of application files, or each shared file can have its own lock file - it just depends on what you need.
Rod
Start with a lock file name such as "lockfile.off". When an application needs to lock a file it should attempt to rename the lock file to something else. If the rename fails then another program has control of the lock. In this case the application should sit in a wait loop, retrying the rename until it has control of the lock file. Once it finishes its file I/O it can rename the file back to "lockfile.off". This will then allow other programs to take control of the lock.
We use this method to share files between our DOS, Windows and Linux applications. It's a flexible technique that can be applied in different ways. A single lock file can be used for a pool of application files, or each shared file can have its own lock file - it just depends on what you need.
Rod
-
- Posts: 606
- Joined: Nov 28, 2012 1:27
- Location: CA, USA moving to WA, USA
- Contact:
Re: LOCK and UNLOCK in the Wiki/Manuals
My method, also.
I use a ramdisk in a common mapped directory for the lockfile to trim the time hit a little.
Windows and Linux.
David
I use a ramdisk in a common mapped directory for the lockfile to trim the time hit a little.
Windows and Linux.
David
Re: LOCK and UNLOCK in the Wiki/Manuals
This is brilliant! Thanks!Boris the Old wrote:You can simulate file locking by using a special lock file in conjunction with the "Name" statement.
Start with a lock file name such as "lockfile.off". When an application needs to lock a file it should attempt to rename the lock file to something else. If the rename fails then another program has control of the lock. In this case the application should sit in a wait loop, retrying the rename until it has control of the lock file.
Re: LOCK and UNLOCK in the Wiki/Manuals
Am I understanding that you read/write your lockfile on a ramdisk instead of a hard drive to speed up access times?speedfixer wrote:My method, also.
I use a ramdisk in a common mapped directory for the lockfile to trim the time hit a little.
Windows and Linux.
David
How much of a difference does this make?
Re: LOCK and UNLOCK in the Wiki/Manuals
That "Rename" approach sounds excellent - thank you.
Is there any consensus is on how best to deal with a "broken" lock - where an app places the lock (ie, Renames from OFF to ON), and then goes AWOL, and never "releases" the lock (Rename ON back to OFF). Presumably, the broken app:
- might have not attempted any of its intended file-updates, or
- partly did them (perhaps then resulting in file inconsistencies or file-corruption), or
- completed all updates fully (but still did not release the lock).
Presumably, where possible, it would be nice to recover from this mess automatically, while logging some error-msgs on the problem and on "who" caused it. However, if the broken app has also broken our files, we probably should not proceed until the files are checked/repaired.
- Mike
Is there any consensus is on how best to deal with a "broken" lock - where an app places the lock (ie, Renames from OFF to ON), and then goes AWOL, and never "releases" the lock (Rename ON back to OFF). Presumably, the broken app:
- might have not attempted any of its intended file-updates, or
- partly did them (perhaps then resulting in file inconsistencies or file-corruption), or
- completed all updates fully (but still did not release the lock).
Presumably, where possible, it would be nice to recover from this mess automatically, while logging some error-msgs on the problem and on "who" caused it. However, if the broken app has also broken our files, we probably should not proceed until the files are checked/repaired.
- Mike
-
- Posts: 139
- Joined: Feb 04, 2011 20:34
- Location: Ontario, Canada
Re: LOCK and UNLOCK in the Wiki/Manuals
Crash recovery would be the same for "rename" locks as it would be for normal locks - it depends entirely on the application. There are so many variables it's difficult to offer any advice. However, I've found that restoring from backups is safer than trying to fixed corrupted files. It's too easy to miss something.MJK wrote:Is there any consensus is on how best to deal with a "broken" lock - where an app places the lock (ie, Renames from OFF to ON), and then goes AWOL, and never "releases" the lock (Rename ON back to OFF)..........Presumably, where possible, it would be nice to recover from this mess automatically, while logging some error-msgs on the problem and on "who" caused it. However, if the broken app has also broken our files, we probably should not proceed until the files are checked/repaired.
For my customers this has never been a problem. Hardware problems are very rare and power outages can be handled with a UPS. And software bugs don't exist in my applications -- IBM trained me to think before I code. :-)
My programs try to do an orderly shutdown if they detect a bad lock or a corrupted file. Of course, regular backups are a must - just in case.
Rod
Re: LOCK and UNLOCK in the Wiki/Manuals
Thank you, Rod.
It's great news that apps don't blow up (apart from the power outages, and users misbehaving) - and therefore, shutting down apps, and restoring backups, is a very safe procedure.
And, I also spent some years with IBM (but... way-back-when!), and I understand your comment! For lurkers, the development approach was to FULLY document each new program's tasks first. Also, superb docs were available on the OS environment, compilers, runtime environments, etc. (No "help-desks!). Then, coding was treated as a fast, clerical exercise, and, expecting that the coder followed the specs exactly, very little time (if any!) was allocated for... "testing"! A "crash" was a National Emergency!
- Mike
It's great news that apps don't blow up (apart from the power outages, and users misbehaving) - and therefore, shutting down apps, and restoring backups, is a very safe procedure.
And, I also spent some years with IBM (but... way-back-when!), and I understand your comment! For lurkers, the development approach was to FULLY document each new program's tasks first. Also, superb docs were available on the OS environment, compilers, runtime environments, etc. (No "help-desks!). Then, coding was treated as a fast, clerical exercise, and, expecting that the coder followed the specs exactly, very little time (if any!) was allocated for... "testing"! A "crash" was a National Emergency!
- Mike