Merged revisions 319866 via svnmerge from
authorJonathan Rose <jrose@digium.com>
Thu, 19 May 2011 18:36:38 +0000 (18:36 +0000)
committerJonathan Rose <jrose@digium.com>
Thu, 19 May 2011 18:36:38 +0000 (18:36 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r319866 | jrose | 2011-05-19 13:32:38 -0500 (Thu, 19 May 2011) | 11 lines

  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/trunk@319867 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/features.c

index 23f105e..e11081b 100644 (file)
@@ -1047,42 +1047,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);
        }