Fix increment bug

This fixes duplicate $index values by:
1. Incrementing as early as possible
2. By searching the persisted config first to
make sure we don't reuse an existing $index

Tested: No more duplicate drive indexes, even with
persisted addresses

Change-Id: I7026bf284907d3c0e9bf702717be13411cab22a8
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp
index 8928b82..2f49e69 100644
--- a/src/EntityManager.cpp
+++ b/src/EntityManager.cpp
@@ -1194,6 +1194,37 @@
     return true;
 }
 
+std::string getRecordName(
+    const boost::container::flat_map<std::string, BasicVariantType>& probe,
+    const std::string& probeName)
+{
+    if (probe.empty())
+    {
+        return probeName;
+    }
+
+    // use an array so alphabetical order from the
+    // flat_map is maintained
+    auto device = nlohmann::json::array();
+    for (auto& devPair : probe)
+    {
+        device.push_back(devPair.first);
+        std::visit([&device](auto&& v) { device.push_back(v); },
+                   devPair.second);
+    }
+    size_t hash = std::hash<std::string>{}(probeName + device.dump());
+    // hashes are hard to distinguish, use the
+    // non-hashed version if we want debug
+    if constexpr (DEBUG)
+    {
+        return probeName + device.dump();
+    }
+    else
+    {
+        return std::to_string(hash);
+    }
+}
+
 PerformScan::PerformScan(
     nlohmann::json& systemConfiguration, nlohmann::json& missingConfigurations,
     std::list<nlohmann::json>& configurations,
@@ -1256,42 +1287,18 @@
                 _passed = true;
 
                 passedProbes.push_back(probeName);
-                size_t foundDeviceIdx = 1;
+                std::list<size_t> indexes(foundDevices.size());
+                std::iota(indexes.begin(), indexes.end(), 1);
 
-                for (auto& foundDevice : foundDevices)
+                size_t indexIdx = probeName.find("$index");
+                bool hasIndex = (indexIdx != std::string::npos);
+
+                // copy over persisted configurations and make sure we remove
+                // indexes that are already used
+                for (auto itr = foundDevices.begin();
+                     itr != foundDevices.end();)
                 {
-                    nlohmann::json record = *recordPtr;
-                    std::string recordName;
-                    size_t hash = 0;
-                    if (foundDevice.size())
-                    {
-                        // use an array so alphabetical order from the
-                        // flat_map is maintained
-                        auto device = nlohmann::json::array();
-                        for (auto& devPair : foundDevice)
-                        {
-                            device.push_back(devPair.first);
-                            std::visit(
-                                [&device](auto&& v) { device.push_back(v); },
-                                devPair.second);
-                        }
-                        hash =
-                            std::hash<std::string>{}(probeName + device.dump());
-                        // hashes are hard to distinguish, use the
-                        // non-hashed version if we want debug
-                        if constexpr (DEBUG)
-                        {
-                            recordName = probeName + device.dump();
-                        }
-                        else
-                        {
-                            recordName = std::to_string(hash);
-                        }
-                    }
-                    else
-                    {
-                        recordName = probeName;
-                    }
+                    std::string recordName = getRecordName(*itr, probeName);
 
                     auto fromLastJson = lastJson.find(recordName);
                     if (fromLastJson != lastJson.end())
@@ -1315,9 +1322,40 @@
                         // keep user changes
                         _systemConfiguration[recordName] = *fromLastJson;
                         _missingConfigurations.erase(recordName);
+                        itr = foundDevices.erase(itr);
+                        if (hasIndex)
+                        {
+                            auto nameIt = fromLastJson->find("Name");
+                            if (nameIt == fromLastJson->end())
+                            {
+                                std::cerr << "Last JSON Illegal\n";
+                                continue;
+                            }
+
+                            int index = std::stoi(
+                                nameIt->get<std::string>().substr(indexIdx),
+                                nullptr, 0);
+                            auto usedIt = std::find(indexes.begin(),
+                                                    indexes.end(), index);
+
+                            if (usedIt == indexes.end())
+                            {
+                                continue; // less items now
+                            }
+                            indexes.erase(usedIt);
+                        }
+
                         continue;
                     }
-
+                    itr++;
+                }
+                for (auto& foundDevice : foundDevices)
+                {
+                    nlohmann::json record = *recordPtr;
+                    std::string recordName =
+                        getRecordName(foundDevice, probeName);
+                    size_t foundDeviceIdx = indexes.front();
+                    indexes.pop_front();
                     // insert into configuration temporarily to be able to
                     // reference ourselves
 
@@ -1334,7 +1372,6 @@
                     if (findExpose == record.end())
                     {
                         _systemConfiguration[recordName] = record;
-                        foundDeviceIdx++;
                         continue;
                     }
 
@@ -1452,8 +1489,6 @@
                     // overwrite ourselves with cleaned up version
                     _systemConfiguration[recordName] = record;
                     _missingConfigurations.erase(recordName);
-
-                    foundDeviceIdx++;
                 }
             });