diff --git a/src/servers/package/Root.cpp b/src/servers/package/Root.cpp index 7a138789a5..012f5d0276 100644 --- a/src/servers/package/Root.cpp +++ b/src/servers/package/Root.cpp @@ -202,10 +202,43 @@ Root::_GetVolume(PackageFSMountType mountType) } +Volume* +Root::_NextVolumeFor(Volume* volume) +{ + if (volume == NULL) + return NULL; + + PackageFSMountType mountType = volume->MountType(); + + do { + switch (mountType) { + case PACKAGE_FS_MOUNT_TYPE_HOME: + mountType = PACKAGE_FS_MOUNT_TYPE_COMMON; + break; + case PACKAGE_FS_MOUNT_TYPE_COMMON: + mountType = PACKAGE_FS_MOUNT_TYPE_SYSTEM; + break; + case PACKAGE_FS_MOUNT_TYPE_SYSTEM: + case PACKAGE_FS_MOUNT_TYPE_CUSTOM: + default: + return NULL; + } + + volume = *_GetVolume(mountType); + } while (volume == NULL); + + return volume; +} + + void Root::_InitPackages(Volume* volume) { - volume->InitPackages(this); + if (volume->InitPackages(this) == B_OK) { + Volume* nextVolume = _NextVolumeFor(volume); + Volume* nextNextVolume = _NextVolumeFor(nextVolume); + volume->InitialVerify(nextVolume, nextNextVolume); + } } diff --git a/src/servers/package/Root.h b/src/servers/package/Root.h index b2afd2c6e9..4709d32f86 100644 --- a/src/servers/package/Root.h +++ b/src/servers/package/Root.h @@ -52,6 +52,7 @@ private: private: Volume** _GetVolume(PackageFSMountType mountType); + Volume* _NextVolumeFor(Volume* volume); void _InitPackages(Volume* volume); void _DeleteVolume(Volume* volume); diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp index b3664924f0..f5082baab9 100644 --- a/src/servers/package/Volume.cpp +++ b/src/servers/package/Volume.cpp @@ -20,6 +20,13 @@ #include #include +#include +#include +#include +#include +#include +#include + #include #include @@ -205,6 +212,114 @@ Volume::InitPackages(Listener* listener) } +status_t +Volume::AddPackagesToRepository(BSolverRepository& repository, bool activeOnly) +{ + for (PackageFileNameHashTable::Iterator it + = fPackagesByFileName.GetIterator(); it.HasNext();) { + Package* package = it.Next(); + if (activeOnly && !package->IsActive()) + continue; + + status_t error = repository.AddPackage(package->Info()); + if (error != B_OK) { + ERROR("Volume::AddPackagesToRepository(): failed to add package %s " + "to repository: %s\n", package->FileName().String(), + strerror(error)); + return error; + } + } + + return B_OK; +} + + +void +Volume::InitialVerify(Volume* nextVolume, Volume* nextNextVolume) +{ +INFORM("Volume::InitialVerify(%p, %p)\n", nextVolume, nextNextVolume); + // create the solver + BSolver* solver; + status_t error = BSolver::Create(solver); + if (error != B_OK) { + ERROR("Volume::InitialVerify(): failed to create solver: %s\n", + strerror(error)); + return; + } + ObjectDeleter solverDeleter(solver); + + // add a repository with all active packages + BSolverRepository repository; + error = _AddRepository(solver, repository, true, true); + if (error != B_OK) { + ERROR("Volume::InitialVerify(): failed to add repository: %s\n", + strerror(error)); + return; + } + + // add a repository for the next volume + BSolverRepository nextRepository; + if (nextVolume != NULL) { + nextRepository.SetPriority(1); + error = nextVolume->_AddRepository(solver, nextRepository, true, false); + if (error != B_OK) { + ERROR("Volume::InitialVerify(): failed to add repository: %s\n", + strerror(error)); + return; + } + } + + // add a repository for the next next volume + BSolverRepository nextNextRepository; + if (nextNextVolume != NULL) { + nextNextRepository.SetPriority(2); + error = nextNextVolume->_AddRepository(solver, nextNextRepository, true, + false); + if (error != B_OK) { + ERROR("Volume::InitialVerify(): failed to add repository: %s\n", + strerror(error)); + return; + } + } + + // verify + error = solver->VerifyInstallation(); + if (error != B_OK) { + ERROR("Volume::InitialVerify(): failed to verify: %s\n", + strerror(error)); + return; + } + + if (!solver->HasProblems()) { + INFORM("Volume::InitialVerify(): volume at \"%s\" is consistent\n", + Path().String()); + return; + } + + // print the problems +// TODO: Notify the user ... + INFORM("Volume::InitialVerify(): volume at \"%s\" has problems:\n", + Path().String()); + + int32 problemCount = solver->CountProblems(); + for (int32 i = 0; i < problemCount; i++) { + BSolverProblem* problem = solver->ProblemAt(i); + INFORM(" %" B_PRId32 ": %s\n", i + 1, problem->ToString().String()); + int32 solutionCount = problem->CountSolutions(); + for (int32 k = 0; k < solutionCount; k++) { + const BSolverProblemSolution* solution = problem->SolutionAt(k); + INFORM(" solution %" B_PRId32 ":\n", k + 1); + int32 elementCount = solution->CountElements(); + for (int32 l = 0; l < elementCount; l++) { + const BSolverProblemSolutionElement* element + = solution->ElementAt(l); + INFORM(" - %s\n", element->ToString().String()); + } + } + } +} + + void Volume::Unmounted() { @@ -647,3 +762,34 @@ for (PackageNodeRefHashTable::Iterator it = fPackagesByNodeRef.GetIterator(); return B_OK; } + + +status_t +Volume::_AddRepository(BSolver* solver, BSolverRepository& repository, + bool activeOnly, bool installed) +{ + status_t error = repository.SetTo(Path()); + if (error != B_OK) { + ERROR("Volume::_AddRepository(): failed to init repository: %s\n", + strerror(error)); + return error; + } + + repository.SetInstalled(installed); + + error = AddPackagesToRepository(repository, true); + if (error != B_OK) { + ERROR("Volume::_AddRepository(): failed to add packages to " + "repository: %s\n", strerror(error)); + return error; + } + + error = solver->AddRepository(&repository); + if (error != B_OK) { + ERROR("Volume::_AddRepository(): failed to add repository to solver: " + "%s\n", strerror(error)); + return error; + } + + return B_OK; +} diff --git a/src/servers/package/Volume.h b/src/servers/package/Volume.h index b83bc401cd..ba95caac5a 100644 --- a/src/servers/package/Volume.h +++ b/src/servers/package/Volume.h @@ -25,6 +25,11 @@ class BDirectory; class Root; +namespace BPackageKit { + class BSolver; + class BSolverRepository; +} + class Volume : public BHandler { public: @@ -38,6 +43,12 @@ public: node_ref& _packageRootRef); status_t InitPackages(Listener* listener); + status_t AddPackagesToRepository( + BSolverRepository& repository, + bool activeOnly); + void InitialVerify(Volume* nextVolume, + Volume* nextNextVolume); + void Unmounted(); virtual void MessageReceived(BMessage* message); @@ -98,6 +109,10 @@ private: status_t _ReadPackagesDirectory(); status_t _GetActivePackages(int fd); + status_t _AddRepository(BSolver* solver, + BSolverRepository& repository, + bool activeOnly, bool installed); + private: BString fPath; PackageFSMountType fMountType;