diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 4b2992303..25cbaa7f3 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -131,85 +131,60 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version bool Database::GetUnusedInstanceID(uint16 &instance_id) { uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances); - uint32 max = 32000; + uint32 max_instance_id = 32000; + // sanity check reserved + if (max_reserved_instance_id >= max_instance_id) { + instance_id = 0; + return false; + } + + // initial query - get max unused id above reserved auto query = fmt::format( "SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}", max_reserved_instance_id, max_reserved_instance_id ); + // recycle instances - change query to get first unused id above reserved if (RuleB(Instances, RecycleInstanceIds)) { - query = ( + query = fmt::format( SQL( - SELECT i.id + 1 AS next_available + SELECT MIN(i.id + 1) AS next_available FROM instance_list i - LEFT JOIN instance_list i2 ON i2.id = i.id + 1 - WHERE i2.id IS NULL - ORDER BY i.id - LIMIT 0, 1; - - ) + LEFT JOIN instance_list i2 ON i.id + 1 = i2.id + WHERE i.id > {} + AND i2.id IS NULL; + ), + RuleI(Instances, ReservedInstances) ); } auto results = QueryDatabase(query); + // could not successfully query - bail out if (!results.Success()) { instance_id = 0; return false; } + // no instances running - assign first id above reserved if (results.RowCount() == 0) { - instance_id = max_reserved_instance_id; + instance_id = max_reserved_instance_id + 1; return true; } auto row = results.begin(); - if (Strings::ToInt(row[0]) <= max) { + // check that id is within limits + if (Strings::ToInt(row[0]) <= max_instance_id) { instance_id = Strings::ToInt(row[0]); - return true; } - if (instance_id < max_reserved_instance_id) { - instance_id = max_reserved_instance_id; - return true; - } - - query = fmt::format("SELECT id FROM instance_list where id > {} ORDER BY id", max_reserved_instance_id); - results = QueryDatabase(query); - - if (!results.Success()) { - instance_id = 0; - return false; - } - - if (results.RowCount() == 0) { - instance_id = 0; - return false; - } - - max_reserved_instance_id++; - - for (auto row : results) { - if (max_reserved_instance_id < Strings::ToUnsignedInt(row[0])) { - instance_id = max_reserved_instance_id; - return true; - } - - if (max_reserved_instance_id > max) { - instance_id = 0; - return false; - } - - max_reserved_instance_id++; - } - - instance_id = max_reserved_instance_id; - - return true; + // unhandled situation - should not reach here + instance_id = 0; + return false; } bool Database::IsGlobalInstance(uint16 instance_id)