r5103 Do not fetch locations list and build location tree each time request is processed
authorAlexey Andriyanov <alan@al-an.info>
Fri, 8 Jun 2012 15:17:29 +0000 (15:17 +0000)
committerAlexey Andriyanov <alan@al-an.info>
Fri, 8 Jun 2012 15:17:29 +0000 (15:17 +0000)
no more $locationlist, $locationtree globals

listCells, spotEntity: added 'refcnt' key for 'location' realm
-getLocationList: removed, because its resulting data structure is obscure and unclean
getTagList: do not fill ci (collation-index)
getLocationSelectAJAX: fetch locationlist instead of using global
getRenderedAlloc: idem
renderRackspaceLocationEditor: idem
renderLocationFilterPortlet: idem, use tree instead of iterating list
renderRackspaceRowEditor: idem
renderEditLocationForm: idem
renderLocationRowForEditor: takes tree as argument, not tree item

wwwroot/inc/ajax-interface.php
wwwroot/inc/database.php
wwwroot/inc/functions.php
wwwroot/inc/init.php
wwwroot/inc/interface.php

index 797240ad72e40ab3a775e812e0d63e53b18bbe61..909948fd2d32822593b04e6a5cd1d3e392bb31a1 100644 (file)
@@ -138,7 +138,8 @@ function getTagSelectAJAX()
 
 function getLocationSelectAJAX()
 {
-       global $locationlist;
+       $locationlist = listCells ('location');
+       $locationtree = treeFromList ($locationlist); // adds ['trace'] keys into $locationlist items
        $options = array();
        $selected_id = '';
        if (! isset($_REQUEST['locationid']))
index 31b3ec9d2fba49b3ae7ca3bf43d94a036c525749..fcd3baea5fb676100f2c34300e8144ed80cac36f 100644 (file)
@@ -171,6 +171,7 @@ $SQLSchema = array
                        'comment' => 'comment',
                        'parent_id' => 'parent_id',
                        'parent_name' => 'parent_name',
+                       'refcnt' => "(SELECT COUNT(child_entity_id) FROM EntityLink EL WHERE EL.parent_entity_type = 'location' AND EL.parent_entity_id = Location.id)",
                ),
                'keycolumn' => 'id',
                'ordcolumns' => array ('name'),
@@ -234,41 +235,6 @@ $port_role_options = array
 
 $object_attribute_cache = array();
 
-// Return a chain of locations
-function getLocationList ()
-{
-       $ret = array();
-       $result = usePreparedSelectBlade
-       (
-               "SELECT P.id, P.name, P.parent_id, P.parent_name, count(C.id) AS refcnt " .
-               "FROM Location P LEFT JOIN Location C ON P.id = C.parent_id " .
-               "GROUP BY P.id, P.parent_id ORDER BY P.name"
-       );
-       // Collation index. The resulting rows are ordered according to default collation,
-       // which is utf8_general_ci for UTF-8.
-       $ci = 0;
-       while ($row = $result->fetch (PDO::FETCH_ASSOC))
-       {
-               if (!isset ($ret[$row['id']]))
-                       $ret[$row['id']] = array
-                       (
-                               'id' => $row['id'],
-                               'name' => $row['name'],
-                               'ci' => $ci++,
-                               'parent_id' => $row['parent_id'],
-                               'parent_name' => $row['parent_name'],
-                               'childcnt' => $row['refcnt'],
-                               'refcnt' => array ('total' => 0)
-                       );
-               if ($row['parent_id'])
-               {
-                       $ret[$row['id']]['refcnt'][$row['parent_id']] = $row['refcnt'];
-                       $ret[$row['id']]['refcnt']['total'] += $row['refcnt'];
-               }
-       }
-       return $ret;
-}
-
 // Return list of locations directly under a specified location
 function getLocations ($location_id)
 {
@@ -3687,9 +3653,6 @@ function getTagList ()
                "from TagTree left join TagStorage on id = tag_id " .
                "group by id, entity_realm order by tag"
        );
-       // Collation index. The resulting rows are ordered according to default collation,
-       // which is utf8_general_ci for UTF-8.
-       $ci = 0;
        while ($row = $result->fetch (PDO::FETCH_ASSOC))
        {
                if (!isset ($ret[$row['id']]))
@@ -3697,7 +3660,6 @@ function getTagList ()
                        (
                                'id' => $row['id'],
                                'tag' => $row['tag'],
-                               'ci' => $ci++,
                                'parent_id' => $row['parent_id'],
                                'refcnt' => array ('total' => 0)
                        );
index 826ceee02b58def5e1146e489b9d34b87f95cbd2..5adff98b5cedfd5ea71d6d57593947fe35d33445 100644 (file)
@@ -1218,6 +1218,11 @@ function peekNode ($tree, $trace, $target_id)
        throw new RackTablesError ('inconsistent tree data', RackTablesError::INTERNAL);
 }
 
+function treeItemCmp ($a, $b)
+{
+       return $a['__tree_index'] - $b['__tree_index'];
+}
+
 // Build a tree from the item list and return it. Input and output data is
 // indexed by item id (nested items in output are recursively stored in 'kids'
 // key, which is in turn indexed by id. Functions, which are ready to handle
@@ -1227,6 +1232,12 @@ function treeFromList (&$orig_nodelist, $threshold = 0, $return_main_payload = T
 {
        $tree = array();
        $nodelist = $orig_nodelist;
+
+       // index the tree items by their order in $orig_nodelist
+       $ti = 0;
+       foreach ($nodelist as &$node)
+               $node['__tree_index'] = $ti++;
+
        // Array equivalent of traceEntity() function.
        $trace = array();
        // set kidc and kids only once
@@ -1271,6 +1282,7 @@ function treeFromList (&$orig_nodelist, $threshold = 0, $return_main_payload = T
        // update each input node with its backtrace route
        foreach ($trace as $nodeid => $route)
                $orig_nodelist[$nodeid]['trace'] = $route;
+       sortTree ($tree, 'treeItemCmp'); // sort the resulting tree by the order in original list
        return $tree;
 }
 
@@ -1876,12 +1888,6 @@ function findRouters ($addrlist)
        return $ret;
 }
 
-// Assist in tag chain sorting.
-function taginfoCmp ($tagA, $tagB)
-{
-       return $tagA['ci'] - $tagB['ci'];
-}
-
 // Compare networks. When sorting a tree, the records on the list will have
 // distinct base IP addresses.
 // "The comparison function must return an integer less than, equal to, or greater
@@ -2434,7 +2440,6 @@ function makeIPTree ($netlist)
        unset ($stack);
 
        $tree = treeFromList ($netlist); // medium call
-       sortTree ($tree, 'IPNetworkCmp');
        return $tree;
 }
 
index 149c865ad722bcf6334c999d92c549d3c6962bf2..1f4c3e9d2f9f631b783bf7f6b36cd78e699ff071 100644 (file)
@@ -92,15 +92,11 @@ $tagRelCache = array();
 
 $taglist = getTagList();
 $tagtree = treeFromList ($taglist);
-sortTree ($tagtree, 'taginfoCmp');
 
-$locationlist = getLocationList();
-$locationtree = treeFromList ($locationlist);
-sortTree ($locationtree, 'taginfoCmp'); // should be locationinfoCmp, but re-using the tag function is good enough
 // Add all locations to the filter upon login
 @session_start();
 if (!isset ($_SESSION['locationFilter']))
-       $_SESSION['locationFilter'] = array_keys ($locationlist);
+       $_SESSION['locationFilter'] = array_keys (listCells ('location'));
 
 $auto_tags = array();
 // Initial chain for the current user.
index 525c4cb4a69002651c92fa0dc8da52c7ac5c1231..337d156faa40c3af1d46439ba5765d176e3e4723 100644 (file)
@@ -278,24 +278,19 @@ function getRenderedAlloc ($object_id, $alloc)
 function renderLocationFilterPortlet ()
 {
        @session_start();
-       global $locationlist;
        // Recursive function used to build the location tree
-       function renderLocationCheckbox ($parent_id, $level)
+       function renderLocationCheckbox ($subtree, $level = 0)
        {
                $self = __FUNCTION__;
-               global $locationlist;
 
-               foreach ($locationlist as $location_id => $location)
+               foreach ($subtree as $location_id => $location)
                {
-                       if ($location['parent_id'] == $parent_id)
-                       {
-                               echo "<tr><td class=tagbox style='padding-left: " . ($level * 16) . "px;'><label>";
-                               $checked = (in_array ($location['id'], $_SESSION['locationFilter'])) ? 'checked' : '';
-                               echo "<label><input type=checkbox name='location_id[]' value='${location['id']}'${checked}>${location['name']}";
-                               echo "</label></td></tr>\n";
-                               if ($location['childcnt'] > 0)
-                                       $self ($location['id'], $level + 1);
-                       }
+                       echo "<tr><td class=tagbox style='padding-left: " . ($level * 16) . "px;'><label>";
+                       $checked = (in_array ($location['id'], $_SESSION['locationFilter'])) ? 'checked' : '';
+                       echo "<label><input type=checkbox name='location_id[]' value='${location['id']}'${checked}>${location['name']}";
+                       echo "</label></td></tr>\n";
+                       if ($location['kidc'])
+                               $self ($location['kids'], $level + 1);
                }
        }
 
@@ -308,10 +303,12 @@ function renderLocationFilterPortlet ()
     <input type=hidden name=tab value=default>
     <input type=hidden name=changeLocationFilter value=true>
 END;
+
+       $locationlist = listCells ('location');
        if (count ($locationlist))
        {
                echo "<tr><td class=tagbox><hr></td></tr>\n";
-               renderLocationCheckbox ('', 0);
+               renderLocationCheckbox (treeFromList ($locationlist));
                echo "<tr><td class=tagbox><hr></td></tr>\n";
                echo "<tr><td>";
                printImageHREF ('setfilter', 'set filter', TRUE);
@@ -421,35 +418,35 @@ function renderRackspace ()
        echo "</td></tr></table>\n";
 }
 
-function renderLocationRowForEditor ($locationinfo, $level = 0)
+function renderLocationRowForEditor ($subtree, $level = 0)
 {
        $self = __FUNCTION__;
-       global $locationlist;
-       if (!count ($locationinfo['kids']))
-               $level++; // Idem
-       echo "<tr><td align=left style='padding-left: " . ($level * 16) . "px;'>";
-       if ($locationinfo['kidc'])
-               printImageHREF ('node-expanded-static');
-       if ($locationinfo['refcnt']['total'] > 0 or $locationinfo['kidc'])
-               printImageHREF ('nodestroy');
-       else
-               echo '<a href="' . makeHrefProcess (array ('op' => 'deleteLocation', 'location_id' => $locationinfo['id']))
-                       . '">' . getImageHREF ('destroy', 'Delete location') . '</a>';
-       echo '</td><td class=tdleft>';
-       printOpFormIntro ('updateLocation', array ('location_id' => $locationinfo['id']));
-       $parent = isset ($locationinfo['parent_id']) ? $locationinfo['parent_id'] : 0;
-       echo getSelect
-       (
-               array ( $parent => $parent ? htmlspecialchars ($locationlist[$parent]['name']) : '-- NONE --'),
-               array ('name' => 'parent_id', 'id' => 'locationid_' . $locationinfo['id'], 'class' => 'locationlist-popup'),
-               $parent,
-               FALSE
-       );
-       echo "</td><td class=tdleft>";
-       echo "<input type=text size=48 name=name value='${locationinfo['name']}'>";
-       echo '</td><td>' . getImageHREF ('save', 'Save changes', TRUE) . "</form></td></tr>\n";
-       foreach ($locationinfo['kids'] as $kid)
-               $self ($kid, $level + 1);
+       foreach ($subtree as $locationinfo)
+       {
+               echo "<tr><td align=left style='padding-left: " . ($locationinfo['kidc'] ? $level : ($level + 1) * 16) . "px;'>";
+               if ($locationinfo['kidc'])
+                       printImageHREF ('node-expanded-static');
+               if ($locationinfo['refcnt'] > 0 || $locationinfo['kidc'] > 0)
+                       printImageHREF ('nodestroy');
+               else
+                       echo '<a href="' . makeHrefProcess (array ('op' => 'deleteLocation', 'location_id' => $locationinfo['id']))
+                               . '">' . getImageHREF ('destroy', 'Delete location') . '</a>';
+               echo '</td><td class=tdleft>';
+               printOpFormIntro ('updateLocation', array ('location_id' => $locationinfo['id']));
+               $parent = isset ($locationinfo['parent_id']) ? $locationinfo['parent_id'] : 0;
+               echo getSelect
+               (
+                       array ( $parent => $parent ? htmlspecialchars ($locationinfo['parent_name']) : '-- NONE --'),
+                       array ('name' => 'parent_id', 'id' => 'locationid_' . $locationinfo['id'], 'class' => 'locationlist-popup'),
+                       $parent,
+                       FALSE
+               );
+               echo "</td><td class=tdleft>";
+               echo "<input type=text size=48 name=name value='${locationinfo['name']}'>";
+               echo '</td><td>' . getImageHREF ('save', 'Save changes', TRUE) . "</form></td></tr>\n";
+               if ($locationinfo['kidc'])
+                       $self ($locationinfo['kids'], $level + 1);
+       }
 }
 
 function renderRackspaceLocationEditor ()
@@ -469,28 +466,28 @@ END
        );
        function printNewItemTR ()
        {
-               global $locationlist;
                printOpFormIntro ('addLocation');
                echo "<tr><td>";
                printImageHREF ('create', 'Add new location', TRUE);
                echo "</td><td><select name=parent_id tabindex=100>";
                echo "<option value=0>-- NONE --</option>";
-               foreach ($locationlist as $location)
+               foreach (listCells ('location') as $location)
                        echo "<option value=${location['id']}>${location['name']}</option>";
                echo "</select></td>";
                echo "<td><input type=text size=48 name=name tabindex=101></td><td>";
                printImageHREF ('create', 'Add new location', TRUE, 102);
                echo "</td></tr></form>\n";
        }
-       global $locationlist, $locationtree;
+       global $locationtree;
 
        startPortlet ('Locations');
        echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
        echo "<tr><th>&nbsp;</th><th>Parent</th><th>Name</th><th>&nbsp;</th></tr>\n";
        if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
                printNewItemTR();
-       foreach ($locationtree as $locationinfo)
-               renderLocationRowForEditor ($locationinfo);
+
+       renderLocationRowForEditor (treeFromList (listCells ('location')));
+
        if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
                printNewItemTR();
        echo "</table><br>\n";
@@ -499,9 +496,8 @@ END
 
 function renderRackspaceRowEditor ()
 {
-       function printNewItemTR ()
+       function printNewItemTR ($locationlist)
        {
-               global $locationlist;
                printOpFormIntro ('addRow');
                echo "<tr><td>";
                printImageHREF ('create', 'Add new row', TRUE);
@@ -514,13 +510,13 @@ function renderRackspaceRowEditor ()
                printImageHREF ('create', 'Add new row', TRUE, 102);
                echo "</td></tr></form>";
        }
-       global $locationlist;
+       $locationlist = listCells ('location');
 
        startPortlet ('Rows');
        echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
        echo "<tr><th>&nbsp;</th><th>Location</th><th>Name</th><th>&nbsp;</th></tr>\n";
        if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
-               printNewItemTR();
+               printNewItemTR($locationlist);
        foreach (getAllRows() as $row_id => $rowInfo)
        {
                echo "<tr><td>";
@@ -544,7 +540,7 @@ function renderRackspaceRowEditor ()
                echo "</form></td></tr>\n";
        }
        if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
-               printNewItemTR();
+               printNewItemTR($locationlist);
        echo "</table><br>\n";
        finishPortlet();
 }
@@ -3799,7 +3795,7 @@ function renderEditLocationForm ($location_id)
        echo "<tr><td>&nbsp;</td><th class=tdright>Parent location:</th><td class=tdleft>";
        $locations = array ();
        $locations[0] = '-- NOT SET --';
-       foreach (getLocationList () as $id => $locationInfo)
+       foreach (listCells ('location') as $id => $locationInfo)
                $locations[$id] = $locationInfo['name'];
        natcasesort($locations);
        printSelect ($locations, array ('name' => 'parent_id'), $location['parent_id']);