From f86b7bd86945df33843e90a7ac84d5967a7e7e82 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Fri, 24 Jan 2014 18:12:32 -0800 Subject: [PATCH 85/85] Ticket #47649 - Server hangs in cos_cache when adding a user entry Bug description: cos_dn_defs_cb reads cosDefinition and sets up the cos Definition part of cos cache. In the function, when processing cosAttribute, cosTargetTree and cosTemlpateDn are missing, it sets the parent dn of the cos definition dn. This parent setting is needed only when the 2 attributes are completely missing from the cos definition. But if the attributes are located below cosAttribute (see the Example cos definition), in addition to "cn=cosTemplates,ou=people,dc=example, dc=com", the parent of "cn=generatePostalCode,ou=People,dc=example,dc=com" is added to the cos cache as cosTemplateDn. Example cos definition: dn: cn=generatePostalCode,ou=People,dc=example,dc=com description: generate postalCode attr based on location objectClass: top objectClass: ldapsubentry objectClass: cossuperdefinition objectClass: cosClassicDefinition cosAttribute: postalCode costemplatedn: cn=cosTemplates,ou=people,dc=example,dc=com cosSpecifier: l cn: generatePostalCode The mistakenly added cosTemplatedDn makes adding an entry under ou=People notify recreating the cos cache. The notification needs to be outside of backend transaction since it causes a deadlock with the cos_cache_wait_ on_change thread which cannot read the DB due to the transaction but holds the lock that the notifier thread is waiting for. Fix description: The parent of the cos definition dn is set to the cosTargetTree and the cosTemlpateDn, only when the attributes are completely missing. https://fedorahosted.org/389/ticket/47649 Reviewed by rmeggins@redhat.com (Thank you, Rich!!) (cherry picked from commit 1e52401d3abd0377f55676f4a1508a02aaa7f955) (cherry picked from commit 01c0794cde7eb91a1a4e477a0286533df4a4ae38) (cherry picked from commit 1ebad4bd50fb1483998a32b5d3e232e89aeda0f7) --- ldap/servers/plugins/cos/cos_cache.c | 82 +++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c index fed2aa9..a68e59f 100644 --- a/ldap/servers/plugins/cos/cos_cache.c +++ b/ldap/servers/plugins/cos/cos_cache.c @@ -727,7 +727,8 @@ struct dn_defs_info { * if a particular attempt to add a definition fails: info.ret gets set to * zero only if we succed to add a def. */ -static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) +static int +cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) { struct dn_defs_info *info; cosAttrValue **pSneakyVal = 0; @@ -877,31 +878,10 @@ static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) dnVals[valIndex]->bv_val); } - if(!pCosTargetTree) - { - /* get the parent of the definition */ - char *orig = slapi_dn_parent(pDn->val); - Slapi_DN *psdn = slapi_sdn_new_dn_byval(orig); - char *parent = (char *)slapi_sdn_get_dn(psdn); - if (!parent) { - parent = (char *)slapi_sdn_get_udn(psdn); - LDAPDebug(LDAP_DEBUG_ANY, - "cos_cache_build_definition_list: " - "failed to normalize parent dn %s. " - "Adding the pre normalized dn.\n", - parent, 0, 0); - } - cos_cache_add_attrval(&pCosTargetTree, parent); - if (!pCosTemplateDn) { - cos_cache_add_attrval(&pCosTemplateDn, parent); - } - slapi_sdn_free(&psdn); - } - slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle, dnVals[valIndex]->bv_val, NULL, NULL); } /* if(attrType is cosAttribute) */ - + /* * Add the attributetype to the appropriate * list. @@ -913,6 +893,47 @@ static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) ber_bvecfree( dnVals ); dnVals = NULL; } while(!slapi_entry_next_attr(e, dnAttr, &dnAttr)); + + if (pCosAttribute && (!pCosTargetTree || !pCosTemplateDn)) { + /* get the parent of the definition */ + char *orig = slapi_dn_parent(pDn->val); + char *parent = NULL; + if (orig) { + parent = slapi_create_dn_string("%s", orig); + if (!parent) { + parent = orig; + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "cos_dn_defs_cb: " + "failed to normalize parent dn %s. " + "Adding the pre normalized dn.\n", + parent); + } + if (!pCosTargetTree) { + cos_cache_add_attrval(&pCosTargetTree, parent); + } + if (!pCosTemplateDn) { + cos_cache_add_attrval(&pCosTemplateDn, parent); + } + if (parent != orig) { + slapi_ch_free_string(&parent); + } + slapi_ch_free_string(&orig); + } else { + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "cos_dn_defs_cb: " + "failed to get parent dn of cos definition %s.\n", + pDn->val); + if (!pCosTemplateDn) { + if (!pCosTargetTree) { + LDAPDebug0Args(LDAP_DEBUG_ANY, "cosTargetTree and cosTemplateDn are not set.\n"); + } else { + LDAPDebug0Args(LDAP_DEBUG_ANY, "cosTemplateDn is not set.\n"); + } + } else if (!pCosTargetTree) { + LDAPDebug0Args(LDAP_DEBUG_ANY, "cosTargetTree is not set.\n"); + } + } + } /* determine the type of class of service scheme @@ -951,9 +972,7 @@ static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) */ /* these must exist */ - if( pDn && - pObjectclass && - + if(pDn && pObjectclass && ( (cosType == COSTYPE_CLASSIC && pCosTemplateDn && @@ -3582,14 +3601,9 @@ static int cos_cache_entry_is_cos_related( Slapi_Entry *e) { { pObj = (char*)slapi_value_get_string(val); - /* - * objectclasses are ascii--maybe strcasecmp() is faster than - * slapi_utf8casecmp() - */ - if( !strcasecmp(pObj, "cosdefinition") || - !strcasecmp(pObj, "cossuperdefinition") || - !strcasecmp(pObj, "costemplate") - ) + if(!strcasecmp(pObj, "cosdefinition") || + !strcasecmp(pObj, "cossuperdefinition") || + !strcasecmp(pObj, "costemplate")) { rc = 1; } -- 1.8.1.4