Skip to content

Commit 2413ab9

Browse files
committed
[sm,servicemanager] Clear cached services if desired services exceeds app limit
Signed-off-by: Mykhailo Lohvynenko <Mykhailo_Lohvynenko@epam.com>
1 parent 37d9018 commit 2413ab9

File tree

3 files changed

+135
-30
lines changed

3 files changed

+135
-30
lines changed

include/aos/sm/servicemanager.hpp

+12-10
Original file line numberDiff line numberDiff line change
@@ -355,19 +355,21 @@ class ServiceManager : public ServiceManagerItf, public spaceallocator::ItemRemo
355355
Error RemoveItem(const String& id) override;
356356

357357
private:
358-
static constexpr auto cNumInstallThreads = AOS_CONFIG_SERVICEMANAGER_NUM_COOPERATE_INSTALLS;
359-
static constexpr auto cImageManifestFile = "manifest.json";
360-
static constexpr auto cImageBlobsFolder = "blobs";
361-
static constexpr auto cAllocatorItemLen = cServiceIDLen + cVersionLen + 1;
358+
static constexpr auto cNumInstallThreads = AOS_CONFIG_SERVICEMANAGER_NUM_COOPERATE_INSTALLS;
359+
static constexpr auto cImageManifestFile = "manifest.json";
360+
static constexpr auto cImageBlobsFolder = "blobs";
361+
static constexpr auto cAllocatorItemLen = cServiceIDLen + cVersionLen + 1;
362+
static constexpr auto cNumServiceVersions = 2;
362363

363364
Error ProcessAlreadyInstalledServices(Array<ServiceInfo>& desiredServices, Array<ServiceStatus>& serviceStatuses);
364365
Error InstallServices(const Array<ServiceInfo>& services, Array<ServiceStatus>& serviceStatuses);
365-
366-
Error RemoveDamagedServiceFolders(const Array<ServiceData>& services);
367-
Error RemoveOutdatedServices(const Array<ServiceData>& services);
368-
Error RemoveServiceFromSystem(const ServiceData& service);
369-
Error InstallService(const ServiceInfo& service);
370-
Error SetServiceState(const ServiceData& service, ServiceState state);
366+
Error PrepareSpaceForServices(size_t desiredServicesSize);
367+
Error TruncServiceVersions(const String& serviceID, size_t threshold);
368+
Error RemoveDamagedServiceFolders(const Array<ServiceData>& services);
369+
Error RemoveOutdatedServices(const Array<ServiceData>& services);
370+
Error RemoveServiceFromSystem(const ServiceData& service);
371+
Error InstallService(const ServiceInfo& service);
372+
Error SetServiceState(const ServiceData& service, ServiceState state);
371373
RetWithError<StaticString<cFilePathLen>> DigestToPath(const String& imagePath, const String& digest);
372374
RetWithError<StaticString<cAllocatorItemLen>> FormatAllocatorItemID(const ServiceData& service);
373375
RetWithError<StaticString<oci::cMaxDigestLen>> GetManifestChecksum(const String& servicePath);

src/sm/servicemanager/servicemanager.cpp

+84-7
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,19 @@ Error ServiceManager::ProcessDesiredServices(const Array<ServiceInfo>& services,
168168
return err;
169169
}
170170

171+
if (auto err = PrepareSpaceForServices(desiredServices->Size()); !err.IsNone()) {
172+
return err;
173+
}
174+
171175
if (auto err = InstallServices(*desiredServices, serviceStatuses); !err.IsNone()) {
172176
return err;
173177
}
174178

175-
// Install new services
179+
for (const auto& service : services) {
180+
if (auto err = TruncServiceVersions(service.mServiceID, cNumServiceVersions); !err.IsNone()) {
181+
LOG_WRN() << "Can't truncate service versions: serviceID=" << service.mServiceID << ", err=" << err;
182+
}
183+
}
176184

177185
LOG_DBG() << "Allocator: allocated=" << mAllocator.MaxAllocatedSize() << ", maxSize=" << mAllocator.MaxSize();
178186
#if AOS_CONFIG_THREAD_STACK_USAGE
@@ -329,12 +337,6 @@ Error ServiceManager::ProcessAlreadyInstalledServices(
329337
return storageService.mServiceID == info.mServiceID && storageService.mVersion == info.mVersion;
330338
});
331339

332-
if (auto err = serviceStatuses.EmplaceBack(
333-
storageService.mServiceID, storageService.mVersion, ItemStatusEnum::eInstalled);
334-
!err.IsNone()) {
335-
return err;
336-
}
337-
338340
if (it == desiredServices.end()) {
339341
if (storageService.mState != ServiceStateEnum::eCached) {
340342
if (auto err = SetServiceState(storageService, ServiceStateEnum::eCached); !err.IsNone()) {
@@ -349,6 +351,12 @@ Error ServiceManager::ProcessAlreadyInstalledServices(
349351
return err;
350352
}
351353

354+
if (auto err = serviceStatuses.EmplaceBack(
355+
storageService.mServiceID, storageService.mVersion, ItemStatusEnum::eInstalled);
356+
!err.IsNone()) {
357+
return err;
358+
}
359+
352360
desiredServices.Erase(it);
353361

354362
if (auto err = ValidateService(storageService); !err.IsNone()) {
@@ -395,6 +403,75 @@ Error ServiceManager::InstallServices(const Array<ServiceInfo>& services, Array<
395403
return ErrorEnum::eNone;
396404
}
397405

406+
Error ServiceManager::PrepareSpaceForServices(size_t desiredServicesSize)
407+
{
408+
auto installedServices = MakeUnique<ServiceDataStaticArray>(&mAllocator);
409+
410+
if (auto err = mStorage->GetAllServices(*installedServices); !err.IsNone()) {
411+
return err;
412+
}
413+
414+
installedServices->Sort([](const ServiceData& lhs, const ServiceData& rhs) {
415+
return lhs.mServiceID < rhs.mServiceID || semver::CompareSemver(lhs.mVersion, rhs.mVersion).mValue == -1;
416+
});
417+
418+
while (installedServices->Size() + desiredServicesSize > cMaxNumServices) {
419+
auto it = installedServices->FindIf(
420+
[](const ServiceData& service) { return service.mState == ServiceStateEnum::eCached; });
421+
422+
if (it == installedServices->end()) {
423+
return ErrorEnum::eNoMemory;
424+
}
425+
426+
if (auto err = RemoveServiceFromSystem(*it); !err.IsNone()) {
427+
return AOS_ERROR_WRAP(err);
428+
}
429+
430+
installedServices->Erase(it);
431+
}
432+
433+
return ErrorEnum::eNone;
434+
}
435+
436+
Error ServiceManager::TruncServiceVersions(const String& serviceID, size_t threshold)
437+
{
438+
auto storageServices = MakeUnique<StaticArray<ServiceData, cNumServiceVersions + 1>>(&mAllocator);
439+
440+
if (auto err = mStorage->GetServiceVersions(serviceID, *storageServices);
441+
!err.IsNone() && !err.Is(ErrorEnum::eNotFound)) {
442+
return AOS_ERROR_WRAP(err);
443+
}
444+
445+
if (storageServices->Size() <= threshold) {
446+
return ErrorEnum::eNone;
447+
}
448+
449+
LOG_DBG() << "Truncate service versions: serviceID=" << serviceID << ", versions=" << storageServices->Size()
450+
<< ", threshold=" << threshold;
451+
452+
storageServices->Sort([](const ServiceData& lhs, const ServiceData& rhs) {
453+
return semver::CompareSemver(lhs.mVersion, rhs.mVersion).mValue == -1;
454+
});
455+
456+
size_t removedVersions = 0;
457+
458+
for (const auto& service : *storageServices) {
459+
if (service.mState == ServiceStateEnum::eActive) {
460+
continue;
461+
}
462+
463+
if (auto err = RemoveService(service); !err.IsNone()) {
464+
return AOS_ERROR_WRAP(err);
465+
}
466+
467+
if (++removedVersions == storageServices->Size() - threshold) {
468+
break;
469+
}
470+
}
471+
472+
return ErrorEnum::eNone;
473+
}
474+
398475
Error ServiceManager::RemoveDamagedServiceFolders(const Array<ServiceData>& services)
399476
{
400477
LOG_DBG() << "Remove damaged service folders";

tests/sm/servicemanager/servicemanager_test.cpp

+39-13
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,6 @@ TEST_F(ServiceManagerTest, ProcessDesiredServices)
233233
{"service6", "provider6", "4.0.0", 0, "url", {}, 0},
234234
},
235235
std::vector<ServiceData> {
236-
{"service1", "provider1", "1.0.0", FS::JoinPath(cServicesDir, "service1"), "", {},
237-
ServiceStateEnum::eCached, 0, 0},
238236
{"service2", "provider2", "1.0.0", FS::JoinPath(cServicesDir, "service2"), "", {},
239237
ServiceStateEnum::eCached, 0, 0},
240238
{"service3", "provider3", "1.0.0", FS::JoinPath(cServicesDir, "service3"), "", {},
@@ -253,26 +251,54 @@ TEST_F(ServiceManagerTest, ProcessDesiredServices)
253251
ServiceStateEnum::eActive, 0, 0},
254252
},
255253
},
254+
{
255+
std::vector<ServiceInfo> {
256+
{"service1", "provider1", "3.0.0", 0, "url", {}, 0},
257+
{"service2", "provider2", "3.0.0", 0, "url", {}, 0},
258+
{"service3", "provider3", "3.0.0", 0, "url", {}, 0},
259+
{"service4", "provider4", "3.0.0", 0, "url", {}, 0},
260+
{"service5", "provider5", "3.0.0", 0, "url", {}, 0},
261+
{"service6", "provider6", "3.0.0", 0, "url", {}, 0},
262+
{"service7", "provider7", "3.0.0", 0, "url", {}, 0},
263+
{"service8", "provider8", "3.0.0", 0, "url", {}, 0},
264+
},
265+
std::vector<ServiceData> {
266+
{"service1", "provider1", "3.0.0", FS::JoinPath(cServicesDir, "service1"), "", {},
267+
ServiceStateEnum::eActive, 0, 0},
268+
{"service2", "provider2", "3.0.0", FS::JoinPath(cServicesDir, "service2"), "", {},
269+
ServiceStateEnum::eActive, 0, 0},
270+
{"service3", "provider3", "3.0.0", FS::JoinPath(cServicesDir, "service3"), "", {},
271+
ServiceStateEnum::eActive, 0, 0},
272+
{"service4", "provider4", "3.0.0", FS::JoinPath(cServicesDir, "service4"), "", {},
273+
ServiceStateEnum::eActive, 0, 0},
274+
{"service5", "provider5", "3.0.0", FS::JoinPath(cServicesDir, "service5"), "", {},
275+
ServiceStateEnum::eActive, 0, 0},
276+
{"service6", "provider6", "3.0.0", FS::JoinPath(cServicesDir, "service6"), "", {},
277+
ServiceStateEnum::eActive, 0, 0},
278+
{"service7", "provider7", "3.0.0", FS::JoinPath(cServicesDir, "service7"), "", {},
279+
ServiceStateEnum::eActive, 0, 0},
280+
{"service8", "provider8", "3.0.0", FS::JoinPath(cServicesDir, "service8"), "", {},
281+
ServiceStateEnum::eActive, 0, 0},
282+
},
283+
},
256284
{
257285
std::vector<ServiceInfo> {},
258286
std::vector<ServiceData> {
259-
{"service1", "provider1", "1.0.0", FS::JoinPath(cServicesDir, "service1"), "", {},
260-
ServiceStateEnum::eCached, 0, 0},
261-
{"service2", "provider2", "1.0.0", FS::JoinPath(cServicesDir, "service2"), "", {},
262-
ServiceStateEnum::eCached, 0, 0},
263-
{"service3", "provider3", "1.0.0", FS::JoinPath(cServicesDir, "service3"), "", {},
287+
{"service1", "provider1", "3.0.0", FS::JoinPath(cServicesDir, "service1"), "", {},
264288
ServiceStateEnum::eCached, 0, 0},
265-
{"service4", "provider4", "1.0.0", FS::JoinPath(cServicesDir, "service4"), "", {},
289+
{"service2", "provider2", "3.0.0", FS::JoinPath(cServicesDir, "service2"), "", {},
266290
ServiceStateEnum::eCached, 0, 0},
267-
{"service4", "provider4", "2.0.0", FS::JoinPath(cServicesDir, "service4"), "", {},
291+
{"service3", "provider3", "3.0.0", FS::JoinPath(cServicesDir, "service3"), "", {},
268292
ServiceStateEnum::eCached, 0, 0},
269-
{"service5", "provider5", "1.0.0", FS::JoinPath(cServicesDir, "service5"), "", {},
293+
{"service4", "provider4", "3.0.0", FS::JoinPath(cServicesDir, "service4"), "", {},
270294
ServiceStateEnum::eCached, 0, 0},
271295
{"service5", "provider5", "3.0.0", FS::JoinPath(cServicesDir, "service5"), "", {},
272296
ServiceStateEnum::eCached, 0, 0},
273-
{"service6", "provider6", "1.0.0", FS::JoinPath(cServicesDir, "service6"), "", {},
297+
{"service6", "provider6", "3.0.0", FS::JoinPath(cServicesDir, "service6"), "", {},
274298
ServiceStateEnum::eCached, 0, 0},
275-
{"service6", "provider6", "4.0.0", FS::JoinPath(cServicesDir, "service6"), "", {},
299+
{"service7", "provider7", "3.0.0", FS::JoinPath(cServicesDir, "service7"), "", {},
300+
ServiceStateEnum::eCached, 0, 0},
301+
{"service8", "provider8", "3.0.0", FS::JoinPath(cServicesDir, "service8"), "", {},
276302
ServiceStateEnum::eCached, 0, 0},
277303
},
278304
},
@@ -295,7 +321,7 @@ TEST_F(ServiceManagerTest, ProcessDesiredServices)
295321
Array<ServiceInfo>(testItem.mInfo.data(), testItem.mInfo.size()), *serviceStatuses)
296322
.IsNone());
297323

298-
ASSERT_EQ(serviceStatuses->Size(), testItem.mData.size()) << "Invalid service status size";
324+
ASSERT_EQ(serviceStatuses->Size(), testItem.mInfo.size()) << "Invalid service status size";
299325

300326
if (auto it
301327
= serviceStatuses->FindIf([](const auto& status) { return status.mStatus != ItemStatusEnum::eInstalled; });

0 commit comments

Comments
 (0)