Call freeSpace() function before update

Add new function to delete version objects as part of the Activation.
The code update service automatically removes the ubi volumes to make
space, but it does not remove the dbus object associated with the
removed volume. The side effect of leaving the dbus object is that
when freePriority() is called at the end of the Activation, a new
priority value is assigned to all version dbus objects (including the
deleted one) which fills up the u-boot environment variables.

Tested: Verified that after an Activation, there were only 2 priority
values in the u-boot env variables instead of 3, and they corresponded
to existing volumes.

Change-Id: I41a7ea95eeea1c8a2cb8ce4b41671e77f5c42cac
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/item_updater.cpp b/item_updater.cpp
index e4c9e9c..1596a4b 100644
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -1,4 +1,5 @@
 #include <fstream>
+#include <queue>
 #include <set>
 #include <string>
 #include <phosphor-logging/log.hpp>
@@ -658,6 +659,44 @@
     updateUbootEnvVars(lowestPriorityVersion);
 }
 
+void ItemUpdater::freeSpace()
+{
+    //  Versions with the highest priority in front
+    std::priority_queue<std::pair<int, std::string>,
+                        std::vector<std::pair<int, std::string>>,
+                        std::less<std::pair<int, std::string>>> versionsPQ;
+
+    std::size_t count = 0;
+    for (const auto& iter : activations)
+    {
+        if ((iter.second.get()->activation() ==
+                    server::Activation::Activations::Active)  ||
+            (iter.second.get()->activation() ==
+                    server::Activation::Activations::Failed))
+        {
+            count++;
+            // Don't put the functional version on the queue since we can't
+            // remove the "running" BMC version.
+            if (versions.find(iter.second->versionId)->second->isFunctional())
+            {
+                continue;
+            }
+            versionsPQ.push(std::make_pair(
+                    iter.second->redundancyPriority.get()->priority(),
+                    iter.second->versionId));
+        }
+    }
+
+    // If the number of BMC versions is over ACTIVE_BMC_MAX_ALLOWED -1,
+    // remove the highest priority one(s).
+    while ((count >= ACTIVE_BMC_MAX_ALLOWED) && (!versionsPQ.empty()))
+    {
+        erase(versionsPQ.top().second);
+        versionsPQ.pop();
+        count--;
+    }
+}
+
 } // namespace updater
 } // namespace software
 } // namespace phosphor