LOCK and UNLOCK in the Wiki/Manuals

Forum for discussion about the documentation project.
MJK
Posts: 179
Joined: Nov 08, 2005 17:14
Location: Dublin, Ireland
Contact:

LOCK and UNLOCK in the Wiki/Manuals

Post by MJK »

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
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Post by dkl »

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".
MJK
Posts: 179
Joined: Nov 08, 2005 17:14
Location: Dublin, Ireland
Contact:

Post by MJK »

dkl wrote:... the implementations are at best incomplete on Windows and DOS...
I failed to get anything "locked" under windows [XP].
dkl wrote:I'll add a note to those wiki pages, along the lines of "this command is currently a bit broken".
I think that's a good idea. Thank you.

- Mike
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Post by MichaelW »

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

dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Post by dkl »

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.
MJK
Posts: 179
Joined: Nov 08, 2005 17:14
Location: Dublin, Ireland
Contact:

Post by MJK »

MichaelW,
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.
Same here...

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
MJK
Posts: 179
Joined: Nov 08, 2005 17:14
Location: Dublin, Ireland
Contact:

Post by MJK »

DKL,
dkl wrote:I found that I can LOCK something, and then another process can't LOCK it again.
Gee, that's MUCH better than I experienced!
But the other process can still write to the file.
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.

- Mike
skystrick
Posts: 104
Joined: May 19, 2013 23:25
Location: Florida

Re: LOCK and UNLOCK in the Wiki/Manuals

Post by skystrick »

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.
Boris the Old
Posts: 139
Joined: Feb 04, 2011 20:34
Location: Ontario, Canada

Re: LOCK and UNLOCK in the Wiki/Manuals

Post by Boris the Old »

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
speedfixer
Posts: 606
Joined: Nov 28, 2012 1:27
Location: CA, USA moving to WA, USA
Contact:

Re: LOCK and UNLOCK in the Wiki/Manuals

Post by speedfixer »

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
skystrick
Posts: 104
Joined: May 19, 2013 23:25
Location: Florida

Re: LOCK and UNLOCK in the Wiki/Manuals

Post by skystrick »

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.
This is brilliant! Thanks!
skystrick
Posts: 104
Joined: May 19, 2013 23:25
Location: Florida

Re: LOCK and UNLOCK in the Wiki/Manuals

Post by skystrick »

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
Am I understanding that you read/write your lockfile on a ramdisk instead of a hard drive to speed up access times?

How much of a difference does this make?
MJK
Posts: 179
Joined: Nov 08, 2005 17:14
Location: Dublin, Ireland
Contact:

Re: LOCK and UNLOCK in the Wiki/Manuals

Post by MJK »

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
Boris the Old
Posts: 139
Joined: Feb 04, 2011 20:34
Location: Ontario, Canada

Re: LOCK and UNLOCK in the Wiki/Manuals

Post by Boris the Old »

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.
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.

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
MJK
Posts: 179
Joined: Nov 08, 2005 17:14
Location: Dublin, Ireland
Contact:

Re: LOCK and UNLOCK in the Wiki/Manuals

Post by MJK »

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
Post Reply