# -*- coding: utf-8 -*-

# daemon/pidlockfile.py
# Part of python-daemon, an implementation of PEP 3143.
#
# Copyright © 2008–2010 Ben Finney <ben+python@benfinney.id.au>
#
# This is free software: you may copy, modify, and/or distribute this work
# under the terms of the Python Software Foundation License, version 2 or
# later as published by the Python Software Foundation.
# No warranty expressed or implied. See the file LICENSE.PSF-2 for details.

""" Lockfile behaviour implemented via Unix PID files.
    """

import os
import errno

from lockfile import (
    LinkFileLock,
    AlreadyLocked, LockFailed,
    NotLocked, NotMyLock,
    )


class PIDFileError(Exception):
    """ Abstract base class for errors specific to PID files. """

class PIDFileParseError(ValueError, PIDFileError):
    """ Raised when parsing contents of PID file fails. """


class PIDLockFile(LinkFileLock, object):
    """ Lockfile implemented as a Unix PID file.

        The PID file is named by the attribute `path`. When locked,
        the file will be created with a single line of text,
        containing the process ID (PID) of the process that acquired
        the lock.

        The lock is acquired and maintained as per `LinkFileLock`.

        """

    def read_pid(self):
        """ Get the PID from the lock file.
            """
        result = read_pid_from_pidfile(self.path)
        return result

    def acquire(self, *args, **kwargs):
        """ Acquire the lock.

            Locks the PID file then creates the PID file for this
            lock. The `timeout` parameter is used as for the
            `LinkFileLock` class.

            """
        super(PIDLockFile, self).acquire(*args, **kwargs)
        try:
            write_pid_to_pidfile(self.path)
        except OSError, exc:
            error = LockFailed("%(exc)s" % vars())
            raise error

    def release(self):
        """ Release the lock.

            Removes the PID file then releases the lock, or raises an
            error if the current process does not hold the lock.

            """
        if self.i_am_locking():
            remove_existing_pidfile(self.path)
        super(PIDLockFile, self).release()

    def break_lock(self):
        """ Break an existing lock.

            If the lock is held, breaks the lock and removes the PID
            file.

            """
        super(PIDLockFile, self).break_lock()
        remove_existing_pidfile(self.path)


class TimeoutPIDLockFile(PIDLockFile):
    """ Lockfile with default timeout, implemented as a Unix PID file.

        This uses the ``PIDLockFile`` implementation, with the
        following changes:

        * The `acquire_timeout` parameter to the initialiser will be
          used as the default `timeout` parameter for the `acquire`
          method.

        """

    def __init__(self, path, acquire_timeout=None, *args, **kwargs):
        """ Set up the parameters of a DaemonRunnerLock. """
        self.acquire_timeout = acquire_timeout
        super(TimeoutPIDLockFile, self).__init__(path, *args, **kwargs)

    def acquire(self, timeout=None, *args, **kwargs):
        """ Acquire the lock. """
        if timeout is None:
            timeout = self.acquire_timeout
        super(TimeoutPIDLockFile, self).acquire(timeout, *args, **kwargs)


def read_pid_from_pidfile(pidfile_path):
    """ Read the PID recorded in the named PID file.

        Read and return the numeric PID recorded as text in the named
        PID file. If the PID file does not exist, return ``None``. If
        the content is not a valid PID, raise ``PIDFileParseError``.

        """
    pid = None
    pidfile = None
    try:
        pidfile = open(pidfile_path, 'r')
    except IOError, exc:
        if exc.errno == errno.ENOENT:
            pass
        else:
            raise

    if pidfile:
        # According to the FHS 2.3 section on PID files in ‘/var/run’:
        #
        #   The file must consist of the process identifier in
        #   ASCII-encoded decimal, followed by a newline character. …
        #
        #   Programs that read PID files should be somewhat flexible
        #   in what they accept; i.e., they should ignore extra
        #   whitespace, leading zeroes, absence of the trailing
        #   newline, or additional lines in the PID file.

        line = pidfile.readline().strip()
        try:
            pid = int(line)
        except ValueError:
            raise PIDFileParseError(
                "PID file %(pidfile_path)r contents invalid" % vars())
        pidfile.close()

    return pid


def write_pid_to_pidfile(pidfile_path):
    """ Write the PID in the named PID file.

        Get the numeric process ID (“PID”) of the current process
        and write it to the named file as a line of text.

        """
    open_flags = (os.O_CREAT | os.O_EXCL | os.O_WRONLY)
    open_mode = (
        ((os.R_OK | os.W_OK) << 6) |
        ((os.R_OK) << 3) |
        ((os.R_OK)))
    pidfile_fd = os.open(pidfile_path, open_flags, open_mode)
    pidfile = os.fdopen(pidfile_fd, 'w')

    # According to the FHS 2.3 section on PID files in ‘/var/run’:
    #
    #   The file must consist of the process identifier in
    #   ASCII-encoded decimal, followed by a newline character. For
    #   example, if crond was process number 25, /var/run/crond.pid
    #   would contain three characters: two, five, and newline.

    pid = os.getpid()
    line = "%(pid)d\n" % vars()
    pidfile.write(line)
    pidfile.close()


def remove_existing_pidfile(pidfile_path):
    """ Remove the named PID file if it exists.

        Remove the named PID file. Ignore the condition if the file
        does not exist, since that only means we are already in the
        desired state.

        """
    try:
        os.remove(pidfile_path)
    except OSError, exc:
        if exc.errno == errno.ENOENT:
            pass
        else:
            raise
