diff options
author | Nathan Kinder <nkinder@redhat.com> | 2008-07-31 16:22:25 +0000 |
---|---|---|
committer | Nathan Kinder <nkinder@redhat.com> | 2008-07-31 16:22:25 +0000 |
commit | 0efccdb3791412040c671b6c41294d93289e6f73 (patch) | |
tree | 2a5daecba0d2e3625dfaa6eeabe7c59ff7e27f9e /ldap | |
parent | f6bafd7eb35e1b4345f894dc3c398731b5f0dc20 (diff) | |
download | ds-0efccdb3791412040c671b6c41294d93289e6f73.tar.gz ds-0efccdb3791412040c671b6c41294d93289e6f73.tar.xz ds-0efccdb3791412040c671b6c41294d93289e6f73.zip |
Resolves: 457329
Summary: Make better use of cached DNA config information
Diffstat (limited to 'ldap')
-rw-r--r-- | ldap/servers/plugins/dna/dna.c | 238 |
1 files changed, 74 insertions, 164 deletions
diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c index 05f99dfc..e2d807ab 100644 --- a/ldap/servers/plugins/dna/dna.c +++ b/ldap/servers/plugins/dna/dna.c @@ -695,7 +695,7 @@ static void deleteConfig() Distributed ranges Helpers ****************************************************/ -static int dna_fix_maxval(Slapi_DN *dn, PRUint64 *cur, PRUint64 *max) +static int dna_fix_maxval(struct configEntry *config_entry, PRUint64 *cur) { /* TODO: check the main partition to see if another range * is available, and set the new local configuration @@ -707,8 +707,13 @@ static int dna_fix_maxval(Slapi_DN *dn, PRUint64 *cur, PRUint64 *max) return LDAP_OPERATIONS_ERROR; } -static void dna_notice_allocation(Slapi_DN *dn, PRUint64 new) +static void dna_notice_allocation(struct configEntry *config_entry, PRUint64 new) { + /* update our cached config entry with the newly allocated + * value. + */ + config_entry->nextval = new; + /* TODO: check if we passed a new chunk threshold and update * the shared configuration on the public partition. */ @@ -794,13 +799,11 @@ static LDAPControl *dna_build_sort_control(const char *attr) than config and startup ****************************************************/ -/* we do search all values between newval and maxval asking the +/* we do search all values between nextval and maxval asking the * server to sort them, then we check the first free spot and * use it as newval */ static int dna_first_free_value(struct configEntry *config_entry, - PRUint64 *newval, - PRUint64 maxval, - PRUint64 increment) + PRUint64 *newval) { Slapi_Entry **entries = NULL; Slapi_PBlock *pb = NULL; @@ -816,7 +819,7 @@ static int dna_first_free_value(struct configEntry *config_entry, prefix = config_entry->prefix; type = config_entry->type; - tmpval = *newval; + tmpval = config_entry->nextval; attrs[0] = type; attrs[1] = NULL; @@ -834,7 +837,7 @@ static int dna_first_free_value(struct configEntry *config_entry, filter = slapi_ch_smprintf("(&%s(&(%s>=%s%llu)(%s<=%s%llu)))", config_entry->filter, type, prefix?prefix:"", tmpval, - type, prefix?prefix:"", maxval); + type, prefix?prefix:"", config_entry->maxval); if (NULL == filter) { ldap_control_free(ctrls[0]); slapi_ch_free((void **)&ctrls); @@ -870,6 +873,7 @@ static int dna_first_free_value(struct configEntry *config_entry, if (NULL == entries || NULL == entries[0]) { /* no values means we already have a good value */ + *newval = tmpval; status = LDAP_SUCCESS; goto cleanup; } @@ -904,10 +908,10 @@ static int dna_first_free_value(struct configEntry *config_entry, if (tmpval != sval) break; - if (maxval < sval) + if (config_entry->maxval < sval) break; - tmpval += increment; + tmpval += config_entry->interval; } *newval = tmpval; @@ -924,201 +928,107 @@ cleanup: /* * Perform ldap operationally atomic increment * Return the next value to be assigned - * Method: - * 1. retrieve entry - * 2. do increment operations - * 3. remove current value, add new value in one operation - * 4. if failed, and less than 3 times, goto 1 */ static int dna_get_next_value(struct configEntry *config_entry, char **next_value_ret) { Slapi_PBlock *pb = NULL; - char *old_value = NULL; - Slapi_Entry *e = NULL; - Slapi_DN *dn = NULL; - char *attrlist[4]; - int attempts; + LDAPMod mod_replace; + LDAPMod *mods[2]; + char *replace_val[2]; + char next_value[16]; + PRUint64 setval = 0; + PRUint64 nextval = 0; int ret; slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM, "--> dna_get_next_value\n"); - /* get pre-requisites to search */ - dn = slapi_sdn_new_dn_byref(config_entry->dn); - attrlist[0] = DNA_NEXTVAL; - attrlist[1] = DNA_MAXVAL; - attrlist[2] = DNA_INTERVAL; - attrlist[3] = NULL; - - - /* the operation is constructed such that race conditions - * to increment the value are detected and avoided - one wins, - * one loses - however, there is no need for the server to compete - * with itself so we lock here - */ - + /* get the lock to prevent contention with other threads over + * the next new value for this range. */ slapi_lock_mutex(config_entry->new_value_lock); - for (attempts = 0; attempts < 3; attempts++) { - - LDAPMod mod_add; - LDAPMod mod_delete; - LDAPMod *mods[3]; - char *delete_val[2]; - char *add_val[2]; - char new_value[16]; - char *interval; - char *max_value; - PRUint64 increment = 1; /* default increment */ - PRUint64 setval = 0; - PRUint64 newval = 0; - PRUint64 maxval = -1; - - /* do update */ - ret = slapi_search_internal_get_entry(dn, attrlist, &e, - getPluginID()); - if (LDAP_SUCCESS != ret) { - ret = LDAP_OPERATIONS_ERROR; - goto done; - } + /* get the first value */ + ret = dna_first_free_value(config_entry, &setval); + if (LDAP_SUCCESS != ret) + goto done; - old_value = slapi_entry_attr_get_charptr(e, DNA_NEXTVAL); - if (NULL == old_value) { - ret = LDAP_OPERATIONS_ERROR; + /* try for a new range or fail */ + if (setval > config_entry->maxval) { + ret = dna_fix_maxval(config_entry, &setval); + if (LDAP_SUCCESS != ret) { + slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, + "dna_get_next_value: no more IDs available!!\n"); goto done; } - setval = strtoul(old_value, 0, 0); - - max_value = slapi_entry_attr_get_charptr(e, DNA_MAXVAL); - if (max_value) { - maxval = strtoul(max_value, 0, 0); - slapi_ch_free_string(&max_value); - } - - /* if not present the default is 1 */ - interval = slapi_entry_attr_get_charptr(e, DNA_INTERVAL); - if (NULL != interval) { - increment = strtoul(interval, 0, 0); - } - - slapi_entry_free(e); - e = NULL; - - /* check the value is actually in range */ - - /* verify the new value is actually free and get the first - * one free if not*/ - ret = dna_first_free_value(config_entry, &setval, maxval, increment); + /* get the first value from our newly extended range */ + ret = dna_first_free_value(config_entry, &setval); if (LDAP_SUCCESS != ret) goto done; + } - /* try for a new range or fail */ - if (setval > maxval) { - ret = dna_fix_maxval(dn, &setval, &maxval); - if (LDAP_SUCCESS != ret) { - slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, - "dna_get_next_value: no more IDs available!!\n"); - goto done; - } + /* ensure that we haven't gone past the end of our range */ + if (setval > config_entry->maxval) { + ret = LDAP_OPERATIONS_ERROR; + goto done; + } - /* verify the new value is actually free and get the first - * one free if not */ - ret = dna_first_free_value(config_entry, &setval, maxval, increment); - if (LDAP_SUCCESS != ret) - goto done; - } + nextval = setval + config_entry->interval; - if (setval > maxval) { - ret = LDAP_OPERATIONS_ERROR; + /* try for a new range or fail */ + if (nextval > config_entry->maxval) { + ret = dna_fix_maxval(config_entry, &nextval); + if (LDAP_SUCCESS != ret) { + slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, + "dna_get_next_value: no more IDs available!!\n"); goto done; } + } - newval = setval + increment; - - /* try for a new range or fail */ - if (newval > maxval) { - ret = dna_fix_maxval(dn, &newval, &maxval); - if (LDAP_SUCCESS != ret) { - slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, - "dna_get_next_value: no more IDs available!!\n"); - goto done; - } - } - - /* try to set the new value */ + /* try to set the new next value in the config entry */ + snprintf(next_value, sizeof(next_value),"%llu", nextval); - sprintf(new_value, "%llu", newval); + /* set up our replace modify operation */ + replace_val[0] = next_value; + replace_val[1] = 0; + mod_replace.mod_op = LDAP_MOD_REPLACE; + mod_replace.mod_type = DNA_NEXTVAL; + mod_replace.mod_values = replace_val; + mods[0] = &mod_replace; + mods[1] = 0; - delete_val[0] = old_value; - delete_val[1] = 0; + pb = slapi_pblock_new(); + if (NULL == pb) { + ret = LDAP_OPERATIONS_ERROR; + goto done; + } - mod_delete.mod_op = LDAP_MOD_DELETE; - mod_delete.mod_type = DNA_NEXTVAL; - mod_delete.mod_values = delete_val; + slapi_modify_internal_set_pb(pb, config_entry->dn, + mods, 0, 0, getPluginID(), 0); - add_val[0] = new_value; - add_val[1] = 0; + slapi_modify_internal_pb(pb); - mod_add.mod_op = LDAP_MOD_ADD; - mod_add.mod_type = DNA_NEXTVAL; - mod_add.mod_values = add_val; + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret); - mods[0] = &mod_delete; - mods[1] = &mod_add; - mods[2] = 0; + slapi_pblock_destroy(pb); + pb = NULL; - pb = slapi_pblock_new(); - if (NULL == pb) { + if (LDAP_SUCCESS == ret) { + *next_value_ret = slapi_ch_smprintf("%llu", setval); + if (NULL == *next_value_ret) { ret = LDAP_OPERATIONS_ERROR; goto done; } - slapi_modify_internal_set_pb(pb, config_entry->dn, - mods, 0, 0, getPluginID(), 0); - - slapi_modify_internal_pb(pb); - - slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret); - - slapi_pblock_destroy(pb); - pb = NULL; - slapi_ch_free_string(&interval); - slapi_ch_free_string(&old_value); - - if (LDAP_SUCCESS == ret) { - *next_value_ret = slapi_ch_smprintf("%llu", setval); - if (NULL == *next_value_ret) { - ret = LDAP_OPERATIONS_ERROR; - goto done; - } - - dna_notice_allocation(dn, newval); - goto done; - } - - if (LDAP_NO_SUCH_ATTRIBUTE != ret) { - /* not the result of a race - to change the value - */ - goto done; - } + /* update our cached config */ + dna_notice_allocation(config_entry, nextval); } done: slapi_unlock_mutex(config_entry->new_value_lock); - if (LDAP_SUCCESS != ret) - slapi_ch_free_string(&old_value); - - if (dn) - slapi_sdn_free(&dn); - - if (e) - slapi_entry_free(e); - if (pb) slapi_pblock_destroy(pb); |