Skip to content

Commit f090de7

Browse files
authored
Purge packs when clear global model
1 parent fb3e895 commit f090de7

9 files changed

Lines changed: 81 additions & 74 deletions

File tree

libs/rtemodel/include/RteItem.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,15 @@ class RteRootItem : public RteItem
10311031
* @return true if file has been modified and this item might represent outdated data
10321032
*/
10331033
bool IsFileTimeModified() const {
1034-
return GetModificationTime() != RteFsUtils::GetModificationTime(m_rootFileName);
1034+
return GetModificationTime() != RteFsUtils::GetModificationTime(GetRootFileName());
1035+
}
1036+
1037+
/**
1038+
* @brief check if associated file exists
1039+
* @return true if file exists
1040+
*/
1041+
bool Exists() const {
1042+
return !GetRootFileName().empty() && RteFsUtils::Exists(GetRootFileName());
10351043
}
10361044

10371045
/**

libs/rtemodel/include/RtePackage.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,6 +1335,12 @@ class RtePackRegistry
13351335
*/
13361336
bool ErasePack(const std::string& pdscFile);
13371337

1338+
/**
1339+
* @brief removes all non-existing packs
1340+
* @return true if at least one pack was removed
1341+
*/
1342+
bool PurgePacks();
1343+
13381344
/**
13391345
* @brief get collection of loaded packs
13401346
* @return const map of loaded packs (filename to RtePackage)

libs/rtemodel/src/RteKernel.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ bool RteKernel::LoadPacks(const std::list<std::string>& pdscFiles, std::list<Rte
338338
packRegistry->ErasePack(pdscFile);
339339
} else {
340340
packs.push_back(pack);
341+
pack->Reparent(model, false);
341342
continue;
342343
}
343344
bool result = xmlTree->AddFileName(pdscFile, true);
@@ -450,6 +451,8 @@ bool RteKernel::GetEffectivePdscFilesAsMap(map<string, string, RtePackageCompara
450451

451452
bool RteKernel::GetEffectivePdscFiles(std::list<std::string>& pdscFiles, bool latest) const
452453
{
454+
GetPackRegistry()->PurgePacks(); // remove non-existing files from the registry
455+
453456
map<string, string, RtePackageComparator> pdscMap;
454457
if(!GetEffectivePdscFilesAsMap(pdscMap, latest)) {
455458
return false;
@@ -463,15 +466,15 @@ bool RteKernel::GetEffectivePdscFiles(std::list<std::string>& pdscFiles, bool la
463466

464467
bool RteKernel::LoadAndInsertPacks(std::list<RtePackage*>& packs, std::list<std::string>& pdscFiles) {
465468
RteGlobalModel* globalModel = GetGlobalModel();
466-
if (!globalModel) {
469+
if(!globalModel) {
467470
return false;
468471
}
469472
std::list<RtePackage*> newPacks;
470473
pdscFiles.unique();
471-
for (const auto& pdscFile : pdscFiles) {
474+
for(const auto& pdscFile : pdscFiles) {
472475
PackageState state = pdscFile.find(GetCmsisPackRoot()) == 0 ? PS_INSTALLED : PS_EXPLICIT_PATH;
473476
RtePackage* pack = LoadPack(pdscFile, state);
474-
if (!pack) {
477+
if(!pack) {
475478
return false;
476479
}
477480
// pack with explicit path must override installed pack
@@ -480,12 +483,11 @@ bool RteKernel::LoadAndInsertPacks(std::list<RtePackage*>& packs, std::list<std:
480483
newPacks.push_back(pack);
481484
}
482485
}
483-
484486
globalModel->InsertPacks(newPacks);
485487

486488
// Track only packs that were actually inserted into the model
487489
packs.clear();
488-
for (const auto& [_, pack] : globalModel->GetPackages()) {
490+
for(const auto& [_, pack] : globalModel->GetPackages()) {
489491
packs.push_back(pack);
490492
}
491493
return true;

libs/rtemodel/src/RteModel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ void RteGlobalModel::ClearModel()
842842
{
843843
ClearProjectTargets();
844844
RteModel::ClearModel();
845-
m_packRegistry->Clear();
845+
m_packRegistry->PurgePacks(); // pack loading is expensive, only remove deleted
846846
}
847847

848848

libs/rtemodel/src/RtePackage.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,7 @@ RtePackRegistry::~RtePackRegistry()
14801480

14811481
void RtePackRegistry::Clear()
14821482
{
1483+
ClearPdscMap();
14831484
for(auto [_, p] : m_loadedPacks) {
14841485
delete p;
14851486
}
@@ -1521,5 +1522,24 @@ bool RtePackRegistry::ErasePack(const std::string& pdscFile)
15211522
return false;
15221523
}
15231524

1525+
bool RtePackRegistry::PurgePacks() {
1526+
ClearPdscMap(); // clear because packs can be added or removed after this call
1527+
1528+
set<string> toErase;
1529+
// collect packs that no longer exist
1530+
for(auto& [pdscFile, pack] : m_loadedPacks) {
1531+
if(!pack || !pack->Exists()) {
1532+
toErase.insert(pdscFile);
1533+
}
1534+
}
1535+
if(toErase.empty()) {
1536+
return false;
1537+
}
1538+
for(auto& pdscFile : toErase) {
1539+
ErasePack(pdscFile);
1540+
}
1541+
return true;
1542+
}
1543+
15241544

15251545
// End of RtePackage.cpp

libs/rtemodel/test/src/RteModelTest.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ TEST_F(RteModelTestConfig, PackRegistry) {
3333
RteModel testModel(PackageState::PS_AVAILABLE);
3434

3535
RtePackage* pack = new RtePackage(&testModel);
36+
EXPECT_FALSE(pack->Exists());
3637
pack->SetAttribute("name", "foo");
3738
pack->SetRootFileName("foo");
39+
EXPECT_FALSE(pack->Exists());
3840
EXPECT_TRUE(packRegistry->AddPack(pack));
3941
EXPECT_FALSE(packRegistry->AddPack(pack)); // not second time
4042
EXPECT_EQ(packRegistry->GetPack("foo"), pack);
@@ -45,11 +47,10 @@ TEST_F(RteModelTestConfig, PackRegistry) {
4547
EXPECT_EQ(packRegistry->GetPack("foo"), pack);
4648
EXPECT_EQ(packRegistry->GetLoadedPacks().size(), 1);
4749

48-
EXPECT_TRUE(packRegistry->ErasePack("foo"));
50+
EXPECT_TRUE(packRegistry->PurgePacks());
4951
EXPECT_EQ(packRegistry->GetPack("foo"), nullptr);
50-
EXPECT_FALSE(packRegistry->ErasePack("foo")); // already erased
52+
EXPECT_FALSE(packRegistry->ErasePack("foo")); // already erased via Purge
5153
EXPECT_EQ(packRegistry->GetLoadedPacks().size(), 0);
52-
5354
}
5455

5556
TEST_F(RteModelTestConfig, PackRegistryLoadPacks) {
@@ -80,6 +81,7 @@ TEST_F(RteModelTestConfig, PackRegistryLoadPacks) {
8081
ASSERT_NE(packs.begin(), packs.end());
8182
RtePackage* pack = *(packs.begin());
8283
ASSERT_TRUE(pack != nullptr);
84+
EXPECT_TRUE(pack->Exists());
8385
RteItem* dummyChild = new RteItem("dummy_child", pack);
8486
pack->AddItem(dummyChild);
8587
// no reload of the same files by default

libs/xmltree/include/XmlTreeItem.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,16 @@ class XmlTreeItem : public XmlItem
139139
*/
140140
virtual void Reparent(TITEM* newParent, bool addToChildren = true) {
141141
TITEM* parent = GetParent();
142-
if (parent) {
142+
if (newParent == parent) {
143+
return;
144+
}
145+
if (addToChildren && parent) { //an item can have only one parent
143146
parent->RemoveChild(GetThis(), false);
144147
}
145148
m_parent = newParent;
146-
if (addToChildren && newParent)
149+
if (addToChildren && newParent) {
147150
newParent->AddChild(GetThis());
151+
}
148152
}
149153

150154
/**

tools/projmgr/src/ProjMgrRpcServer.cpp

Lines changed: 16 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ class RpcHandler : public RpcMethods {
121121
ProjMgrRpcServer& m_server;
122122
ProjMgr& m_manager;
123123
ProjMgrWorker& m_worker;
124-
bool m_packsLoaded = false;
125124
bool m_solutionLoaded = false;
126125
bool m_bUseAllPacks = false;
127126

@@ -276,10 +275,9 @@ RpcArgs::SuccessResult RpcHandler::LoadPacks(void) {
276275
m_solutionLoaded = false;
277276
m_worker.InitializeModel();
278277
m_worker.SetLoadPacksPolicy(LoadPacksPolicy::ALL);
279-
m_packsLoaded = m_worker.LoadAllRelevantPacks();
278+
result.success = m_worker.LoadAllRelevantPacks();
280279
m_worker.SetLoadPacksPolicy(LoadPacksPolicy::DEFAULT);
281-
result.success = m_packsLoaded;
282-
if(!m_packsLoaded) {
280+
if(!result.success) {
283281
result.message = "Packs failed to load";
284282
}
285283
return result;
@@ -294,10 +292,6 @@ RpcArgs::SuccessResult RpcHandler::LoadSolution(const string& solution, const st
294292
result.message = solution + " is not a *.csolution.yml file";
295293
return result;
296294
}
297-
if(!m_packsLoaded) {
298-
result.message = "Packs must be loaded before loading solution";
299-
return result;
300-
}
301295
result.success = m_solutionLoaded = m_manager.LoadSolution(csolutionFile, activeTarget);
302296
if(!m_solutionLoaded) {
303297
result.message = "failed to load and process solution " + csolutionFile;
@@ -517,60 +511,41 @@ RpcArgs::VariablesResult RpcHandler::GetVariables(const string& context) {
517511

518512
RpcArgs::DeviceList RpcHandler::GetDeviceList(const string& context, const string& namePattern, const string& vendor)
519513
{
520-
RpcArgs::DeviceList deviceList{{false}};
521-
if(!m_packsLoaded) {
522-
deviceList.message = "Packs must be loaded before accessing device info";
523-
} else {
524-
RteTarget* rteTarget = context.empty() ? nullptr : GetActiveTarget(context);
525-
RteModel* rteModel = rteTarget ? rteTarget->GetFilteredModel() : ProjMgrKernel::Get()->GetGlobalModel();
526-
RpcDataCollector dc(rteTarget, rteModel);
527-
dc.CollectDeviceList(deviceList, namePattern, vendor);
528-
deviceList.success = true;
529-
}
514+
RpcArgs::DeviceList deviceList{{true}};
515+
RteTarget* rteTarget = context.empty() ? nullptr : GetActiveTarget(context);
516+
RteModel* rteModel = rteTarget ? rteTarget->GetFilteredModel() : ProjMgrKernel::Get()->GetGlobalModel();
517+
RpcDataCollector dc(rteTarget, rteModel);
518+
dc.CollectDeviceList(deviceList, namePattern, vendor);
530519
return deviceList;
531520
}
532521

533522
RpcArgs::DeviceInfo RpcHandler::GetDeviceInfo(const string& id)
534523
{
535524
RpcArgs::DeviceInfo deviceInfo{{false}};
536-
if(!m_packsLoaded) {
537-
deviceInfo.message = "Packs must be loaded before accessing device info";
538-
} else {
539-
RpcDataCollector dc(nullptr, ProjMgrKernel::Get()->GetGlobalModel());
540-
dc.CollectDeviceInfo(deviceInfo, id);
541-
}
525+
RpcDataCollector dc(nullptr, ProjMgrKernel::Get()->GetGlobalModel());
526+
dc.CollectDeviceInfo(deviceInfo, id);
542527
return deviceInfo;
543528
}
544529

545530
RpcArgs::BoardList RpcHandler::GetBoardList(const string& context, const string& namePattern, const string& vendor)
546531
{
547532
RpcArgs::BoardList boardList{{false}};
548-
if(!m_packsLoaded) {
549-
boardList.message = "Packs must be loaded before accessing board info";
550-
} else {
551-
RteTarget* rteTarget = context.empty() ? nullptr : GetActiveTarget(context);
552-
RteModel* rteModel = rteTarget ? rteTarget->GetFilteredModel() : ProjMgrKernel::Get()->GetGlobalModel();
553-
RpcDataCollector dc(rteTarget, rteModel);
554-
dc.CollectBoardList(boardList, namePattern, vendor);
555-
boardList.success = true;
556-
}
533+
RteTarget* rteTarget = context.empty() ? nullptr : GetActiveTarget(context);
534+
RteModel* rteModel = rteTarget ? rteTarget->GetFilteredModel() : ProjMgrKernel::Get()->GetGlobalModel();
535+
RpcDataCollector dc(rteTarget, rteModel);
536+
dc.CollectBoardList(boardList, namePattern, vendor);
537+
boardList.success = true;
557538
return boardList;
558-
559539
}
560540

561541
RpcArgs::BoardInfo RpcHandler::GetBoardInfo(const string& id)
562542
{
563543
RpcArgs::BoardInfo boardInfo{{false}};
564-
if(!m_packsLoaded) {
565-
boardInfo.message = "Packs must be loaded before accessing board info";
566-
} else {
567-
RpcDataCollector dc(nullptr, ProjMgrKernel::Get()->GetGlobalModel());
568-
dc.CollectBoardInfo(boardInfo, id);
569-
}
544+
RpcDataCollector dc(nullptr, ProjMgrKernel::Get()->GetGlobalModel());
545+
dc.CollectBoardInfo(boardInfo, id);
570546
return boardInfo;
571547
}
572548

573-
574549
RpcArgs::CtRoot RpcHandler::GetComponentsTree(const string& context, const bool& all) {
575550
RteTarget* rteTarget = GetActiveTarget(context);
576551
UpdateFilter(context, rteTarget, all);
@@ -752,11 +727,6 @@ RpcArgs::DraftProjectsInfo RpcHandler::GetDraftProjects(const RpcArgs::DraftProj
752727
RpcArgs::DraftProjectsInfo applications;
753728
applications.success = false;
754729

755-
if(!m_packsLoaded) {
756-
applications.message = "Packs must be loaded before retrieving draft projects";
757-
return applications;
758-
}
759-
760730
// initialize context and target attributes with board and device
761731
ContextItem context;
762732
m_worker.InitializeTarget(context);

tools/projmgr/test/src/ProjMgrRpcTests.cpp

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -173,21 +173,18 @@ TEST_F(ProjMgrRpcTests, RpcLoadSolutionNoPacks) {
173173
auto csolutionPath = testinput_folder + "/TestRpc/minimal.csolution.yml";
174174
const auto& requests = FormatRequest(1, "LoadSolution", json({{ "solution", csolutionPath }, { "activeTarget", "TestHW" }}));
175175
const auto& responses = RunRpcMethods(requests);
176-
EXPECT_FALSE(responses[0]["result"]["success"]);
177-
string msg = responses[0]["result"]["message"];
178-
EXPECT_EQ(msg, "Packs must be loaded before loading solution");
176+
EXPECT_TRUE(responses[0]["result"]["success"]);
179177
}
180178

181179
TEST_F(ProjMgrRpcTests, RpcDeviceListNoPacks) {
182180
const auto requests = FormatRequest(1, "GetDeviceList", json({{"context", ""},{ "namePattern", ""}, {"vendor", ""}})) +
183181
FormatRequest(2, "GetDeviceInfo", json({{ "id", "ARM::RteTest_ARMCM0"}}));
184182
const auto& responses = RunRpcMethods(requests);
185-
EXPECT_FALSE(responses[0]["result"]["success"]);
186-
string msg = responses[0]["result"]["message"];
187-
EXPECT_EQ(msg, "Packs must be loaded before accessing device info");
183+
EXPECT_TRUE(responses[0]["result"]["success"]);
184+
EXPECT_TRUE(responses[0]["result"]["devices"].empty());
188185
EXPECT_FALSE(responses[1]["result"]["success"]);
189-
msg = responses[1]["result"]["message"];
190-
EXPECT_EQ(msg, "Packs must be loaded before accessing device info");
186+
string msg = responses[1]["result"]["message"];
187+
EXPECT_EQ(msg, "Device 'ARM::RteTest_ARMCM0' not found");
191188
}
192189

193190
TEST_F(ProjMgrRpcTests, RpcDeviceListNoContext) {
@@ -312,14 +309,13 @@ TEST_F(ProjMgrRpcTests, RpcDeviceInfo) {
312309

313310
TEST_F(ProjMgrRpcTests, RpcBoardListNoPacks) {
314311
const auto requests = FormatRequest(1, "GetBoardList", json({{"context", ""},{ "namePattern", ""}, {"vendor", ""}})) +
315-
FormatRequest(2, "GetBoardInfo", json({{ "id", "ARM::RteTest_ARMCM0"}}));
312+
FormatRequest(2, "GetBoardInfo", json({{ "id", "ARM::RteTestBoard"}}));
316313
const auto& responses = RunRpcMethods(requests);
317-
EXPECT_FALSE(responses[0]["result"]["success"]);
318-
string msg = responses[0]["result"]["message"];
319-
EXPECT_EQ(msg, "Packs must be loaded before accessing board info");
314+
EXPECT_TRUE(responses[0]["result"]["success"]);
315+
EXPECT_TRUE(responses[0]["result"]["boards"].empty());
320316
EXPECT_FALSE(responses[1]["result"]["success"]);
321-
msg = responses[1]["result"]["message"];
322-
EXPECT_EQ(msg, "Packs must be loaded before accessing board info");
317+
string msg = responses[1]["result"]["message"];
318+
EXPECT_EQ(msg, "Board 'ARM::RteTestBoard' not found");
323319
}
324320

325321
TEST_F(ProjMgrRpcTests, RpcBoardListNoContext) {
@@ -1326,8 +1322,7 @@ TEST_F(ProjMgrRpcTests, RpcGetDraftProjects) {
13261322
// without loading packs
13271323
requests = FormatRequest(1, "GetDraftProjects", json{{ "filter", json::object() }});
13281324
responses = RunRpcMethods(requests);
1329-
EXPECT_FALSE(responses[0]["result"]["success"]);
1330-
EXPECT_EQ(responses[0]["result"]["message"], "Packs must be loaded before retrieving draft projects");
1325+
EXPECT_TRUE(responses[0]["result"]["success"]);
13311326
}
13321327

13331328
TEST_F(ProjMgrRpcTests, RpcConvertSolution) {

0 commit comments

Comments
 (0)