Changeset 1180

Show
Ignore:
Timestamp:
11/13/03 00:29:24 (20 years ago)
Author:
jalet
Message:

More work on new backend. This commit may be unstable.

Location:
pykota/trunk
Files:
6 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/cupspykota

    r1178 r1180  
    2424# 
    2525# $Log$ 
     26# Revision 1.3  2003/11/12 23:27:44  jalet 
     27# More work on new backend. This commit may be unstable. 
     28# 
    2629# Revision 1.2  2003/11/12 09:33:34  jalet 
    2730# New CUPS backend supports device enumeration 
     
    120123        # we let the job pass through, but log a warning message 
    121124        thebackend.logger.log_message(_("Printer %s not registered in the PyKota system") % thebackend.printername, "warn") 
     125        action = "ALLOW" 
    122126    else :     
    123127        for dummy in range(2) : 
     
    157161                break     
    158162                     
    159         # if user exists, do accounting 
    160163        if user.Exists : 
    161164            # Is the current user allowed to print at all ? 
     
    168171            return 0 
    169172         
    170     MAXTRIES = 12    # maximum number of tries to get the printer's internal page counter 
    171     TIMETOSLEEP = 10 # number of seconds to sleep between two tries to get the printer's internal page counter 
    172     requester = openRequester(thebackend.config, thebackend.printername) 
    173     def getPPC(requester, backend) : 
    174         for i in range(MAXTRIES) : 
    175             try : 
    176                 counterbeforejob = requester.getPrinterPageCounter(backend.printerhostname) 
    177             except PyKotaRequesterError, msg : 
    178                 # can't get actual page counter, assume printer is off or warming up 
    179                 # log the message anyway. 
    180                 backend.logger.log_message("%s" % msg, "warn") 
    181                 counterbeforejob = None 
    182             else :     
    183                 # printer answered, it is on so we can exit the loop 
    184                 break 
    185             time.sleep(TIMETOSLEEP)     
    186         return counterbeforejob     
    187          
    188173    if action not in ["ALLOW", "WARN"] :     
    189174        # if not allowed to print then die, else proceed. 
     
    193178    else : 
    194179        # pass the job untouched to the underlying layer 
    195         # but get printer page counter before and after 
    196         # print job is submitted to the hardware. 
    197          
    198         # get page counter before job 
    199         before = getPPC(requester, thebackend) 
    200          
    201         # executes backend 
    202         # TODO : use correct original backend. 
     180        # and starts accounting at the same time 
     181        thebackend.accounter.beginJob(printer, user) 
     182         
     183        # executes original backend 
     184        #mustclose = 0     
     185        #if thebackend.inputfile is not None :     
     186        #    if hasattr(thebackend.inputfile, "read") : 
     187        #        infile = thebackend.inputfile 
     188        #    else :     
     189        #        infile = open(thebackend.inputfile, "rb") 
     190        #    mustclose = 1 
     191        #else :     
     192        #    infile = sys.stdin 
     193             
    203194        realbackend = os.path.join(os.path.split(sys.argv[0])[0], thebackend.originalbackend) 
    204195        retcode = os.spawnve(os.P_WAIT, realbackend, [os.environ["DEVICE_URI"]] + sys.argv[1:], os.environ) 
    205196     
    206     # get page counter after job 
    207     after = getPPC(requester, thebackend) 
    208      
    209     # Computes the last job size as the difference between internal page 
    210     # counter in the printer and last page counter taken from the Quota 
    211     # Storage database for this particular printer 
    212     try : 
    213         jobsize = (after - before)     
    214     except :     
    215         jobsize = 0 
    216          
     197    # stops accounting.  
     198    thebackend.accounter.endJob(printer, user) 
     199         
     200    # retrieve the job size     
     201    jobsize = thebackend.accounter.getJobSize() 
     202     
    217203    # update the quota for the current user on this printer  
    218204    if printer.Exists : 
     
    223209         
    224210        # adds the current job to history     
    225         printer.addJobToHistory(thebackend.jobid, user, after, action, jobsize) 
     211        printer.addJobToHistory(thebackend.jobid, user, thebackend.accounter.getLastPageCounter(), action, jobsize) 
    226212     
    227213    return retcode 
     
    242228            if status is None : 
    243229                for d in devices : 
     230                    # each line is of the form : 'xxxx xxxx "xxxx xxx" "xxxx xxx"' 
     231                    # so we have to decompose it carefully 
    244232                    fdevice = cStringIO.StringIO("%s" % d) 
    245233                    tokenizer = shlex.shlex(fdevice) 
     
    253241                            break 
    254242                    fdevice.close() 
    255                     (devicetype, device, name, fullname) = arguments 
    256                     if name.startswith('"') and name.endswith('"') : 
    257                         name = name[1:-1] 
    258                     if fullname.startswith('"') and fullname.endswith('"') : 
    259                         fullname = fullname[1:-1] 
    260                     print '%s cupspykota:%s "PyKota+%s" "PyKota managed %s"' % (devicetype, device, name, fullname)     
     243                    try : 
     244                        (devicetype, device, name, fullname) = arguments 
     245                    except ValueError :     
     246                        pass    # ignore this 'bizarre' device 
     247                    else :     
     248                        if name.startswith('"') and name.endswith('"') : 
     249                            name = name[1:-1] 
     250                        if fullname.startswith('"') and fullname.endswith('"') : 
     251                            fullname = fullname[1:-1] 
     252                        print '%s cupspykota:%s "PyKota+%s" "PyKota managed %s"' % (devicetype, device, name, fullname)     
    261253        retcode = 0 
    262254    elif len(sys.argv) not in (6, 7) :     
  • pykota/trunk/bin/edpykota

    r1179 r1180  
    2424# 
    2525# $Log$ 
     26# Revision 1.62  2003/11/12 23:28:38  jalet 
     27# More work on new backend. This commit may be unstable. 
     28# 
    2629# Revision 1.61  2003/11/12 13:06:35  jalet 
    2730# Bug fix wrt no user/group name command line argument to edpykota 
     
    516519                                self.logger.log_message(_("Invalid user name %s") % entry.Name) 
    517520                                 
    518                 if not entrypquota.Exists : 
     521                if entry.Exists and (not entrypquota.Exists) : 
    519522                    # not found 
    520523                    if options["add"] : 
  • pykota/trunk/pykota/accounter.py

    r1144 r1180  
    2222# 
    2323# $Log$ 
     24# Revision 1.6  2003/11/12 23:28:55  jalet 
     25# More work on new backend. This commit may be unstable. 
     26# 
    2427# Revision 1.5  2003/10/07 09:07:28  jalet 
    2528# Character encoding added to please latest version of Python 
     
    5861        self.arguments = arguments 
    5962         
     63    def getLastPageCounter(self) :     
     64        """Returns last internal page counter value (possibly faked).""" 
     65        try : 
     66            return self.LastPageCounter 
     67        except :     
     68            return 0 
     69         
    6070    def filterInput(self, inputfile) : 
    6171        """Transparent filter.""" 
  • pykota/trunk/pykota/accounters/external.py

    r1144 r1180  
    2222# 
    2323# $Log$ 
     24# Revision 1.8  2003/11/12 23:29:24  jalet 
     25# More work on new backend. This commit may be unstable. 
     26# 
    2427# Revision 1.7  2003/10/07 09:07:28  jalet 
    2528# Character encoding added to please latest version of Python 
     
    5457 
    5558class Accounter(AccounterBase) : 
     59    def beginJob(self, printer, user) :     
     60        """Saves the computed job size.""" 
     61        # computes job's size 
     62        self.JobSize = self.computeJobSize() 
     63         
     64        # get last job information for this printer 
     65        if not printer.LastJob.Exists : 
     66            # The printer hasn't been used yet, from PyKota's point of view 
     67            self.LastPageCounter = 0 
     68        else :     
     69            # get last job size and page counter from Quota Storage 
     70            # Last lifetime page counter before actual job is  
     71            # last page counter + last job size 
     72            self.LastPageCounter = int(printer.LastJob.PrinterPageCounter or 0) + int(printer.LastJob.JobSize or 0) 
     73         
     74    def endJob(self, printer, user) :     
     75        """Do nothing.""" 
     76        pass 
     77         
     78    def getJobSize(self) :     
     79        """Returns the actual job size.""" 
     80        try : 
     81            return self.JobSize 
     82        except AttributeError :     
     83            return 0 
     84         
    5685    def doAccounting(self, printer, user) : 
    5786        """Deletgates the computation of the job size to an external command. 
     
    5988           The command must print the job size on its standard output and exit successfully. 
    6089        """ 
     90        self.beginJob(printer, user) 
     91         
    6192        # get the job size, which is real job size * number of copies. 
    6293        jobsize = self.getJobSize() * self.filter.copies 
    63              
    64         # get last job information for this printer 
    65         if not printer.LastJob.Exists : 
    66             # The printer hasn't been used yet, from PyKota's point of view 
    67             counterbeforejob = 0 
    68         else :     
    69             # get last job size and page counter from Quota Storage 
    70             # Last lifetime page counter before actual job is  
    71             # last page counter + last job size 
    72             counterbeforejob = int(printer.LastJob.PrinterPageCounter or 0) + int(printer.LastJob.JobSize or 0) 
    7394             
    7495        # Is the current user allowed to print at all ? 
     
    83104         
    84105        # adds the current job to history     
    85         printer.addJobToHistory(self.filter.jobid, user, counterbeforejob, action, jobsize) 
     106        printer.addJobToHistory(self.filter.jobid, user, self.getLastPageCounter(), action, jobsize) 
     107         
     108        self.endJob(printer, user) 
    86109             
    87110        return action 
    88111         
    89     def getJobSize(self) :     
     112    def computeJobSize(self) :     
    90113        """Feeds an external command with our datas to let it compute the job size, and return its value.""" 
    91114        temporary = None     
  • pykota/trunk/pykota/accounters/querying.py

    r1144 r1180  
    2222# 
    2323# $Log$ 
     24# Revision 1.7  2003/11/12 23:29:24  jalet 
     25# More work on new backend. This commit may be unstable. 
     26# 
    2427# Revision 1.6  2003/10/07 09:07:29  jalet 
    2528# Character encoding added to please latest version of Python 
     
    4447 
    4548import sys 
     49import os 
    4650import time 
    4751from pykota.accounter import AccounterBase, PyKotaAccounterError 
     
    5256 
    5357class Accounter(AccounterBase) : 
     58    def __init__(self, kotabackend, arguments) : 
     59        """Initializes querying accounter.""" 
     60        AccounterBase.__init__(self, kotabackend, arguments) 
     61        self.requester = openRequester(kotabackend.config, kotabackend.printername) 
     62         
     63    def getPrinterInternalPageCounter(self) :     
     64        """Returns the printer's internal page counter.""" 
     65        global MAXTRIES, TIMETOSLEEP 
     66        for i in range(MAXTRIES) : 
     67            try : 
     68                counter = self.requester.getPrinterPageCounter(self.filter.printerhostname) 
     69            except PyKotaRequesterError, msg : 
     70                # can't get actual page counter, assume printer is off or warming up 
     71                # log the message anyway. 
     72                self.filter.logger.log_message("%s" % msg, "warn") 
     73                counter = None 
     74            else :     
     75                # printer answered, it is on so we can exit the loop 
     76                break 
     77            time.sleep(TIMETOSLEEP)     
     78        return counter     
     79         
     80    def beginJob(self, printer, user) :     
     81        """Saves printer internal page counter at start of job.""" 
     82        # save page counter before job 
     83        self.LastPageCounter = self.counterbefore = self.getPrinterInternalPageCounter() 
     84         
     85    def endJob(self, printer, user) :     
     86        """Saves printer internal page counter at end of job.""" 
     87        # save page counter after job 
     88        self.LastPageCounter = self.counterafter = self.getPrinterInternalPageCounter() 
     89         
     90    def getJobSize(self) :     
     91        """Returns the actual job size.""" 
     92        try : 
     93            jobsize = (self.counterafter - self.counterbefore)     
     94            if jobsize < 0 : 
     95                # Try to take care of HP printers  
     96                # Their internal page counter is saved to NVRAM 
     97                # only every 10 pages. If the printer was switched 
     98                # off then back on during the job, and that the 
     99                # counters difference is negative, we know  
     100                # the formula (we can't know if more than eleven 
     101                # pages were printed though) : 
     102                if jobsize > -10 : 
     103                    jobsize += 10 
     104                else :     
     105                    # here we may have got a printer being replaced 
     106                    # DURING the job. This is HIGHLY improbable ! 
     107                    jobsize = 0 
     108        except :     
     109            # takes care of the case where one counter (or both) was never set. 
     110            jobsize = 0 
     111        return jobsize 
     112         
    54113    def doAccounting(self, printer, user) : 
    55114        """Does print accounting and returns if the job status is ALLOW or DENY.""" 
     
    57116        # Tries MAXTRIES times, sleeping two seconds each time, in case the printer is sleeping. 
    58117        # This was seen with my Apple LaserWriter 16/600 PS which doesn't answer before having warmed up. 
    59         global MAXTRIES, TIMETOSLEEP 
    60         requester = openRequester(self.filter.config, self.filter.printername) 
    61         for i in range(MAXTRIES) : 
    62             try : 
    63                 counterbeforejob = requester.getPrinterPageCounter(self.filter.printerhostname) 
    64             except PyKotaRequesterError, msg : 
    65                 # can't get actual page counter, assume printer is off or warming up 
    66                 # log the message anyway. 
    67                 self.filter.logger.log_message("%s" % msg, "warn") 
    68                 counterbeforejob = None 
    69                 printerIsOff = 1 
    70             else :     
    71                 # printer answered, it is on so we can exit the loop 
    72                 printerIsOff = 0 
    73                 break 
    74             time.sleep(TIMETOSLEEP)     
     118        counterbeforejob = self.getPrinterInternalPageCounter() 
    75119         
    76120        # get last job information for this printer 
     
    85129             
    86130        # if printer is off then we assume the correct counter value is the last one 
    87         if printerIsOff : 
     131        if counterbeforejob is None : 
    88132            counterbeforejob = lastpagecounter 
    89133             
  • pykota/trunk/pykota/accounters/stupid.py

    r1144 r1180  
    2222# 
    2323# $Log$ 
     24# Revision 1.6  2003/11/12 23:29:24  jalet 
     25# More work on new backend. This commit may be unstable. 
     26# 
    2427# Revision 1.5  2003/10/07 09:07:29  jalet 
    2528# Character encoding added to please latest version of Python 
     
    4649 
    4750class Accounter(AccounterBase) : 
     51    def beginJob(self) :     
     52        """Saves the computed job size.""" 
     53        self.JobSize = self.computeJobSize() 
     54         
     55        # get last job information for this printer 
     56        if not printer.LastJob.Exists : 
     57            # The printer hasn't been used yet, from PyKota's point of view 
     58            self.LastPageCounter = 0 
     59        else :     
     60            # get last job size and page counter from Quota Storage 
     61            # Last lifetime page counter before actual job is  
     62            # last page counter + last job size 
     63            self.LastPageCounter = int(printer.LastJob.PrinterPageCounter or 0) + int(printer.LastJob.JobSize or 0) 
     64         
     65    def endJob(self) :     
     66        """Do nothing.""" 
     67        pass 
     68         
     69    def getJobSize(self) :     
     70        """Returns the actual job size.""" 
     71        try : 
     72            return self.JobSize 
     73        except AttributeError :     
     74            return 0 
     75         
    4876    def doAccounting(self, printer, user) : 
    4977        """Does print accounting by stupidly counting the 'showpage' postscript instructions in the document. 
     
    5583         
    5684        # get the job size     
    57         jobsize = self.getJobSize() * self.filter.copies 
     85        jobsize = self.computeJobSize() * self.filter.copies 
    5886             
    5987        # get last job information for this printer 
     
    82110        return action 
    83111         
    84     def getJobSize(self) :     
     112    def computeJobSize(self) :     
    85113        """Computes the job size and return its value. 
    86114