package daemon: Check volume package dependencies initially

Dumps the result (i.e. found problems and solutions) to the syslog.
Eventually the user should be asked what to do when inconsistencies are
encountered.
This commit is contained in:
Ingo Weinhold 2013-04-09 19:51:10 +02:00
parent 4b3ca457b6
commit 92b6d58598
4 changed files with 196 additions and 1 deletions

View File

@ -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);
}
}

View File

@ -52,6 +52,7 @@ private:
private:
Volume** _GetVolume(PackageFSMountType mountType);
Volume* _NextVolumeFor(Volume* volume);
void _InitPackages(Volume* volume);
void _DeleteVolume(Volume* volume);

View File

@ -20,6 +20,13 @@
#include <NodeMonitor.h>
#include <Path.h>
#include <package/solver/Solver.h>
#include <package/solver/SolverPackage.h>
#include <package/solver/SolverProblem.h>
#include <package/solver/SolverProblemSolution.h>
#include <package/solver/SolverRepository.h>
#include <package/solver/SolverResult.h>
#include <AutoDeleter.h>
#include <AutoLocker.h>
@ -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<BSolver> 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;
}

View File

@ -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;