diff options
author | Rob Crittenden <rcritten@redhat.com> | 2007-10-08 16:18:38 -0400 |
---|---|---|
committer | Rob Crittenden <rcritten@redhat.com> | 2007-10-08 16:18:38 -0400 |
commit | eddc5d4e42796888c3179df36aa6967c573136ab (patch) | |
tree | 9894c2eb4596b03d707981e258798703da5d0c1f /ipa-server/xmlrpc-server/funcs.py | |
parent | 60ce1db5815804fa698b894fb661dc4141d8f72d (diff) | |
download | freeipa-eddc5d4e42796888c3179df36aa6967c573136ab.tar.gz freeipa-eddc5d4e42796888c3179df36aa6967c573136ab.tar.xz freeipa-eddc5d4e42796888c3179df36aa6967c573136ab.zip |
New LDAP connection pool that does locking
Diffstat (limited to 'ipa-server/xmlrpc-server/funcs.py')
-rw-r--r-- | ipa-server/xmlrpc-server/funcs.py | 86 |
1 files changed, 62 insertions, 24 deletions
diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index bf2cde4f4..8a6bbf910 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -34,6 +34,11 @@ from types import * import os import re +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock + # Need a global to store this between requests _LDAPPool = None @@ -45,35 +50,68 @@ DefaultGroupContainer = "cn=groups,cn=accounts" # connection. This could theoretically drive the total number of connections # very high but since this represents just the administrative interface # this is not anticipated. -class IPAConnPool: - def __init__(self): - self.freelist = [] +# +# The pool consists of two things, a dictionary keyed on the principal name +# that contains the connection and a list that is used to keep track of the +# order. If the list fills up just pop the top entry off and you've got +# the least recently used. - def getConn(self, host, port, bindca, bindcert, bindkey, proxydn=None, krbccache=None, debug=None): +# maxsize = 0 means no limit +class IPAConnPool: + def __init__(self, maxsize = 0): + self._dict = {} + self._lru = [] + self._lock = Lock() + self._maxsize = maxsize + self._ctx = krbV.default_context() + + def getConn(self, host, port, krbccache=None, debug=None): conn = None - if len(self.freelist) > 0: - for i in range(len(self.freelist)): - c = self.freelist[i] - if ((c.host == host) and (c.port == port)): - conn = self.freelist.pop(i) - break - if conn is None: - conn = ipaserver.ipaldap.IPAdmin(host,port,bindca,bindcert,bindkey,None,debug) - if proxydn is not None: - conn.set_proxydn(proxydn) - else: - conn.set_krbccache(krbccache) + ccache = krbV.CCache(name=krbccache, context=self._ctx) + cprinc = ccache.principal() + self._lock.acquire() + try: + try: + conn = self._dict[cprinc.name] + del self._dict[cprinc.name] + self._lru.remove(cprinc.name) + except KeyError: + conn = ipaserver.ipaldap.IPAdmin(host,port,None,None,None,debug) + conn.set_krbccache(krbccache, cprinc.name) + finally: + self._lock.release() + return conn def releaseConn(self, conn): if conn is None: return - # We can't re-use SASL connections. If proxydn is None it means - # we have a Kerberos credentials cache set. See ipaldap.set_krbccache - if conn.proxydn is None: - conn.unbind_s() - else: - self.freelist.append(conn) + + cprinc = conn.principal + + self._lock.acquire() + try: + + # Look to see if we are already on the list from another source and + # if so, remove it. + try: + c = self._dict[cprinc] + del self._dict[cprinc] + self._lru.remove(cprinc) + except KeyError: + # Not in the list + pass + + if self._maxsize and len(self._dict) > self._maxsize: + princ = self._lru.pop(0) + c = self._dict[princ] + c.unbind_s() + del self._dict[cprinc] + + self._lru.append(cprinc) + self._dict[cprinc] = conn + finally: + self._lock.release() class IPAServer: @@ -90,7 +128,7 @@ class IPAServer: self.realm = self.krbctx.default_realm if _LDAPPool is None: - _LDAPPool = IPAConnPool() + _LDAPPool = IPAConnPool(128) self.basedn = ipa.ipautil.realm_to_suffix(self.realm) self.scope = ldap.SCOPE_SUBTREE self.princ = None @@ -169,7 +207,7 @@ class IPAServer: raise ipaerror.gen_exception(ipaerror.CONNECTION_NO_CCACHE) try: - conn = _LDAPPool.getConn(self.host,port,bindca,bindcert,bindkey,proxy_dn,krbccache,debug) + conn = _LDAPPool.getConn(self.host,port,krbccache,debug) except ldap.INVALID_CREDENTIALS, e: raise ipaerror.gen_exception(ipaerror.CONNECTION_GSSAPI_CREDENTIALS, nested_exception=e) |