From 95592092bf60b3934aec15366c3c6efd16db6aad Mon Sep 17 00:00:00 2001 From: William Brown Date: Fri, 25 Nov 2016 10:27:46 +1000 Subject: [PATCH] Ticket 48894 - Issues with delete of entrywsi with large entries. Bug Description: During delets of entries with a high number of attributes, a high amount of latency was observed. This was because during the valueset purge for older csn's the vs->sorted was disposed of. This triggered a rebuild of the valueset. Fix Description: During the delete, don't purge the vs->sorted array. We need to preserve it if possible which prevents the need to resort the array after the delete. https://fedorahosted.org/389/ticket/48894 Author: Mohammad N., Burk, J. Review by: wibrown, ??? --- ldap/servers/slapd/valueset.c | 141 ++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 66 deletions(-) diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c index 729a924..66ecc82 100644 --- a/ldap/servers/slapd/valueset.c +++ b/ldap/servers/slapd/valueset.c @@ -422,61 +422,6 @@ valuearray_remove_value(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value return r; } -/* - * Remove any values older than the CSN. - */ -int -valuearray_purge(Slapi_Value ***va, const CSN *csn) -{ - int numValues=0; - int i=0; - int nextValue=0; - - PR_ASSERT(va!=NULL && *va!=NULL); - - /* Loop over all the values freeing the old ones. */ - for(i=0; (*va)[i]; i++) - { - csnset_purge(&((*va)[i]->v_csnset),csn); - if ((*va)[i]->v_csnset == NULL) - { - slapi_value_free(&(*va)[i]); - (*va)[i] = NULL; - } - } - /* Now compact the value list. */ - numValues=i; - nextValue = 0; - i = 0; - for(i=0;inum; i++) + { + if (vs->sorted) { + j = vs->sorted[i]; + } else { + j = i; + } + csnset_purge(&(vs->va[j]->v_csnset),csn); + if (vs->va[j]->v_csnset == NULL) { + slapi_value_free(&vs->va[j]); + vs->va[j] = NULL; + } + } + /* Now compact the value/sorted list. */ + numValues = i; + nextValue = 0; + for(i = 0; isorted) { + j = vs->sorted[nextValue]; + } else { + j = nextValue; + } + while((nextValue < numValues) && (NULL == vs->va[j])) { + if (vs->sorted) { + j = vs->sorted[nextValue++]; + } else { + nextValue++; + } + } + if(nextValue < numValues) { + if(vs->sorted) { + vs->va[vs->sorted[i]] = vs->va[j]; + vs->sorted[i] = j; + } else { + vs->va[i] = vs->va[j]; + } + nextValue++; + } else { + break; + } + } + + if(vs->sorted) { + vs->va[vs->sorted[i]] = NULL; + vs->sorted[i] = 0; + } else { + vs->va[i] = NULL; + } + + /* All the values were deleted, we can discard the whole array. */ + if(NULL == vs->va[0]) { + if(vs->sorted) { + slapi_ch_free ((void **)&vs->sorted); + } + slapi_ch_free ((void **)&vs->va); + vs->va= NULL; + } + + /* return the number of remaining values */ + return i; +} + /* * Remove any values older than the CSN. */ @@ -793,22 +812,12 @@ valueset_purge(Slapi_ValueSet *vs, const CSN *csn) { int r= 0; if(!valuearray_isempty(vs->va)) { - /* valuearray_purge is not valueset and sorting aware, - * maybe need to rewrite, at least keep the valueset - * consistent - */ - r= valuearray_purge(&vs->va, csn); + r= valueset_array_purge(vs, csn); vs->num = r; if (vs->va == NULL) { /* va was freed */ vs->max = 0; } - /* we can no longer rely on the sorting */ - if (vs->sorted != NULL) - { - slapi_ch_free ((void **)&vs->sorted); - vs->sorted = NULL; - } PR_ASSERT((vs->sorted == NULL) || (vs->num < VALUESET_ARRAY_SORT_THRESHOLD) || ((vs->num >= VALUESET_ARRAY_SORT_THRESHOLD) && (vs->sorted[0] < vs->num))); } return 0; -- 1.8.3.1