Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Iterative Dvc Lock

From Leeroopedia


Knowledge Sources
Domains Concurrency, Process_Management
Last Updated 2026-02-10 10:00 GMT

Overview

dvc/lock.py (222 lines) implements process-level locking for DVC repositories. It defines an abstract base class LockBase, three concrete implementations (LockNoop, Lock, HardlinkLock), and a factory function make_lock(). This prevents concurrent DVC processes from corrupting repository state.

from dvc.lock import make_lock, Lock, HardlinkLock

Source File

Property Value
File dvc/lock.py
Lines 222
Classes LockBase, LockNoop, Lock, HardlinkLock
Factory make_lock()

Constants

Name Value Description
DEFAULT_TIMEOUT 3 Default timeout in seconds for lock acquisition
FAILED_TO_LOCK_MESSAGE (string) User-facing error message with link to DVC troubleshooting docs

Exception: LockError

class LockError(DvcException):
    """Thrown when unable to acquire the lock for DVC repo."""

Raised when a lock cannot be acquired after the configured timeout or retry attempts.

Class: LockBase (ABC)

LockBase is an abstract base class defining the interface for all lock implementations.

Abstract Methods

Method Description
__init__(self, lockfile) Stores the lockfile path
lock(self) Acquires the lock
unlock(self) Releases the lock
is_locked (property) Returns whether the lock is currently held
__enter__(self) Context manager entry
__exit__(self, typ, value, tbck) Context manager exit

Class: LockNoop

LockNoop is a no-op lock implementation that uses a simple boolean flag. It is useful for testing or scenarios where locking is not required.

class LockNoop(LockBase):
    def __init__(self, *args, **kwargs):
        self._lock = False

The unlock() method raises DvcException if called when the lock is not held, maintaining correct lock semantics even in the no-op case.

Class: Lock

Lock is the primary lock implementation, backed by zc.lockfile.

Constructor

def __init__(self, lockfile, friendly=False, wait=False, **kwargs)
Parameter Description
lockfile Path to the lock file
friendly If True, displays a progress bar while waiting
wait If True, waits indefinitely; otherwise retries up to 6 times

Lock Acquisition

The lock() method implements a retry loop:

  • Calculates a delay of DEFAULT_TIMEOUT / 6 (0.5 seconds) between retries
  • If wait=True, retries indefinitely; otherwise gives up after 6 attempts
  • Displays a Tqdm progress bar when friendly=True, with a message directing users to hardlink_lock documentation
  • Catches zc.lockfile.LockError and re-raises as LockError with the troubleshooting message

Unlock

The unlock() method:

  • Returns silently if the lock acquisition previously failed (graceful degradation)
  • Raises DvcException if called on an unlocked lock
  • Calls self._lock.close() on the underlying zc.lockfile.LockFile

Class: HardlinkLock

HardlinkLock extends both flufl.lock.Lock and LockBase. It uses hardlink-based locking, which is more reliable on certain filesystems (especially NFS).

Constructor

def __init__(self, lockfile, tmp_dir=None, wait=False, **kwargs)

Key implementation details:

  • Uses socket.gethostname() instead of socket.getfqdn() for performance (FQDN resolution can take ~5 seconds)
  • Sets a lock lifetime of 365 days (effectively permanent)
  • Supports optional tmp_dir for storing claim files

Lock Acquisition

The lock() method wraps flufl.lock.Lock.lock() with:

  • A default timeout of DEFAULT_TIMEOUT seconds (unless wait=True)
  • A Tqdm progress bar when both wait and friendly are enabled
  • Conversion of flufl.lock.TimeOutError to LockError

Claim File Handling

The _set_claimfile() method overrides the parent to hash the claim file path using MD5 on Windows, where file path length limitations may cause issues.

Factory Function: make_lock

def make_lock(lockfile, tmp_dir=None, friendly=False, hardlink_lock=False, wait=False)

Returns either a HardlinkLock or Lock instance based on the hardlink_lock flag. This is the primary entry point for creating lock objects in DVC.

Parameter Default Description
lockfile (required) Path to the lock file
tmp_dir None Temp directory for claim files (HardlinkLock only)
friendly False Show user-facing progress while waiting
hardlink_lock False Use hardlink-based locking
wait False Wait indefinitely for the lock

Class Hierarchy

LockBase (ABC)
  +-- LockNoop
  +-- Lock (zc.lockfile backend)
  +-- HardlinkLock (flufl.lock + LockBase)

Key Dependencies

Module Usage
zc.lockfile Backend for the standard Lock class
flufl.lock Backend for HardlinkLock class
dvc.progress.Tqdm Progress display while waiting for lock
dvc.exceptions.DvcException Base exception class
dvc.utils.format_link Formatting documentation URLs in error messages

See Also

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment