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:06:26 +02:00
parent d7d9497e31
commit e6216e372a
12 changed files with 329 additions and 124 deletions
+4
View File
@@ -28,6 +28,7 @@ struct BRepositoryConfigVisitor {
}; };
class BInstallationLocationInfo;
class BPackageInfoSet; class BPackageInfoSet;
class BRepositoryCache; class BRepositoryCache;
class BRepositoryConfig; class BRepositoryConfig;
@@ -60,6 +61,9 @@ public:
status_t GetRepositoryConfig(const BString& name, status_t GetRepositoryConfig(const BString& name,
BRepositoryConfig* repositoryConfig); BRepositoryConfig* repositoryConfig);
status_t GetInstallationLocationInfo(
BPackageInstallationLocation location,
BInstallationLocationInfo& _info);
status_t GetActivePackages( status_t GetActivePackages(
BPackageInstallationLocation location, BPackageInstallationLocation location,
BPackageInfoSet& packageInfos); BPackageInfoSet& packageInfos);
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#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_
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#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
@@ -1,37 +0,0 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#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
+137
View File
@@ -0,0 +1,137 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#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
+1
View File
@@ -51,6 +51,7 @@ SharedLibrary libpackage.so
BlockBufferCacheNoLock.cpp BlockBufferCacheNoLock.cpp
ChecksumAccessors.cpp ChecksumAccessors.cpp
Context.cpp Context.cpp
DaemonClient.cpp
DropRepositoryRequest.cpp DropRepositoryRequest.cpp
FetchFileJob.cpp FetchFileJob.cpp
InstallationLocationInfo.cpp InstallationLocationInfo.cpp
+20 -59
View File
@@ -19,6 +19,7 @@
#include <String.h> #include <String.h>
#include <StringList.h> #include <StringList.h>
#include <package/InstallationLocationInfo.h>
#include <package/PackageInfo.h> #include <package/PackageInfo.h>
#include <package/PackageInfoContentHandler.h> #include <package/PackageInfoContentHandler.h>
#include <package/PackageInfoSet.h> #include <package/PackageInfoSet.h>
@@ -28,7 +29,7 @@
#include <package/hpkg/PackageReader.h> #include <package/hpkg/PackageReader.h>
#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU) #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
# include <package/PackageDaemonDefs.h> # include <package/DaemonClient.h>
#endif #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 status_t
BPackageRoster::GetActivePackages(BPackageInstallationLocation location, BPackageRoster::GetActivePackages(BPackageInstallationLocation location,
BPackageInfoSet& packageInfos) BPackageInfoSet& packageInfos)
@@ -195,67 +211,12 @@ BPackageRoster::GetActivePackages(BPackageInstallationLocation location,
// This method makes sense only on an installed Haiku, but not for the build // This method makes sense only on an installed Haiku, but not for the build
// tools. // tools.
#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU) #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
// check the given location BInstallationLocationInfo info;
directory_which packagesDirectory; status_t error = GetInstallationLocationInfo(location, info);
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);
if (error != B_OK) if (error != B_OK)
return error; return error;
// request a list of packages packageInfos = info.ActivePackageInfos();
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;
}
return B_OK; return B_OK;
#else #else
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
+4 -4
View File
@@ -16,7 +16,7 @@
#include <NodeMonitor.h> #include <NodeMonitor.h>
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include <package/PackageDaemonDefs.h> #include <package/DaemonDefs.h>
#include "DebugSupport.h" #include "DebugSupport.h"
#include "Root.h" #include "Root.h"
@@ -28,7 +28,7 @@ using namespace BPackageKit::BPrivate;
PackageDaemon::PackageDaemon(status_t* _error) PackageDaemon::PackageDaemon(status_t* _error)
: :
BServer(PACKAGE_DAEMON_APP_SIGNATURE, false, _error), BServer(B_PACKAGE_DAEMON_APP_SIGNATURE, false, _error),
fSystemRoot(NULL), fSystemRoot(NULL),
fRoots(10, true), fRoots(10, true),
fVolumeWatcher() fVolumeWatcher()
@@ -85,12 +85,12 @@ PackageDaemon::MessageReceived(BMessage* message)
break; break;
} }
case MESSAGE_GET_PACKAGES: case B_MESSAGE_GET_INSTALLATION_LOCATION_INFO:
{ {
if (fSystemRoot == NULL) if (fSystemRoot == NULL)
break; break;
fSystemRoot->HandleGetPackagesRequest(DetachCurrentMessage()); fSystemRoot->HandleGetLocationInfoRequest(DetachCurrentMessage());
break; break;
} }
+9 -9
View File
@@ -42,11 +42,11 @@ private:
}; };
// #pragma mark - VolumeJob // #pragma mark - HandleGetLocationInfoRequestJob
struct Root::HandleGetPackagesJob : public Job { struct Root::HandleGetLocationInfoRequestJob : public Job {
HandleGetPackagesJob(Root* root, BMessage* message) HandleGetLocationInfoRequestJob(Root* root, BMessage* message)
: :
fRoot(root), fRoot(root),
fMessage(message) fMessage(message)
@@ -55,7 +55,7 @@ struct Root::HandleGetPackagesJob : public Job {
virtual void Do() virtual void Do()
{ {
fRoot->_HandleGetPackagesRequest(fMessage.Get()); fRoot->_HandleGetLocationInfoRequest(fMessage.Get());
} }
private: private:
@@ -209,10 +209,10 @@ Root::FindVolume(dev_t deviceID) const
void void
Root::HandleGetPackagesRequest(BMessage* message) Root::HandleGetLocationInfoRequest(BMessage* message)
{ {
HandleGetPackagesJob* job HandleGetLocationInfoRequestJob* job
= new(std::nothrow) HandleGetPackagesJob(this, message); = new(std::nothrow) HandleGetLocationInfoRequestJob(this, message);
if (job == NULL) { if (job == NULL) {
delete message; delete message;
return; return;
@@ -314,7 +314,7 @@ Root::_ProcessNodeMonitorEvents(Volume* volume)
void void
Root::_HandleGetPackagesRequest(BMessage* message) Root::_HandleGetLocationInfoRequest(BMessage* message)
{ {
int32 location; int32 location;
if (message->FindInt32("location", &location) != B_OK if (message->FindInt32("location", &location) != B_OK
@@ -341,7 +341,7 @@ Root::_HandleGetPackagesRequest(BMessage* message)
} }
if (volume != NULL) if (volume != NULL)
volume->HandleGetPackagesRequest(message); volume->HandleGetLocationInfoRequest(message);
} }
+5 -4
View File
@@ -41,7 +41,7 @@ public:
Volume* FindVolume(dev_t deviceID) const; Volume* FindVolume(dev_t deviceID) const;
void HandleGetPackagesRequest(BMessage* message); void HandleGetLocationInfoRequest(BMessage* message);
private: private:
// Volume::Listener // Volume::Listener
@@ -52,9 +52,9 @@ protected:
private: private:
struct VolumeJob; struct VolumeJob;
struct HandleGetPackagesJob; struct HandleGetLocationInfoRequestJob;
friend struct HandleGetPackagesJob; friend struct HandleGetLocationInfoRequestJob;
private: private:
Volume** _GetVolume(PackageFSMountType mountType); Volume** _GetVolume(PackageFSMountType mountType);
@@ -63,7 +63,8 @@ private:
void _InitPackages(Volume* volume); void _InitPackages(Volume* volume);
void _DeleteVolume(Volume* volume); void _DeleteVolume(Volume* volume);
void _ProcessNodeMonitorEvents(Volume* volume); void _ProcessNodeMonitorEvents(Volume* volume);
void _HandleGetPackagesRequest(BMessage* message); void _HandleGetLocationInfoRequest(
BMessage* message);
status_t _QueueJob(Job* job); status_t _QueueJob(Job* job);
+48 -10
View File
@@ -30,7 +30,7 @@
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include <AutoLocker.h> #include <AutoLocker.h>
#include <package/PackageDaemonDefs.h> #include <package/DaemonDefs.h>
#include <package/PackagesDirectoryDefs.h> #include <package/PackagesDirectoryDefs.h>
#include "DebugSupport.h" #include "DebugSupport.h"
@@ -104,7 +104,9 @@ Volume::Volume(BLooper* looper)
fPendingNodeMonitorEventsLock("pending node monitor events"), fPendingNodeMonitorEventsLock("pending node monitor events"),
fPendingNodeMonitorEvents(), fPendingNodeMonitorEvents(),
fPackagesToBeActivated(), fPackagesToBeActivated(),
fPackagesToBeDeactivated() fPackagesToBeDeactivated(),
fChangeCount(0),
fLocationInfoReply(B_MESSAGE_GET_INSTALLATION_LOCATION_INFO_REPLY)
{ {
looper->AddHandler(this); looper->AddHandler(this);
} }
@@ -335,20 +337,49 @@ INFORM("Volume::InitialVerify(%p, %p)\n", nextVolume, nextNextVolume);
void 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 for (PackageFileNameHashTable::Iterator it
= fPackagesByFileName.GetIterator(); it.HasNext();) { = fPackagesByFileName.GetIterator(); it.HasNext();) {
Package* package = it.Next(); Package* package = it.Next();
const char* fieldName = package->IsActive() const char* fieldName = package->IsActive()
? "active packages" : "inactive packages"; ? "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; 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(); for (PackageSet::iterator it = fPackagesToBeActivated.begin();
it != fPackagesToBeActivated.end(); ++it) { it != fPackagesToBeActivated.end(); ++it) {
(*it)->SetActive(true); (*it)->SetActive(true);
fChangeCount++;
} }
for (PackageSet::iterator it = fPackagesToBeDeactivated.begin(); for (PackageSet::iterator it = fPackagesToBeDeactivated.begin();
@@ -671,8 +703,7 @@ INFORM("Volume::_PackagesEntryCreated(\"%s\")\n", name);
return; return;
} }
fPackagesByFileName.Insert(package); _AddPackage(package);
fPackagesByNodeRef.Insert(package);
packageDeleter.Detach(); packageDeleter.Detach();
try { try {
@@ -731,11 +762,19 @@ Volume::_FillInActivationChangeItem(PackageFSActivationChangeItem* item,
} }
void
Volume::_AddPackage(Package* package)
{
fPackagesByFileName.Insert(package);
fPackagesByNodeRef.Insert(package);
}
void void
Volume::_RemovePackage(Package* package) Volume::_RemovePackage(Package* package)
{ {
fPackagesByFileName.Remove(package); fPackagesByFileName.Remove(package);
fPackagesByNodeRef.Remove(package); fPackagesByNodeRef.Remove(package);
fChangeCount++;
} }
@@ -762,8 +801,7 @@ Volume::_ReadPackagesDirectory()
status_t error = package->Init(entry); status_t error = package->Init(entry);
if (error == B_OK) { if (error == B_OK) {
fPackagesByFileName.Insert(package); _AddPackage(package);
fPackagesByNodeRef.Insert(package);
packageDeleter.Detach(); packageDeleter.Detach();
} }
} }
+6 -1
View File
@@ -13,6 +13,7 @@
#include <Handler.h> #include <Handler.h>
#include <Locker.h> #include <Locker.h>
#include <Message.h>
#include <String.h> #include <String.h>
#include <package/packagefs.h> #include <package/packagefs.h>
@@ -48,7 +49,7 @@ public:
bool activeOnly); bool activeOnly);
void InitialVerify(Volume* nextVolume, void InitialVerify(Volume* nextVolume,
Volume* nextNextVolume); Volume* nextNextVolume);
void HandleGetPackagesRequest(BMessage* message); void HandleGetLocationInfoRequest(BMessage* message);
void Unmounted(); void Unmounted();
@@ -105,6 +106,8 @@ private:
PackageFSActivationChangeItem* item, PackageFSActivationChangeItem* item,
PackageFSActivationChangeType type, PackageFSActivationChangeType type,
Package* package, char*& nameBuffer); Package* package, char*& nameBuffer);
void _AddPackage(Package* package);
void _RemovePackage(Package* package); void _RemovePackage(Package* package);
status_t _ReadPackagesDirectory(); status_t _ReadPackagesDirectory();
@@ -133,6 +136,8 @@ private:
NodeMonitorEventList fPendingNodeMonitorEvents; NodeMonitorEventList fPendingNodeMonitorEvents;
PackageSet fPackagesToBeActivated; PackageSet fPackagesToBeActivated;
PackageSet fPackagesToBeDeactivated; PackageSet fPackagesToBeDeactivated;
int64 fChangeCount;
BMessage fLocationInfoReply;
}; };