From 1ccc3e7d15e01d7eac41d4e22c23c13da2f0a7cd Mon Sep 17 00:00:00 2001 From: Mykola Kobets Date: Tue, 20 Jan 2026 13:35:34 +0200 Subject: [PATCH] cm: database: persist version in launcher::InstanceInfo Signed-off-by: Mykola Kobets --- src/cm/database/database.cpp | 17 ++++++----- src/cm/database/database.hpp | 5 ++-- src/cm/database/tests/database.cpp | 45 +++++++++++++++++++----------- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/cm/database/database.cpp b/src/cm/database/database.cpp index 66dd6544..080926cf 100644 --- a/src/cm/database/database.cpp +++ b/src/cm/database/database.cpp @@ -475,8 +475,8 @@ Error Database::AddInstance(const launcher::InstanceInfo& info) FromAos(info, row); *mSession << "INSERT INTO launcher_instances (itemID, subjectID, instance, type, manifestDigest, " - "nodeID, prevNodeID, runtimeID, uid, gid, timestamp, state, isUnitSubject) " - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);", + "nodeID, prevNodeID, runtimeID, uid, gid, timestamp, state, isUnitSubject, version) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);", bind(row), now; } catch (const std::exception& e) { return AOS_ERROR_WRAP(common::utils::ToAosError(e)); @@ -494,12 +494,12 @@ Error Database::UpdateInstance(const launcher::InstanceInfo& info) statement << "UPDATE launcher_instances SET manifestDigest = ?, nodeID = ?, prevNodeID = " "?, runtimeID = ?, uid = ?, gid = ?, timestamp = ?, state = ?, isUnitSubject = ? " - "WHERE itemID = ? AND subjectID = ? AND instance = ? AND type = ?;", + "WHERE itemID = ? AND subjectID = ? AND instance = ? AND type = ? AND version = ?;", bind(info.mManifestDigest.CStr()), bind(info.mNodeID.CStr()), bind(info.mPrevNodeID.CStr()), bind(info.mRuntimeID.CStr()), bind(info.mUID), bind(info.mGID), bind(info.mTimestamp.UnixNano()), bind(info.mState.ToString().CStr()), bind(info.mIsUnitSubject), bind(info.mInstanceIdent.mItemID.CStr()), bind(info.mInstanceIdent.mSubjectID.CStr()), bind(info.mInstanceIdent.mInstance), - bind(info.mInstanceIdent.mType.ToString().CStr()); + bind(info.mInstanceIdent.mType.ToString().CStr()), bind(info.mVersion.CStr()); if (statement.execute() != 1) { return ErrorEnum::eNotFound; @@ -519,7 +519,7 @@ Error Database::GetInstance(const InstanceIdent& instanceID, launcher::InstanceI std::vector rows; *mSession << "SELECT itemID, subjectID, instance, type, manifestDigest, nodeID, prevNodeID, " - "runtimeID, uid, gid, timestamp, state, isUnitSubject " + "runtimeID, uid, gid, timestamp, state, isUnitSubject, version " "FROM launcher_instances WHERE itemID = ? AND subjectID = ? AND instance = ? AND type = ?;", bind(instanceID.mItemID.CStr()), bind(instanceID.mSubjectID.CStr()), bind(instanceID.mInstance), bind(instanceID.mType.ToString().CStr()), into(rows), now; @@ -544,7 +544,7 @@ Error Database::GetActiveInstances(Array& instances) con std::vector rows; *mSession << "SELECT itemID, subjectID, instance, type, manifestDigest, nodeID, prevNodeID, " - "runtimeID, uid, gid, timestamp, state, isUnitSubject FROM launcher_instances;", + "runtimeID, uid, gid, timestamp, state, isUnitSubject, version FROM launcher_instances;", into(rows), now; auto instanceInfo = std::make_unique(); @@ -781,7 +781,8 @@ void Database::CreateTables() "timestamp INTEGER," "state TEXT," "isUnitSubject INTEGER," - "PRIMARY KEY(itemID,subjectID,instance,type)" + "version TEXT," + "PRIMARY KEY(itemID,subjectID,instance,type,version)" ");", now; } @@ -889,6 +890,7 @@ void Database::FromAos(const launcher::InstanceInfo& src, LauncherInstanceInfoRo dst.set(src.mTimestamp.UnixNano()); dst.set(src.mState.ToString().CStr()); dst.set(src.mIsUnitSubject); + dst.set(src.mVersion.CStr()); } void Database::ToAos(const LauncherInstanceInfoRow& src, launcher::InstanceInfo& dst) @@ -910,6 +912,7 @@ void Database::ToAos(const LauncherInstanceInfoRow& src, launcher::InstanceInfo& dst.mTimestamp = Time::Unix(timestamp / Time::cSeconds.Nanoseconds(), timestamp % Time::cSeconds.Nanoseconds()); dst.mIsUnitSubject = src.get(); + dst.mVersion = src.get().c_str(); const auto& stateStr = src.get(); AOS_ERROR_CHECK_AND_THROW(dst.mState.FromString(stateStr.c_str()), "failed to parse instance state"); diff --git a/src/cm/database/database.hpp b/src/cm/database/database.hpp index 89cba64a..2a35dd72 100644 --- a/src/cm/database/database.hpp +++ b/src/cm/database/database.hpp @@ -322,10 +322,11 @@ class Database : public storagestate::StorageItf, eGID, eTimestamp, eState, - eIsUnitSubject + eIsUnitSubject, + eVersion }; using LauncherInstanceInfoRow = Poco::Tuple; + std::string, std::string, std::string, uint32_t, uint32_t, uint64_t, std::string, bool, std::string>; enum class ImageManagerItemInfoColumns : int { eItemID = 0, eVersion, eIndexDigest, eState, eTimestamp }; using ImageManagerItemInfoRow = Poco::Tuple; diff --git a/src/cm/database/tests/database.cpp b/src/cm/database/tests/database.cpp index cdd8d48b..ab2e795b 100644 --- a/src/cm/database/tests/database.cpp +++ b/src/cm/database/tests/database.cpp @@ -103,7 +103,8 @@ networkmanager::Instance CreateInstance(const char* itemID, const char* subjectI launcher::InstanceInfo CreateLauncherInstanceInfo(const char* itemID, const char* subjectID, uint64_t instance, const char* manifestDigest, const char* nodeID, UpdateItemType itemType = UpdateItemTypeEnum::eService, - launcher::InstanceStateEnum state = launcher::InstanceStateEnum::eCached, bool isUnitSubject = false) + launcher::InstanceStateEnum state = launcher::InstanceStateEnum::eCached, bool isUnitSubject = false, + const char* version = "1.0.0") { launcher::InstanceInfo info; @@ -117,6 +118,7 @@ launcher::InstanceInfo CreateLauncherInstanceInfo(const char* itemID, const char info.mTimestamp = Time::Now(); info.mState = state; info.mIsUnitSubject = isUnitSubject; + info.mVersion = version; return info; } @@ -497,26 +499,32 @@ TEST_F(CMDatabaseTest, LauncherAddInstance) ASSERT_TRUE(mDB.Init(mDatabaseConfig).IsNone()); auto instance1 = CreateLauncherInstanceInfo("service1", "subject1", 0, "image1", "node1", - UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, false); + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, false, "1.0.0"); auto instance2 = CreateLauncherInstanceInfo("service1", "subject1", 1, "image1", "node1", - UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eCached, true); + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eCached, true, "1.0.0"); auto instance3 = CreateLauncherInstanceInfo("service2", "subject2", 0, "image2", "node2", - UpdateItemTypeEnum::eComponent, launcher::InstanceStateEnum::eDisabled, false); + UpdateItemTypeEnum::eComponent, launcher::InstanceStateEnum::eDisabled, false, "2.0.0"); // Add instances ASSERT_TRUE(mDB.AddInstance(instance1).IsNone()); ASSERT_TRUE(mDB.AddInstance(instance2).IsNone()); ASSERT_TRUE(mDB.AddInstance(instance3).IsNone()); - // Add duplicate instance - auto duplicateInstance = CreateLauncherInstanceInfo("service1", "subject1", 0, "image99", "node99"); + // Add duplicate instance (same primary key including version) + auto duplicateInstance = CreateLauncherInstanceInfo("service1", "subject1", 0, "image99", "node99", + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eCached, false, "1.0.0"); ASSERT_FALSE(mDB.AddInstance(duplicateInstance).IsNone()); + // Add instance with same InstanceIdent but different version (should succeed) + auto instance1v2 = CreateLauncherInstanceInfo("service1", "subject1", 0, "image1", "node1", + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, false, "2.0.0"); + ASSERT_TRUE(mDB.AddInstance(instance1v2).IsNone()); + // Verify instances - StaticArray instances; + StaticArray instances; ASSERT_TRUE(mDB.GetActiveInstances(instances).IsNone()); - EXPECT_THAT(ToVector(instances), UnorderedElementsAre(instance1, instance2, instance3)); + EXPECT_THAT(ToVector(instances), UnorderedElementsAre(instance1, instance2, instance3, instance1v2)); } TEST_F(CMDatabaseTest, LauncherUpdateInstance) @@ -524,9 +532,9 @@ TEST_F(CMDatabaseTest, LauncherUpdateInstance) ASSERT_TRUE(mDB.Init(mDatabaseConfig).IsNone()); auto instance1 = CreateLauncherInstanceInfo("service1", "subject1", 0, "image1", "node1", - UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eCached, false); + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eCached, false, "1.0.0"); auto instance2 = CreateLauncherInstanceInfo("service2", "subject2", 0, "image2", "node2", - UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, true); + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, true, "1.0.0"); // Add instances ASSERT_TRUE(mDB.AddInstance(instance1).IsNone()); @@ -544,7 +552,8 @@ TEST_F(CMDatabaseTest, LauncherUpdateInstance) ASSERT_TRUE(mDB.UpdateInstance(instance1).IsNone()); // Update non-existent instance - auto nonExistentInstance = CreateLauncherInstanceInfo("nonexistent", "subject", 99, "image99", "node99"); + auto nonExistentInstance = CreateLauncherInstanceInfo("nonexistent", "subject", 99, "image99", "node99", + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eCached, false, "1.0.0"); ASSERT_FALSE(mDB.UpdateInstance(nonExistentInstance).IsNone()); // Verify updated instance @@ -564,9 +573,9 @@ TEST_F(CMDatabaseTest, LauncherGetInstance) ASSERT_TRUE(mDB.Init(mDatabaseConfig).IsNone()); auto instance1 = CreateLauncherInstanceInfo("service1", "subject1", 0, "image1", "node1", - UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, false); + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, false, "1.0.0"); auto instance2 = CreateLauncherInstanceInfo("service2", "subject2", 0, "image2", "node2", - UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eCached, true); + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eCached, true, "2.0.0"); // Add instances ASSERT_TRUE(mDB.AddInstance(instance1).IsNone()); @@ -577,9 +586,11 @@ TEST_F(CMDatabaseTest, LauncherGetInstance) ASSERT_TRUE(mDB.GetInstance(instance1.mInstanceIdent, retrievedInstance).IsNone()); EXPECT_EQ(retrievedInstance, instance1); + EXPECT_EQ(retrievedInstance.mVersion, "1.0.0"); ASSERT_TRUE(mDB.GetInstance(instance2.mInstanceIdent, retrievedInstance).IsNone()); EXPECT_EQ(retrievedInstance, instance2); + EXPECT_EQ(retrievedInstance.mVersion, "2.0.0"); // Get non-existent instance auto nonExistentIdent = CreateInstanceIdent("nonexistent", "subject", 99); @@ -596,9 +607,9 @@ TEST_F(CMDatabaseTest, LauncherGetActiveInstances) EXPECT_EQ(emptyInstances.Size(), 0); auto instance1 = CreateLauncherInstanceInfo("service1", "subject1", 0, "image1", "node1", - UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, false); + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, false, "1.0.0"); auto instance2 = CreateLauncherInstanceInfo("service2", "subject2", 0, "image2", "node2", - UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eDisabled, true); + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eDisabled, true, "2.0.0"); // Add instances ASSERT_TRUE(mDB.AddInstance(instance1).IsNone()); @@ -616,9 +627,9 @@ TEST_F(CMDatabaseTest, LauncherRemoveInstance) ASSERT_TRUE(mDB.Init(mDatabaseConfig).IsNone()); auto instance1 = CreateLauncherInstanceInfo("service1", "subject1", 0, "image1", "node1", - UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eCached, true); + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eCached, true, "1.0.0"); auto instance2 = CreateLauncherInstanceInfo("service2", "subject2", 0, "image2", "node2", - UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, false); + UpdateItemTypeEnum::eService, launcher::InstanceStateEnum::eActive, false, "2.0.0"); ASSERT_TRUE(mDB.AddInstance(instance1).IsNone()); ASSERT_TRUE(mDB.AddInstance(instance2).IsNone());