Implement getting a BInstallationLocationInfo

* Rename PackageDaemonDefs.h to DaemonDefs.h.
* Replace the MESSAGE_GET_PACKAGES by the new
  B_MESSAGE_GET_INSTALLATION_LOCATION_INFO, which not only returns the
  packages, but also other information about the installation location.
* daemon: Volume: Implement a change count which is bumped whenever
  packages are activated/deactivated/added/removed. Cache the reply
  for a location info request, using the change count to check whether
  it is still up-to-date.
* Add private BDaemonClient for communication with the daemon.
* BRoster:
  - Add GetInstallationLocationInfo() using BDaemonClient.
  - Reimplement GetActivePackages(), using
    GetInstallationLocationInfo().
This commit is contained in:
Ingo Weinhold 2013-04-14 17:04:33 +02:00
parent d7d9497e31
commit e6216e372a
12 changed files with 329 additions and 124 deletions

View File

@ -28,6 +28,7 @@ struct BRepositoryConfigVisitor {
};
class BInstallationLocationInfo;
class BPackageInfoSet;
class BRepositoryCache;
class BRepositoryConfig;
@ -60,6 +61,9 @@ public:
status_t GetRepositoryConfig(const BString& name,
BRepositoryConfig* repositoryConfig);
status_t GetInstallationLocationInfo(
BPackageInstallationLocation location,
BInstallationLocationInfo& _info);
status_t GetActivePackages(
BPackageInstallationLocation location,
BPackageInfoSet& packageInfos);

View File

@ -0,0 +1,49 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <ingo_weinhold@gmx.de>
*/
#ifndef _PACKAGE__PRIVATE__DAEMON_CLIENT_H_
#define _PACKAGE__PRIVATE__DAEMON_CLIENT_H_
#include <Messenger.h>
#include <package/PackageDefs.h>
namespace BPackageKit {
class BInstallationLocationInfo;
class BPackageInfoSet;
namespace BPrivate {
class BDaemonClient {
public:
BDaemonClient();
~BDaemonClient();
status_t GetInstallationLocationInfo(
BPackageInstallationLocation location,
BInstallationLocationInfo& _info);
private:
status_t _InitMessenger();
status_t _ExtractPackageInfoSet(const BMessage& message,
const char* field, BPackageInfoSet& _infos);
private:
BMessenger fDaemonMessenger;
};
} // namespace BPrivate
} // namespace BPackageKit
#endif // _PACKAGE__PRIVATE__DAEMON_CLIENT_H_

View File

@ -0,0 +1,46 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <ingo_weinhold@gmx.de>
*/
#ifndef _PACKAGE__PRIVATE__DAEMON_DEFS_H_
#define _PACKAGE__PRIVATE__DAEMON_DEFS_H_
namespace BPackageKit {
namespace BPrivate {
#define B_PACKAGE_DAEMON_APP_SIGNATURE "application/x-vnd.haiku-package_daemon"
enum BDaemonError {
B_DAEMON_OK
};
// message codes for requests to and replies from the daemon
enum {
B_MESSAGE_GET_INSTALLATION_LOCATION_INFO = 'PKLI',
// "location": int32
// the respective installation location constant
B_MESSAGE_GET_INSTALLATION_LOCATION_INFO_REPLY = 'PKLR',
// "base directory device": int32
// "base directory node": int64
// "packages directory device": int32
// "packages directory node": int64
// "change count": int64
// "active packages": message[]
// archived BPackageInfos of the active packages
// "inactive packages": message[]
// archived BPackageInfos of the inactive packages
};
#endif // _PACKAGE__PRIVATE__DAEMON_DEFS_H_
} // namespace BPrivate
} // namespace BPackageKit

View File

@ -1,37 +0,0 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <ingo_weinhold@gmx.de>
*/
#ifndef _PACKAGE__PRIVATE__PACKAGE_DAEMON_DEFS_H_
#define _PACKAGE__PRIVATE__PACKAGE_DAEMON_DEFS_H_
namespace BPackageKit {
namespace BPrivate {
#define PACKAGE_DAEMON_APP_SIGNATURE "application/x-vnd.haiku-package_daemon"
// message codes for requests to and replies from the daemon
enum {
MESSAGE_GET_PACKAGES = 'PKGG',
// "location": int32
// the respective installation location constant
MESSAGE_GET_PACKAGES_REPLY = 'PKGR'
// "active packages": string[]
// file names of the active packages (no path)
// "inactive packages": string[]
// file names of the inactive packages (no path)
};
#endif // _PACKAGE__PRIVATE__PACKAGE_DAEMON_DEFS_H_
} // namespace BPrivate
} // namespace BPackageKit

View File

@ -0,0 +1,137 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <ingo_weinhold@gmx.de>
*/
#include <package/DaemonClient.h>
#include <package/InstallationLocationInfo.h>
#include <package/PackageInfo.h>
#include <package/DaemonDefs.h>
namespace BPackageKit {
namespace BPrivate {
BDaemonClient::BDaemonClient()
:
fDaemonMessenger()
{
}
BDaemonClient::~BDaemonClient()
{
}
status_t
BDaemonClient::GetInstallationLocationInfo(
BPackageInstallationLocation location, BInstallationLocationInfo& _info)
{
status_t error = _InitMessenger();
if (error != B_OK)
return error;
// send the request
BMessage request(B_MESSAGE_GET_INSTALLATION_LOCATION_INFO);
error = request.AddInt32("location", location);
if (error != B_OK)
return error;
BMessage reply;
fDaemonMessenger.SendMessage(&request, &reply);
if (reply.what != B_MESSAGE_GET_INSTALLATION_LOCATION_INFO_REPLY)
return B_ERROR;
// extract the location info
int32 baseDirectoryDevice;
int64 baseDirectoryNode;
int32 packagesDirectoryDevice;
int64 packagesDirectoryNode;
int64 changeCount;
BPackageInfoSet activePackages;
BPackageInfoSet inactivePackages;
if ((error = reply.FindInt32("base directory device", &baseDirectoryDevice))
!= B_OK
|| (error = reply.FindInt64("base directory node", &baseDirectoryNode))
!= B_OK
|| (error = reply.FindInt32("packages directory device",
&packagesDirectoryDevice)) != B_OK
|| (error = reply.FindInt64("packages directory node",
&packagesDirectoryNode)) != B_OK
|| (error = _ExtractPackageInfoSet(reply, "active packages",
activePackages)) != B_OK
|| (error = _ExtractPackageInfoSet(reply, "inactive packages",
inactivePackages)) != B_OK
|| (error = reply.FindInt64("change count", &changeCount)) != B_OK) {
return error;
}
_info.Unset();
_info.SetLocation(location);
_info.SetBaseDirectoryRef(node_ref(baseDirectoryDevice, baseDirectoryNode));
_info.SetPackagesDirectoryRef(
node_ref(packagesDirectoryDevice, packagesDirectoryNode));
_info.SetActivePackageInfos(activePackages);
_info.SetInactivePackageInfos(inactivePackages);
_info.SetChangeCount(changeCount);
return B_OK;
}
status_t
BDaemonClient::_InitMessenger()
{
if (fDaemonMessenger.IsValid())
return B_OK;
// get the package daemon's address
status_t error;
fDaemonMessenger = BMessenger(B_PACKAGE_DAEMON_APP_SIGNATURE, -1, &error);
return error;
}
status_t
BDaemonClient::_ExtractPackageInfoSet(const BMessage& message,
const char* field, BPackageInfoSet& _infos)
{
// get the number of items
type_code type;
int32 count;
if (message.GetInfo(field, &type, &count)) {
// the field is missing
return B_OK;
}
if (type != B_MESSAGE_TYPE)
return B_BAD_DATA;
for (int32 i = 0; i < count; i++) {
BMessage archive;
status_t error = message.FindMessage(field, i, &archive);
if (error != B_OK)
return error;
BPackageInfo info(&archive, &error);
if (error != B_OK)
return error;
error = _infos.AddInfo(info);
if (error != B_OK)
return error;
}
return B_OK;
}
} // namespace BPrivate
} // namespace BPackageKit

View File

@ -51,6 +51,7 @@ SharedLibrary libpackage.so
BlockBufferCacheNoLock.cpp
ChecksumAccessors.cpp
Context.cpp
DaemonClient.cpp
DropRepositoryRequest.cpp
FetchFileJob.cpp
InstallationLocationInfo.cpp

View File

@ -19,6 +19,7 @@
#include <String.h>
#include <StringList.h>
#include <package/InstallationLocationInfo.h>
#include <package/PackageInfo.h>
#include <package/PackageInfoContentHandler.h>
#include <package/PackageInfoSet.h>
@ -28,7 +29,7 @@
#include <package/hpkg/PackageReader.h>
#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
# include <package/PackageDaemonDefs.h>
# include <package/DaemonClient.h>
#endif
@ -188,6 +189,21 @@ BPackageRoster::GetRepositoryConfig(const BString& name,
}
status_t
BPackageRoster::GetInstallationLocationInfo(
BPackageInstallationLocation location, BInstallationLocationInfo& _info)
{
// This method makes sense only on an installed Haiku, but not for the build
// tools.
#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
return BPackageKit::BPrivate::BDaemonClient().GetInstallationLocationInfo(
location, _info);
#else
return B_NOT_SUPPORTED;
#endif
}
status_t
BPackageRoster::GetActivePackages(BPackageInstallationLocation location,
BPackageInfoSet& packageInfos)
@ -195,67 +211,12 @@ BPackageRoster::GetActivePackages(BPackageInstallationLocation location,
// This method makes sense only on an installed Haiku, but not for the build
// tools.
#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
// check the given location
directory_which packagesDirectory;
switch (location) {
case B_PACKAGE_INSTALLATION_LOCATION_SYSTEM:
packagesDirectory = B_SYSTEM_PACKAGES_DIRECTORY;
break;
case B_PACKAGE_INSTALLATION_LOCATION_COMMON:
packagesDirectory = B_COMMON_PACKAGES_DIRECTORY;
break;
case B_PACKAGE_INSTALLATION_LOCATION_HOME:
packagesDirectory = B_USER_PACKAGES_DIRECTORY;
break;
default:
return B_BAD_VALUE;
}
// get the package daemon's address
status_t error;
BMessenger messenger(PACKAGE_DAEMON_APP_SIGNATURE, -1, &error);
BInstallationLocationInfo info;
status_t error = GetInstallationLocationInfo(location, info);
if (error != B_OK)
return error;
// request a list of packages
BMessage request(BPackageKit::BPrivate::MESSAGE_GET_PACKAGES);
error = request.AddInt32("location", location);
if (error != B_OK)
return error;
BMessage reply;
messenger.SendMessage(&request, &reply);
if (reply.what != BPackageKit::BPrivate::MESSAGE_GET_PACKAGES_REPLY)
return B_ERROR;
// find and open the packages directory
BPath packagesDirPath;
error = find_directory(packagesDirectory, &packagesDirPath);
if (error != B_OK)
return error;
// iterate through the packages
const char* packageFileName;
for (int32 i = 0;
reply.FindString("active packages", i, &packageFileName) == B_OK; i++) {
// get the full package file path
BPath packagePath;
error = packagePath.SetTo(packagesDirPath.Path(), packageFileName);
if (error != B_OK)
continue;
// read the package info from the file
BPackageInfo info;
error = info.ReadFromPackageFile(packagePath.Path());
if (error != B_OK || info.InitCheck() != B_OK)
continue;
// add the info
error = packageInfos.AddInfo(info);
if (error != B_OK)
return error;
}
packageInfos = info.ActivePackageInfos();
return B_OK;
#else
return B_NOT_SUPPORTED;

View File

@ -16,7 +16,7 @@
#include <NodeMonitor.h>
#include <AutoDeleter.h>
#include <package/PackageDaemonDefs.h>
#include <package/DaemonDefs.h>
#include "DebugSupport.h"
#include "Root.h"
@ -28,7 +28,7 @@ using namespace BPackageKit::BPrivate;
PackageDaemon::PackageDaemon(status_t* _error)
:
BServer(PACKAGE_DAEMON_APP_SIGNATURE, false, _error),
BServer(B_PACKAGE_DAEMON_APP_SIGNATURE, false, _error),
fSystemRoot(NULL),
fRoots(10, true),
fVolumeWatcher()
@ -85,12 +85,12 @@ PackageDaemon::MessageReceived(BMessage* message)
break;
}
case MESSAGE_GET_PACKAGES:
case B_MESSAGE_GET_INSTALLATION_LOCATION_INFO:
{
if (fSystemRoot == NULL)
break;
fSystemRoot->HandleGetPackagesRequest(DetachCurrentMessage());
fSystemRoot->HandleGetLocationInfoRequest(DetachCurrentMessage());
break;
}

View File

@ -42,11 +42,11 @@ private:
};
// #pragma mark - VolumeJob
// #pragma mark - HandleGetLocationInfoRequestJob
struct Root::HandleGetPackagesJob : public Job {
HandleGetPackagesJob(Root* root, BMessage* message)
struct Root::HandleGetLocationInfoRequestJob : public Job {
HandleGetLocationInfoRequestJob(Root* root, BMessage* message)
:
fRoot(root),
fMessage(message)
@ -55,7 +55,7 @@ struct Root::HandleGetPackagesJob : public Job {
virtual void Do()
{
fRoot->_HandleGetPackagesRequest(fMessage.Get());
fRoot->_HandleGetLocationInfoRequest(fMessage.Get());
}
private:
@ -209,10 +209,10 @@ Root::FindVolume(dev_t deviceID) const
void
Root::HandleGetPackagesRequest(BMessage* message)
Root::HandleGetLocationInfoRequest(BMessage* message)
{
HandleGetPackagesJob* job
= new(std::nothrow) HandleGetPackagesJob(this, message);
HandleGetLocationInfoRequestJob* job
= new(std::nothrow) HandleGetLocationInfoRequestJob(this, message);
if (job == NULL) {
delete message;
return;
@ -314,7 +314,7 @@ Root::_ProcessNodeMonitorEvents(Volume* volume)
void
Root::_HandleGetPackagesRequest(BMessage* message)
Root::_HandleGetLocationInfoRequest(BMessage* message)
{
int32 location;
if (message->FindInt32("location", &location) != B_OK
@ -341,7 +341,7 @@ Root::_HandleGetPackagesRequest(BMessage* message)
}
if (volume != NULL)
volume->HandleGetPackagesRequest(message);
volume->HandleGetLocationInfoRequest(message);
}

View File

@ -41,7 +41,7 @@ public:
Volume* FindVolume(dev_t deviceID) const;
void HandleGetPackagesRequest(BMessage* message);
void HandleGetLocationInfoRequest(BMessage* message);
private:
// Volume::Listener
@ -52,9 +52,9 @@ protected:
private:
struct VolumeJob;
struct HandleGetPackagesJob;
struct HandleGetLocationInfoRequestJob;
friend struct HandleGetPackagesJob;
friend struct HandleGetLocationInfoRequestJob;
private:
Volume** _GetVolume(PackageFSMountType mountType);
@ -63,7 +63,8 @@ private:
void _InitPackages(Volume* volume);
void _DeleteVolume(Volume* volume);
void _ProcessNodeMonitorEvents(Volume* volume);
void _HandleGetPackagesRequest(BMessage* message);
void _HandleGetLocationInfoRequest(
BMessage* message);
status_t _QueueJob(Job* job);

View File

@ -30,7 +30,7 @@
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include <package/PackageDaemonDefs.h>
#include <package/DaemonDefs.h>
#include <package/PackagesDirectoryDefs.h>
#include "DebugSupport.h"
@ -104,7 +104,9 @@ Volume::Volume(BLooper* looper)
fPendingNodeMonitorEventsLock("pending node monitor events"),
fPendingNodeMonitorEvents(),
fPackagesToBeActivated(),
fPackagesToBeDeactivated()
fPackagesToBeDeactivated(),
fChangeCount(0),
fLocationInfoReply(B_MESSAGE_GET_INSTALLATION_LOCATION_INFO_REPLY)
{
looper->AddHandler(this);
}
@ -335,20 +337,49 @@ INFORM("Volume::InitialVerify(%p, %p)\n", nextVolume, nextNextVolume);
void
Volume::HandleGetPackagesRequest(BMessage* message)
Volume::HandleGetLocationInfoRequest(BMessage* message)
{
BMessage reply(MESSAGE_GET_PACKAGES_REPLY);
// If the cached reply message is up-to-date, just send it.
int64 changeCount;
if (fLocationInfoReply.FindInt64("change count", &changeCount) == B_OK
&& changeCount == fChangeCount) {
message->SendReply(&fLocationInfoReply, (BHandler*)NULL,
kCommunicationTimeout);
return;
}
// rebuild the reply message
fLocationInfoReply.MakeEmpty();
if (fLocationInfoReply.AddInt32("base directory device",
fRootDirectoryRef.device) != B_OK
|| fLocationInfoReply.AddInt64("base directory node",
fRootDirectoryRef.node) != B_OK
|| fLocationInfoReply.AddInt32("packages directory device",
fPackagesDirectoryRef.device) != B_OK
|| fLocationInfoReply.AddInt64("packages directory node",
fPackagesDirectoryRef.node) != B_OK) {
return;
}
for (PackageFileNameHashTable::Iterator it
= fPackagesByFileName.GetIterator(); it.HasNext();) {
Package* package = it.Next();
const char* fieldName = package->IsActive()
? "active packages" : "inactive packages";
if (reply.AddString(fieldName, package->FileName()) != B_OK)
BMessage packageArchive;
if (package->Info().Archive(&packageArchive) != B_OK
|| fLocationInfoReply.AddMessage(fieldName, &packageArchive)
!= B_OK) {
return;
}
}
message->SendReply(&reply, (BHandler*)NULL, kCommunicationTimeout);
if (fLocationInfoReply.AddInt64("change count", fChangeCount) != B_OK)
return;
message->SendReply(&fLocationInfoReply, (BHandler*)NULL,
kCommunicationTimeout);
}
@ -514,6 +545,7 @@ fPackagesToBeActivated.size(), fPackagesToBeDeactivated.size());
for (PackageSet::iterator it = fPackagesToBeActivated.begin();
it != fPackagesToBeActivated.end(); ++it) {
(*it)->SetActive(true);
fChangeCount++;
}
for (PackageSet::iterator it = fPackagesToBeDeactivated.begin();
@ -671,8 +703,7 @@ INFORM("Volume::_PackagesEntryCreated(\"%s\")\n", name);
return;
}
fPackagesByFileName.Insert(package);
fPackagesByNodeRef.Insert(package);
_AddPackage(package);
packageDeleter.Detach();
try {
@ -731,11 +762,19 @@ Volume::_FillInActivationChangeItem(PackageFSActivationChangeItem* item,
}
void
Volume::_AddPackage(Package* package)
{
fPackagesByFileName.Insert(package);
fPackagesByNodeRef.Insert(package);
}
void
Volume::_RemovePackage(Package* package)
{
fPackagesByFileName.Remove(package);
fPackagesByNodeRef.Remove(package);
fChangeCount++;
}
@ -762,8 +801,7 @@ Volume::_ReadPackagesDirectory()
status_t error = package->Init(entry);
if (error == B_OK) {
fPackagesByFileName.Insert(package);
fPackagesByNodeRef.Insert(package);
_AddPackage(package);
packageDeleter.Detach();
}
}

View File

@ -13,6 +13,7 @@
#include <Handler.h>
#include <Locker.h>
#include <Message.h>
#include <String.h>
#include <package/packagefs.h>
@ -48,7 +49,7 @@ public:
bool activeOnly);
void InitialVerify(Volume* nextVolume,
Volume* nextNextVolume);
void HandleGetPackagesRequest(BMessage* message);
void HandleGetLocationInfoRequest(BMessage* message);
void Unmounted();
@ -105,6 +106,8 @@ private:
PackageFSActivationChangeItem* item,
PackageFSActivationChangeType type,
Package* package, char*& nameBuffer);
void _AddPackage(Package* package);
void _RemovePackage(Package* package);
status_t _ReadPackagesDirectory();
@ -133,6 +136,8 @@ private:
NodeMonitorEventList fPendingNodeMonitorEvents;
PackageSet fPackagesToBeActivated;
PackageSet fPackagesToBeDeactivated;
int64 fChangeCount;
BMessage fLocationInfoReply;
};