Show
Ignore:
Timestamp:
02/20/04 15:42:21 (20 years ago)
Author:
jalet
Message:

Experimental ldapcache directive added

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/pykota/storages/ldapstorage.py

    r1348 r1356  
    2222# 
    2323# $Log$ 
     24# Revision 1.53  2004/02/20 14:42:21  jalet 
     25# Experimental ldapcache directive added 
     26# 
    2427# Revision 1.52  2004/02/17 23:41:48  jalet 
    2528# Preliminary work on low-level LDAP specific cache. 
     
    211214try : 
    212215    import ldap 
    213     from ldap import modlist 
     216    import ldap.modlist 
    214217except ImportError :     
    215218    import sys 
     
    232235            raise PyKotaStorageError, "Unable to connect to LDAP server %s as %s." % (host, user) # TODO : translate 
    233236        else :     
    234             self.ldapcache = {} # low-level cache specific to LDAP backend 
     237            self.useldapcache = pykotatool.config.getLDAPCache() 
     238            if self.useldapcache : 
     239                self.tool.logdebug("Low-Level LDAP Caching enabled.") 
     240                self.ldapcache = {} # low-level cache specific to LDAP backend 
    235241            self.closed = 0 
    236242            self.tool.logdebug("Database opened (host=%s, dbname=%s, user=%s)" % (host, dbname, user)) 
     
    272278        self.tool.logdebug("Transaction aborted. WARNING : No transaction in LDAP !") 
    273279         
    274     def doSearch(self, key, fields=None, base="", scope=ldap.SCOPE_SUBTREE) : 
     280    def doSearch(self, key, fields=None, base="", scope=ldap.SCOPE_SUBTREE, flushcache=0) : 
    275281        """Does an LDAP search query.""" 
    276282        try : 
    277283            base = base or self.basedn 
    278             self.tool.logdebug("QUERY : Filter : %s, BaseDN : %s, Scope : %s, Attributes : %s" % (key, base, scope, fields)) 
    279             result = self.database.search_s(base, scope, key, fields) # TODO : put 'None' instead of 'fields' 
     284            if self.useldapcache : 
     285                # Here we overwrite the fields the app want, to try and 
     286                # retrieve ALL user defined attributes ("*") 
     287                # + the createTimestamp attribute, needed by job history 
     288                #  
     289                # This may not work with all LDAP servers 
     290                # but works at least in OpenLDAP (2.1.25)  
     291                # and iPlanet Directory Server (5.1 SP3) 
     292                fields = ["*", "createTimestamp"]          
     293                 
     294            if self.useldapcache and (not flushcache) and (scope == ldap.SCOPE_BASE) and self.ldapcache.has_key(base) : 
     295                entry = self.ldapcache[base] 
     296                self.tool.logdebug("LDAP cache hit %s => %s" % (base, entry)) 
     297                result = [(base, entry)] 
     298            else : 
     299                self.tool.logdebug("QUERY : Filter : %s, BaseDN : %s, Scope : %s, Attributes : %s" % (key, base, scope, fields)) 
     300                result = self.database.search_s(base, scope, key, fields) 
    280301        except ldap.LDAPError, msg :     
    281302            raise PyKotaStorageError, (_("Search for %s(%s) from %s(scope=%s) returned no answer.") % (key, fields, base, scope)) + " : %s" % str(msg) 
    282303        else :      
    283304            self.tool.logdebug("QUERY : Result : %s" % result) 
    284             for (dn, attributes) in result : 
    285                 self.tool.logdebug("LDAP cache store (%s)" % dn) 
    286                 self.ldapcache[dn] = attributes 
     305            if self.useldapcache : 
     306                for (dn, attributes) in result : 
     307                    self.tool.logdebug("LDAP cache store %s => %s" % (dn, attributes)) 
     308                    self.ldapcache[dn] = attributes 
    287309            return result 
    288310             
     
    293315        try : 
    294316            self.tool.logdebug("QUERY : ADD(%s, %s)" % (dn, str(fields))) 
    295             self.database.add_s(dn, modlist.addModlist(fields)) 
     317            entry = ldap.modlist.addModlist(fields) 
     318            self.tool.logdebug("%s" % entry) 
     319            self.database.add_s(dn, entry) 
    296320        except ldap.LDAPError, msg : 
    297321            raise PyKotaStorageError, (_("Problem adding LDAP entry (%s, %s)") % (dn, str(fields))) + " : %s" % str(msg) 
    298322        else : 
     323            if self.useldapcache : 
     324                self.tool.logdebug("LDAP cache add %s => %s" % (dn, fields)) 
     325                self.ldapcache[dn] = fields 
    299326            return dn 
    300327             
     
    307334        except ldap.LDAPError, msg : 
    308335            raise PyKotaStorageError, (_("Problem deleting LDAP entry (%s)") % dn) + " : %s" % str(msg) 
    309              
    310     def doModify(self, dn, fields, ignoreold=1) : 
     336        else :     
     337            if self.useldapcache : 
     338                try : 
     339                    self.tool.logdebug("LDAP cache del %s" % dn) 
     340                    del self.ldapcache[dn] 
     341                except KeyError :     
     342                    pass 
     343             
     344    def doModify(self, dn, fields, ignoreold=1, flushcache=0) : 
    311345        """Modifies an entry in the LDAP directory.""" 
    312346        try : 
    313347            # TODO : take care of, and update LDAP specific cache 
    314             if self.ldapcache.has_key(dn) : 
    315                 self.tool.logdebug("LDAP cache hit (%s)" % dn) 
    316             else :     
    317                 self.tool.logdebug("LDAP cache miss (%s)" % dn) 
    318             oldentry = self.doSearch("objectClass=*", base=dn, scope=ldap.SCOPE_BASE) 
     348            if self.useldapcache and not flushcache : 
     349                if self.ldapcache.has_key(dn) : 
     350                    old = self.ldapcache[dn] 
     351                    self.tool.logdebug("LDAP cache hit %s => %s" % (dn, old)) 
     352                    oldentry = {} 
     353                    for (k, v) in old.items() : 
     354                        if k != "createTimestamp" : 
     355                            oldentry[k] = v 
     356                else :     
     357                    self.tool.logdebug("LDAP cache miss %s" % dn) 
     358                    oldentry = self.doSearch("objectClass=*", base=dn, scope=ldap.SCOPE_BASE)[0][1] 
     359            else :         
     360                oldentry = self.doSearch("objectClass=*", base=dn, scope=ldap.SCOPE_BASE, flushcache=flushcache)[0][1] 
    319361            for (k, v) in fields.items() : 
    320362                if type(v) == type({}) : 
    321363                    try : 
    322                         oldvalue = v["convert"](oldentry[0][1].get(k, [0])[0]) 
     364                        oldvalue = v["convert"](oldentry.get(k, [0])[0]) 
    323365                    except ValueError :     
    324                         self.tool.logdebug("Error converting %s with %s(%s)" % (oldentry[0][1].get(k), k, v)) 
     366                        self.tool.logdebug("Error converting %s with %s(%s)" % (oldentry.get(k), k, v)) 
    325367                        oldvalue = 0 
    326368                    if v["operator"] == '+' : 
     
    330372                    fields[k] = str(newvalue) 
    331373            fields = self.normalizeFields(fields) 
    332             self.tool.logdebug("QUERY : Modify(%s, %s ==> %s)" % (dn, oldentry[0][1], fields)) 
    333             self.database.modify_s(dn, modlist.modifyModlist(oldentry[0][1], fields, ignore_oldexistent=ignoreold)) 
     374            self.tool.logdebug("QUERY : Modify(%s, %s ==> %s)" % (dn, oldentry, fields)) 
     375            entry = ldap.modlist.modifyModlist(oldentry, fields, ignore_oldexistent=ignoreold) 
     376            self.database.modify_s(dn, entry) 
    334377        except ldap.LDAPError, msg : 
    335378            raise PyKotaStorageError, (_("Problem modifying LDAP entry (%s, %s)") % (dn, fields)) + " : %s" % str(msg) 
    336379        else : 
     380            if self.useldapcache : 
     381                cachedentry = self.ldapcache[dn] 
     382                for (mop, mtyp, mval) in entry : 
     383                    if mop in (ldap.MOD_ADD, ldap.MOD_REPLACE) : 
     384                        cachedentry[mtyp] = mval 
     385                    else : 
     386                        try : 
     387                            del cachedentry[mtyp] 
     388                        except KeyError :     
     389                            pass 
     390                self.tool.logdebug("LDAP cache update %s => %s" % (dn, cachedentry)) 
    337391            return dn 
    338392             
     
    798852                   "pykotaBalance" : { "operator" : "-", "value" : amount, "convert" : float }, 
    799853                 } 
    800         return self.doModify(user.idbalance, fields)          
     854        return self.doModify(user.idbalance, fields, flushcache=1)          
    801855        
    802856    def writeUserAccountBalance(self, user, newbalance, newlifetimepaid=None) :     
     
    807861        if newlifetimepaid is not None : 
    808862            fields.update({ "pykotaLifeTimePaid" : str(newlifetimepaid) }) 
    809         return self.doModify(user.idbalance, fields)          
     863        return self.doModify(user.idbalance, fields, flushcache=1)          
    810864             
    811865    def writeLastJobSize(self, lastjob, jobsize, jobprice) :