next up previous contents index
Next: Conflicts Up: The Model Previous: Creating & Deleting   Contents   Index


Locking

Introducing locks into a system inevitably leads to a lot of decisions that must be made. To cut things short, I have decided to go with a very simple solution:
  1. Locks are non-blocking.
  2. All locks must be accepted by the server.
  3. A file can have multiple readlocks (by the same number of clients) or a single writelock (by a single client).
  4. A client can obtain at most one lock pr. file.
  5. A client cannot renew a previously obtained lock for additional time.
  6. A client cannot convert a readlock to a writelock or vice versa.
  7. Locks that are obtained in order to read and write are treated as writelocks.

Decision 1 renders it unnecessary to implement waiting queues or the like, but it also lessens the possibility of deadlocks (now programming deadlocks are left entirely to the programmers). Decisions 2 and 3 are obvious. Decisions 4 to 7 reduce the complexity of the implementation, but they also reduce server traffic--a client knows if it already has a lock on a file, and thus do not need to contact the server to learn that a new lock request must fail. Furthermore, decisions 5 and 6 give fairness, and thus no starvation. Schematic overviews of the outcome of performing a readlock, a writelock, a readunlock, and a writeunlock are given in Figures 5.4, 5.5, 5.6, and 5.7. The decisions admittedly give little flexibility, but on the other hand the locking mechanism is easily understood.

Note, that the decisions naturally reflect back on pessimistic read and write opens, since they require locking.

I have decided to provide primitives for locking and unlocking files. These may come in handy when a user does a voluntary disconnection, knowing that he or she is going to update the file later.

If a client locks a file that is not cached on the mobile client, then the file gets cached. This is done under the assumption that if the client locks the file (e.g., in a situation like the one just mentioned), then it is going to be used.

In order to provide an interface that is similar to that of the other file operation primitives I have decided upon these two file locking primitives:


Table 5.4: Performing a read lock
REQUEST: p_lock(name,"r",$RET \! B$)
STATUS BEFORE OUTCOME STATUS AFTER S
NOT_LOCKED success READ_LOCKED by yourself,
$RET$=$T_{C}$+$RET \! B$
*
READ_LOCKED
by yourself
failure READ_LOCKED by yourself,
$RET$ unchanged
 
READ_LOCKED
by others
success READ_LOCKED along with others,
$RET$=$T_{C}$+$RET \! B$
*
READ_LOCKED
along with others
failure READ_LOCKED along with others,
$RET$ unchanged
 
WRITE_LOCKED
by yourself
failure WRITE_LOCKED by yourself,
$W \! ET$ unchanged
 
WRITE_LOCKED
by another
failure WRITE_LOCKED by another *

Note: The S-columns indicates with an asterix when it is necessary to contact the server. If the server is unreachable in these cases then the outcome is failure.


Table 5.5: Performing a write lock
REQUEST: p_lock(name,"w",$W \! ET \! B$)
STATUS BEFORE OUTCOME STATUS AFTER S
NOT_LOCKED success WRITE_LOCKED by yourself,
$W \! ET$=$T_{C}$+$W \! ET \! B$
*
READ_LOCKED
by yourself
failure READ_LOCKED by yourself,
$RET$ unchanged
 
READ_LOCKED
by others
failure READ_LOCKED by others *
READ_LOCKED
along with others
failure READ_LOCKED along with others,
$RET$ unchanged
 
WRITE_LOCKED
by yourself
failure WRITE_LOCKED by yourself,
$W \! ET$ unchanged
 
WRITE_LOCKED
by another
failure WRITE_LOCKED by another *


Table 5.6: Performing a read unlock
REQUEST: p_unlock(name,"r")
STATUS BEFORE OUTCOME STATUS AFTER S
NOT_LOCKED failure (!) NOT_LOCKED  
READ_LOCKED
by yourself
success NOT_LOCKED *
READ_LOCKED
by others
failure READ_LOCKED by others  
READ_LOCKED
along with others
success READ_LOCKED by others *
WRITE_LOCKED
by yourself
failure WRITE_LOCKED by yourself,
$W \! ET$ unchanged
 
WRITE_LOCKED
by another
failure WRITE_LOCKED by another *

(!): Even though this is what is wanted it must be considered a fault.

Note: The S-column indicates with an asterix when it is necessary to contact the server. If the server is unreachable in these cases then the outcome is failure.


Table 5.7: Performing a write unlock
REQUEST: p_unlock(name,"w")
STATUS BEFORE OUTCOME STATUS AFTER S
NOT_LOCKED failure (!) NOT_LOCKED  
READ_LOCKED
by yourself
failure READ_LOCKED by yourself,
$RET$ unchanged
 
READ_LOCKED
by others
failure READ_LOCKED by others *
READ_LOCKED
along with others
failure READ_LOCKED along with others,
$RET$ unchanged
 
WRITE_LOCKED
by yourself
success NOT_LOCKED *
WRITE_LOCKED
by another
failure WRITE_LOCKED by another *

(!): Even though this is what is wanted it must be considered a fault.



Footnotes

... *mode);5.3
Since it has been decided that a client can obtain at most one lock pr. file, the mode parameter is actually not needed--the system knows which kind of lock that the client has on the file. However, at the time this was pointed out to me [3], it had already been implemented (and partly tested). It is not really that bad, because the client should also know which kind of lock that has been put on the file!

next up previous contents index
Next: Conflicts Up: The Model Previous: Creating & Deleting   Contents   Index

michael@garfield.dk
2000-05-08