From: Jonathan Rose Date: Thu, 19 May 2011 18:32:38 +0000 (+0000) Subject: Fix Randomize option on Park() X-Git-Tag: 1.8.5-rc1~11^2~100 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3eaedb901c9a3b597b9a64548050800ce0bfc791;p=thirdparty%2Fasterisk.git Fix Randomize option on Park() The randomize option was generally not working like it should have at all on Park(). This patch restores intended functionality. (closes issue #18862) Reported by: davidw Tested by: jrose Review: https://reviewboard.asterisk.org/r/1222/ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@319866 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/main/features.c b/main/features.c index bcbc6814b4..c59284ab5b 100644 --- a/main/features.c +++ b/main/features.c @@ -1027,42 +1027,60 @@ static struct parkeduser *park_space_reserve(struct ast_channel *chan, struct as ast_free(pu); return NULL; } - } else { - int start; + } else { /* parkingexten not length zero, so find a usable extension in the lot to park the call */ + int start; /* The first slot we look in the parkinglot. It can be randomized. */ + int start_checked = 0; /* flag raised once the first slot is checked */ struct parkeduser *cur = NULL; + /* If using randomize mode, set start to random position on parking range */ if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) { start = ast_random() % (parkinglot->parking_stop - parkinglot->parking_start + 1); - } else { + start+=parkinglot->parking_start; + } else { /* Otherwise, just set it to the start position. */ start = parkinglot->parking_start; } + /* free parking extension linear search: O(n^2) */ for (i = start; 1; i++) { + /* If we are past the end, wrap around to the first parking slot*/ if (i == parkinglot->parking_stop + 1) { - i = parkinglot->parking_start - 1; - break; + i = parkinglot->parking_start; + } + + if (i == start) { /* At this point, if start_checked, we've exhausted all the possible slots. */ + if (start_checked) { + i = -1; + break; + } else { + start_checked = 1; + } } + /* Search the list of parked calls already in use for i. If we find it, it's in use. */ AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) { if (cur->parkingnum == i) { break; } } + + /* If list traversal was successful, we can terminate the loop here at parkinglot i */ if (!cur) { parking_space = i; break; } } - if (i == start - 1 && cur) { + /* If we exited without a match, our i value was set to -1 and we still have an item in cur. */ + if (i == -1 && cur) { ast_log(LOG_WARNING, "No more parking spaces\n"); ast_free(pu); AST_LIST_UNLOCK(&parkinglot->parkings); parkinglot_unref(parkinglot); return NULL; } + /* Set pointer for next parking */ - if (parkinglot->parkfindnext) + if (parkinglot->parkfindnext) parkinglot->parking_offset = parking_space - parkinglot->parking_start + 1; snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space); }