Changeset 3175
- Timestamp:
- 05/28/07 18:47:32 (18 years ago)
- Location:
- pykota/trunk/pykota
- Files:
-
- 2 modified
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/pykota/accounters/pjl.py
r3163 r3175 26 26 import os 27 27 import socket 28 import errno 28 29 import time 29 import signal 30 31 # NB : in fact these variables don't do much, since the time 32 # is in fact wasted in the sock.recv() blocking call, with the timeout 33 ITERATIONDELAY = 1 # 1 Second 34 STABILIZATIONDELAY = 3 # We must read three times the same value to consider it to be stable 35 NOPRINTINGMAXDELAY = 60 # The printer must begin to print within 60 seconds byb default. 36 37 # Here's the real thing : 38 TIMEOUT = 5 30 import threading 31 import Queue 32 33 from pykota import constants 34 35 FORMFEEDCHAR = 0x0c # Form Feed character, ends PJL answers. 39 36 40 37 # Old method : pjlMessage = "\033%-12345X@PJL USTATUSOFF\r\n@PJL INFO STATUS\r\n@PJL INFO PAGECOUNT\r\n\033%-12345X" … … 67 64 self.port = 9100 68 65 self.printerInternalPageCounter = self.printerStatus = None 69 self.timedout = 0 70 71 def alarmHandler(self, signum, frame) : 72 """Query has timedout, handle this.""" 73 self.timedout = 1 74 raise IOError, "Waiting for PJL answer timed out. Please try again later." 75 76 def retrievePJLValues(self) : 77 """Retrieves a printer's internal page counter and status via PJL.""" 66 self.closed = False 67 self.sock = None 68 self.queue = None 69 self.readthread = None 70 self.quitEvent = threading.Event() 71 72 def __del__(self) : 73 """Ensures the network connection is closed at object deletion time.""" 74 self.close() 75 76 def open(self) : 77 """Opens the network connection.""" 78 78 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 79 79 try : … … 81 81 except socket.error, msg : 82 82 self.parent.filter.printInfo(_("Problem during connection to %s:%s : %s") % (self.printerHostname, self.port, str(msg)), "warn") 83 return False 83 84 else : 84 self.parent.filter.logdebug("Connected to printer %s" % self.printerHostname) 85 sock.setblocking(False) 86 self.sock = sock 87 self.closed = False 88 self.quitEvent.clear() 89 self.queue = Queue.Queue(0) 90 self.readthread = threading.Thread(target=self.readloop) 91 self.readthread.start() 92 self.parent.filter.logdebug("Connected to printer %s:%s" % (self.printerHostname, self.port)) 93 return True 94 95 def close(self) : 96 """Closes the network connection.""" 97 if not self.closed : 98 self.quitEvent.set() 99 if self.readthread is not None : 100 self.readthread.join() 101 self.readthread = None 102 if self.sock is not None : 103 self.sock.close() 104 self.sock = None 105 self.parent.filter.logdebug("Connection to %s:%s is now closed." % (self.printerHostname, self.port)) 106 self.queue = None 107 self.closed = True 108 109 def readloop(self) : 110 """Reading loop thread.""" 111 self.parent.filter.logdebug("Reading thread started.") 112 buffer = [] 113 while not self.quitEvent.isSet() : 85 114 try : 86 sock.send(pjlMessage) 87 except socket.error, msg : 88 self.parent.filter.printInfo(_("Problem while sending PJL query to %s:%s : %s") % (self.printerHostname, self.port, str(msg)), "warn") 115 answer = self.sock.recv(4096) 116 except socket.error, (err, msg) : 117 time.sleep(0.1) # We will try again later in all cases 118 if err != errno.EAGAIN : 119 self.parent.filter.printInfo(_("Problem while receiving PJL answer from %s:%s : %s") % (self.printerHostname, self.port, str(msg)), "warn") 89 120 else : 90 self.parent.filter.logdebug("Query sent to %s : %s" % (self.printerHostname, repr(pjlMessage))) 91 actualpagecount = self.printerStatus = None 92 self.timedout = 0 93 while (self.timedout == 0) or (actualpagecount is None) or (self.printerStatus is None) : 94 signal.signal(signal.SIGALRM, self.alarmHandler) 95 signal.alarm(TIMEOUT) 96 try : 97 answer = sock.recv(1024) 98 except IOError, msg : 99 self.parent.filter.logdebug("I/O Error [%s] : alarm handler probably called" % msg) 100 break # our alarm handler was launched, probably 101 except socket.error, msg : 102 self.parent.filter.printInfo(_("Problem while receiving PJL answer from %s:%s : %s") % (self.printerHostname, self.port, str(msg)), "warn") 103 else : 104 readnext = 0 105 self.parent.filter.logdebug("PJL answer : %s" % repr(answer)) 106 for line in [l.strip() for l in answer.split()] : 107 if line.startswith("CODE=") : 108 self.printerStatus = line.split("=")[1] 109 self.parent.filter.logdebug("Found status : %s" % self.printerStatus) 110 elif line.startswith("PAGECOUNT=") : 111 try : 112 actualpagecount = int(line.split('=')[1].strip()) 113 except ValueError : 114 self.parent.filter.logdebug("Received incorrect datas : [%s]" % line.strip()) 115 else : 116 self.parent.filter.logdebug("Found pages counter : %s" % actualpagecount) 117 elif line.startswith("PAGECOUNT") : 118 readnext = 1 # page counter is on next line 119 elif readnext : 120 try : 121 actualpagecount = int(line.strip()) 122 except ValueError : 123 self.parent.filter.logdebug("Received incorrect datas : [%s]" % line.strip()) 124 else : 125 self.parent.filter.logdebug("Found pages counter : %s" % actualpagecount) 126 readnext = 0 127 signal.alarm(0) 128 self.printerInternalPageCounter = max(actualpagecount, self.printerInternalPageCounter) 129 sock.close() 130 self.parent.filter.logdebug("Connection to %s is now closed." % self.printerHostname) 121 buffer.append(answer) 122 if answer.endswith(constants.FORMFEEDCHAR) : 123 self.queue.put("".join(buffer)) 124 buffer = [] 125 if buffer : 126 self.queue.put("".join(buffer)) 127 self.parent.filter.logdebug("Reading thread ended.") 128 129 def retrievePJLValues(self) : 130 """Retrieves a printer's internal page counter and status via PJL.""" 131 try : 132 self.sock.send(pjlMessage) 133 except socket.error, msg : 134 self.parent.filter.printInfo(_("Problem while sending PJL query to %s:%s : %s") % (self.printerHostname, self.port, str(msg)), "warn") 135 else : 136 self.parent.filter.logdebug("Query sent to %s : %s" % (self.printerHostname, repr(pjlMessage))) 137 actualpagecount = self.printerStatus = None 138 while (actualpagecount is None) or (self.printerStatus is None) : 139 try : 140 answer = self.queue.get(True, 5) 141 except Queue.Empty : 142 self.parent.filter.logdebug("Timeout when reading printer's answer from %s:%s" % (self.printerHostname, self.port)) 143 else : 144 readnext = False 145 self.parent.filter.logdebug("PJL answer : %s" % repr(answer)) 146 for line in [l.strip() for l in answer.split()] : 147 if line.startswith("CODE=") : 148 self.printerStatus = line.split("=")[1] 149 self.parent.filter.logdebug("Found status : %s" % self.printerStatus) 150 elif line.startswith("PAGECOUNT=") : 151 try : 152 actualpagecount = int(line.split('=')[1].strip()) 153 except ValueError : 154 self.parent.filter.logdebug("Received incorrect datas : [%s]" % line.strip()) 155 else : 156 self.parent.filter.logdebug("Found pages counter : %s" % actualpagecount) 157 elif line.startswith("PAGECOUNT") : 158 readnext = True # page counter is on next line 159 elif readnext : 160 try : 161 actualpagecount = int(line.strip()) 162 except ValueError : 163 self.parent.filter.logdebug("Received incorrect datas : [%s]" % line.strip()) 164 else : 165 self.parent.filter.logdebug("Found pages counter : %s" % actualpagecount) 166 readnext = False 167 self.printerInternalPageCounter = max(actualpagecount, self.printerInternalPageCounter) 131 168 132 169 def waitPrinting(self) : … … 135 172 noprintingmaxdelay = int(self.parent.filter.config.getNoPrintingMaxDelay(self.parent.filter.PrinterName)) 136 173 except (TypeError, AttributeError) : # NB : AttributeError in testing mode because I'm lazy ! 137 noprintingmaxdelay = NOPRINTINGMAXDELAY174 noprintingmaxdelay = constants.NOPRINTINGMAXDELAY 138 175 self.parent.filter.logdebug("No max delay defined for printer %s, using %i seconds." % (self.parent.filter.PrinterName, noprintingmaxdelay)) 139 176 if not noprintingmaxdelay : … … 144 181 timebefore = time.time() 145 182 firstvalue = None 146 while 1:183 while True : 147 184 self.retrievePJLValues() 148 185 if self.printerStatus in ('10023', '10003') : … … 175 212 break 176 213 self.parent.filter.logdebug(_("Waiting for printer %s to be printing...") % self.parent.filter.PrinterName) 177 time.sleep( ITERATIONDELAY)214 time.sleep(constants.ITERATIONDELAY) 178 215 179 216 def waitIdle(self) : 180 217 """Waits for printer status being 'idle'.""" 181 218 idle_num = 0 182 while 1:219 while True : 183 220 self.retrievePJLValues() 184 221 if self.printerStatus in ('10000', '10001', '35078', '40000') : … … 189 226 return 190 227 idle_num += 1 191 if idle_num >= STABILIZATIONDELAY :228 if idle_num >= constants.STABILIZATIONDELAY : 192 229 # printer status is stable, we can exit 193 230 break … … 195 232 idle_num = 0 196 233 self.parent.filter.logdebug(_("Waiting for printer %s's idle status to stabilize...") % self.parent.filter.PrinterName) 197 time.sleep( ITERATIONDELAY)234 time.sleep(constants.ITERATIONDELAY) 198 235 199 236 def retrieveInternalPageCounter(self) : 200 237 """Returns the page counter from the printer via internal PJL handling.""" 201 try : 202 if (os.environ.get("PYKOTASTATUS") != "CANCELLED") and \ 203 (os.environ.get("PYKOTAACTION") == "ALLOW") and \ 204 (os.environ.get("PYKOTAPHASE") == "AFTER") and \ 205 self.parent.filter.JobSizeBytes : 206 self.waitPrinting() 207 self.waitIdle() 208 except : 209 self.parent.filter.printInfo(_("PJL querying stage interrupted. Using latest value seen for internal page counter (%s) on printer %s.") % (self.printerInternalPageCounter, self.parent.filter.PrinterName), "warn") 210 raise 211 return self.printerInternalPageCounter 238 while not self.open() : 239 self.parent.filter.logdebug("Will retry in 1 second.") 240 time.sleep(1) 241 try : 242 try : 243 if (os.environ.get("PYKOTASTATUS") != "CANCELLED") and \ 244 (os.environ.get("PYKOTAACTION") == "ALLOW") and \ 245 (os.environ.get("PYKOTAPHASE") == "AFTER") and \ 246 self.parent.filter.JobSizeBytes : 247 self.waitPrinting() 248 self.waitIdle() 249 except : 250 self.parent.filter.printInfo(_("PJL querying stage interrupted. Using latest value seen for internal page counter (%s) on printer %s.") % (self.printerInternalPageCounter, self.parent.filter.PrinterName), "warn") 251 raise 252 else : 253 return self.printerInternalPageCounter 254 finally : 255 self.close() 212 256 213 257 def main(hostname) : -
pykota/trunk/pykota/accounters/snmp.py
r3163 r3175 29 29 """ 30 30 31 ITERATIONDELAY = 4 # time to sleep between two loops32 STABILIZATIONDELAY = 5 # number of consecutive times the idle status must be seen before we consider it to be stable33 NOPRINTINGMAXDELAY = 60 # The printer must begin to print within 60 seconds by default.34 31 35 32 import sys … … 52 49 else : 53 50 hasV4 = True 51 52 from pykota import constants 54 53 55 54 # … … 158 157 noprintingmaxdelay = int(self.parent.filter.config.getNoPrintingMaxDelay(self.parent.filter.PrinterName)) 159 158 except (TypeError, AttributeError) : # NB : AttributeError in testing mode because I'm lazy ! 160 noprintingmaxdelay = NOPRINTINGMAXDELAY159 noprintingmaxdelay = constants.NOPRINTINGMAXDELAY 161 160 self.parent.filter.logdebug("No max delay defined for printer %s, using %i seconds." % (self.parent.filter.PrinterName, noprintingmaxdelay)) 162 161 if not noprintingmaxdelay : … … 204 203 break 205 204 self.parent.filter.logdebug(_("Waiting for printer %s to be printing...") % self.parent.filter.PrinterName) 206 time.sleep( ITERATIONDELAY)205 time.sleep(constants.ITERATIONDELAY) 207 206 208 207 def waitIdle(self) : … … 226 225 return 227 226 idle_num += 1 228 if idle_num >= STABILIZATIONDELAY :227 if idle_num >= constants.STABILIZATIONDELAY : 229 228 # printer status is stable, we can exit 230 229 break … … 232 231 idle_num = 0 233 232 self.parent.filter.logdebug(_("Waiting for printer %s's idle status to stabilize...") % self.parent.filter.PrinterName) 234 time.sleep( ITERATIONDELAY)233 time.sleep(constants.ITERATIONDELAY) 235 234 236 235 def retrieveInternalPageCounter(self) : -
pykota/trunk/pykota/constants.py
r3133 r3175 2 2 # -*- coding: ISO-8859-15 -*- 3 3 # 4 # PyKota : Print Quotas for CUPS and LPRng4 # PyKota : Print Quotas for CUPS 5 5 # 6 6 # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet <alet@librelogiciel.com> … … 21 21 # $Id$ 22 22 # 23 24 """This module contains the definitions of constants used by PyKota.""" 25 26 ITERATIONDELAY = 4 # time to sleep between two loops 27 STABILIZATIONDELAY = 5 # number of consecutive times the idle status must be seen before we consider it to be stable 28 NOPRINTINGMAXDELAY = 60 # The printer must begin to print within 60 seconds by default.