Class: Ferret::Store::Lock

A Lock is used to lock a data source so that not more than one output stream can access a data source at one time. It is possible that locks could be disabled. For example a read only index stored on a CDROM would have no need for a lock.

You can use a lock in two ways. Firstly:

  write_lock = @directory.make_lock(LOCK_NAME)
  write_lock.obtain(WRITE_LOCK_TIME_OUT)
    ... # Do your file modifications # ...
  write_lock.release()

Alternatively you could use the while locked method. This ensures that the lock will be released once processing has finished.

  write_lock = @directory.make_lock(LOCK_NAME)
  write_lock.while_locked(WRITE_LOCK_TIME_OUT) do
    ... # Do your file modifications # ...
  end

Child modules and classes

Class Ferret::Store::Lock::LockError

Public Instance Methods


lock.locked? → bool

Returns true if the lock has been obtained.

/*
 *  call-seq:
 *     lock.locked? -> bool
 *
 *  Returns true if the lock has been obtained.
 */
static VALUE
frt_lock_is_locked(VALUE self)
{
    Lock *lock;
    GET_LOCK(lock, self);
    return lock->is_locked(lock) ? Qtrue : Qfalse;
}

lock.obtain(timeout = 1) → bool

Obtain a lock. Returns true if lock was successfully obtained. Make sure the lock is released using Lock#release. Otherwise you‘ll be left with a stale lock file.

The timeout defaults to 1 second and 5 attempts are made to obtain the lock. If you‘re doing large batch updates on the index with multiple processes you may need to increase the lock timeout but 1 second will be substantial in most cases.

timeout:seconds to wait to obtain lock before timing out and returning false
return:true if lock was successfully obtained. Raises a Lock::LockError otherwise.
/*
 *  call-seq:
 *     lock.obtain(timeout = 1) -> bool
 *
 *  Obtain a lock. Returns true if lock was successfully obtained. Make sure
 *  the lock is released using Lock#release. Otherwise you'll be left with a
 *  stale lock file.
 *
 *  The timeout defaults to 1 second and 5 attempts are made to obtain the
 *  lock. If you're doing large batch updates on the index with multiple
 *  processes you may need to increase the lock timeout but 1 second will be
 *  substantial in most cases.
 *
 *  timeout:: seconds to wait to obtain lock before timing out and returning
 *            false
 *  return::  true if lock was successfully obtained. Raises a
 *            Lock::LockError otherwise.
 */
static VALUE
frt_lock_obtain(int argc, VALUE *argv, VALUE self)
{
    VALUE rtimeout;
    int timeout = 1;
    Lock *lock;
    GET_LOCK(lock, self);

    if (rb_scan_args(argc, argv, "01", &rtimeout) > 0) {
        timeout = FIX2INT(rtimeout);
    }
    /* TODO: use the lock timeout */
    if (!lock->obtain(lock)) {
        rb_raise(cLockError, "could not obtain lock: #%s", lock->name);
    }
    return Qtrue;
}

lock.release() → self

Release the lock. This should only be called by the process which obtains the lock.

/*
 *  call-seq:
 *     lock.release() -> self
 *
 *  Release the lock. This should only be called by the process which obtains
 *  the lock.
 */
static VALUE
frt_lock_release(VALUE self)
{
    Lock *lock;
    GET_LOCK(lock, self);
    lock->release(lock);
    return self;
}

lock.while_locked(timeout = 1) { do_something() } → bool

Run the code in a block while a lock is obtained, automatically releasing the lock when the block returns.

See Lock#obtain for more information on lock timeout.

timeout:seconds to wait to obtain lock before timing out and returning false
return:true if lock was successfully obtained. Raises a Lock::LockError otherwise.
/*
 *  call-seq:
 *     lock.while_locked(timeout = 1) { do_something() } -> bool
 *
 *  Run the code in a block while a lock is obtained, automatically releasing
 *  the lock when the block returns.
 *
 *  See Lock#obtain for more information on lock timeout.
 *
 *  timeout:: seconds to wait to obtain lock before timing out and returning
 *            false
 *  return::  true if lock was successfully obtained. Raises a
 *            Lock::LockError otherwise.
 */
static VALUE
frt_lock_while_locked(int argc, VALUE *argv, VALUE self)
{
    VALUE rtimeout;
    int timeout = 1;
    Lock *lock;
    GET_LOCK(lock, self);
    if (rb_scan_args(argc, argv, "01", &rtimeout) > 0) {
        timeout = FIX2INT(rtimeout);
    }
    if (!lock->obtain(lock)) {
        rb_raise(cLockError, "could not obtain lock: #%s", lock->name);
    }
    rb_yield(Qnil);
    lock->release(lock);
    return Qtrue;
}