Loading...
Searching...
No Matches
casacore::LockFile Class Reference
casa package (libcasa_casa) » IO_module

More...

`#include <LockFile.h>`

## Public Member Functions

| LockFile (const String &fileName, double inspectInterval=0, Bool create=False, Bool addToRequestList=True, Bool mustExist=True, uInt seqnr=0, Bool permLocking=False, Bool noLocking=False)
| Create or open the lock file with the given name.
| ~LockFile ()
| The destructor does not delete the file, because it is not known when the last process using the lock file will stop.
Bool | isMultiUsed ()
| Is the file associated with the LockFile object in use in another process?
Bool | acquire (FileLocker::LockType=FileLocker::Write, uInt nattempts=0)
| Acquire a read or write lock.
Bool | acquire (MemoryIO &info, FileLocker::LockType=FileLocker::Write, uInt nattempts=0)
Bool | acquire (MemoryIO *info, FileLocker::LockType type, uInt nattempts)
Bool | release ()
| Release a lock and write the information (if given) into the lock file.
Bool | release (const MemoryIO &info)
Bool | release (const MemoryIO *info)
Bool | inspect (Bool always=False)
| Inspect if another process wants to access the file (i.e.
Bool | canLock (FileLocker::LockType=FileLocker::Write)
| Test if the file can be locked for read or write.
Bool | hasLock (FileLocker::LockType=FileLocker::Write) const
| Test if the process has a lock for read or write on the file.
int | lastError () const
| Get the last error.
String | lastMessage () const
| Get the message belonging to the last error.
const String & | name () const
| Get the name of the lock file.
const Block< Int > & | reqIds () const
| Get the block of request id's.
void | getInfo (MemoryIO &info)
| Get the request id's and the info from the lock file.
void | putInfo (const MemoryIO &info) const
| Put the info into the file (after the request id's).

## Static Public Member Functions

static uInt | showLock (uInt &pid, Bool &permLocked, const String &fileName)
| Tell if another process holds a read or write lock on the given file or has the file opened.

## Private Member Functions

| LockFile (const LockFile &)
| The copy constructor cannot be used (its semantics are too difficult).
LockFile & | operator= (const LockFile &)
| Assignment cannot be used (its semantics are too difficult).
Int | getInt (const uChar *buffer, uInt leng, uInt offset) const
| Get an Int from the buffer at the given offset and convert it from canonical to local format.
void | addReqId ()
| Add the request id of this process to the list.
void | removeReqId ()
| Remove the request id of this process from the list (and all the ones before it).
void | getReqId ()
| Get the request list from the file.
void | putReqId (int fd) const
| Put the request list into the file.
void | convReqId (const uChar *buffer, uInt leng)
| Convert the request id from canonical to local format.
Int | getNrReqId () const
| Get the number of request id's.

## Private Attributes

FileLocker | itsLocker
FileLocker | itsUseLocker
std::shared_ptr< FiledesIO > | itsFileIO
Bool | itsWritable
Bool | itsAddToList
double | itsInterval
Time | itsLastTime
String | itsName
uInt | itsPid
uInt | itsHostId
Block< Int > | itsReqId
Int | itsInspectCount

## Detailed Description

Class to handle file locking and synchronization.

### Intended use:

Public interface

### Review Status

Reviewed By:
  UNKNOWN
Date Reviewed:
  before2004/08/25
Test programs:
  tLockFile

### Prerequisite

- class FileLocker
- class MemoryIO

### Synopsis

This class handles file locking by means of a special lock file which serves as the locking mechanism for another file or group of files. It is for instance used to lock a table in the Casacore Table System.

The lock file has in principle world read/write access, so every process accessing the main file can write information in it. The lock file contains the following information (in canonical format):

- A request list indicating which processes want to acquire a lock. The process holding the lock can inspect this list to decide if it should release its lock. An interval can be defined to be sure that the list is not inspected too often. A user can choose not to add to this list, because it incurs some overhead to write the list. However, that should only be done when one is sure that another process cannot keep a lock forever.
- Some information telling if the state of the main file has changed. The information can be used by a process to synchronize its internal buffers with the new contents of the file(s). E.g. a table could store one or more counters in it, which can be used to determine if the table has to refresh its caches. This information is passed as a MemoryIO object and is opaque for the LockFile class. It is simply handled as a stream of bytes.

Acquiring a lock works as follows:

- Class FileLocker is used to do one attempt to acquire a read or write lock.
- If it fails and multiple attempts have to be done, the request is added to the request list in the lock file to tell the process holding the lock that another process needs a lock.
- Other attempts (with 1 second intervals) will be done until the lock is acquired or until the maximum number of attempts is reached.
- The lock request is removed from the request list.
- When the lock was acquired, the synchronization info is read from the lock file.

Releasing a lock writes the synchronization info into the lock file and tells FileLocker to release the lock.

When the lock file cannot be opened as read/write, it is opened as readonly. It means that the request list cannot be stored in it, so the process has no way to tell the other processes it wants access to the file. It has to wait until the lock is released.
In principle a lock file should always be there. However, it is possible (with a constructor option) that there is no lock file. In that case each lock request succeeds without doing actual locking. This mode is needed to be able to handle readonly tables containing no lock file.

After each write the fsync function is called to make sure that the contents of the file are written to disk. This is necessary for correct file synchronization in NFS. However, at the moment this feature is switched off, because it degraded performance severely.

Apart from the read/write lock handling, the LockFile also contains a mechanism to detect if a file is opened by another process. This can be used to test if a process can safely delete the file. For this purpose it sets another read lock when the file gets opened. The function isMultiUsed tests this lock to see if the file is used in other processes.
This lock is also used to tell if the file is permanently locked. If that is the case, the locked block is 2 bytes instead of 1.

When in the same process multiple LockFile objects are created for the same file, deleting one object releases all locks on the file, thus also the locks held by the other LockFile objects. This behaviour is due to the way file locking is working on UNIX machines (certainly on Solaris 2.6). One can use the test program tLockFile to test for this behaviour.

### Example

// Create/open the lock file (with 1 sec inspection interval).
// Acquire the lock and get the synchronization info.
LockFile lock ("file.name", 1);
MemoryIO syncInfo;
if (! lock.acquire (syncInfo)) {
throw (AipsError ("Locking failed: " + lock.message()));
}
while (...) {
... do something with the table files..\.
// Test if another process needs the files.
// If so, synchronize files and release lock.
if (lock.inspect()) {
do fsync for all other files
syncInfo.seek (0);
syncInfo.write (...);
lock.release (syncInfo);
// At this point another process can grab the lock.
// Reacquire the lock
lock.acquire (syncInfo);
throw (AipsError ("Locking failed: " + lock.message()));
}
}
}
casacore::AipsError
Definition Error.h:133
casacore::ByteIO::seek
Int64 seek(Int offset, ByteIO::SeekOption=ByteIO::Begin)
This function sets the position on the given offset.
Definition ByteIO.h:189
casacore::LockFile::LockFile
LockFile(const String &fileName, double inspectInterval=0, Bool create=False, Bool addToRequestList=True, Bool mustExist=True, uInt seqnr=0, Bool permLocking=False, Bool noLocking=False)
Create or open the lock file with the given name.
casacore::MemoryIO
Definition MemoryIO.h:123
casacore::MemoryIO::write
virtual void write(Int64 size, const void *buf)
Write the number of bytes.
casacore::all
LatticeExprNode all(const LatticeExprNode &expr)

### Motivation

Make it possible to lock and synchronize tables in an easy and efficient way.

Definition at line 169 of file LockFile.h.

## Constructor & Destructor Documentation

## LockFile() [1/2]

casacore::LockFile::LockFile | ( | const String & | fileName,
|  | double | inspectInterval = 0,
|  | Bool | create = False,
|  | Bool | addToRequestList = True,
|  | Bool | mustExist = True,
|  | uInt | seqnr = 0,
|  | Bool | permLocking = False,
|  | Bool | noLocking = False )

explicit

Create or open the lock file with the given name.

It is created if create=True or if the file does not exist yet. The interval (in seconds) defines how often function inspect inspects the request list in the lock file. An interval>0 means that it is only inspected if the last inspect was at least inspectInterval seconds ago. An interval<=0 means that inspect always inspects the request list.
When addToRequestList=False, function acquire does not add the request to the lock file when a lock cannot be acquired. This may result in better performance, but should be used with care.
If create==True, a new lock file will always be created. Otherwise it will be created if it does not exist yet.
If mustExist==False, it is allowed that the LockFile does not exist and cannot be created either.
The seqnr is used to set the offset where LockFile will use 2 bytes to set the locks on. Only in special cases it should be other than 0. At the moment the offset is 2*seqnr.
The permLocking argument is used to indicate if permanent locking will be used. If so, it'll indicate so. In that way showLock() can find out if if table is permanently locked.
The noLocking argument is used to indicate that no locking is needed. It means that acquiring a lock always succeeds.

References casacore::False, and casacore::True.

Referenced by LockFile(), and operator=().

## ~LockFile()

casacore::LockFile::~LockFile | ( |  | ) |

The destructor does not delete the file, because it is not known when the last process using the lock file will stop.

For the table system this is no problem, because the lock file is contained in the directory of the table, thus deleted when the table gets deleted.

## LockFile() [2/2]

casacore::LockFile::LockFile | ( | const LockFile & |  | ) |

private

The copy constructor cannot be used (its semantics are too difficult).

References LockFile().

## Member Function Documentation

## acquire() [1/3]

Bool casacore::LockFile::acquire | ( | FileLocker::LockType | type = FileLocker::Write,
|  | uInt | nattempts = 0 )

inline

Acquire a read or write lock.

It reads the information (if the info argument is given) from the lock file. The user is responsible for interpreting the information (e.g. converting from canonical to local format). The seek pointer in the MemoryIO object is set to 0, so the user can simply start reading the pointer.
The argument nattempts tells how often it is attempted (with 1 second intervals) to acquire the lock if it does not succeed. 0 means forever, while 1 means do not retry.

Definition at line 336 of file LockFile.h.

References acquire().

Referenced by acquire(), and acquire().

## acquire() [2/3]

Bool casacore::LockFile::acquire | ( | MemoryIO & | info,
|  | FileLocker::LockType | type = FileLocker::Write,
|  | uInt | nattempts = 0 )

inline

Definition at line 340 of file LockFile.h.

References acquire().

## acquire() [3/3]

Bool casacore::LockFile::acquire | ( | MemoryIO * | info,
|  | FileLocker::LockType | type,
|  | uInt | nattempts )

## addReqId()

void casacore::LockFile::addReqId | ( |  | ) |

private

Add the request id of this process to the list.

## canLock()

Bool casacore::LockFile::canLock | ( | FileLocker::LockType | type = FileLocker::Write | ) |

inline

Test if the file can be locked for read or write.

Definition at line 353 of file LockFile.h.

References itsFileIO, itsLocker, and casacore::True.

## convReqId()

void casacore::LockFile::convReqId | ( | const uChar * | buffer,
|  | uInt | leng )

private

Convert the request id from canonical to local format.

## getInfo()

void casacore::LockFile::getInfo | ( | MemoryIO & | info | ) |

Get the request id's and the info from the lock file.

## getInt()

Int casacore::LockFile::getInt | ( | const uChar * | buffer,
|  | uInt | leng,
|  | uInt | offset ) const

private

Get an Int from the buffer at the given offset and convert it from canonical to local format.

If the buffer is too short (i.e. does not contain the value), a zero value is returned.

References casacore::offset().

## getNrReqId()

Int casacore::LockFile::getNrReqId | ( |  | ) | const

private

Get the number of request id's.

## getReqId()

void casacore::LockFile::getReqId | ( |  | ) |

private

Get the request list from the file.

## hasLock()

Bool casacore::LockFile::hasLock | ( | FileLocker::LockType | type = FileLocker::Write | ) | const

inline

Test if the process has a lock for read or write on the file.

Definition at line 357 of file LockFile.h.

References itsFileIO, itsLocker, and casacore::True.

## inspect()

Bool casacore::LockFile::inspect | ( | Bool | always = False | ) |

Inspect if another process wants to access the file (i.e.

if the request list is not empty). It only inspects if the time passed since the last inspection exceeds the inspection interval as given in the constructor. If the time passed is too short, False is returned (indicating that no access is needed). If always==True, no test on inspection interval is done, so the inspect is always done.

References casacore::False, and casacore::FileLocker::Write.

## isMultiUsed()

Bool casacore::LockFile::isMultiUsed | ( |  | ) |

Is the file associated with the LockFile object in use in another process?

References casacore::FileLocker::Write.

## lastError()

int casacore::LockFile::lastError | ( |  | ) | const

inline

Get the last error.

Definition at line 361 of file LockFile.h.

References itsLocker.

## lastMessage()

String casacore::LockFile::lastMessage | ( |  | ) | const

inline

Get the message belonging to the last error.

Definition at line 365 of file LockFile.h.

References itsLocker.

## name()

const String & casacore::LockFile::name | ( |  | ) | const

inline

Get the name of the lock file.

Definition at line 369 of file LockFile.h.

References itsName.

## operator=()

LockFile & casacore::LockFile::operator= | ( | const LockFile & |  | ) |

private

Assignment cannot be used (its semantics are too difficult).

References LockFile().

## putInfo()

void casacore::LockFile::putInfo | ( | const MemoryIO & | info | ) | const

Put the info into the file (after the request id's).

## putReqId()

void casacore::LockFile::putReqId | ( | int | fd | ) | const

private

Put the request list into the file.

## release() [1/3]

Bool casacore::LockFile::release | ( |  | ) |

inline

Release a lock and write the information (if given) into the lock file.

The user is responsible for making the information machine-independent (e.g. converting from local to canonical format).

Definition at line 345 of file LockFile.h.

References release().

Referenced by release(), and release().

## release() [2/3]

Bool casacore::LockFile::release | ( | const MemoryIO & | info | ) |

inline

Definition at line 349 of file LockFile.h.

References release().

## release() [3/3]

Bool casacore::LockFile::release | ( | const MemoryIO * | info | ) |

## removeReqId()

void casacore::LockFile::removeReqId | ( |  | ) |

private

Remove the request id of this process from the list (and all the ones before it).

## reqIds()

const Block< Int > & casacore::LockFile::reqIds | ( |  | ) | const

inline

Get the block of request id's.

Definition at line 373 of file LockFile.h.

References itsReqId.

## showLock()

uInt casacore::LockFile::showLock | ( | uInt & | pid,
|  | Bool & | permLocked,
|  | const String & | fileName )

static

Tell if another process holds a read or write lock on the given file or has the file opened.

It returns:
3 if write-locked elsewhere.
2 if read-locked elsewhere.
1 if opened elsewhere.
0 if locked nor opened.
It fills in the PID of the process having the file locked or opened.
If locked, it also tells if it is permanently locked.
An exception is thrown if the file does not exist or cannot be opened.

## Member Data Documentation

## itsAddToList

Bool casacore::LockFile::itsAddToList

private

Definition at line 321 of file LockFile.h.

## itsFileIO

std::shared_ptr<FiledesIO> casacore::LockFile::itsFileIO

private

Definition at line 319 of file LockFile.h.

Referenced by canLock(), and hasLock().

## itsHostId

uInt casacore::LockFile::itsHostId

private

Definition at line 326 of file LockFile.h.

## itsInspectCount

Int casacore::LockFile::itsInspectCount

private

Definition at line 330 of file LockFile.h.

## itsInterval

double casacore::LockFile::itsInterval

private

Definition at line 322 of file LockFile.h.

## itsLastTime

Time casacore::LockFile::itsLastTime

private

Definition at line 323 of file LockFile.h.

## itsLocker

FileLocker casacore::LockFile::itsLocker

private

Definition at line 317 of file LockFile.h.

Referenced by canLock(), hasLock(), lastError(), and lastMessage().

## itsName

String casacore::LockFile::itsName

private

Definition at line 324 of file LockFile.h.

Referenced by name().

## itsPid

uInt casacore::LockFile::itsPid

private

Definition at line 325 of file LockFile.h.

## itsReqId

Block<Int> casacore::LockFile::itsReqId

private

Definition at line 327 of file LockFile.h.

Referenced by reqIds().

## itsUseLocker

FileLocker casacore::LockFile::itsUseLocker

private

Definition at line 318 of file LockFile.h.

## itsWritable

Bool casacore::LockFile::itsWritable

private

Definition at line 320 of file LockFile.h.

The documentation for this class was generated from the following file:

- casa/IO/LockFile.h