root / pykota / trunk / pykota / accounters / hardware.py @ 1495

Revision 1495, 5.4 kB (checked in by jalet, 20 years ago)

New 'enforcement' directive added
Polling loop improvements

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1# PyKota
2# -*- coding: ISO-8859-15 -*-
3#
4# PyKota - Print Quotas for CUPS and LPRng
5#
6# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20#
21# $Id$
22#
23# $Log$
24# Revision 1.4  2004/05/24 22:45:49  jalet
25# New 'enforcement' directive added
26# Polling loop improvements
27#
28# Revision 1.3  2004/05/24 14:36:40  jalet
29# Revert to old polling loop. Will need optimisations
30#
31# Revision 1.2  2004/05/18 14:49:22  jalet
32# Big code changes to completely remove the need for "requester" directives,
33# jsut use "hardware(... your previous requester directive's content ...)"
34#
35# Revision 1.1  2004/05/13 13:59:30  jalet
36# Code simplifications
37#
38#
39#
40
41import sys
42import os
43import popen2
44from pykota.accounter import AccounterBase, PyKotaAccounterError
45
46class Accounter(AccounterBase) :
47    def __init__(self, kotabackend, arguments) :
48        """Initializes querying accounter."""
49        AccounterBase.__init__(self, kotabackend, arguments)
50       
51    def getPrinterInternalPageCounter(self) :   
52        """Returns the printer's internal page counter."""
53        self.filter.logdebug("Reading printer's internal page counter...")
54        try :
55            counter = self.askPrinterPageCounter(self.filter.printerhostname)
56        except PyKotaAccounterError, msg :
57            # can't get actual page counter, assume printer is off or warming up
58            # log the message anyway.
59            self.filter.logger.log_message("%s" % msg, "warn")
60            counter = None
61        self.filter.logdebug("Printer's internal page counter value is : %s" % str(counter))
62        return counter   
63       
64    def beginJob(self, userpquota) :   
65        """Saves printer internal page counter at start of job."""
66        # save page counter before job
67        self.LastPageCounter = self.counterbefore = self.getPrinterInternalPageCounter()
68       
69    def endJob(self, userpquota) :   
70        """Saves printer internal page counter at end of job."""
71        # save page counter after job
72        self.LastPageCounter = self.counterafter = self.getPrinterInternalPageCounter()
73       
74    def getJobSize(self) :   
75        """Returns the actual job size."""
76        try :
77            jobsize = (self.counterafter - self.counterbefore)   
78            if jobsize < 0 :
79                # Try to take care of HP printers
80                # Their internal page counter is saved to NVRAM
81                # only every 10 pages. If the printer was switched
82                # off then back on during the job, and that the
83                # counters difference is negative, we know
84                # the formula (we can't know if more than eleven
85                # pages were printed though) :
86                if jobsize > -10 :
87                    jobsize += 10
88                else :   
89                    # here we may have got a printer being replaced
90                    # DURING the job. This is HIGHLY improbable !
91                    jobsize = 0
92        except :   
93            # takes care of the case where one counter (or both) was never set.
94            jobsize = 0
95        return jobsize
96       
97    def askPrinterPageCounter(self, printer) :
98        """Returns the page counter from the printer via an external command.
99       
100           The external command must report the life time page number of the printer on stdout.
101        """
102        commandline = self.arguments.strip() % locals()
103        if printer is None :
104            raise PyKotaAccounterError, _("Unknown printer address in HARDWARE(%s) for printer %s") % (commandline, self.filter.printername)
105        error = 1
106        pagecounter = None
107        child = popen2.Popen4(commandline)   
108        try :
109            pagecounter = int(child.fromchild.readline().strip())
110        except ValueError :   
111            pass
112        except IOError :   
113            # we were interrupted by a signal, certainely a SIGTERM
114            # caused by the user cancelling the current job
115            try :
116                os.kill(child.pid, signal.SIGTERM)
117            except :   
118                pass # already killed ?
119            self.filter.logger.log_message(_("SIGTERM was sent to hardware accounter %s (pid: %s)") % (commandline, child.pid), "info")
120        else :   
121            error = 0
122        child.fromchild.close()   
123        child.tochild.close()
124        try :
125            status = child.wait()
126        except OSError, msg :   
127            self.filter.logdebug("Error while waiting for hardware accounter pid %s : %s" % (child.pid, msg))
128            error = 1
129        if (not error) and os.WIFEXITED(status) and (not os.WEXITSTATUS(status)) :
130            return pagecounter
131        else :   
132            raise PyKotaAccounterError, _("Unable to query printer %s via HARDWARE(%s)") % (printer, commandline) 
133           
Note: See TracBrowser for help on using the browser.