- Timestamp:
- 02/20/04 15:42:21 (21 years ago)
- Location:
- pykota/trunk
- Files:
-
- 5 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/conf/pykota.conf.sample
r1353 r1356 118 118 # common values are : memberUid, uniqueMember, member 119 119 #groupmembers: memberUid 120 121 # Activate low-level LDAP cache yes/no 122 # Nothing to do with "storagecaching" which is higher level 123 # and database independant. 124 ldapcache: no 120 125 121 126 # Where to log ? -
pykota/trunk/NEWS
r1353 r1356 22 22 PyKota NEWS : 23 23 24 - 1.18alpha7 : 25 26 - New experimental ldapcache directive to improve 27 LDAP caching. 28 24 29 - 1.18alpha6 : 25 30 -
pykota/trunk/pykota/config.py
r1353 r1356 22 22 # 23 23 # $Log$ 24 # Revision 1.44 2004/02/20 14:42:21 jalet 25 # Experimental ldapcache directive added 26 # 24 27 # Revision 1.43 2004/02/19 14:20:21 jalet 25 28 # maildomain pykota.conf directive added. … … 471 474 return self.isTrue(self.getGlobalOption("storagecaching", ignore=1)) 472 475 476 def getLDAPCache(self) : 477 """Returns 1 if low-level LDAP caching is enabled, else 0.""" 478 return self.isTrue(self.getGlobalOption("ldapcache", ignore=1)) 479 473 480 def getDisableHistory(self) : 474 481 """Returns 1 if we want to disable history, else 0.""" -
pykota/trunk/pykota/storages/ldapstorage.py
r1348 r1356 22 22 # 23 23 # $Log$ 24 # Revision 1.53 2004/02/20 14:42:21 jalet 25 # Experimental ldapcache directive added 26 # 24 27 # Revision 1.52 2004/02/17 23:41:48 jalet 25 28 # Preliminary work on low-level LDAP specific cache. … … 211 214 try : 212 215 import ldap 213 from ldap importmodlist216 import ldap.modlist 214 217 except ImportError : 215 218 import sys … … 232 235 raise PyKotaStorageError, "Unable to connect to LDAP server %s as %s." % (host, user) # TODO : translate 233 236 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 235 241 self.closed = 0 236 242 self.tool.logdebug("Database opened (host=%s, dbname=%s, user=%s)" % (host, dbname, user)) … … 272 278 self.tool.logdebug("Transaction aborted. WARNING : No transaction in LDAP !") 273 279 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) : 275 281 """Does an LDAP search query.""" 276 282 try : 277 283 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) 280 301 except ldap.LDAPError, msg : 281 302 raise PyKotaStorageError, (_("Search for %s(%s) from %s(scope=%s) returned no answer.") % (key, fields, base, scope)) + " : %s" % str(msg) 282 303 else : 283 304 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 287 309 return result 288 310 … … 293 315 try : 294 316 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) 296 320 except ldap.LDAPError, msg : 297 321 raise PyKotaStorageError, (_("Problem adding LDAP entry (%s, %s)") % (dn, str(fields))) + " : %s" % str(msg) 298 322 else : 323 if self.useldapcache : 324 self.tool.logdebug("LDAP cache add %s => %s" % (dn, fields)) 325 self.ldapcache[dn] = fields 299 326 return dn 300 327 … … 307 334 except ldap.LDAPError, msg : 308 335 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) : 311 345 """Modifies an entry in the LDAP directory.""" 312 346 try : 313 347 # 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] 319 361 for (k, v) in fields.items() : 320 362 if type(v) == type({}) : 321 363 try : 322 oldvalue = v["convert"](oldentry [0][1].get(k, [0])[0])364 oldvalue = v["convert"](oldentry.get(k, [0])[0]) 323 365 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)) 325 367 oldvalue = 0 326 368 if v["operator"] == '+' : … … 330 372 fields[k] = str(newvalue) 331 373 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) 334 377 except ldap.LDAPError, msg : 335 378 raise PyKotaStorageError, (_("Problem modifying LDAP entry (%s, %s)") % (dn, fields)) + " : %s" % str(msg) 336 379 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)) 337 391 return dn 338 392 … … 798 852 "pykotaBalance" : { "operator" : "-", "value" : amount, "convert" : float }, 799 853 } 800 return self.doModify(user.idbalance, fields )854 return self.doModify(user.idbalance, fields, flushcache=1) 801 855 802 856 def writeUserAccountBalance(self, user, newbalance, newlifetimepaid=None) : … … 807 861 if newlifetimepaid is not None : 808 862 fields.update({ "pykotaLifeTimePaid" : str(newlifetimepaid) }) 809 return self.doModify(user.idbalance, fields )863 return self.doModify(user.idbalance, fields, flushcache=1) 810 864 811 865 def writeLastJobSize(self, lastjob, jobsize, jobprice) : -
pykota/trunk/pykota/version.py
r1353 r1356 22 22 # 23 23 24 __version__ = "1.18alpha 6_unofficial"24 __version__ = "1.18alpha7_unofficial" 25 25 26 26 __doc__ = """PyKota : a complete Printing Quota Solution for CUPS and LPRng."""