LINUX TIPS AND TRICKS --- May 26, 2000

Published by ITworld.com, the IT problem-solving network
http://www.itworld.com/newsletters

*********************************************************************

Locking A File Record 
By Danny Kalev

Locking an entire file for a single user is impractical when several
users or processes need to update it simultaneously. Instead, you can
use record locks. A record lock locks only a portion of a file. For
example, if user A locks bytes 500-550 of payroll.dat, user B can still
lock bytes 551-600 of payroll.dat without a lock conflict. 

There are two types of record locks: read locks (also called "shared
locks") and write locks (exclusive locks). Multiple users can hold read
locks over the same file region simultaneously. Reading a region of a
file that isn't being updated is always safe. Write locks are exclusive.
Only one user may hold a write lock for a certain region of a file.
Other users are not allowed to read or update that region as long as
it's locked. 

The function fcntl() locks a file record. fcntl() and its associated
data structures are declared in "fcntl.h":

int fcntl(int fd, int cmd, flock* p);

fd is the file descriptor. cmd specifies one of the following locking
modes:

F_SETLK -- set the lock and return 0 on success; if the lock can't be
obtained due to a conflict, exit with an error code.

F_SETLKW -- same as above, except that if the lock can't be obtained,
fcntl() waits until it can be obtained.

F_GETLK -- check whether the lock can be obtained. If it can, set the
value of l_type in struct flock (see below) to F_UNLCK. Otherwise, set
l_pid to the pid of the process currently holding the requested lock.
With F_GETLK, fcntl() always returns 0.

The third parameter of fcntl() is a pointer to struct flock:

struct flock
{
 short l_type; /* lock type; F_RDLCK, F_WRLCK, or F_UNLCK */
 short l_whence; /* beginning of lock: SEEK_SET, SEEK_CUR etc. */
 off_t l_start; /* start of lock as an offset from l_whence */
 off_t l_len /* number of bytes to lock */
 pid_t L-pid; /* when using F_GETLK: pid of lock holder */
};

The member l_type can have one of three values:

F_RDLCK -- read (shared) lock
F_WRLCK -- write (exclusive) lock
F_UNLCK -- release an existing lock

In the following example, the function update_file attempts to lock
bytes 50-150 in a file using fcntl():

int update_file(int fd)
{
 struct flock lck;
 lck.l_type = F_WRLCK; /*exclusive lock*/
 lck.l_whence = SEEK_SET; /*file beginning*/
 lck.l_start = 50; /*offset 50 from the file's beginning*/
 lck.l_len = 100 /*lock 100 bytes from offset 50*/
 if (fcntl(fd, F_SETLK, &lck) != 0);
  return -1; /*error, couldn't obtain lock*/
 else
  /*... update file*/
 return 0;
} 

About the author
----------------
Danny Kalev is a system analyst and software engineer with more
than 10 years of experience, specializing in C++ and
object-oriented analysis and design on various platforms including
VMS, DOS, Windows, Unix, and Linux. His technical interests involve
code optimization, networking, and distributed computing. He is
also a member of the ANSI C++ standardization committee and the
author of ANSI/ISO C++ Professional Programmer's Handbook (Que,
1999). Contact him at linuxnl@excite.com.

*********************************************************************

CUSTOMER SERVICE

You can subscribe or unsubscribe to any of your e-mail newsletters by 
updating your form at: 
http://www.itworld.com/cgi-bin/w3-msql/newsletters/subcontent12.html?

For subscription changes that cannot be handled via the web, please send 
an email to our customer service dept: support@itworld.com

*********************************************************************

Copyright 2000 ITworld.com, Inc., All Rights Reserved. 

http://www.itworld.com
