From 6a1430716c8746b3a044bb65fb1849e906ae0453 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 20 Apr 2013 21:24:28 +0200 Subject: [PATCH] BDaemonClient: Add support for creating activation transactions * BActivationTransaction: - Remove non-trivial constructor. - Remove package list parameters from SetTo(). - Add AddPackageTo{Dea,A}ctivate(). * BDaemonClient: - Add CreateTransaction(). It creates a transaction directory and initializes a BActivationTransaction. Packages to de-/activate have to be added afterwards. - Add BCommitTransactionResult::FullErrorMessage(). --- .../private/package/ActivationTransaction.h | 19 ++-- headers/private/package/DaemonClient.h | 10 ++ src/kits/package/ActivationTransaction.cpp | 51 ++++----- src/kits/package/DaemonClient.cpp | 103 ++++++++++++++++++ 4 files changed, 142 insertions(+), 41 deletions(-) diff --git a/headers/private/package/ActivationTransaction.h b/headers/private/package/ActivationTransaction.h index 11b5094325..76e311e887 100644 --- a/headers/private/package/ActivationTransaction.h +++ b/headers/private/package/ActivationTransaction.h @@ -20,20 +20,13 @@ namespace BPrivate { class BActivationTransaction { public: BActivationTransaction(); - BActivationTransaction( - BPackageInstallationLocation location, - int64 changeCount, - const BString& directoryName, - const BStringList& packagesToActivate, - const BStringList& packagesToDeactivate); ~BActivationTransaction(); - status_t InitCheck() const; status_t SetTo(BPackageInstallationLocation location, int64 changeCount, - const BString& directoryName, - const BStringList& packagesToActivate, - const BStringList& packagesToDeactivate); + const BString& directoryName); + + status_t InitCheck() const; BPackageInstallationLocation Location() const; void SetLocation( @@ -47,12 +40,14 @@ public: const BString& directoryName); const BStringList& PackagesToActivate() const; - void SetPackagesToActivate( + bool SetPackagesToActivate( const BStringList& packages); + bool AddPackageToActivate(const BString& package); const BStringList& PackagesToDeactivate() const; - void SetPackagesToDeactivate( + bool SetPackagesToDeactivate( const BStringList& packages); + bool AddPackageToDeactivate(const BString& package); private: BPackageInstallationLocation fLocation; diff --git a/headers/private/package/DaemonClient.h b/headers/private/package/DaemonClient.h index bcad84ad59..339f04bfa3 100644 --- a/headers/private/package/DaemonClient.h +++ b/headers/private/package/DaemonClient.h @@ -16,6 +16,9 @@ #include +class BDirectory; + + namespace BPackageKit { @@ -44,6 +47,11 @@ public: const BActivationTransaction& transaction, BCommitTransactionResult& _result); + status_t CreateTransaction( + BPackageInstallationLocation location, + BActivationTransaction& _transaction, + BDirectory& _transactionDirectory); + private: status_t _InitMessenger(); status_t _ExtractPackageInfoSet(const BMessage& message, @@ -81,6 +89,8 @@ public: const BString& ErrorPackage() const; // may be empty, even on error + BString FullErrorMessage() const; + const BString& OldStateDirectory() const; private: diff --git a/src/kits/package/ActivationTransaction.cpp b/src/kits/package/ActivationTransaction.cpp index 838b071774..813ecf33b3 100644 --- a/src/kits/package/ActivationTransaction.cpp +++ b/src/kits/package/ActivationTransaction.cpp @@ -25,20 +25,6 @@ BActivationTransaction::BActivationTransaction() } -BActivationTransaction::BActivationTransaction( - BPackageInstallationLocation location, int64 changeCount, - const BString& directoryName, const BStringList& packagesToActivate, - const BStringList& packagesToDeactivate) - : - fLocation(location), - fChangeCount(changeCount), - fTransactionDirectoryName(directoryName), - fPackagesToActivate(packagesToActivate), - fPackagesToDeactivate(packagesToDeactivate) -{ -} - - BActivationTransaction::~BActivationTransaction() { } @@ -57,27 +43,18 @@ BActivationTransaction::InitCheck() const status_t BActivationTransaction::SetTo(BPackageInstallationLocation location, - int64 changeCount, const BString& directoryName, - const BStringList& packagesToActivate, - const BStringList& packagesToDeactivate) + int64 changeCount, const BString& directoryName) { if (location < 0 || location >= B_PACKAGE_INSTALLATION_LOCATION_ENUM_COUNT - || directoryName.IsEmpty() - || (packagesToActivate.IsEmpty() && packagesToDeactivate.IsEmpty())) { + || directoryName.IsEmpty()) { return B_BAD_VALUE; } fLocation = location; fChangeCount = changeCount; fTransactionDirectoryName = directoryName; - fPackagesToActivate = packagesToActivate; - fPackagesToDeactivate = packagesToDeactivate; - - if (fPackagesToActivate.CountStrings() != packagesToActivate.CountStrings() - || fPackagesToDeactivate.CountStrings() - != packagesToDeactivate.CountStrings()) { - return B_NO_MEMORY; - } + fPackagesToActivate.MakeEmpty(); + fPackagesToDeactivate.MakeEmpty(); return B_OK; } @@ -133,10 +110,18 @@ BActivationTransaction::PackagesToActivate() const } -void +bool BActivationTransaction::SetPackagesToActivate(const BStringList& packages) { fPackagesToActivate = packages; + return fPackagesToActivate.CountStrings() == packages.CountStrings(); +} + + +bool +BActivationTransaction::AddPackageToActivate(const BString& package) +{ + return fPackagesToActivate.Add(package); } @@ -147,10 +132,18 @@ BActivationTransaction::PackagesToDeactivate() const } -void +bool BActivationTransaction::SetPackagesToDeactivate(const BStringList& packages) { fPackagesToDeactivate = packages; + return fPackagesToDeactivate.CountStrings() == packages.CountStrings(); +} + + +bool +BActivationTransaction::AddPackageToDeactivate(const BString& package) +{ + return fPackagesToDeactivate.Add(package); } diff --git a/src/kits/package/DaemonClient.cpp b/src/kits/package/DaemonClient.cpp index 8d2c1bf310..f3446dcf00 100644 --- a/src/kits/package/DaemonClient.cpp +++ b/src/kits/package/DaemonClient.cpp @@ -9,10 +9,15 @@ #include +#include + +#include +#include #include #include #include +#include namespace BPackageKit { @@ -103,6 +108,60 @@ BDaemonClient::CommitTransaction(const BActivationTransaction& transaction, } +status_t +BDaemonClient::CreateTransaction(BPackageInstallationLocation location, + BActivationTransaction& _transaction, BDirectory& _transactionDirectory) +{ + // get an info for the location + BInstallationLocationInfo info; + status_t error = GetInstallationLocationInfo(location, info); + if (error != B_OK) + return error; + + // open admin directory + entry_ref entryRef; + entryRef.device = info.PackagesDirectoryRef().device; + entryRef.directory = info.PackagesDirectoryRef().node; + error = entryRef.set_name(PACKAGES_DIRECTORY_ADMIN_DIRECTORY); + if (error != B_OK) + return error; + + BDirectory adminDirectory; + error = adminDirectory.SetTo(&entryRef); + if (error != B_OK) + return error; + + // create a transaction directory + int uniqueId = 1; + BString directoryName; + for (;; uniqueId++) { + directoryName.SetToFormat("transaction-%d", uniqueId); + if (directoryName.IsEmpty()) + return B_NO_MEMORY; + + error = adminDirectory.CreateDirectory(directoryName, + &_transactionDirectory); + if (error == B_OK) + break; + if (error != B_FILE_EXISTS) + return error; + } + + // init the transaction + error = _transaction.SetTo(location, info.ChangeCount(), directoryName); + if (error != B_OK) { + BEntry entry; + _transactionDirectory.GetEntry(&entry); + _transactionDirectory.Unset(); + if (entry.InitCheck() == B_OK) + entry.Remove(); + return error; + } + + return B_OK; +} + + status_t BDaemonClient::_InitMessenger() { @@ -273,6 +332,50 @@ BDaemonClient::BCommitTransactionResult::ErrorPackage() const } +BString +BDaemonClient::BCommitTransactionResult::FullErrorMessage() const +{ + if (fError == 0) + return "no error"; + + const char* errorString; + if (fError > 0) { + switch ((BDaemonError)fError) { + case B_DAEMON_CHANGE_COUNT_MISMATCH: + errorString = "transaction out of date"; + break; + case B_DAEMON_BAD_REQUEST: + errorString = "invalid transaction"; + break; + case B_DAEMON_NO_SUCH_PACKAGE: + errorString = "no such package"; + break; + case B_DAEMON_PACKAGE_ALREADY_EXISTS: + errorString = "package already exists"; + break; + case B_DAEMON_OK: + default: + errorString = "unknown error"; + break; + } + } else + errorString = strerror(fError); + + BString result; + if (!fErrorMessage.IsEmpty()) { + result = fErrorMessage; + result << ": "; + } + + result << errorString; + + if (!fErrorPackage.IsEmpty()) + result << ", package: \"" << fErrorPackage << '"'; + + return result; +} + + const BString& BDaemonClient::BCommitTransactionResult::OldStateDirectory() const {