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

Revision 1494, 6.0 kB (checked in by jalet, 20 years ago)

Revert to old polling loop. Will need optimisations

  • 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.3  2004/05/24 14:36:40  jalet
25# Revert to old polling loop. Will need optimisations
26#
27# Revision 1.2  2004/05/18 14:49:22  jalet
28# Big code changes to completely remove the need for "requester" directives,
29# jsut use "hardware(... your previous requester directive's content ...)"
30#
31# Revision 1.1  2004/05/13 13:59:30  jalet
32# Code simplifications
33#
34#
35#
36
37import sys
38import os
39import popen2
40from pykota.accounter import AccounterBase, PyKotaAccounterError
41
42class Accounter(AccounterBase) :
43    def __init__(self, kotabackend, arguments) :
44        """Initializes querying accounter."""
45        AccounterBase.__init__(self, kotabackend, arguments)
46        self.isDelayed = 1 # With the pykota filter, accounting is delayed by one job
47       
48    def getPrinterInternalPageCounter(self) :   
49        """Returns the printer's internal page counter."""
50        self.filter.logdebug("Reading printer's internal page counter...")
51        try :
52            counter = self.askPrinterPageCounter(self.filter.printerhostname)
53        except PyKotaAccounterError, msg :
54            # can't get actual page counter, assume printer is off or warming up
55            # log the message anyway.
56            self.filter.logger.log_message("%s" % msg, "warn")
57            counter = None
58        self.filter.logdebug("Printer's internal page counter value is : %s" % str(counter))
59        return counter   
60       
61    def beginJob(self, userpquota) :   
62        """Saves printer internal page counter at start of job."""
63        # save page counter before job
64        self.LastPageCounter = self.counterbefore = self.getPrinterInternalPageCounter()
65       
66    def endJob(self, userpquota) :   
67        """Saves printer internal page counter at end of job."""
68        # save page counter after job
69        self.LastPageCounter = self.counterafter = self.getPrinterInternalPageCounter()
70       
71    def getJobSize(self) :   
72        """Returns the actual job size."""
73        try :
74            jobsize = (self.counterafter - self.counterbefore)   
75            if jobsize < 0 :
76                # Try to take care of HP printers
77                # Their internal page counter is saved to NVRAM
78                # only every 10 pages. If the printer was switched
79                # off then back on during the job, and that the
80                # counters difference is negative, we know
81                # the formula (we can't know if more than eleven
82                # pages were printed though) :
83                if jobsize > -10 :
84                    jobsize += 10
85                else :   
86                    # here we may have got a printer being replaced
87                    # DURING the job. This is HIGHLY improbable !
88                    jobsize = 0
89        except :   
90            # takes care of the case where one counter (or both) was never set.
91            jobsize = 0
92        return jobsize
93       
94    def doAccounting(self, userpquota) :
95        """Does print accounting and returns if the job status is ALLOW or DENY."""
96        # Get the page counter directly from the printer itself
97        counterbeforejob = self.getPrinterInternalPageCounter() or 0
98       
99        # Is the current user allowed to print at all ?
100        action = self.filter.warnUserPQuota(userpquota)
101       
102        # adds the current job to history   
103        userpquota.Printer.addJobToHistory(self.filter.jobid, userpquota.User, counterbeforejob, action, filename=self.filter.preserveinputfile, title=self.filter.title, copies=self.filter.copies, options=self.filter.options)
104        return action
105       
106    def askPrinterPageCounter(self, printer) :
107        """Returns the page counter from the printer via an external command.
108       
109           The external command must report the life time page number of the printer on stdout.
110        """
111        commandline = self.arguments.strip() % locals()
112        if printer is None :
113            raise PyKotaAccounterError, _("Unknown printer address in HARDWARE(%s) for printer %s") % (commandline, self.filter.printername)
114        error = 1
115        pagecounter = None
116        child = popen2.Popen4(commandline)   
117        try :
118            pagecounter = int(child.fromchild.readline().strip())
119        except ValueError :   
120            pass
121        except IOError :   
122            # we were interrupted by a signal, certainely a SIGTERM
123            # caused by the user cancelling the current job
124            try :
125                os.kill(child.pid, signal.SIGTERM)
126            except :   
127                pass # already killed ?
128            self.filter.logger.log_message(_("SIGTERM was sent to hardware accounter %s (pid: %s)") % (commandline, child.pid), "info")
129        else :   
130            error = 0
131        child.fromchild.close()   
132        child.tochild.close()
133        try :
134            status = child.wait()
135        except OSError, msg :   
136            self.filter.logdebug("Error while waiting for hardware accounter pid %s : %s" % (child.pid, msg))
137            error = 1
138        if (not error) and os.WIFEXITED(status) and (not os.WEXITSTATUS(status)) :
139            return pagecounter
140        else :   
141            raise PyKotaAccounterError, _("Unable to query printer %s via HARDWARE(%s)") % (printer, commandline) 
142           
Note: See TracBrowser for help on using the browser.