root / pykota / trunk / pykota / accounters / external.py @ 1200

Revision 1200, 6.7 kB (checked in by jalet, 21 years ago)

More complete job history.

  • 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 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.9  2003/11/21 14:28:45  jalet
25# More complete job history.
26#
27# Revision 1.8  2003/11/12 23:29:24  jalet
28# More work on new backend. This commit may be unstable.
29#
30# Revision 1.7  2003/10/07 09:07:28  jalet
31# Character encoding added to please latest version of Python
32#
33# Revision 1.6  2003/09/04 07:57:18  jalet
34# Problem with Python 2.3 fixed : a bug of me.
35#
36# Revision 1.5  2003/07/07 11:49:24  jalet
37# Lots of small fixes with the help of PyChecker
38#
39# Revision 1.4  2003/06/25 14:10:01  jalet
40# Hey, it may work (edpykota --reset excepted) !
41#
42# Revision 1.3  2003/05/27 23:00:21  jalet
43# Big rewrite of external accounting methods.
44# Should work well now.
45#
46# Revision 1.2  2003/05/13 13:54:20  jalet
47# Better handling of broken pipes
48#
49# Revision 1.1  2003/05/07 19:47:06  jalet
50# v1.07 Release of the Shame is out !
51#
52#
53#
54
55import sys
56import os
57import popen2
58import tempfile
59from pykota.accounter import AccounterBase, PyKotaAccounterError
60
61class Accounter(AccounterBase) :
62    def beginJob(self, printer, user) :   
63        """Saves the computed job size."""
64        # computes job's size
65        self.JobSize = self.computeJobSize()
66       
67        # get last job information for this printer
68        if not printer.LastJob.Exists :
69            # The printer hasn't been used yet, from PyKota's point of view
70            self.LastPageCounter = 0
71        else :   
72            # get last job size and page counter from Quota Storage
73            # Last lifetime page counter before actual job is
74            # last page counter + last job size
75            self.LastPageCounter = int(printer.LastJob.PrinterPageCounter or 0) + int(printer.LastJob.JobSize or 0)
76       
77    def endJob(self, printer, user) :   
78        """Do nothing."""
79        pass
80       
81    def getJobSize(self) :   
82        """Returns the actual job size."""
83        try :
84            return self.JobSize
85        except AttributeError :   
86            return 0
87       
88    def doAccounting(self, printer, user) :
89        """Deletgates the computation of the job size to an external command.
90       
91           The command must print the job size on its standard output and exit successfully.
92        """
93        self.beginJob(printer, user)
94       
95        # get the job size, which is real job size * number of copies.
96        jobsize = self.getJobSize() * self.filter.copies
97           
98        # Is the current user allowed to print at all ?
99        userpquota = self.filter.storage.getUserPQuota(user, printer)
100        action = self.filter.warnUserPQuota(userpquota)
101       
102        # update the quota for the current user on this printer, if allowed to print
103        if action == "DENY" :
104            jobsize = 0
105        else :   
106            userpquota.increasePagesUsage(jobsize)
107       
108        # adds the current job to history   
109        printer.addJobToHistory(self.filter.jobid, user, self.getLastPageCounter(), action, jobsize, self.filter.preserveinputfile, self.filter.title, self.filter.copies, self.filter.options)
110       
111        self.endJob(printer, user)
112           
113        return action
114       
115    def computeJobSize(self) :   
116        """Feeds an external command with our datas to let it compute the job size, and return its value."""
117        temporary = None   
118        if self.filter.inputfile is None :   
119            infile = sys.stdin
120            # we will have to duplicate our standard input
121            temporary = tempfile.TemporaryFile()
122        else :   
123            infile = open(self.filter.inputfile, "rb")
124           
125        # launches external accounter
126        # TODO : USE tempfile.mkstemp() instead ! Needs some work !
127        infilename = tempfile.mktemp()
128        outfilename = tempfile.mktemp()
129        errfilename = tempfile.mktemp()
130       
131        try :
132            # feed it with our data
133            fakeinput = open(infilename, "wb")
134            data = infile.read(256*1024)   
135            while data :
136                fakeinput.write(data)
137                if temporary is not None :
138                    temporary.write(data)
139                data = infile.read(256*1024)
140            fakeinput.close()
141       
142            # launches child process
143            command = "%s <%s >%s 2>%s" % (self.arguments, infilename, outfilename, errfilename)
144            retcode = os.system(command)
145           
146            # check exit status
147            if (os.WIFEXITED(retcode) and not os.WEXITSTATUS(retcode)) or os.stat(errfilename) :
148                # tries to extract the job size from the external accounter's
149                # standard output
150                childoutput = open(outfilename, "r")
151                try :
152                    pagecount = int(childoutput.readline().strip())
153                except (AttributeError, ValueError) :
154                    self.filter.logger.log_message(_("Unable to compute job size with external accounter %s") % self.arguments)
155                    pagecount = 0
156                childoutput.close()   
157            else :
158                self.filter.logger.log_message(_("Unable to compute job size with external accounter %s") % self.arguments)
159                pagecount = 0
160            os.remove(infilename)
161            os.remove(outfilename)
162            os.remove(errfilename)
163        except IOError, msg :   
164            # TODO : temporary files may remain on the filesystem...
165            msg = "%s : %s" % (self.arguments, msg) 
166            self.filter.logger.log_message(_("Unable to compute job size with external accounter %s") % msg)
167            pagecount = 0
168           
169        if temporary is not None :   
170            # this is a copy of our previous standard input
171            # flush, then rewind
172            temporary.flush()
173            temporary.seek(0, 0)
174            # our temporary file will be used later if the
175            # job is allowed.
176            self.filter.inputfile = temporary
177        else :
178            infile.close()
179           
180        return pagecount   
181           
Note: See TracBrowser for help on using the browser.