summaryrefslogtreecommitdiffstats
path: root/server/responder
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-11-17 20:22:36 -0500
committerStephen Gallagher <sgallagh@redhat.com>2009-11-20 16:46:47 -0500
commit7e4bf8856e9b65e612ca195a3b4f10bfb53a8259 (patch)
treec890f41e3f48e25c9c2eb0ceaa8bffb6625303c4 /server/responder
parent9cbcc60997b3d9fd6c5c17f956bc90aac1abba70 (diff)
downloadsssd-7e4bf8856e9b65e612ca195a3b4f10bfb53a8259.tar.gz
sssd-7e4bf8856e9b65e612ca195a3b4f10bfb53a8259.tar.xz
sssd-7e4bf8856e9b65e612ca195a3b4f10bfb53a8259.zip
Optimize sysdb_enumgrent
This brings down the time needed to enumerate my group database from 2.4 seconds to 0.15 seconds.
Diffstat (limited to 'server/responder')
-rw-r--r--server/responder/nss/nsssrv_cmd.c350
1 files changed, 178 insertions, 172 deletions
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
index e4b08cb30..2466ae718 100644
--- a/server/responder/nss/nsssrv_cmd.c
+++ b/server/responder/nss/nsssrv_cmd.c
@@ -1478,14 +1478,17 @@ static int fill_grent(struct sss_packet *packet,
int max, int *count)
{
struct ldb_message *msg;
+ struct ldb_message_element *el;
uint8_t *body;
size_t blen;
- uint32_t gid, uid;
+ uint32_t gid;
const char *name;
size_t nsize;
size_t delim;
size_t dom_len;
- int i, ret, num, memnum, used;
+ int i, j;
+ int ret, num, memnum;
+ size_t sysnamelen, sysuserslen;
size_t rzero, rsize;
bool add_domain = dom->fqnames;
const char *domain = dom->name;
@@ -1499,9 +1502,10 @@ static int fill_grent(struct sss_packet *packet,
dom_len = 0;
}
+ sysnamelen = strlen(SYSDB_NAME);
+ sysuserslen = strlen(SYSDB_USERS_CONTAINER);
+
num = 0;
- memnum = 0;
- used = 0;
/* first 2 fields (len and reserved), filled up later */
ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
@@ -1512,220 +1516,222 @@ static int fill_grent(struct sss_packet *packet,
rzero = 2*sizeof(uint32_t);
rsize = 0;
- for (i = 0; i < *count; i++, used++) {
+ for (i = 0; i < *count; i++) {
msg = msgs[i];
/* new group */
- if (ldb_msg_check_string_attribute(msg, "objectClass",
- SYSDB_GROUP_CLASS)) {
- if (memnum) {
- /* set num of members */
- ((uint32_t *)(&body[rzero+MNUM_ROFFSET]))[0] = memnum;
- memnum = 0;
- }
+ if (!ldb_msg_check_string_attribute(msg, "objectClass",
+ SYSDB_GROUP_CLASS)) {
+ DEBUG(1, ("Wrong object (%s) found on stack!\n",
+ ldb_dn_get_linearized(msg->dn)));
+ continue;
+ }
- /* if we reached the max allowed entries, simply return */
- if (num >= max) {
- goto done;
- }
+ /* if we reached the max allowed entries, simply return */
+ if (num >= max) {
+ goto done;
+ }
- /* new result starts at end of previous result */
- rzero += rsize;
- rsize = 0;
+ /* new result starts at end of previous result */
+ rzero += rsize;
+ rsize = 0;
- /* find group name/gid */
- name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
- gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
- if (!name || !gid) {
- DEBUG(1, ("Incomplete group object for %s[%llu]! Skipping\n",
- name?name:"<NULL>", (unsigned long long int)gid));
+ /* find group name/gid */
+ name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+ gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
+ if (!name || !gid) {
+ DEBUG(1, ("Incomplete group object for %s[%llu]! Skipping\n",
+ name?name:"<NULL>", (unsigned long long int)gid));
+ continue;
+ }
+
+ if (filter_groups) {
+ ret = nss_ncache_check_group(nctx->ncache,
+ nctx->neg_timeout, domain, name);
+ if (ret == EEXIST) {
+ DEBUG(4, ("Group [%s@%s] filtered out! (negative cache)\n",
+ name, domain));
continue;
}
+ }
- if (filter_groups) {
- ret = nss_ncache_check_group(nctx->ncache,
- nctx->neg_timeout, domain, name);
- if (ret == EEXIST) {
- DEBUG(4, ("Group [%s@%s] filtered out! (negative cache)\n",
- name, domain));
- continue;
- }
- }
+ /* check that the gid is valid for this domain */
+ if ((dom->id_min && (gid < dom->id_min)) ||
+ (dom->id_max && (gid > dom->id_max))) {
+ DEBUG(4, ("Group [%s@%s] filtered out! (id out of range)\n",
+ name, domain));
+ continue;
+ }
- /* check that the gid is valid for this domain */
- if ((dom->id_min && (gid < dom->id_min)) ||
- (dom->id_max && (gid > dom->id_max))) {
- DEBUG(4, ("Group [%s@%s] filtered out! (id out of range)\n",
- name, domain));
- continue;
- }
+ nsize = strlen(name) + 1; /* includes terminating \0 */
+ if (add_domain) nsize += delim + dom_len;
- nsize = strlen(name) + 1; /* includes terminating \0 */
- if (add_domain) nsize += delim + dom_len;
+ /* fill in gid and name and set pointer for number of members */
+ rsize = STRS_ROFFSET + nsize + 2; /* name\0x\0 */
- /* fill in gid and name and set pointer for number of members */
- rsize = STRS_ROFFSET + nsize + 2; /* name\0x\0 */
+ ret = sss_packet_grow(packet, rsize);
+ if (ret != EOK) {
+ num = 0;
+ goto done;
+ }
+ sss_packet_get_body(packet, &body, &blen);
- ret = sss_packet_grow(packet, rsize);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
+ /* 0-3: 32bit number gid */
+ ((uint32_t *)(&body[rzero+GID_ROFFSET]))[0] = gid;
- /* 0-3: 32bit number gid */
- ((uint32_t *)(&body[rzero+GID_ROFFSET]))[0] = gid;
+ /* 4-7: 32bit unsigned number of members */
+ ((uint32_t *)(&body[rzero+MNUM_ROFFSET]))[0] = 0;
- /* 4-7: 32bit unsigned number of members */
- ((uint32_t *)(&body[rzero+MNUM_ROFFSET]))[0] = 0;
+ /* 8-X: sequence of strings (name, passwd, mem..) */
+ if (add_domain) {
+ ret = snprintf((char *)&body[rzero+STRS_ROFFSET],
+ nsize, namefmt, name, domain);
+ if (ret >= nsize) {
+ /* need more space, got creative with the print format ? */
+ int t = ret - nsize + 1;
+ ret = sss_packet_grow(packet, t);
+ if (ret != EOK) {
+ num = 0;
+ goto done;
+ }
+ sss_packet_get_body(packet, &body, &blen);
+ rsize += t;
+ delim += t;
+ nsize += t;
- /* 8-X: sequence of strings (name, passwd, mem..) */
- if (add_domain) {
+ /* retry */
ret = snprintf((char *)&body[rzero+STRS_ROFFSET],
nsize, namefmt, name, domain);
- if (ret >= nsize) {
- /* need more space, got creative with the print format ? */
- int t = ret - nsize + 1;
- ret = sss_packet_grow(packet, t);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
- rsize += t;
- delim += t;
- nsize += t;
-
- /* retry */
- ret = snprintf((char *)&body[rzero+STRS_ROFFSET],
- nsize, namefmt, name, domain);
- }
+ }
- if (ret != nsize-1) {
- DEBUG(1, ("Failed to generate a fully qualified name for"
- " group [%s] in [%s]! Skipping\n", name, domain));
- /* reclaim space */
- ret = sss_packet_shrink(packet, rsize);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- rsize = 0;
- continue;
+ if (ret != nsize-1) {
+ DEBUG(1, ("Failed to generate a fully qualified name for"
+ " group [%s] in [%s]! Skipping\n", name, domain));
+ /* reclaim space */
+ ret = sss_packet_shrink(packet, rsize);
+ if (ret != EOK) {
+ num = 0;
+ goto done;
}
- } else {
- memcpy(&body[rzero+STRS_ROFFSET], name, nsize);
+ rsize = 0;
+ continue;
}
-
- body[rzero + rsize -2] = 'x'; /* group passwd field */
- body[rzero + rsize -1] = '\0';
-
- num++;
- continue;
+ } else {
+ memcpy(&body[rzero+STRS_ROFFSET], name, nsize);
}
- if (rsize == 0) {
- /* some error occurred and there is no result structure ready to
- * store members */
- continue;
- }
+ body[rzero + rsize -2] = 'x'; /* group passwd field */
+ body[rzero + rsize -1] = '\0';
- /* member */
- if (ldb_msg_check_string_attribute(msg, "objectClass",
- SYSDB_USER_CLASS)) {
+ el = ldb_msg_find_element(msg, SYSDB_MEMBER);
+ if (el) {
+ memnum = 0;
- nsize = 0;
+ for (j = 0; j < el->num_values; j++) {
+ int nlen;
+ char *p;
- name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
- uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
- if (!name || !uid) {
- DEBUG(1, ("Incomplete user object! Skipping\n"));
- continue;
- }
+ if (strncmp((const char *)el->values[j].data,
+ SYSDB_NAME, sysnamelen) != 0) {
+ DEBUG(1, ("Member [%.*s] not in the std format ?! "
+ "("SYSDB_NAME"=value,...)\n",
+ el->values[i].length,
+ (const char *)el->values[i].data));
+ continue;
+ }
- if (nctx->filter_users_in_groups) {
- ret = nss_ncache_check_user(nctx->ncache,
- nctx->neg_timeout, domain, name);
- if (ret == EEXIST) {
- DEBUG(4, ("Group [%s] member [%s@%s] filtered out! (negative"
- " cache)\n", (char *)&body[rzero+STRS_ROFFSET],
- name, domain));
+ name = &((const char *)el->values[j].data)[sysnamelen + 1];
+ p = strchr(name, ',');
+ if (!p) {
+ DEBUG(1, ("Member [%.*s] not in the std format ?! "
+ "("SYSDB_NAME"=value,...)\n",
+ el->values[i].length,
+ (const char *)el->values[j].data));
+ continue;
+ }
+ nlen = p - name;
+ p++;
+ if (strncmp(p, SYSDB_USERS_CONTAINER, sysuserslen) != 0) {
+ DEBUG(1, ("Member [%.*s] not in the std format ?! "
+ "("SYSDB_NAME"=value,...)\n",
+ el->values[i].length,
+ (const char *)el->values[j].data));
continue;
}
- }
- /* check that the uid is valid for this domain */
- if ((dom->id_min && (uid < dom->id_min)) ||
- (dom->id_max && (uid > dom->id_max))) {
- DEBUG(4, ("Group [%s] member [%s@%s] filtered out! (id out"
- " of range)\n", (char *)&body[rzero+STRS_ROFFSET],
- name, domain));
- continue;
- }
+ nsize = nlen + 1; /* includes terminating \0 */
+ if (add_domain) nsize += delim + dom_len;
- nsize = strlen(name) + 1;
- if (add_domain) nsize += delim + dom_len;
+ ret = sss_packet_grow(packet, nsize);
+ if (ret != EOK) {
+ num = 0;
+ goto done;
+ }
+ sss_packet_get_body(packet, &body, &blen);
- ret = sss_packet_grow(packet, nsize);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
+ if (add_domain) {
+ char tmp[nlen+1];
+
+ memcpy(tmp, name, nlen);
+ tmp[nlen] = '\0';
- if (add_domain) {
- ret = snprintf((char *)&body[rzero + rsize],
- nsize, namefmt, name, domain);
- if (ret >= nsize) {
- /* need more space, got creative with the print format ? */
- int t = ret - nsize + 1;
- ret = sss_packet_grow(packet, t);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
- delim += t;
- nsize += t;
- /* retry */
ret = snprintf((char *)&body[rzero + rsize],
- nsize, namefmt, name, domain);
- }
+ nsize, namefmt, tmp, domain);
+ if (ret >= nsize) {
+ /* need more space,
+ * got creative with the print format ? */
+ int t = ret - nsize + 1;
+ ret = sss_packet_grow(packet, t);
+ if (ret != EOK) {
+ num = 0;
+ goto done;
+ }
+ sss_packet_get_body(packet, &body, &blen);
+ delim += t;
+ nsize += t;
+
+ /* retry */
+ ret = snprintf((char *)&body[rzero + rsize],
+ nsize, namefmt, tmp, domain);
+ }
- if (ret != nsize-1) {
- DEBUG(1, ("Failed to generate a fully qualified name for"
- " member [%s@%s] of group [%s]! Skipping\n", name,
- domain, (char *)&body[rzero+STRS_ROFFSET]));
- /* reclaim space */
- ret = sss_packet_shrink(packet, nsize);
- if (ret != EOK) {
- num = 0;
- goto done;
+ if (ret != nsize-1) {
+ DEBUG(1, ("Failed to generate a fully qualified name"
+ " for member [%s@%s] of group [%s]!"
+ " Skipping\n", name, domain,
+ (char *)&body[rzero+STRS_ROFFSET]));
+ /* reclaim space */
+ ret = sss_packet_shrink(packet, nsize);
+ if (ret != EOK) {
+ num = 0;
+ goto done;
+ }
+ continue;
}
- continue;
+
+ } else {
+ memcpy(&body[rzero + rsize], name, nlen);
+ body[rzero + rsize + nlen] = '\0';
}
- } else {
- memcpy(&body[rzero + rsize], name, nsize);
+
+ rsize += nsize;
+
+ memnum++;
}
- rsize += nsize;
- memnum++;
- continue;
+ if (memnum) {
+ /* set num of members */
+ ((uint32_t *)(&body[rzero+MNUM_ROFFSET]))[0] = memnum;
+ }
}
- DEBUG(1, ("Wrong object (%s) found on stack!\n",
- ldb_dn_get_linearized(msg->dn)));
+ num++;
continue;
}
- if (memnum) {
- /* set num of members for the last result */
- ((uint32_t *)(&body[rzero+MNUM_ROFFSET]))[0] = memnum;
- }
-
done:
- *count = used;
+ *count = i;
if (num == 0) {
/* if num is 0 most probably something went wrong,