[Freeipa-devel] [PATCH] add asynchronous user search
Kevin McCarthy
kmccarth at redhat.com
Tue Aug 28 23:03:10 UTC 2007
This patch adds asynchronous searching: ipaldap.getListAsync(). This
method returns a counter as a first entry which is -1 in the case of
partial results.
The change allows user search to show results even if it's truncated.
-Kevin
-------------- next part --------------
# HG changeset patch
# User Kevin McCarthy <kmccarth at redhat.com>
# Date 1188342067 25200
# Node ID 1748d1e697b26272617d2058ecdf7582608726ed
# Parent 2b57d537aacaa15a5be1d75756b276d7ee874dc8
Change user search to be asynchronous.
This way it returns results even if the search times out.
The find_users() search now returns a counter as the first result, which
is set to -1 if the results are partial.
diff -r 2b57d537aaca -r 1748d1e697b2 ipa-python/ipaclient.py
--- a/ipa-python/ipaclient.py Tue Aug 28 09:20:12 2007 -0700
+++ b/ipa-python/ipaclient.py Tue Aug 28 16:01:07 2007 -0700
@@ -94,12 +94,14 @@ class IPAClient:
return result
def find_users(self, criteria, sattrs=None):
- """Find users whose uid matches the criteria. Wildcards are
- acceptable. Returns a list of User objects."""
+ """Return a list: counter followed by a User object for each user that
+ matches the criteria. If the results are truncated, counter will
+ be set to -1"""
result = self.transport.find_users(criteria, sattrs)
-
- users = []
- for attrs in result:
+ counter = result[0]
+
+ users = [counter]
+ for attrs in result[1:]:
if attrs is not None:
users.append(user.User(attrs))
diff -r 2b57d537aaca -r 1748d1e697b2 ipa-python/rpcclient.py
--- a/ipa-python/rpcclient.py Tue Aug 28 09:20:12 2007 -0700
+++ b/ipa-python/rpcclient.py Tue Aug 28 16:01:07 2007 -0700
@@ -151,8 +151,9 @@ class RPCClient:
return ipautil.unwrap_binary_data(result)
def find_users (self, criteria, sattrs=None):
- """Return a list containing a User object for each user that matches
- the criteria."""
+ """Return a list: counter followed by a User object for each user that
+ matches the criteria. If the results are truncated, counter will
+ be set to -1"""
server = self.setup_server()
try:
diff -r 2b57d537aaca -r 1748d1e697b2 ipa-server/ipa-gui/ipagui/controllers.py
--- a/ipa-server/ipa-gui/ipagui/controllers.py Tue Aug 28 09:20:12 2007 -0700
+++ b/ipa-server/ipa-gui/ipagui/controllers.py Tue Aug 28 16:01:07 2007 -0700
@@ -140,10 +140,16 @@ class Root(controllers.RootController):
def userlist(self, **kw):
"""Retrieve a list of all users and display them in one huge list"""
users = None
+ counter = 0
uid = kw.get('uid')
if uid != None and len(uid) > 0:
try:
users = client.find_users(uid.encode('utf-8'))
+ counter = users[0]
+ users = users[1:]
+ if counter == -1:
+ turbogears.flash("These results are truncated.\n" +
+ "Please refine your search and try again.")
except ipaerror.IPAError, e:
turbogears.flash("User list failed: " + str(e))
raise turbogears.redirect("/userlist")
diff -r 2b57d537aaca -r 1748d1e697b2 ipa-server/ipa-gui/ipagui/static/css/style.css
--- a/ipa-server/ipa-gui/ipagui/static/css/style.css Tue Aug 28 09:20:12 2007 -0700
+++ b/ipa-server/ipa-gui/ipagui/static/css/style.css Tue Aug 28 16:01:07 2007 -0700
@@ -129,7 +129,7 @@ body {
#status_block {
margin: 0 auto 0.5em auto;
padding: 15px 10px 15px 55px;
- background: #cec URL('../images/ok.png') left center no-repeat;
+ background: #cec;
border: 1px solid #9c9;
width: 450px;
font-size: 120%;
diff -r 2b57d537aaca -r 1748d1e697b2 ipa-server/ipa-gui/ipagui/templates/userlist.kid
--- a/ipa-server/ipa-gui/ipagui/templates/userlist.kid Tue Aug 28 09:20:12 2007 -0700
+++ b/ipa-server/ipa-gui/ipagui/templates/userlist.kid Tue Aug 28 16:01:07 2007 -0700
@@ -8,13 +8,13 @@
<body>
<div id="search">
<form action="${tg.url('/userlist')}" method="post">
- Search by login/name:
+ Search:
<input type="text" name="uid" />
<input type="submit" />
</form>
</div>
<div py:if='users != None'>
- <h2>Results</h2>
+ <h2>${len(users)} results returned:</h2>
<table py:if='len(users) > 0' border="1">
<tr>
<th>
diff -r 2b57d537aaca -r 1748d1e697b2 ipa-server/ipaserver/ipaldap.py
--- a/ipa-server/ipaserver/ipaldap.py Tue Aug 28 09:20:12 2007 -0700
+++ b/ipa-server/ipaserver/ipaldap.py Tue Aug 28 16:01:07 2007 -0700
@@ -300,6 +300,44 @@ class IPAdmin(SimpleLDAPObject):
return all_users
+ def getListAsync(self,*args):
+ """This version performs an asynchronous search, to allow
+ results even if we hit a limit.
+
+ It returns a list: counter followed by the results.
+ If the results are truncated, counter will be set to -1.
+ """
+
+ sctrl = self.__get_server_controls__()
+ if sctrl is not None:
+ self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
+
+ entries = []
+ partial = 0
+
+ try:
+ msgid = self.search_ext(*args)
+ type, result_list = self.result(msgid, 0)
+ while result_list:
+ for result in result_list:
+ entries.append(result)
+ type, result_list = self.result(msgid, 0)
+ except (ldap.ADMINLIMIT_EXCEEDED, ldap.SIZELIMIT_EXCEEDED), e:
+ partial = 1
+ except ldap.LDAPError, e:
+ raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
+
+ if not entries:
+ raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND,
+ "no such entry for " + str(args))
+
+ if partial == 1:
+ counter = -1
+ else:
+ counter = len(entries)
+
+ return [counter] + entries
+
def addEntry(self,*args):
"""This wraps the add function. It assumes that the entry is already
populated with all of the desired objectclasses and attributes"""
diff -r 2b57d537aaca -r 1748d1e697b2 ipa-server/xmlrpc-server/funcs.py
--- a/ipa-server/xmlrpc-server/funcs.py Tue Aug 28 09:20:12 2007 -0700
+++ b/ipa-server/xmlrpc-server/funcs.py Tue Aug 28 16:01:07 2007 -0700
@@ -372,9 +372,8 @@ class IPAServer:
return users
def find_users (self, criteria, sattrs=None, opts=None):
- """Return a list containing a User object for each
- existing user that matches the criteria.
- """
+ """Returns a list: counter followed by the results.
+ If the results are truncated, counter will be set to -1."""
global _LDAPPool
if opts:
@@ -400,25 +399,36 @@ class IPAServer:
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
try:
try:
- exact_results = m1.getList(self.basedn, self.scope,
+ exact_results = m1.getListAsync(self.basedn, self.scope,
exact_match_filter, sattrs)
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
- exact_results = []
+ exact_results = [0]
try:
- partial_results = m1.getList(self.basedn, self.scope,
+ partial_results = m1.getListAsync(self.basedn, self.scope,
partial_match_filter, sattrs)
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
- partial_results = []
- finally:
- _LDAPPool.releaseConn(m1)
+ partial_results = [0]
+ finally:
+ _LDAPPool.releaseConn(m1)
+
+ exact_counter = exact_results[0]
+ partial_counter = partial_results[0]
+
+ exact_results = exact_results[1:]
+ partial_results = partial_results[1:]
# Remove exact matches from the partial_match list
exact_dns = set(map(lambda e: e.dn, exact_results))
partial_results = filter(lambda e: e.dn not in exact_dns,
partial_results)
- users = []
+ if (exact_counter == -1) or (partial_counter == -1):
+ counter = -1
+ else:
+ counter = len(exact_results) + len(partial_results)
+
+ users = [counter]
for u in exact_results + partial_results:
users.append(self.convert_entry(u))
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 2228 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20070828/b07be349/attachment.bin>
More information about the Freeipa-devel
mailing list