Changeset 2074

Show
Ignore:
Timestamp:
02/19/05 19:16:06 (20 years ago)
Author:
jalet
Message:

Optimize print job parsing by avoiding to pass the job's datas through
PyKota's internal parser if the special construct "software()" is used
with no argument in the 'accounter' directive.

Location:
pykota/trunk
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/conf/pykota.conf.sample

    r2066 r2074  
    364364#                 this way : 
    365365# 
     366#                   accounter: software() 
     367# 
     368#                 which uses PyKota's internal parser to compute 
     369#                 the size of the job. 
     370# 
     371#                 You could obtain exactly the same result with : 
     372# 
    366373#                   accounter: software(/usr/bin/pkpgcounter) 
     374# 
     375#                 But in this case the job would be passed through 
     376#                 PyKota's internal parser a second time. 
    367377# 
    368378#                 pkpgcounter is a command line tool which is 
     
    372382#                 in the future, as time permits. 
    373383# 
    374 #                 while pkpgcounter is the recommended value 
    375 #                 you can use whatever command you want provided 
    376 #                 that your command accepts the job's data on its 
    377 #                 standard input and prints the job's size in pages 
    378 #                 as a single integer on its standard output. 
     384#                 while pkpgcounter is the recommended value if you want 
     385#                 to use an external command here, you can use whatever  
     386#                 command you want provided your command accepts the job's 
     387#                 data on its standard input and prints the job's size in  
     388#                 pages as a single integer on its standard output. 
    379389#  
    380390# This value can be set either globally or on a per printer basis 
     
    384394# accounter: hardware(snmp) 
    385395# accounter: hardware(pjl) 
    386 accounter: software(/usr/bin/pkpgcounter) 
     396# accounter: software(/usr/bin/pkpgcounter) 
     397# 
     398# The following is only allowed since PyKota 1.21  
     399accounter: software() 
    387400 
    388401# What should we do if the accounter's subprocess doesn't return 
  • pykota/trunk/NEWS

    r2073 r2074  
    2424    - 1.21alpha27 : 
    2525     
     26        - Allows software() (no arguments) to the software accounting 
     27          directive. This saves a lot of CPU since the job is not 
     28          parsed again : the precomputed size is used directly in this 
     29          case. 
     30           
    2631        - epykota's --prototype option now works fine with accounts 
    2732          limited by balance. 
  • pykota/trunk/pykota/accounters/software.py

    r1743 r2074  
    2222# 
    2323# $Log$ 
     24# Revision 1.12  2005/02/19 18:16:06  jalet 
     25# Optimize print job parsing by avoiding to pass the job's datas through 
     26# PyKota's internal parser if the special construct "software()" is used 
     27# with no argument in the 'accounter' directive. 
     28# 
    2429# Revision 1.11  2004/09/24 21:19:48  jalet 
    2530# Did a pass of PyChecker 
     
    7580        """Feeds an external command with our datas to let it compute the job size, and return its value.""" 
    7681        self.filter.printInfo(_("Launching SOFTWARE(%s)...") % self.arguments) 
    77         MEGABYTE = 1024*1024 
    78         self.filter.jobdatastream.seek(0) 
    79         child = popen2.Popen4(self.arguments) 
    80         try : 
    81             data = self.filter.jobdatastream.read(MEGABYTE)     
    82             while data : 
    83                 child.tochild.write(data) 
    84                 data = self.filter.jobdatastream.read(MEGABYTE) 
    85             child.tochild.flush() 
    86             child.tochild.close()     
    87         except (IOError, OSError), msg :     
    88             msg = "%s : %s" % (self.arguments, msg)  
    89             self.filter.printInfo(_("Unable to compute job size with accounter %s") % msg) 
    90          
    91         pagecounter = None 
    92         try : 
    93             answer = child.fromchild.read() 
    94         except (IOError, OSError), msg :     
    95             msg = "%s : %s" % (self.arguments, msg)  
    96             self.filter.printInfo(_("Unable to compute job size with accounter %s") % msg) 
    97         else :     
    98             lines = [l.strip() for l in answer.split("\n")] 
    99             for i in range(len(lines)) :  
    100                 try : 
    101                     pagecounter = int(lines[i]) 
    102                 except (AttributeError, ValueError) : 
    103                     self.filter.printInfo(_("Line [%s] skipped in accounter's output. Trying again...") % lines[i]) 
    104                 else :     
    105                     break 
    106         child.fromchild.close() 
    107          
    108         try : 
    109             status = child.wait() 
    110         except OSError, msg :     
    111             self.filter.printInfo(_("Problem while waiting for software accounter pid %s to exit : %s") % (child.pid, msg)) 
    112         else :     
    113             if os.WIFEXITED(status) : 
    114                 status = os.WEXITSTATUS(status) 
    115             self.filter.printInfo(_("Software accounter %s exit code is %s") % (self.arguments, str(status))) 
     82        if not self.arguments : 
     83            pagecounter = self.filter.softwareJobSize   # Optimize : already computed ! 
     84            self.filter.logdebug("Internal software accounter said job is %s pages long." % repr(pagecounter)) 
     85        else : 
     86            MEGABYTE = 1024*1024 
     87            self.filter.jobdatastream.seek(0) 
     88            child = popen2.Popen4(self.arguments) 
     89            try : 
     90                data = self.filter.jobdatastream.read(MEGABYTE)     
     91                while data : 
     92                    child.tochild.write(data) 
     93                    data = self.filter.jobdatastream.read(MEGABYTE) 
     94                child.tochild.flush() 
     95                child.tochild.close()     
     96            except (IOError, OSError), msg :     
     97                msg = "%s : %s" % (self.arguments, msg)  
     98                self.filter.printInfo(_("Unable to compute job size with accounter %s") % msg) 
    11699             
    117         if pagecounter is None :     
    118             message = _("Unable to compute job size with accounter %s") % self.arguments 
    119             if self.onerror == "CONTINUE" : 
    120                 self.filter.printInfo(message, "error") 
    121             else : 
    122                 raise PyKotaAccounterError, message 
     100            pagecounter = None 
     101            try : 
     102                answer = child.fromchild.read() 
     103            except (IOError, OSError), msg :     
     104                msg = "%s : %s" % (self.arguments, msg)  
     105                self.filter.printInfo(_("Unable to compute job size with accounter %s") % msg) 
     106            else :     
     107                lines = [l.strip() for l in answer.split("\n")] 
     108                for i in range(len(lines)) :  
     109                    try : 
     110                        pagecounter = int(lines[i]) 
     111                    except (AttributeError, ValueError) : 
     112                        self.filter.printInfo(_("Line [%s] skipped in accounter's output. Trying again...") % lines[i]) 
     113                    else :     
     114                        break 
     115            child.fromchild.close() 
    123116             
    124         self.filter.logdebug("Software accounter %s said job is %s pages long." % (self.arguments, repr(pagecounter))) 
     117            try : 
     118                status = child.wait() 
     119            except OSError, msg :     
     120                self.filter.printInfo(_("Problem while waiting for software accounter pid %s to exit : %s") % (child.pid, msg)) 
     121            else :     
     122                if os.WIFEXITED(status) : 
     123                    status = os.WEXITSTATUS(status) 
     124                self.filter.printInfo(_("Software accounter %s exit code is %s") % (self.arguments, str(status))) 
     125                 
     126            if pagecounter is None :     
     127                message = _("Unable to compute job size with accounter %s") % self.arguments 
     128                if self.onerror == "CONTINUE" : 
     129                    self.filter.printInfo(message, "error") 
     130                else : 
     131                    raise PyKotaAccounterError, message 
     132            self.filter.logdebug("Software accounter %s said job is %s pages long." % (self.arguments, repr(pagecounter))) 
     133             
    125134        return pagecounter or 0 
  • pykota/trunk/pykota/config.py

    r2066 r2074  
    2222# 
    2323# $Log$ 
     24# Revision 1.62  2005/02/19 18:16:06  jalet 
     25# Optimize print job parsing by avoiding to pass the job's datas through 
     26# PyKota's internal parser if the special construct "software()" is used 
     27# with no argument in the 'accounter' directive. 
     28# 
    2429# Revision 1.61  2005/02/16 00:29:33  jalet 
    2530# Fixed the maxdenybanners directive. 
     
    393398                raise PyKotaConfigError, _("Invalid accounter %s for printer %s") % (fullaccounter, printername) 
    394399            if args.endswith(')') : 
    395                 args = args[:-1] 
    396             if not args : 
     400                args = args[:-1].strip() 
     401            if (accounter == "hardware") and not args : 
    397402                raise PyKotaConfigError, _("Invalid accounter %s for printer %s") % (fullaccounter, printername) 
    398403            return (accounter.lower(), args)