[comp.databases] rlock

rey@safn2.UUCP (rey) (09/24/90)

Set up is SCO Unix 3.2.2 on Compaq 386. SCO Foxbase+.

Could some one please explain rlock() in foxbase+. I am converting 
Dbase single user programs.

Who owns the lock? (Same question as who can write to an rlocked record.)
	a) The foxbase procedure that called rlock() sucessfully.
	b) The work area that called rlock() sucessfully.
	c) The process (pid).
	d) The user (uid).
	e) The tty?

I think the answer is a). When I rlock() then call another
	procedure I cannot append. But that doesn't seem correct design.

My Dbase IV guide talks about rlock() being cumlative up to 50 locks.
	On the same record? Can only 50 different records be locked?

How are the locks implemented? Are they in the .dbf file header or
	in the record being locked or in shared memory (Which I
	don't think I am using).
How about flock().
 hanks in advance.
-- 
Reynolds McClatchey (Southern Aluminum Finishing Co, Atlanta, GA, USA)
uunet!safn2!rey

joeb@ashtate (Joe Budge) (09/25/90)

From article <553@safn2.UUCP>, by rey@safn2.UUCP (rey):
> 
> My Dbase IV guide talks about rlock() being cumlative up to 50 locks.
> 	On the same record? Can only 50 different records be locked?

----> A networked PC running dBASE IV under DOS can lock up to 50
      different records at once on a shared file server.  This is per
      PC, so if you had 10 PC's on the net they could lock 500
      different records - though I pity the guy who then comes along
      to try to find an unlocked record <g>.

      If a networked PC needs to lock more records than that, it should
      try for an flock() on the files in question.  A PC can get up
      to 10 flock()'s, since that's how many work areas you have.

      The automatic locking mechanism within dBASE IV looks at the scope
      of the command and determines if it should go for a record lock or
      a file lock.  If you're doing it manually instead (with the rlock()
      and flock() functions) you have to be judicious in selecting the
      appropriate one.
> 
> How are the locks implemented? Are they in the .dbf file header or
> 	in the record being locked or in shared memory (Which I
> 	don't think I am using).

---->  You are using shared memory, you just don't know it.  Networks
       which support the DOS file locking protocols keep a table of
       locks on the server itself.  The table includes filenames,
       owner of the lock, and the range of bytes within the file which
       are locked.  All the products I've ever seen which support locking
       on a DOS network use this protocol.

       When these products are moved to other operating systems, the
       vendors still rely on the operating system itself to maintain the
       locks.

       Joe Budge

alan@mq.COM (Alan H. Mintz) (09/25/90)

In article <553@safn2.UUCP>, rey@safn2.UUCP (rey) writes:
> Set up is SCO Unix 3.2.2 on Compaq 386. SCO Foxbase+.
> 
> Could some one please explain rlock() in foxbase+. I am converting 
> Dbase single user programs.
> 
> Who owns the lock? (Same question as who can write to an rlocked record.)
> 	a) The foxbase procedure that called rlock() sucessfully.
> 	b) The work area that called rlock() sucessfully.
> 	c) The process (pid).
> 	d) The user (uid).
> 	e) The tty?

The Foxbase+ session (process) "owns" the lock(s). What this means is that
YOU may do REPLACEs on the record that YOU locked. The record remains locked
until you UNLOCK or USE the area that you performed the lock in, or perform
another rlock() in that area.

> I think the answer is a). When I rlock() then call another
> 	procedure I cannot append. But that doesn't seem correct design.

APPENDs require flock() (which cannot be performed on a file that is rloc()d
by another user. Note that you can flock() a file in which YOU have rlocked
a record - the flock() simply supercedes the rlock().

> My Dbase IV guide talks about rlock() being cumlative up to 50 locks.
> 	On the same record? Can only 50 different records be locked?

It would be impossible to have more than one lock on the same record. The
number of record locks possible for a given Foxbase+ session is equal
to the number of database areas that can be open at once, namely 10 :(

> How are the locks implemented? Are they in the .dbf file header or
> 	in the record being locked or in shared memory (Which I
> 	don't think I am using).

It appears that they are implemented in shared memory. There is no difference
in the hex dumps of the database while the file is closed, open, rlock()d, or
flock()d. There is also no diff in the inode tables (from pstat) (i.e. Fox
does not use UNIX file locks).
-- 
< Alan H. Mintz             | Voice +1 714 980 1034       >
< Micro-Quick Systems, Inc. | FAX   +1 714 944 3995       >
< 10384 Hillside Road       | uucp:     ...!uunet!mq!alan >
< Alta Loma, CA  91701 USA  | Internet: alan@MQ.COM       >

alexis@panix.UUCP (Alexis Rosen) (09/25/90)

I know it can be confusing, but I'd suggest that you RTFM, two times. briefly:

The *PROGRAM* (which is to say, the pid in unix) owns locks. However, you can't
use rlock to append. It's a really stupid way to do things, but the only way
to append in multi-user is:
1) Obvious but slow- Flock() the file, and if you get the lock, append and
   release.
2) Fast and ugly- just do append blank. If you can't make the record, it'll
   generate an error. Catch the error in your error-handling routine (you do
   have one, right?)  This becomes enourmously easier if you encapsulate the
   Append routine. Here's mine, for Fox/Mac, which should work identically:

* DelayAppnd(secs)
* Try up to 'secs' seconds to append a blank record.
* Relies on the error-handling routine to set appenderr to .F. if the
* append fails.  Returns .T. if append succeeded, .F. if not
 
Param secs		&& number of seconds to wait
Priv appenderr		&& semaphore flipped by Error-handler if append fails
Priv t			&& ending time
Priv junk
 
t = Val(Sys(2))+secs
Do While (Val(Sys(2)) <= t)
	appenderr = .F.		&& no error condition yet this pass in loop
	Append Blank		&& give it a shot
	If appenderr		&& if append failed, the error-handler set this
		junk = Inkey(1)	&& wait a second so we don't thrash the DBMS
	Else
		appenderr = !Rlock()	&& We don't get a lock on a record
					&& just by creating it
		Exit
	Endif
Enddo		&& loop for 'secs' seconds or until we achieve a lock
Return !appenderr

-----
Remeber to look for the specific error number for a "failed to append" in
B
your error-trapping routine.

Also, don't forget to release any lock you create. Generally speaking you
shouldn't hold on to locks for more than a fraction of a second- no reason.

Unlike dBase IV and FoxPro, you can only have ONE lock at a time- I think.
There's some small possibility that the unix version is different.


Hope this helps,
---
Alexis Rosen
cmcl2!panix!alexis

shevett@mccc.uucp (Dave Shevett) (09/26/90)

In article <79@mq.COM> alan@mq.COM (Alan H. Mintz) writes:
=In article <553@safn2.UUCP>, rey@safn2.UUCP (rey) writes:
=> Set up is SCO Unix 3.2.2 on Compaq 386. SCO Foxbase+.
=> 
=> Could some one please explain rlock() in foxbase+. I am converting 
=> Dbase single user programs.
=>
=> I think the answer is a). When I rlock() then call another
=> 	procedure I cannot append. But that doesn't seem correct design.
=
=APPENDs require flock() (which cannot be performed on a file that is rloc()d
=by another user. Note that you can flock() a file in which YOU have rlocked
=a record - the flock() simply supercedes the rlock().

Careful here.  The 'append' function standalone requires a flock().
However, I think 'rey' is running inside a procedure, therefore is 
probably doing APPEND BLANK.  In this case, the normal sequence is:

Build your screen using memory variables, and READ it.
append blank
if rlock()
	replace etc etc etc etc
	unlock
else
	do error with "Can't lock that sucker"
endif

=< Alan H. Mintz             | Voice +1 714 980 1034       >
=< Micro-Quick Systems, Inc. | FAX   +1 714 944 3995       >
=< 10384 Hillside Road       | uucp:     ...!uunet!mq!alan >
=< Alta Loma, CA  91701 USA  | Internet: alan@MQ.COM       >

On another tack - has anyone seen 'Invalid Signal Received' cropping up
when returning to a function called after a READ MENU TO mVAR 
function?  It happens 5 out of 7 times on a customer's machine, and
it's *EXTREMELY* annoying.  How about getting an error 'Feature Not
Available' at the same point, eh? (oh - SCO Xenix 2.3.1, SCO Fox
2.1.1, '386/20 w/4megs RAM, DigiBoard/8i)

/--------------------+                        +----------------------\
|    Dave Shevett    | "The shortest distance |   Labyrinth II BBS   |
|  Lawrenceville, NJ | between two puns is a  |    (609) 584-8774    |
|  shevett@mccc.UUCP | straight line..."      | 12/24/19200 PEP 24hrs|
\--------------------+        - Doc Webster   +----------------------/

alan@mq.COM (Alan H. Mintz) (09/28/90)

In article <1990Sep25.234729.5299@mccc.uucp>, shevett@mccc.uucp (Dave Shevett) writes:
> =APPENDs require flock() (which cannot be performed on a file that is rloc()d
> =by another user. Note that you can flock() a file in which YOU have rlocked
> =a record - the flock() simply supercedes the rlock().
> 
> Careful here.  The 'append' function standalone requires a flock().
> However, I think 'rey' is running inside a procedure, therefore is 
> probably doing APPEND BLANK.  In this case, the normal sequence is:

I think that is what I said, unless I misunderstand you. What I meant to say
was that, in order to do the APPE BLAN, you needed to do an flock()
first. 

I consulted TFM on the subject - this is WRONG. Apparently,
APPEND BLANK only locks the database HEADER and does not require that you
flock() first. It apparently asserts some "other" kind of lock on the
database header that does not conflict with any other kind of lock except
EXCLUSIVE use. This makes sense, since the lock is not under user control, 
and can therefore be managed by an internal handler.

I was completely dumbfounded by this. The application that I learned dBase
on always did an flock() before APPE BLAN. Does anyone know if this was
required under a previous incarnation of Foxbase, dBase III/III+, etc. ?

> On another tack - has anyone seen 'Invalid Signal Received' cropping up
> when returning to a function called after a READ MENU TO mVAR 
> function?  It happens 5 out of 7 times on a customer's machine, and
> it's *EXTREMELY* annoying.  How about getting an error 'Feature Not
> Available' at the same point, eh? (oh - SCO Xenix 2.3.1, SCO Fox
> 2.1.1, '386/20 w/4megs RAM, DigiBoard/8i)

I see this error on our developement system when someone re-compiles a
module that is being run by another user. It comes down to the run-time
interpreter losing it's place in the file. This would also happen if
the "compiled" .fox file is corrupted. Try re-compiling.
-- 
< Alan H. Mintz             | Voice +1 714 980 1034       >
< Micro-Quick Systems, Inc. | FAX   +1 714 944 3995       >
< 10384 Hillside Road       | uucp:     ...!uunet!mq!alan >
< Alta Loma, CA  91701 USA  | Internet: alan@MQ.COM       >

alexis@panix.uucp (Alexis Rosen) (10/02/90)

I posted an article about six days ago which must not have made it out. Since
lots of other things got lost too, I'll just repost it. Here's the latest from
this thread:

In article <1990Sep25.234729.5299@mccc.uucp> shevett@mccc.edu (Dave Shevett) writes:
>In article <79@mq.COM> alan@mq.COM (Alan H. Mintz) writes:
>=In article <553@safn2.UUCP>, rey@safn2.UUCP (rey) writes:
>=> Set up is SCO Unix 3.2.2 on Compaq 386. SCO Foxbase+.
>=> 
>=> Could some one please explain rlock() in foxbase+. I am converting 
>=> Dbase single user programs.
>=>
>=> I think the answer is a). When I rlock() then call another
>=> 	procedure I cannot append. But that doesn't seem correct design.
>=
>=APPENDs require flock() (which cannot be performed on a file that is rloc()d
>=by another user. Note that you can flock() a file in which YOU have rlocked
>=a record - the flock() simply supercedes the rlock().
>
>Careful here.  The 'append' function standalone requires a flock().
>However, I think 'rey' is running inside a procedure, therefore is 
>probably doing APPEND BLANK.  In this case, the normal sequence is:
>
>Build your screen using memory variables, and READ it.
>append blank
>if rlock()
>	replace etc etc etc etc
>	unlock
>else
>	do error with "Can't lock that sucker"
>endif

Hm. All of these are wrong. The Flock method will work, but it's lazy and
inefficient programming. Here's the original message, which clarifies the
situation. BTW, I believe this features has been around since the baseline
Fox 2.0 release. Also, that 'third type' of lock is the Header Lock, which
is inaccessable to you from foxbase. Append Blank uses that lock.

Any of you guys gonna be in Toledo next week?...

---------------------------------------------------------------------
From alexis Tue Oct  2 03:29:27 EDT 1990


I know it can be confusing, but I'd suggest that you RTFM, two times. briefly:

The *PROGRAM* (which is to say, the pid in unix) owns locks. However, you can't
use rlock to append. It's a really stupid way to do things, but the only way
to append in multi-user is:
1) Obvious but slow- Flock() the file, and if you get the lock, append and
   release.
2) Fast and ugly- just do append blank. If you can't make the record, it'll
   generate an error. Catch the error in your error-handling routine (you do
   have one, right?)  This becomes enormously easier if you encapsulate the
   Append routine. Here's mine, for Fox/Mac, which should work identically:

* DelayAppnd(secs)
* Try up to 'secs' seconds to append a blank record.
* Relies on the error-handling routine to set appenderr to .F. if the
* append fails.  Returns .T. if append succeeded, .F. if not
 
Param secs		&& number of seconds to wait
Priv appenderr		&& semaphore flipped by Error-handler if append fails
Priv t			&& ending time
Priv junk
 
t = Val(Sys(2))+secs
Do While (Val(Sys(2)) <= t)
	appenderr = .F.		&& no error condition yet this pass in loop
	Append Blank		&& give it a shot
	If appenderr		&& if append failed, the error-handler set this
		junk = Inkey(1)	&& wait a second so we don't thrash the DBMS
	Else
		appenderr = !Rlock()	&& We don't get a lock on a record
					&& just by creating it
		Exit
	Endif
Enddo		&& loop for 'secs' seconds or until we achieve a lock
Return !appenderr

-----
Remeber to look for the specific error number for a "failed to append" in
your error-trapping routine.

Also, don't forget to release any lock you create. Generally speaking you
shouldn't hold on to locks for more than a fraction of a second- no reason.

Unlike dBase IV and FoxPro, you can only have ONE lock at a time- I think.
There's some small possibility that the unix version is different.


Hope this helps,
---
Alexis Rosen
cmcl2!panix!alexis