package daemon: Rework error and issue propagation to client

* BDaemonClient: Move inner class BCommitTransactionResult to top level
  and make it public.
* BCommitTransactionResult:
  - Add a whole bunch of specific error code enum values. Such an error
    code is now the primary error, as opposed to before where we would
    mix status_t and enum value errors. There's a systemError property
    of type status_t which may provide additional information, though
    (depending on the primary error type).
  - Remove the errorMessage property. Due to mapping all errors to the
    specific error codes this is no longer necessary. Mixing such a
    message with another error description is also not very helpful when
    it comes to localization (still not supported, though).
  - Add several properties (paths, strings, error codes) that serve as
    arguments to the primary error and are used by FullErrorMessage().
  - Add issues property, a list of instances of new class
    BTransactionIssue. Those describe non-critical issues (e.g. failed
    update of a settings file) that occurred in the process of
    committing the transaction. Those issues should be presented to the
    user by the package management program.
* Exception: Adjust to transport the BCommitTransactionResult
  properties.
* CommitTransactionHandler, FsTransactions, Root, Volume: Adjust to
  BCommitTransactionResult/Exception changes.
* CommitTransactionHandler: Now requires a BCommitTransactionResult to
  which it adds the issues it encounters. The reply BMessage is no
  longer needed, though.
* Volume: Refactor common code from the three methods that use
  CommitTransactionHandler into new method _CommitTransaction.
This commit is contained in:
Ingo Weinhold
2014-06-15 17:21:01 +02:00
parent 6077cad882
commit 0de3219e33
20 changed files with 1573 additions and 612 deletions
@@ -0,0 +1 @@
#include <../os/package/CommitTransactionResult.h>
@@ -0,0 +1,168 @@
/*
* Copyright 2014, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _PACKAGE__COMMIT_TRANSACTION_RESULT_H_
#define _PACKAGE__COMMIT_TRANSACTION_RESULT_H_
#include <ObjectList.h>
#include <String.h>
class BMessage;
namespace BPackageKit {
enum BTransactionError {
B_TRANSACTION_OK = 0,
B_TRANSACTION_NO_MEMORY,
B_TRANSACTION_INTERNAL_ERROR,
B_TRANSACTION_INSTALLATION_LOCATION_BUSY,
B_TRANSACTION_CHANGE_COUNT_MISMATCH,
B_TRANSACTION_BAD_REQUEST,
B_TRANSACTION_NO_SUCH_PACKAGE,
B_TRANSACTION_PACKAGE_ALREADY_EXISTS,
B_TRANSACTION_FAILED_TO_GET_ENTRY_PATH,
B_TRANSACTION_FAILED_TO_OPEN_DIRECTORY,
B_TRANSACTION_FAILED_TO_CREATE_DIRECTORY,
B_TRANSACTION_FAILED_TO_REMOVE_DIRECTORY,
B_TRANSACTION_FAILED_TO_MOVE_DIRECTORY,
B_TRANSACTION_FAILED_TO_WRITE_ACTIVATION_FILE,
B_TRANSACTION_FAILED_TO_READ_PACKAGE_FILE,
B_TRANSACTION_FAILED_TO_EXTRACT_PACKAGE_FILE,
B_TRANSACTION_FAILED_TO_OPEN_FILE,
B_TRANSACTION_FAILED_TO_MOVE_FILE,
B_TRANSACTION_FAILED_TO_COPY_FILE,
B_TRANSACTION_FAILED_TO_WRITE_FILE_ATTRIBUTE,
B_TRANSACTION_FAILED_TO_ACCESS_ENTRY,
B_TRANSACTION_FAILED_TO_ADD_GROUP,
B_TRANSACTION_FAILED_TO_ADD_USER,
B_TRANSACTION_FAILED_TO_ADD_USER_TO_GROUP,
B_TRANSACTION_FAILED_TO_CHANGE_PACKAGE_ACTIVATION,
};
class BTransactionIssue {
public:
enum BType {
B_WRITABLE_FILE_TYPE_MISMATCH,
B_WRITABLE_FILE_NO_PACKAGE_ATTRIBUTE,
B_WRITABLE_FILE_OLD_ORIGINAL_FILE_MISSING,
B_WRITABLE_FILE_OLD_ORIGINAL_FILE_TYPE_MISMATCH,
B_WRITABLE_FILE_COMPARISON_FAILED,
B_WRITABLE_FILE_NOT_EQUAL,
B_WRITABLE_SYMLINK_COMPARISON_FAILED,
B_WRITABLE_SYMLINK_NOT_EQUAL,
B_POST_INSTALL_SCRIPT_NOT_FOUND,
B_STARTING_POST_INSTALL_SCRIPT_FAILED,
B_POST_INSTALL_SCRIPT_FAILED,
};
public:
BTransactionIssue();
BTransactionIssue(BType type,
const BString& packageName,
const BString& path1, const BString& path2,
status_t systemError, int exitCode);
BTransactionIssue(
const BTransactionIssue& other);
~BTransactionIssue();
BType Type() const;
const BString& PackageName() const;
const BString& Path1() const;
const BString& Path2() const;
status_t SystemError() const;
int ExitCode() const;
BString ToString() const;
status_t AddToMessage(BMessage& message) const;
status_t ExtractFromMessage(const BMessage& message);
BTransactionIssue& operator=(const BTransactionIssue& other);
private:
BType fType;
BString fPackageName;
BString fPath1;
BString fPath2;
status_t fSystemError;
int fExitCode;
};
class BCommitTransactionResult {
public:
BCommitTransactionResult();
BCommitTransactionResult(
BTransactionError error);
BCommitTransactionResult(
const BCommitTransactionResult& other);
~BCommitTransactionResult();
void Unset();
int32 CountIssues() const;
const BTransactionIssue* IssueAt(int32 index) const;
bool AddIssue(const BTransactionIssue& issue);
BTransactionError Error() const;
void SetError(BTransactionError error);
status_t SystemError() const;
void SetSystemError(status_t error);
const BString& ErrorPackage() const;
// may be empty, even on error
void SetErrorPackage(const BString& packageName);
BString FullErrorMessage() const;
const BString& Path1() const;
void SetPath1(const BString& path);
const BString& Path2() const;
void SetPath2(const BString& path);
const BString& Path3() const;
void SetPath3(const BString& path);
const BString& String1() const;
void SetString1(const BString& string);
const BString& String2() const;
void SetString2(const BString& string);
const BString& OldStateDirectory() const;
void SetOldStateDirectory(const BString& directory);
status_t AddToMessage(BMessage& message) const;
status_t ExtractFromMessage(const BMessage& message);
BCommitTransactionResult& operator=(
const BCommitTransactionResult& other);
private:
typedef BObjectList<BTransactionIssue> IssueList;
private:
BTransactionError fError;
status_t fSystemError;
BString fErrorPackage;
BString fPath1;
BString fPath2;
BString fString1;
BString fString2;
BString fOldStateDirectory;
IssueList fIssues;
};
} // namespace BPackageKit
#endif // _PACKAGE__COMMIT_TRANSACTION_RESULT_H_
+1 -38
View File
@@ -22,6 +22,7 @@ class BDirectory;
namespace BPackageKit {
class BCommitTransactionResult;
class BInstallationLocationInfo;
class BPackageInfoSet;
@@ -33,9 +34,6 @@ class BActivationTransaction;
class BDaemonClient {
public:
class BCommitTransactionResult;
public:
BDaemonClient();
~BDaemonClient();
@@ -65,41 +63,6 @@ private:
};
class BDaemonClient::BCommitTransactionResult {
public:
BCommitTransactionResult();
BCommitTransactionResult(int32 error,
const BString& errorMessage,
const BString& errorPackage,
const BString& oldStateDirectory);
~BCommitTransactionResult();
void SetTo(int32 error, const BString& errorMessage,
const BString& errorPackage,
const BString& oldStateDirectory);
status_t Error() const;
BDaemonError DaemonError() const;
// may be B_DAEMON_OK, even if Error() is
// != B_OK, then Error() is as specific as
// is known
const BString& ErrorMessage() const;
// may be empty, even on error
const BString& ErrorPackage() const;
// may be empty, even on error
BString FullErrorMessage() const;
const BString& OldStateDirectory() const;
private:
int32 fError;
BString fErrorMessage;
BString fErrorPackage;
BString fOldStateDirectory;
};
} // namespace BPrivate
} // namespace BPackageKit
+30 -17
View File
@@ -16,16 +16,6 @@ namespace BPrivate {
#define B_PACKAGE_DAEMON_APP_SIGNATURE "application/x-vnd.haiku-package_daemon"
enum BDaemonError {
B_DAEMON_OK = 0,
B_DAEMON_INSTALLATION_LOCATION_BUSY,
B_DAEMON_CHANGE_COUNT_MISMATCH,
B_DAEMON_BAD_REQUEST,
B_DAEMON_NO_SUCH_PACKAGE,
B_DAEMON_PACKAGE_ALREADY_EXISTS
};
// message codes for requests to and replies from the daemon
enum {
B_MESSAGE_GET_INSTALLATION_LOCATION_INFO = 'PKLI',
@@ -59,17 +49,40 @@ enum {
// transaction directory
B_MESSAGE_COMMIT_TRANSACTION_REPLY = 'PKTR'
// "error": int32
// regular error code or BDaemonError describing how committing
// the transaction went
// "error message": string
// [error case only] gives some additional information what went
// wrong; optional
// a BTransactionError describing how committing the transaction
// went
// "system error": int32
// a status_t for the operation that failed; B_ERROR, if n/a
// "error package": string
// [error case only] file name of the package causing the error,
// if any in particarly; optional
// "path1": string
// [error case only] first path specific to the error
// "path2": string
// [error case only] second path specific to the error
// "string1": string
// [error case only] first string specific to the error
// "string2": string
// [error case only] second string specific to the error
// "old state": string
// name of the directory (subdirectory of the administrative
// directory) containing the deactivated packages
// [success case only] name of the directory (subdirectory of the
// administrative directory) containing the deactivated packages
// "issues": message[]
// A list of non-critical issues that occurred while performing the
// package activation. On success the user should be notified about
// these. Each contains:
// "type": int32
// a BTransactionIssue::BType specifying the kind of issue
// "package": string
// file name of the package which the issue is related to
// "path1": string
// first path specific to the issue
// "path2": string
// second path specific to the issue
// "system error": int32
// a status_t for the operation that failed; B_OK, if n/a
// "exit code": int32
// a exit code of the program that failed; 0, if n/a
};
@@ -234,8 +234,7 @@ public:
virtual status_t PrepareTransaction(Transaction& transaction)
= 0;
virtual status_t CommitTransaction(Transaction& transaction,
BDaemonClient::BCommitTransactionResult&
_result) = 0;
BCommitTransactionResult& _result) = 0;
};
@@ -250,8 +249,7 @@ public:
virtual status_t PrepareTransaction(Transaction& transaction);
virtual status_t CommitTransaction(Transaction& transaction,
BDaemonClient::BCommitTransactionResult&
_result);
BCommitTransactionResult& _result);
private:
BDaemonClient fDaemonClient;
+1
View File
@@ -97,6 +97,7 @@ BuildPlatformSharedLibrary libpackage_build.so
AddRepositoryRequest.cpp
Attributes.cpp
ChecksumAccessors.cpp
CommitTransactionResult.cpp
Context.cpp
DownloadFileRequest.cpp
DropRepositoryRequest.cpp
@@ -0,0 +1,662 @@
/*
* Copyright 2013-2014, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#include <package/CommitTransactionResult.h>
#include <Message.h>
//#include <package/DaemonDefs.h>
namespace BPackageKit {
// #pragma mark - BTransactionIssue
BTransactionIssue::BTransactionIssue()
:
fType(B_WRITABLE_FILE_TYPE_MISMATCH),
fPackageName(),
fPath1(),
fPath2(),
fSystemError(B_OK),
fExitCode(0)
{
}
BTransactionIssue::BTransactionIssue(BType type, const BString& packageName,
const BString& path1, const BString& path2, status_t systemError,
int exitCode)
:
fType(type),
fPackageName(packageName),
fPath1(path1),
fPath2(path2),
fSystemError(systemError),
fExitCode(exitCode)
{
}
BTransactionIssue::BTransactionIssue(const BTransactionIssue& other)
{
*this = other;
}
BTransactionIssue::~BTransactionIssue()
{
}
BTransactionIssue::BType
BTransactionIssue::Type() const
{
return fType;
}
const BString&
BTransactionIssue::PackageName() const
{
return fPackageName;
}
const BString&
BTransactionIssue::Path1() const
{
return fPath1;
}
const BString&
BTransactionIssue::Path2() const
{
return fPath2;
}
status_t
BTransactionIssue::SystemError() const
{
return fSystemError;
}
int
BTransactionIssue::ExitCode() const
{
return fExitCode;
}
BString
BTransactionIssue::ToString() const
{
const char* messageTemplate = "";
switch (fType) {
case B_WRITABLE_FILE_TYPE_MISMATCH:
messageTemplate = "\"%path1%\" cannot be updated automatically,"
" since its type doesn't match the type of \"%path2%\" which it"
" is supposed to be updated with."
" Please perform the update manually if needed.";
break;
case B_WRITABLE_FILE_NO_PACKAGE_ATTRIBUTE:
messageTemplate = "\"%path1%\" cannot be updated automatically,"
" since it doesn't have a SYS:PACKAGE attribute."
" Please perform the update manually if needed.";
break;
case B_WRITABLE_FILE_OLD_ORIGINAL_FILE_MISSING:
messageTemplate = "\"%path1%\" cannot be updated automatically,"
" since \"%path2%\" which we need to compare it with is"
" missing."
" Please perform the update manually if needed.";
break;
case B_WRITABLE_FILE_OLD_ORIGINAL_FILE_TYPE_MISMATCH:
messageTemplate = "\"%path1%\" cannot be updated automatically,"
" since its type doesn't match the type of \"%path2%\" which we"
" need to compare it with."
" Please perform the update manually if needed.";
break;
case B_WRITABLE_FILE_COMPARISON_FAILED:
messageTemplate = "\"%path1%\" cannot be updated automatically,"
" since the comparison with \"%path2%\" failed: %error%."
" Please perform the update manually if needed.";
break;
case B_WRITABLE_FILE_NOT_EQUAL: // !keep old
messageTemplate = "\"%path1%\" cannot be updated automatically,"
" since it was changed manually from previous version"
" \"%path2\""
" Please perform the update manually if needed.";
break;
case B_WRITABLE_SYMLINK_COMPARISON_FAILED: // !keep old
messageTemplate = "Symbolic link \"%path1%\" cannot be updated"
" automatically, since the comparison with \"%path2%\" failed:"
" %error%."
" Please perform the update manually if needed.";
break;
case B_WRITABLE_SYMLINK_NOT_EQUAL: // !keep old
messageTemplate = "Symbolic link \"%path1%\" cannot be updated"
" automatically, since it was changed manually from previous"
" version \"%path2\""
" Please perform the update manually if needed.";
break;
case B_POST_INSTALL_SCRIPT_NOT_FOUND:
messageTemplate = "Failed to find post-installation script "
" \"%path1%\": %error%.";
break;
case B_STARTING_POST_INSTALL_SCRIPT_FAILED:
messageTemplate = "Failed to run post-installation script "
" \"%path1%\": %error%.";
break;
case B_POST_INSTALL_SCRIPT_FAILED:
messageTemplate = "The post-installation script "
" \"%path1%\" failed with exit code %exitCode%.";
break;
}
BString message(messageTemplate);
message.ReplaceAll("%path1%", fPath1)
.ReplaceAll("%path2%", fPath2)
.ReplaceAll("%error%", strerror(fSystemError))
.ReplaceAll("%exitCode%", BString() << fExitCode);
return message;
}
status_t
BTransactionIssue::AddToMessage(BMessage& message) const
{
status_t error;
if ((error = message.AddInt32("type", (int32)fType)) != B_OK
|| (error = message.AddString("package", fPackageName)) != B_OK
|| (error = message.AddString("path1", fPath1)) != B_OK
|| (error = message.AddString("path2", fPath2)) != B_OK
|| (error = message.AddInt32("system error", (int32)fSystemError))
!= B_OK
|| (error = message.AddInt32("exit code", (int32)fExitCode)) != B_OK) {
return error;
}
return B_OK;
}
status_t
BTransactionIssue::ExtractFromMessage(const BMessage& message)
{
status_t error;
int32 type;
int32 systemError;
int32 exitCode;
if ((error = message.FindInt32("type", &type)) != B_OK
|| (error = message.FindString("package", &fPackageName)) != B_OK
|| (error = message.FindString("path1", &fPath1)) != B_OK
|| (error = message.FindString("path2", &fPath2)) != B_OK
|| (error = message.FindInt32("system error", &systemError)) != B_OK
|| (error = message.FindInt32("exit code", &exitCode)) != B_OK) {
return error;
}
fType = (BType)type;
fSystemError = (status_t)systemError;
fExitCode = (int)exitCode;
return B_OK;
}
BTransactionIssue&
BTransactionIssue::operator=(const BTransactionIssue& other)
{
fType = other.fType;
fPackageName = other.fPackageName;
fPath1 = other.fPath1;
fPath2 = other.fPath2;
fSystemError = other.fSystemError;
fExitCode = other.fExitCode;
return *this;
}
// #pragma mark - BCommitTransactionResult
BCommitTransactionResult::BCommitTransactionResult()
:
fError(B_TRANSACTION_INTERNAL_ERROR),
fSystemError(B_ERROR),
fErrorPackage(),
fPath1(),
fPath2(),
fString1(),
fString2(),
fOldStateDirectory(),
fIssues(10, true)
{
}
BCommitTransactionResult::BCommitTransactionResult(BTransactionError error)
:
fError(error),
fSystemError(B_ERROR),
fErrorPackage(),
fPath1(),
fPath2(),
fString1(),
fString2(),
fOldStateDirectory(),
fIssues(10, true)
{
}
BCommitTransactionResult::BCommitTransactionResult(
const BCommitTransactionResult& other)
:
fError(B_TRANSACTION_INTERNAL_ERROR),
fSystemError(B_ERROR),
fErrorPackage(),
fPath1(),
fPath2(),
fString1(),
fString2(),
fOldStateDirectory(),
fIssues(10, true)
{
*this = other;
}
BCommitTransactionResult::~BCommitTransactionResult()
{
}
void
BCommitTransactionResult::Unset()
{
fError = B_TRANSACTION_INTERNAL_ERROR;
fSystemError = B_ERROR;
fErrorPackage.Truncate(0);
fPath1.Truncate(0);
fPath2.Truncate(0);
fString1.Truncate(0);
fString2.Truncate(0);
fOldStateDirectory.Truncate(0);
fIssues.MakeEmpty();
}
int32
BCommitTransactionResult::CountIssues() const
{
return fIssues.CountItems();
}
const BTransactionIssue*
BCommitTransactionResult::IssueAt(int32 index) const
{
if (index < 0 || index >= CountIssues())
return NULL;
return fIssues.ItemAt(index);
}
bool
BCommitTransactionResult::AddIssue(const BTransactionIssue& issue)
{
BTransactionIssue* newIssue = new(std::nothrow) BTransactionIssue(issue);
if (newIssue == NULL || !fIssues.AddItem(newIssue)) {
delete newIssue;
return false;
}
return true;
}
BTransactionError
BCommitTransactionResult::Error() const
{
return fError > 0 ? (BTransactionError)fError : B_TRANSACTION_OK;
}
void
BCommitTransactionResult::SetError(BTransactionError error)
{
fError = error;
}
status_t
BCommitTransactionResult::SystemError() const
{
return fSystemError;
}
void
BCommitTransactionResult::SetSystemError(status_t error)
{
fSystemError = error;
}
const BString&
BCommitTransactionResult::ErrorPackage() const
{
return fErrorPackage;
}
void
BCommitTransactionResult::SetErrorPackage(const BString& packageName)
{
fErrorPackage = packageName;
}
BString
BCommitTransactionResult::FullErrorMessage() const
{
if (fError == 0)
return "no error";
const char* messageTemplate = "";
switch ((BTransactionError)fError) {
case B_TRANSACTION_OK:
messageTemplate = "Everything went fine.";
break;
case B_TRANSACTION_NO_MEMORY:
messageTemplate = "Out of memory.";
break;
case B_TRANSACTION_INTERNAL_ERROR:
messageTemplate = "An internal error occurred. Specifics can be"
" found in the syslog.";
break;
case B_TRANSACTION_INSTALLATION_LOCATION_BUSY:
messageTemplate = "Another package operation is already in"
" progress.";
break;
case B_TRANSACTION_CHANGE_COUNT_MISMATCH:
messageTemplate = "The transaction is out of date.";
break;
case B_TRANSACTION_BAD_REQUEST:
messageTemplate = "The requested transaction is invalid.";
break;
case B_TRANSACTION_NO_SUCH_PACKAGE:
messageTemplate = "No such package \"%package%\".";
break;
case B_TRANSACTION_PACKAGE_ALREADY_EXISTS:
messageTemplate = "The to be activated package \"%package%\" does"
" already exist.";
break;
case B_TRANSACTION_FAILED_TO_GET_ENTRY_PATH:
if (fPath1.IsEmpty()) {
if (fErrorPackage.IsEmpty()) {
messageTemplate = "A file path could not be determined:"
"%error%";
} else {
messageTemplate = "While processing package \"%package%\""
" a file path could not be determined: %error%";
}
} else {
if (fErrorPackage.IsEmpty()) {
messageTemplate = "The file path for \"%path1%\" could not"
" be determined: %error%";
} else {
messageTemplate = "While processing package \"%package%\""
" the file path for \"%path1%\" could not be"
" determined: %error%";
}
}
break;
case B_TRANSACTION_FAILED_TO_OPEN_DIRECTORY:
messageTemplate = "Failed to open directory \"%path1%\": %error%";
break;
case B_TRANSACTION_FAILED_TO_CREATE_DIRECTORY:
messageTemplate = "Failed to create directory \"%path1%\": %error%";
break;
case B_TRANSACTION_FAILED_TO_REMOVE_DIRECTORY:
messageTemplate = "Failed to remove directory \"%path1%\": %error%";
break;
case B_TRANSACTION_FAILED_TO_MOVE_DIRECTORY:
messageTemplate = "Failed to move directory \"%path1%\" to"
" \"%path2%\": %error%";
break;
case B_TRANSACTION_FAILED_TO_WRITE_ACTIVATION_FILE:
messageTemplate = "Failed to write new package activation file"
" \"%path1%\": %error%";
break;
case B_TRANSACTION_FAILED_TO_READ_PACKAGE_FILE:
messageTemplate = "Failed to read package file \"%path1%\":"
" %error%";
break;
case B_TRANSACTION_FAILED_TO_EXTRACT_PACKAGE_FILE:
messageTemplate = "Failed to extract \"%path1%\" from package"
" \"%package%\": %error%";
break;
case B_TRANSACTION_FAILED_TO_OPEN_FILE:
messageTemplate = "Failed to open file \"%path1%\": %error%";
break;
case B_TRANSACTION_FAILED_TO_MOVE_FILE:
messageTemplate = "Failed to move file \"%path1%\" to \"%path2%\":"
" %error%";
break;
case B_TRANSACTION_FAILED_TO_COPY_FILE:
messageTemplate = "Failed to copy file \"%path1%\" to \"%path2%\":"
" %error%";
break;
case B_TRANSACTION_FAILED_TO_WRITE_FILE_ATTRIBUTE:
messageTemplate = "Failed to write attribute \"%string1%\" of file"
" \"%path1%\": %error%";
break;
case B_TRANSACTION_FAILED_TO_ACCESS_ENTRY:
messageTemplate = "Failed to access entry \"%path1%\": %error%";
break;
case B_TRANSACTION_FAILED_TO_ADD_GROUP:
messageTemplate = "Failed to add user group \"%string1%\" required"
" by package \"%package%\".";
break;
case B_TRANSACTION_FAILED_TO_ADD_USER:
messageTemplate = "Failed to add user \"%string1%\" required"
" by package \"%package%\".";
break;
case B_TRANSACTION_FAILED_TO_ADD_USER_TO_GROUP:
messageTemplate = "Failed to add user \"%string1%\" to group"
" \"%string2%\" as required by package \"%package%\".";
break;
case B_TRANSACTION_FAILED_TO_CHANGE_PACKAGE_ACTIVATION:
messageTemplate = "Failed to change the package activation in"
" packagefs: %error%";
break;
}
BString message(messageTemplate);
message.ReplaceAll("%package%", fErrorPackage)
.ReplaceAll("%path1%", fPath1)
.ReplaceAll("%path2%", fPath2)
.ReplaceAll("%string1%", fString1)
.ReplaceAll("%string2%", fString2)
.ReplaceAll("%error%", strerror(fSystemError));
return message;
}
const BString&
BCommitTransactionResult::Path1() const
{
return fPath1;
}
void
BCommitTransactionResult::SetPath1(const BString& path)
{
fPath1 = path;
}
const BString&
BCommitTransactionResult::Path2() const
{
return fPath2;
}
void
BCommitTransactionResult::SetPath2(const BString& path)
{
fPath2 = path;
}
const BString&
BCommitTransactionResult::String1() const
{
return fString1;
}
void
BCommitTransactionResult::SetString1(const BString& string)
{
fString1 = string;
}
const BString&
BCommitTransactionResult::String2() const
{
return fString2;
}
void
BCommitTransactionResult::SetString2(const BString& string)
{
fString2 = string;
}
const BString&
BCommitTransactionResult::OldStateDirectory() const
{
return fOldStateDirectory;
}
void
BCommitTransactionResult::SetOldStateDirectory(const BString& directory)
{
fOldStateDirectory = directory;
}
status_t
BCommitTransactionResult::AddToMessage(BMessage& message) const
{
status_t error;
if ((error = message.AddInt32("error", (int32)fError)) != B_OK
|| (error = message.AddInt32("system error", (int32)fSystemError))
!= B_OK
|| (error = message.AddString("error package", fErrorPackage)) != B_OK
|| (error = message.AddString("path1", fPath1)) != B_OK
|| (error = message.AddString("path2", fPath2)) != B_OK
|| (error = message.AddString("string1", fString1)) != B_OK
|| (error = message.AddString("string2", fString2)) != B_OK
|| (error = message.AddString("old state", fOldStateDirectory))
!= B_OK) {
return error;
}
int32 count = fIssues.CountItems();
for (int32 i = 0; i < count; i++) {
const BTransactionIssue* issue = fIssues.ItemAt(i);
BMessage issueMessage;
if ((error = issue->AddToMessage(issueMessage)) != B_OK
|| (error = message.AddMessage("issues", &issueMessage)) != B_OK) {
return error;
}
}
return B_OK;
}
status_t
BCommitTransactionResult::ExtractFromMessage(const BMessage& message)
{
Unset();
int32 resultError;
int32 systemError;
status_t error;
if ((error = message.FindInt32("error", &resultError)) != B_OK
|| (error = message.FindInt32("system error", &systemError)) != B_OK
|| (error = message.FindString("error package", &fErrorPackage)) != B_OK
|| (error = message.FindString("path1", &fPath1)) != B_OK
|| (error = message.FindString("path2", &fPath2)) != B_OK
|| (error = message.FindString("string1", &fString1)) != B_OK
|| (error = message.FindString("string2", &fString2)) != B_OK
|| (error = message.FindString("old state", &fOldStateDirectory))
!= B_OK) {
return error;
}
fError = (BTransactionError)resultError;
fSystemError = (status_t)systemError;
BMessage issueMessage;
for (int32 i = 0; message.FindMessage("issues", i, &issueMessage) == B_OK;
i++) {
BTransactionIssue issue;
error = issue.ExtractFromMessage(issueMessage);
if (error != B_OK)
return error;
if (!AddIssue(issue))
return B_NO_MEMORY;
}
return B_OK;
}
BCommitTransactionResult&
BCommitTransactionResult::operator=(const BCommitTransactionResult& other)
{
Unset();
fError = other.fError;
fSystemError = other.fSystemError;
fErrorPackage = other.fErrorPackage;
fPath1 = other.fPath1;
fPath2 = other.fPath2;
fString1 = other.fString1;
fString2 = other.fString2;
fOldStateDirectory = other.fOldStateDirectory;
for (int32 i = 0; const BTransactionIssue* issue = other.fIssues.ItemAt(i);
i++) {
AddIssue(*issue);
}
return *this;
}
} // namespace BPackageKit
+2 -147
View File
@@ -13,6 +13,7 @@
#include <Directory.h>
#include <Entry.h>
#include <package/CommitTransactionResult.h>
#include <package/InstallationLocationInfo.h>
#include <package/PackageInfo.h>
@@ -24,9 +25,6 @@ namespace BPackageKit {
namespace BPrivate {
// #pragma mark - BCommitTransactionResult
BDaemonClient::BDaemonClient()
:
fDaemonMessenger()
@@ -131,26 +129,7 @@ BDaemonClient::CommitTransaction(const BActivationTransaction& transaction,
return B_ERROR;
// extract the result
int32 requestError;
error = reply.FindInt32("error", &requestError);
if (error != B_OK)
return error;
BString errorMessage;
BString errorPackage;
BString oldStateDirectory;
if (requestError == 0) {
error = reply.FindString("old state", &oldStateDirectory);
if (error != B_OK)
return error;
} else {
reply.FindString("error message", &errorMessage);
reply.FindString("error package", &errorPackage);
}
_result.SetTo(requestError, errorMessage, errorPackage, oldStateDirectory);
return B_OK;
// Even on error. B_OK just indicates that we have initialized _result.
return _result.ExtractFromMessage(reply);
}
@@ -254,129 +233,5 @@ BDaemonClient::_ExtractPackageInfoSet(const BMessage& message,
}
// #pragma mark - BCommitTransactionResult
BDaemonClient::BCommitTransactionResult::BCommitTransactionResult()
:
fError(B_NO_INIT),
fErrorMessage(),
fErrorPackage(),
fOldStateDirectory()
{
}
BDaemonClient::BCommitTransactionResult::BCommitTransactionResult(int32 error,
const BString& errorMessage, const BString& errorPackage,
const BString& oldStateDirectory)
:
fError(error),
fErrorMessage(errorMessage),
fErrorPackage(errorPackage),
fOldStateDirectory(oldStateDirectory)
{
}
BDaemonClient::BCommitTransactionResult::~BCommitTransactionResult()
{
}
void
BDaemonClient::BCommitTransactionResult::SetTo(int32 error,
const BString& errorMessage, const BString& errorPackage,
const BString& oldStateDirectory)
{
fError = error;
fErrorMessage = errorMessage;
fErrorPackage = errorPackage;
fOldStateDirectory = oldStateDirectory;
}
status_t
BDaemonClient::BCommitTransactionResult::Error() const
{
return fError <= 0 ? fError : B_ERROR;
}
BDaemonError
BDaemonClient::BCommitTransactionResult::DaemonError() const
{
return fError > 0 ? (BDaemonError)fError : B_DAEMON_OK;
}
const BString&
BDaemonClient::BCommitTransactionResult::ErrorMessage() const
{
return fErrorMessage;
}
const BString&
BDaemonClient::BCommitTransactionResult::ErrorPackage() const
{
return fErrorPackage;
}
BString
BDaemonClient::BCommitTransactionResult::FullErrorMessage() const
{
if (fError == 0)
return "no error";
const char* errorString;
if (fError > 0) {
switch ((BDaemonError)fError) {
case B_DAEMON_INSTALLATION_LOCATION_BUSY:
errorString = "another package operation already in progress";
break;
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
{
return fOldStateDirectory;
}
} // namespace BPrivate
} // namespace BPackageKit
+1
View File
@@ -14,6 +14,7 @@ HPKG_SOURCES =
BlockBufferPoolNoLock.cpp
BufferDataOutput.cpp
BufferPool.cpp
CommitTransactionResult.cpp
DataReader.cpp
DataWriters.cpp
ErrorOutput.cpp
+5 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Copyright 2013-2014, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -11,6 +11,7 @@
#include <package/manager/PackageManager.h>
#include <Directory.h>
#include <package/CommitTransactionResult.h>
#include <package/DownloadFileRequest.h>
#include <package/PackageRoster.h>
#include <package/RefreshRepositoryRequest.h>
@@ -576,12 +577,12 @@ BPackageManager::_CommitPackageChanges(Transaction& transaction)
installationRepository);
// commit the transaction
BDaemonClient::BCommitTransactionResult transactionResult;
BCommitTransactionResult transactionResult;
status_t error = fInstallationInterface->CommitTransaction(transaction,
transactionResult);
if (error != B_OK)
DIE(error, "failed to commit transaction");
if (transactionResult.Error() != B_OK) {
if (transactionResult.Error() != B_TRANSACTION_OK) {
DIE("failed to commit transaction: %s",
transactionResult.FullErrorMessage().String());
}
@@ -933,7 +934,7 @@ BPackageManager::ClientInstallationInterface::PrepareTransaction(
status_t
BPackageManager::ClientInstallationInterface::CommitTransaction(
Transaction& transaction, BDaemonClient::BCommitTransactionResult& _result)
Transaction& transaction, BCommitTransactionResult& _result)
{
return fDaemonClient.CommitTransaction(transaction.ActivationTransaction(),
_result);
File diff suppressed because it is too large Load Diff
+26 -10
View File
@@ -22,10 +22,18 @@
typedef std::set<std::string> StringSet;
namespace BPackageKit {
class BCommitTransactionResult;
}
using BPackageKit::BCommitTransactionResult;
class CommitTransactionHandler {
public:
CommitTransactionHandler(Volume* volume,
PackageFileManager* packageFileManager);
PackageFileManager* packageFileManager,
BCommitTransactionResult& result);
~CommitTransactionHandler();
void Init(VolumeState* volumeState,
@@ -33,11 +41,9 @@ public:
const PackageSet& packagesAlreadyAdded,
const PackageSet& packagesAlreadyRemoved);
void HandleRequest(BMessage* request,
BMessage* reply);
void HandleRequest(BMessage* request);
void HandleRequest(
const BActivationTransaction& transaction,
BMessage* reply);
const BActivationTransaction& transaction);
void HandleRequest();
// uses packagesAlreadyAdded and
// packagesAlreadyRemoved from Init()
@@ -47,6 +53,9 @@ public:
const BString& OldStateDirectoryName() const
{ return fOldStateDirectoryName; }
Package* CurrentPackage() const
{ return fCurrentPackage; }
VolumeState* DetachVolumeState();
bool IsActiveVolumeState() const
{ return fVolumeStateIsActive; }
@@ -55,13 +64,15 @@ private:
typedef BObjectList<Package> PackageList;
typedef FSUtils::RelativePath RelativePath;
struct TransactionIssueBuilder;
private:
void _GetPackagesToDeactivate(
const BActivationTransaction& transaction);
void _ReadPackagesToActivate(
const BActivationTransaction& transaction);
void _ApplyChanges(BMessage* reply);
void _CreateOldStateDirectory(BMessage* reply);
void _ApplyChanges();
void _CreateOldStateDirectory();
void _RemovePackagesToDeactivate();
void _AddPackagesToActivate();
@@ -102,13 +113,13 @@ private:
const char* fileName, uint32 openMode,
BFile& _file, BEntry* _entry = NULL);
status_t _WriteActivationFile(
void _WriteActivationFile(
const RelativePath& directoryPath,
const char* fileName,
const PackageSet& toActivate,
const PackageSet& toDeactivate,
BEntry& _entry);
status_t _CreateActivationFileContent(
void _CreateActivationFileContent(
const PackageSet& toActivate,
const PackageSet& toDeactivate,
BString& _content);
@@ -131,10 +142,13 @@ private:
bool _IsSystemPackage(Package* package);
void _AddIssue(
const TransactionIssueBuilder& builder);
static BString _GetPath(const FSUtils::Entry& entry,
const BString& fallback);
static status_t _TagPackageEntriesRecursively(
static void _TagPackageEntriesRecursively(
BDirectory& directory, const BString& value,
bool nonDirectoriesOnly);
@@ -157,6 +171,8 @@ private:
StringSet fAddedGroups;
StringSet fAddedUsers;
FSTransaction fFSTransaction;
BCommitTransactionResult& fResult;
Package* fCurrentPackage;
};
+66 -46
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2013-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
@@ -7,57 +7,77 @@
#include "Exception.h"
using namespace BPackageKit::BPrivate;
using namespace BPackageKit;
Exception::Exception(int32 error, const char* errorMessage,
const char* packageName)
Exception::Exception(BTransactionError error)
:
fError(error),
fErrorMessage(errorMessage),
fPackageName(packageName)
fSystemError(B_ERROR),
fPackageName(),
fPath1(),
fPath2(),
fString1(),
fString2()
{
}
BString
Exception::ToString() const
Exception&
Exception::SetSystemError(status_t error)
{
const char* error;
if (fError >= 0) {
switch (fError) {
case B_DAEMON_OK:
error = "no error";
break;
case B_DAEMON_CHANGE_COUNT_MISMATCH:
error = "transaction out of date";
break;
case B_DAEMON_BAD_REQUEST:
error = "invalid transaction";
break;
case B_DAEMON_NO_SUCH_PACKAGE:
error = "no such package";
break;
case B_DAEMON_PACKAGE_ALREADY_EXISTS:
error = "package already exists";
break;
default:
error = "unknown error";
break;
}
} else
error = strerror(fError);
BString string;
if (!fErrorMessage.IsEmpty()) {
string = fErrorMessage;
string << ": ";
}
string << error;
if (!fPackageName.IsEmpty())
string << ", package: \"" << fPackageName << '"';
return string;
fSystemError = error;
return *this;
}
Exception&
Exception::SetPackageName(const BString& packageName)
{
fPackageName = packageName;
return *this;
}
Exception&
Exception::SetPath1(const BString& path)
{
fPath1 = path;
return *this;
}
Exception&
Exception::SetPath2(const BString& path)
{
fPath2 = path;
return *this;
}
Exception&
Exception::SetString1(const BString& string)
{
fString1 = string;
return *this;
}
Exception&
Exception::SetString2(const BString& string)
{
fString2 = string;
return *this;
}
void
Exception::SetOnResult(BCommitTransactionResult& result)
{
result.SetError(fError);
result.SetSystemError(fSystemError);
result.SetErrorPackage(fPackageName);
result.SetPath1(fPath1);
result.SetPath2(fPath2);
result.SetString1(fString1);
result.SetString2(fString2);
}
+35 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2013-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef EXCEPTION_H
@@ -8,30 +8,54 @@
#include <String.h>
#include <package/DaemonDefs.h>
#include <package/CommitTransactionResult.h>
using BPackageKit::BCommitTransactionResult;
using BPackageKit::BTransactionError;
class Exception {
public:
Exception(int32 error,
const char* errorMessage = NULL,
const char* packageName = NULL);
Exception(BTransactionError error);
int32 Error() const
BTransactionError Error() const
{ return fError; }
const BString& ErrorMessage() const
{ return fErrorMessage; }
status_t SystemError() const
{ return fSystemError; }
Exception& SetSystemError(status_t error);
const BString& PackageName() const
{ return fPackageName; }
Exception& SetPackageName(const BString& packageName);
BString ToString() const;
const BString& Path1() const
{ return fPath1; }
Exception& SetPath1(const BString& path);
const BString& Path2() const
{ return fPath2; }
Exception& SetPath2(const BString& path);
const BString& String1() const
{ return fString1; }
Exception& SetString1(const BString& string);
const BString& String2() const
{ return fString2; }
Exception& SetString2(const BString& string);
void SetOnResult(BCommitTransactionResult& result);
private:
int32 fError;
BString fErrorMessage;
BTransactionError fError;
status_t fSystemError;
BString fPackageName;
BString fPath1;
BString fPath2;
BString fString1;
BString fString2;
};
+12 -5
View File
@@ -7,6 +7,7 @@
#include "FSTransaction.h"
#include <Entry.h>
#include <package/CommitTransactionResult.h>
#include <Path.h>
#include <CopyEngine.h>
@@ -197,9 +198,9 @@ FSTransaction::RemoveOperationAt(int32 index)
{
int32 count = fOperations.size();
if (index < 0 || index >= count) {
throw Exception(B_ERROR,
BString().SetToFormat("FSTransaction::RemoveOperationAt(): invalid "
"operation index %" B_PRId32 "/%" B_PRId32, index, count));
ERROR("FSTransaction::RemoveOperationAt(): invalid "
"operation index %" B_PRId32 "/%" B_PRId32, index, count);
throw Exception(BPackageKit::B_TRANSACTION_INTERNAL_ERROR);
}
fOperations.erase(fOperations.begin() + index);
@@ -225,8 +226,14 @@ FSTransaction::_GetPath(const Entry& entry)
error = pathBuffer.SetTo(path);
}
if (error != B_OK)
throw Exception(error);
if (error != B_OK) {
if (error == B_NO_MEMORY)
throw Exception(BPackageKit::B_TRANSACTION_NO_MEMORY);
throw Exception(BPackageKit::B_TRANSACTION_FAILED_TO_GET_ENTRY_PATH)
.SetPath1(entry.PathOrName())
.SetSystemError(error);
}
return path;
}
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2013-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
@@ -209,7 +209,7 @@ PackageManager::PrepareTransaction(Transaction& transaction)
status_t
PackageManager::CommitTransaction(Transaction& transaction,
BDaemonClient::BCommitTransactionResult& _result)
BCommitTransactionResult& _result)
{
Volume* volume = fRoot->GetVolume(transaction.Repository().Location());
if (volume == NULL)
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2013-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef PACKAGE_MANAGER_H
@@ -16,6 +16,7 @@
#include <package/manager/PackageManager.h>
using BPackageKit::BCommitTransactionResult;
using BPackageKit::BContext;
using BPackageKit::BJob;
using BPackageKit::BJobStateListener;
@@ -51,8 +52,7 @@ private:
virtual status_t PrepareTransaction(Transaction& transaction);
virtual status_t CommitTransaction(Transaction& transaction,
BDaemonClient::BCommitTransactionResult&
_result);
BCommitTransactionResult& _result);
private:
// UserInteractionHandler
+5 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Copyright 2013-2014, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -12,6 +12,7 @@
#include <Alert.h>
#include <Directory.h>
#include <Entry.h>
#include <package/CommitTransactionResult.h>
#include <package/PackageDefs.h>
#include <Path.h>
@@ -330,8 +331,9 @@ Root::HandleRequest(BMessage* message)
// pending already.
if (volume->IsPackageJobPending()) {
BMessage reply(B_MESSAGE_COMMIT_TRANSACTION_REPLY);
if (reply.AddInt32("error", B_DAEMON_INSTALLATION_LOCATION_BUSY)
== B_OK) {
BCommitTransactionResult result(
B_TRANSACTION_INSTALLATION_LOCATION_BUSY);
if (result.AddToMessage(reply) == B_OK) {
message->SendReply(&reply, (BHandler*)NULL,
kCommunicationTimeout);
}
+62 -76
View File
@@ -23,6 +23,7 @@
#include <NodeMonitor.h>
#include <Path.h>
#include <package/CommitTransactionResult.h>
#include <package/solver/Solver.h>
#include <package/solver/SolverPackage.h>
#include <package/solver/SolverProblem.h>
@@ -519,39 +520,18 @@ Volume::HandleGetLocationInfoRequest(BMessage* message)
void
Volume::HandleCommitTransactionRequest(BMessage* message)
{
// Prepare the reply in so far that we can at least set the error code
// without risk of failure.
BCommitTransactionResult result;
PackageSet dummy;
_CommitTransaction(message, NULL, dummy, dummy, result);
BMessage reply(B_MESSAGE_COMMIT_TRANSACTION_REPLY);
if (reply.AddInt32("error", B_ERROR) != B_OK)
status_t error = result.AddToMessage(reply);
if (error != B_OK) {
ERROR("Volume::HandleCommitTransactionRequest(): Failed to add "
"transaction result to reply: %s\n", strerror(error));
return;
// perform the request
CommitTransactionHandler handler(this, fPackageFileManager);
int32 error;
try {
PackageSet dummy;
handler.Init(fLatestState, fLatestState == fActiveState, dummy, dummy);
handler.HandleRequest(message, &reply);
_SetLatestState(handler.DetachVolumeState(),
handler.IsActiveVolumeState());
error = B_DAEMON_OK;
} catch (Exception& exception) {
error = exception.Error();
if (!exception.ErrorMessage().IsEmpty())
reply.AddString("error message", exception.ErrorMessage());
if (!exception.PackageName().IsEmpty())
reply.AddString("error package", exception.PackageName());
} catch (std::bad_alloc& exception) {
error = B_NO_MEMORY;
}
// revert on error
if (error != B_DAEMON_OK)
handler.Revert();
// send the reply
reply.ReplaceInt32("error", error);
message->SendReply(&reply, (BHandler*)NULL, kCommunicationTimeout);
}
@@ -709,31 +689,16 @@ Volume::ProcessPendingPackageActivationChanges()
return;
// perform the request
CommitTransactionHandler handler(this, fPackageFileManager);
int32 error;
try {
handler.Init(fLatestState, fLatestState == fActiveState,
fPackagesToBeActivated, fPackagesToBeDeactivated);
handler.HandleRequest();
_SetLatestState(handler.DetachVolumeState(),
handler.IsActiveVolumeState());
error = B_DAEMON_OK;
} catch (Exception& exception) {
error = exception.Error();
BCommitTransactionResult result;
_CommitTransaction(NULL, NULL, fPackagesToBeActivated,
fPackagesToBeDeactivated, result);
if (result.Error() != B_TRANSACTION_OK) {
ERROR("Volume::ProcessPendingPackageActivationChanges(): package "
"activation failed: %s\n", exception.ToString().String());
// TODO: Notify the user!
} catch (std::bad_alloc& exception) {
error = B_NO_MEMORY;
ERROR("Volume::ProcessPendingPackageActivationChanges(): package "
"activation failed: out of memory\n");
"activation failed: %s\n", result.FullErrorMessage().String());
// TODO: Notify the user!
}
// revert on error
if (error != B_DAEMON_OK)
handler.Revert();
// clear the activation/deactivation sets in any event
fPackagesToBeActivated.clear();
fPackagesToBeDeactivated.clear();
@@ -793,33 +758,10 @@ Volume::CreateTransaction(BPackageInstallationLocation location,
void
Volume::CommitTransaction(const BActivationTransaction& transaction,
const PackageSet& packagesAlreadyAdded,
const PackageSet& packagesAlreadyRemoved,
BDaemonClient::BCommitTransactionResult& _result)
const PackageSet& packagesAlreadyRemoved, BCommitTransactionResult& _result)
{
// perform the request
CommitTransactionHandler handler(this, fPackageFileManager);
int32 error;
try {
handler.Init(fLatestState, fLatestState == fActiveState,
packagesAlreadyAdded, packagesAlreadyRemoved);
handler.HandleRequest(transaction, NULL);
_SetLatestState(handler.DetachVolumeState(),
handler.IsActiveVolumeState());
error = B_DAEMON_OK;
_result.SetTo(error, BString(), BString(),
handler.OldStateDirectoryName());
} catch (Exception& exception) {
error = exception.Error();
_result.SetTo(error, exception.ErrorMessage(), exception.PackageName(),
BString());
} catch (std::bad_alloc& exception) {
error = B_NO_MEMORY;
_result.SetTo(error, BString(), BString(), BString());
}
// revert on error
if (error != B_DAEMON_OK)
handler.Revert();
_CommitTransaction(NULL, &transaction, packagesAlreadyAdded,
packagesAlreadyRemoved, _result);
}
@@ -1325,3 +1267,47 @@ Volume::_OpenPackagesSubDirectory(const RelativePath& path, bool create,
return FSUtils::OpenSubDirectory(directory, path, create, _directory);
}
void
Volume::_CommitTransaction(BMessage* message,
const BActivationTransaction* transaction,
const PackageSet& packagesAlreadyAdded,
const PackageSet& packagesAlreadyRemoved, BCommitTransactionResult& _result)
{
_result.Unset();
// perform the request
CommitTransactionHandler handler(this, fPackageFileManager, _result);
BTransactionError error = B_TRANSACTION_INTERNAL_ERROR;
try {
handler.Init(fLatestState, fLatestState == fActiveState,
packagesAlreadyAdded, packagesAlreadyRemoved);
if (message != NULL)
handler.HandleRequest(message);
else if (transaction != NULL)
handler.HandleRequest(*transaction);
else
handler.HandleRequest();
_SetLatestState(handler.DetachVolumeState(),
handler.IsActiveVolumeState());
error = B_TRANSACTION_OK;
} catch (Exception& exception) {
error = exception.Error();
exception.SetOnResult(_result);
if (_result.ErrorPackage().IsEmpty()
&& handler.CurrentPackage() != NULL) {
_result.SetErrorPackage(handler.CurrentPackage()->FileName());
}
} catch (std::bad_alloc& exception) {
error = B_TRANSACTION_NO_MEMORY;
}
_result.SetError(B_TRANSACTION_OK);
// revert on error
if (error != B_TRANSACTION_OK)
handler.Revert();
}
+7 -2
View File
@@ -137,8 +137,7 @@ public:
const BActivationTransaction& transaction,
const PackageSet& packagesAlreadyAdded,
const PackageSet& packagesAlreadyRemoved,
BDaemonClient::BCommitTransactionResult&
_result);
BCommitTransactionResult& _result);
private:
struct NodeMonitorEvent;
@@ -175,6 +174,12 @@ private:
const RelativePath& path, bool create,
BDirectory& _directory);
void _CommitTransaction(BMessage* message,
const BActivationTransaction* transaction,
const PackageSet& packagesAlreadyAdded,
const PackageSet& packagesAlreadyRemoved,
BCommitTransactionResult& _result);
private:
BString fPath;
PackageFSMountType fMountType;