Index: pykota/trunk/docs/installation.sgml
===================================================================
--- pykota/trunk/docs/installation.sgml (revision 3472)
+++ pykota/trunk/docs/installation.sgml (revision 3506)
@@ -842,5 +842,5 @@
           <listitem>
             <para>
-              The <application>pysnmp</application> Python module version 3.4.2, or higher, version 4 is recommanded.
+              The <application>pysnmp</application> Python module version 4.x, or higher.
               You can download it from <ulink url="http://pysnmp.sourceforge.net">http://pysnmp.sourceforge.net</ulink>.
             </para>
Index: pykota/trunk/README
===================================================================
--- pykota/trunk/README (revision 3481)
+++ pykota/trunk/README (revision 3506)
@@ -150,6 +150,6 @@
     - The Python-SNMP module to query printers for their page counter.
       (http://pysnmp.sourceforge.net)
-      IMPORTANT : version 3.4.2 or higher, preferably v4.x is now REQUIRED.
-      Versions 2.x won't work.
+      IMPORTANT : version v4.x is now REQUIRED.
+      Versions 3.x or earlier are not supported anymore.
     - The Python-OSD module to use the graphical print quota reminder.
       (http://repose.cx/pyosd/)
Index: pykota/trunk/CREDITS
===================================================================
--- pykota/trunk/CREDITS (revision 3481)
+++ pykota/trunk/CREDITS (revision 3506)
@@ -94,4 +94,6 @@
     problem with MySQL connections to 'localhost:3306'.
   - Darin Perusich - Cognigen Corp. - Ported the LDAP schema to Sun DS
+  - Ilya Etingof and B� Sennung - Fixed performance problems in SNMP
+    queries.
 
 ==============================================================
Index: pykota/trunk/pykota/accounters/snmp.py
===================================================================
--- pykota/trunk/pykota/accounters/snmp.py (revision 3503)
+++ pykota/trunk/pykota/accounters/snmp.py (revision 3506)
@@ -37,14 +37,5 @@
     from pysnmp.entity.rfc3413.oneliner import cmdgen
 except ImportError :
-    hasV4 = False
-    try :
-        from pysnmp.asn1.encoding.ber.error import TypeMismatchError
-        from pysnmp.mapping.udp.error import SnmpOverUdpError
-        from pysnmp.mapping.udp.role import Manager
-        from pysnmp.proto.api import alpha
-    except ImportError :
-        raise RuntimeError, "The pysnmp module is not available. Download it from http://pysnmp.sf.net/"
-else :
-    hasV4 = True
+    raise RuntimeError, "The pysnmp v4.x module is not available. Download it from http://pysnmp.sf.net/\nPyKota doesn't support earlier releases anymore."
 
 from pykota import constants
@@ -257,96 +248,44 @@
         return self.printerInternalPageCounter
 
-if hasV4 :
-    class Handler(BaseHandler) :
-        """A class for pysnmp v4.x"""
-        def retrieveSNMPValues(self) :
-            """Retrieves a printer's internal page counter and status via SNMP."""
-            try :
-                errorIndication, errorStatus, errorIndex, varBinds = \
-                 cmdgen.CommandGenerator().getCmd(cmdgen.CommunityData("pykota", self.community, 0), \
-                                                  cmdgen.UdpTransportTarget((self.printerHostname, self.port)), \
-                                                  tuple([int(i) for i in pageCounterOID.split('.')]), \
-                                                  tuple([int(i) for i in hrPrinterStatusOID.split('.')]), \
-                                                  tuple([int(i) for i in hrDeviceStatusOID.split('.')]), \
-                                                  tuple([int(i) for i in hrPrinterDetectedErrorStateOID.split('.')]))
-            except socket.gaierror, msg :
-                errorIndication = repr(msg)
-            except :
-                errorIndication = "Unknown SNMP/Network error. Check your wires."
-            if errorIndication :
-                self.parent.filter.printInfo("SNMP Error : %s" % errorIndication, "error")
-                self.initValues()
-            elif errorStatus :
-                self.parent.filter.printInfo("SNMP Error : %s at %s" % (errorStatus.prettyPrint(), \
+class Handler(BaseHandler) :
+    """A class for pysnmp v4.x, PyKota doesn't support earlier releases of pysnmp anymore.'"""
+    def __init__(self, *args):
+        BaseHandler.__init__(self, *args)
+        self.snmpEngine = cmdgen.CommandGenerator()
+        self.snmpAuth = cmdgen.CommunityData("pykota", self.community, 0)
+        self.snmpTarget = cmdgen.UdpTransportTarget((self.printerHostname, self.port))
+
+    def retrieveSNMPValues(self) :
+        """Retrieves a printer's internal page counter and status via SNMP."""
+        try :
+            errorIndication, errorStatus, errorIndex, varBinds = \
+                self.snmpEngine.getCmd(self.snmpAuth, \
+                                       self.snmpTarget, \
+                                       tuple([int(i) for i in pageCounterOID.split('.')]), \
+                                       tuple([int(i) for i in hrPrinterStatusOID.split('.')]), \
+                                       tuple([int(i) for i in hrDeviceStatusOID.split('.')]), \
+                                       tuple([int(i) for i in hrPrinterDetectedErrorStateOID.split('.')]))
+        except socket.gaierror, msg :
+            errorIndication = repr(msg)
+        except :
+            errorIndication = "Unknown SNMP/Network error. Check your wires."
+        if errorIndication :
+            self.parent.filter.printInfo("SNMP Error : %s" % errorIndication, "error")
+            self.initValues()
+        elif errorStatus :
+            self.parent.filter.printInfo("SNMP Error : %s at %s" % (errorStatus.prettyPrint(), \
                                                                         varBinds[int(errorIndex)-1]), \
                                              "error")
-                self.initValues()
-            else :
-                self.printerInternalPageCounter = max(self.printerInternalPageCounter, int(varBinds[0][1].prettyPrint() or "0"))
-                self.printerStatus = int(varBinds[1][1].prettyPrint() or "2") # or unknown
-                self.deviceStatus = int(varBinds[2][1].prettyPrint() or "1")  # or unknown
-                self.printerDetectedErrorState = self.extractErrorStates(str(varBinds[3][1]))
-                self.parent.filter.logdebug("SNMP answer decoded : PageCounter : %s  PrinterStatus : '%s'  DeviceStatus : '%s'  PrinterErrorState : '%s'" \
-                     % (self.printerInternalPageCounter, \
-                        printerStatusValues.get(self.printerStatus), \
-                        deviceStatusValues.get(self.deviceStatus), \
-                        self.printerDetectedErrorState))
-else :
-    class Handler(BaseHandler) :
-        """A class for pysnmp v3.4.x"""
-        def retrieveSNMPValues(self) :
-            """Retrieves a printer's internal page counter and status via SNMP."""
-            ver = alpha.protoVersions[alpha.protoVersionId1]
-            req = ver.Message()
-            req.apiAlphaSetCommunity(self.community)
-            req.apiAlphaSetPdu(ver.GetRequestPdu())
-            req.apiAlphaGetPdu().apiAlphaSetVarBindList((pageCounterOID, ver.Null()), \
-                                                        (hrPrinterStatusOID, ver.Null()), \
-                                                        (hrDeviceStatusOID, ver.Null()), \
-                                                        (hrPrinterDetectedErrorStateOID, ver.Null()))
-            tsp = Manager()
-            try :
-                tsp.sendAndReceive(req.berEncode(), \
-                                   (self.printerHostname, self.port), \
-                                   (self.handleAnswer, req))
-            except (SnmpOverUdpError, select.error), msg :
-                self.parent.filter.printInfo(_("Network error while doing SNMP queries on printer %s : %s") % (self.printerHostname, msg), "warn")
-                self.initValues()
-            tsp.close()
-
-        def handleAnswer(self, wholeMsg, notusedhere, req):
-            """Decodes and handles the SNMP answer."""
-            ver = alpha.protoVersions[alpha.protoVersionId1]
-            rsp = ver.Message()
-            try :
-                rsp.berDecode(wholeMsg)
-            except TypeMismatchError, msg :
-                self.parent.filter.printInfo(_("SNMP message decoding error for printer %s : %s") % (self.printerHostname, msg), "warn")
-                self.initValues()
-            else :
-                if req.apiAlphaMatch(rsp):
-                    errorStatus = rsp.apiAlphaGetPdu().apiAlphaGetErrorStatus()
-                    if errorStatus:
-                        self.parent.filter.printInfo(_("Problem encountered while doing SNMP queries on printer %s : %s") % (self.printerHostname, errorStatus), "warn")
-                    else:
-                        self.values = []
-                        for varBind in rsp.apiAlphaGetPdu().apiAlphaGetVarBindList():
-                            self.values.append(varBind.apiAlphaGetOidVal()[1].rawAsn1Value)
-                        try :
-                            # keep maximum value seen for printer's internal page counter
-                            self.printerInternalPageCounter = max(self.printerInternalPageCounter, self.values[0])
-                            self.printerStatus = self.values[1]
-                            self.deviceStatus = self.values[2]
-                            self.printerDetectedErrorState = self.extractErrorStates(self.values[3])
-                            self.parent.filter.logdebug("SNMP answer decoded : PageCounter : %s  PrinterStatus : '%s'  DeviceStatus : '%s'  PrinterErrorState : '%s'" \
-                                 % (self.printerInternalPageCounter, \
-                                    printerStatusValues.get(self.printerStatus), \
-                                    deviceStatusValues.get(self.deviceStatus), \
-                                    self.printerDetectedErrorState))
-                        except IndexError :
-                            self.parent.filter.logdebug("SNMP answer is incomplete : %s" % str(self.values))
-                            pass
-                        else :
-                            return 1
+            self.initValues()
+        else :
+            self.printerInternalPageCounter = max(self.printerInternalPageCounter, int(varBinds[0][1].prettyPrint() or "0"))
+            self.printerStatus = int(varBinds[1][1].prettyPrint() or "2") # or unknown
+            self.deviceStatus = int(varBinds[2][1].prettyPrint() or "1")  # or unknown
+            self.printerDetectedErrorState = self.extractErrorStates(str(varBinds[3][1]))
+            self.parent.filter.logdebug("SNMP answer decoded : PageCounter : %s  PrinterStatus : '%s'  DeviceStatus : '%s'  PrinterErrorState : '%s'" \
+                                            % (self.printerInternalPageCounter, \
+                                                   printerStatusValues.get(self.printerStatus), \
+                                                   deviceStatusValues.get(self.deviceStatus), \
+                                                   self.printerDetectedErrorState))
 
 def main(hostname) :
Index: pykota/trunk/bin/pkturnkey
===================================================================
--- pykota/trunk/bin/pkturnkey (revision 3490)
+++ pykota/trunk/bin/pkturnkey (revision 3506)
@@ -163,73 +163,17 @@
             from pysnmp.entity.rfc3413.oneliner import cmdgen
         except ImportError :
-            hasV4 = False
-            try :
-                from pysnmp.asn1.encoding.ber.error import TypeMismatchError
-                from pysnmp.mapping.udp.role import Manager
-                from pysnmp.proto.api import alpha
-            except ImportError :
-                logerr("pysnmp doesn't seem to be installed. SNMP checks will be ignored !\n")
-                return False
-        else :
-            hasV4 = True
-
-        if hasV4 :
-            def retrieveSNMPValues(hostname, community) :
-                """Retrieves a printer's internal page counter and status via SNMP."""
-                errorIndication, errorStatus, errorIndex, varBinds = \
-                     cmdgen.CommandGenerator().getCmd(cmdgen.CommunityData("pykota", community, 0), \
-                                                      cmdgen.UdpTransportTarget((hostname, 161)), \
-                                                      tuple([int(i) for i in pageCounterOID.split('.')]))
-                if errorIndication :
-                    raise "No SNMP !"
-                elif errorStatus :
-                    raise "No SNMP !"
-                else :
-                    self.SNMPOK = True
-        else :
-            def retrieveSNMPValues(hostname, community) :
-                """Retrieves a printer's internal page counter and status via SNMP."""
-                ver = alpha.protoVersions[alpha.protoVersionId1]
-                req = ver.Message()
-                req.apiAlphaSetCommunity(community)
-                req.apiAlphaSetPdu(ver.GetRequestPdu())
-                req.apiAlphaGetPdu().apiAlphaSetVarBindList((pageCounterOID, ver.Null()))
-                tsp = Manager()
-                try :
-                    tsp.sendAndReceive(req.berEncode(), \
-                                       (hostname, 161), \
-                                       (handleAnswer, req))
-                except :
-                    raise "No SNMP !"
-                tsp.close()
-
-            def handleAnswer(wholemsg, notusedhere, req):
-                """Decodes and handles the SNMP answer."""
-                ver = alpha.protoVersions[alpha.protoVersionId1]
-                rsp = ver.Message()
-                try :
-                    rsp.berDecode(wholemsg)
-                except TypeMismatchError, msg :
-                    raise "No SNMP !"
-                else :
-                    if req.apiAlphaMatch(rsp):
-                        errorStatus = rsp.apiAlphaGetPdu().apiAlphaGetErrorStatus()
-                        if errorStatus:
-                            raise "No SNMP !"
-                        else:
-                            self.values = []
-                            for varBind in rsp.apiAlphaGetPdu().apiAlphaGetVarBindList():
-                                self.values.append(varBind.apiAlphaGetOidVal()[1].rawAsn1Value)
-                            try :
-                                pagecounter = self.values[0]
-                            except :
-                                raise "No SNMP !"
-                            else :
-                                self.SNMPOK = True
-                                return True
-
-        self.SNMPOK = False
+            logerr("pysnmp doesn't seem to be installed. PyKota needs pysnmp v4.x, otherwise SNMP checks will be ignored !\n")
+            return False
         try :
-            retrieveSNMPValues(hostname, community)
+            errorIndication, errorStatus, errorIndex, varBinds = \
+                cmdgen.CommandGenerator().getCmd(cmdgen.CommunityData("pykota", community, 0), \
+                                                     cmdgen.UdpTransportTarget((hostname, 161)), \
+                                                     tuple([int(i) for i in pageCounterOID.split('.')]))
+            if errorIndication :
+                raise "No SNMP !"
+            elif errorStatus :
+                raise "No SNMP !"
+            else :
+                self.SNMPOK = True
         except :
             self.SNMPOK = False
