# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Lock files.

Please read:

fcntl(2)
flock(2)
lockf(3)
http://pubs.opengroup.org/onlinepubs/9699919799/functions/lockf.html
http://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
https://github.com/python/cpython/blob/2.7/Modules/fcntlmodule.c

Informal references:

http://0pointer.de/blog/projects/locking.html
https://www.samba.org/samba/news/articles/low_point/tale_two_stds_os2.html
http://chris.improbable.org/2010/12/16/everything-you-never-wanted-to-know-about-file-locking/
"""

from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals

import errno
import fcntl
import logging
import os
import random
import time


logger = logging.getLogger(__name__)


class FileLock(object):
    """Context manager for an exclusive file lock.

    This uses fcntl() locks for portability.  Refer to the module
    docstring and the links therein for details that informed this
    choice.

    fcntl() locks have a number of important quirks:

    This may or may not work if the lock is on a remote filesystem.

    Locks are per-process and therefore not thread-safe.

    The lock is bound to the file inode:

    >>> tmp = getfixture('tmpdir')
    >>> f1 = str(tmp.join('lock'))
    >>> f2 = str(tmp.join('lock2'))
    >>> with FileLock(f1):
    ...     os.link(f1, f2)
    ...     f = open(f2)  # Same inode
    ...     f.close()     # This will release the lock
    ...     # Stuff here will run without the lock
    """

    def __init__(self, lockfile, timeout=180):
        """Initialize instance.

        Args:
            lockfile: Path to lockfile
            timeout: Timeout for grabbing lock, in seconds
        """
        self._lockfile = lockfile
        self._timeout = timeout
        self._fd = None

    def __enter__(self):
        timeout = time.time() + self._timeout
        # Wait for possible symlink locks and open lock file.
        while True:
            if not self._symlink_lock_present():
                try:
                    self._fd = os.open(self._lockfile,
                                       os.O_RDWR | os.O_CREAT,
                                       0666)
                    break
                except OSError as e:  # pragma: no cover
                    logger.debug('Error opening lock file: %s', e)
            if time.time() > timeout:
                raise TimeoutError(self._lockfile, self._timeout)
            time.sleep(random.random())

        # Grab lock on file.
        while True:
            try:
                fcntl.lockf(self._fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
            except IOError as e:
                logger.debug('Error acquiring lock: %s', e)
            else:
                return
            if time.time() > timeout:
                raise TimeoutError(self._lockfile, self._timeout)
            time.sleep(random.random())

    def __exit__(self, exc_type, exc_value, traceback):
        os.close(self._fd)

    def _symlink_lock_present(self):
        """Check if an old style symlink lock is in place."""
        # TODO(ayatane): 2017-08-21 Old symlink lock file handling can
        # be removed after the code has existed for Long Enough that
        # there aren't reasonably any instances of it left on developer
        # or prod machines.
        try:
            target = os.readlink(self._lockfile)
        except OSError as e:
            if e.errno == errno.EINVAL:
                # Not a symlink.
                return False
            elif e.errno == errno.ENOENT:
                # Lock is gone.
                return False
            else:  # pragma: no cover
                raise
        pid = _procdir.getpid(target)
        if _is_pid_running(pid):
            return True
        try:
            os.unlink(self._lockfile)
        except OSError as e:  # pragma: no cover
            if e.errno != errno.ENOENT:
                raise
        return False


class TimeoutError(Exception):
    """Grabbing lock timed out."""

    def __init__(self, filename, timeout):
        super(TimeoutError, self).__init__(filename, timeout)
        self.filename = filename
        self.timeout = timeout

    def __str__(self):
        return ('Grabbing lock %(filename)s'
                ' timed out after %(timeout)s seconds'
                % {
                    'filename': self.filename,
                    'timeout': self.timeout,
                })


class _ProcDir(object):
    """Class wrapping /proc related functions."""

    def __init__(self, procdir):
        self._procdir = procdir

    def getpath(self, pid):
        """Return /proc dir path for pid."""
        return os.path.join(self._procdir, str(pid))

    def getpid(self, path):
        """Return int pid for /proc path."""
        proc_prefix_len = len(self._procdir) + 1  # Handle extra ending slash
        pid_string = path[proc_prefix_len:]
        return int(pid_string)

_procdir = _ProcDir('/proc')


def _is_pid_running(pid):
    """Return True if pid is running."""
    try:
        os.kill(pid, 0)
    except OSError as e:
        return e.errno != errno.ESRCH
    else:
        return True
