summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Server/FileMonitor/Gamin.py
blob: 60f80c9c3e3810ef9b40182452a138adee0a6b47 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
""" Gamin driver for file alteration events """

import os
import stat
import logging
from gamin import WatchMonitor, GAMCreated, GAMExists, GAMEndExist, \
    GAMChanged, GAMDeleted
from Bcfg2.Server.FileMonitor import Event, FileMonitor

logger = logging.getLogger(__name__)

class GaminEvent(Event):
    """
    This class provides an event analogous to
    python-fam events based on gamin sources.
    """
    action_map = {GAMCreated: 'created', GAMExists: 'exists',
                  GAMChanged: 'changed', GAMDeleted: 'deleted',
                  GAMEndExist: 'endExist'}

    def __init__(self, request_id, filename, code):
        Event.__init__(self, request_id, filename, code)
        if code in self.action_map:
            self.action = self.action_map[code]

class Gamin(FileMonitor):
    __priority__ = 10

    def __init__(self, ignore=None, debug=False):
        FileMonitor.__init__(self, ignore=ignore, debug=debug)
        self.mon = WatchMonitor()
        self.counter = 0

    def fileno(self):
        return self.mon.get_fd()

    def queue(self, path, action, request_id):
        """queue up the event for later handling"""
        self.events.append(GaminEvent(request_id, path, action))

    def AddMonitor(self, path, obj):
        """Add a monitor to path, installing a callback to obj."""
        handle = self.counter
        self.counter += 1
        mode = os.stat(path)[stat.ST_MODE]

        # Flush queued gamin events
        while self.mon.event_pending():
            self.mon.handle_one_event()

        if stat.S_ISDIR(mode):
            self.mon.watch_directory(path, self.queue, handle)
        else:
            self.mon.watch_file(path, self.queue, handle)
        self.handles[handle] = obj
        return handle

    def pending(self):
        return FileMonitor.pending(self) or self.mon.event_pending()

    def get_event(self):
        if self.mon.event_pending():
            self.mon.handle_one_event()
        return FileMonitor.get_event(self)