Skip to content

Commit

Permalink
Add watching support for installation location package changes
Browse files Browse the repository at this point in the history
Can be requested/stopped via BPackageRoster::{Start,Stop}Watching().
The notification message has the what code B_PACKAGE_UPDATE and contains
fields "event", "location", and "change count".
  • Loading branch information
weinhold committed Jun 17, 2014
1 parent 3f91ba2 commit 5c9672e
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 3 deletions.
1 change: 1 addition & 0 deletions headers/os/app/AppDefs.h
Expand Up @@ -48,6 +48,7 @@ enum {
B_MOUSE_UP = '_MUP',
B_MOUSE_WHEEL_CHANGED = '_MWC',
B_OPEN_IN_WORKSPACE = '_OWS',
B_PACKAGE_UPDATE = '_PKU',
B_PRINTER_CHANGED = '_PCH',
B_PULSE = '_PUL',
B_READY_TO_RUN = '_RTR',
Expand Down
23 changes: 22 additions & 1 deletion headers/os/package/PackageRoster.h
@@ -1,5 +1,5 @@
/*
* Copyright 2011, Haiku, Inc.
* Copyright 2011-2014, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _PACKAGE__PACKAGE_ROSTER_H_
Expand Down Expand Up @@ -34,6 +34,23 @@ class BRepositoryCache;
class BRepositoryConfig;


// watchable events
enum {
B_WATCH_PACKAGE_INSTALLATION_LOCATIONS = 0x0001,
// de-/activation of packages in standard installation locations
};

// notification message "event" field values
enum {
B_INSTALLATION_LOCATION_PACKAGES_CHANGED,
// "location": int32
// the installation location
// (B_PACKAGE_INSTALLATION_LOCATION_{SYSTEM,HOME}
// "change count": int64
// the installation location change count
};


class BPackageRoster {
public:
BPackageRoster();
Expand Down Expand Up @@ -68,6 +85,10 @@ class BPackageRoster {
BPackageInstallationLocation location,
BPackageInfoSet& packageInfos);

status_t StartWatching(const BMessenger& target,
uint32 eventMask);
status_t StopWatching(const BMessenger& target);

private:
status_t _GetRepositoryPath(BPath* path, bool create,
directory_which whichDir) const;
Expand Down
4 changes: 4 additions & 0 deletions headers/private/app/RegistrarDefs.h
Expand Up @@ -124,6 +124,10 @@ enum {
B_REG_DELETE_USER = 'rdus',
B_REG_UPDATE_GROUP = 'rugr',
B_REG_DELETE_GROUP = 'rdgr',

// package watching requests
B_REG_PACKAGE_START_WATCHING = 'rgPw',
B_REG_PACKAGE_STOP_WATCHING = 'rgPx',
};

// B_REG_MIME_SET_PARAM "which" constants
Expand Down
1 change: 1 addition & 0 deletions src/kits/package/Jamfile
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src kits package ;

UsePrivateHeaders
app
kernel
shared
storage
Expand Down
70 changes: 70 additions & 0 deletions src/kits/package/PackageRoster.cpp
Expand Up @@ -31,6 +31,8 @@

#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
# include <package/DaemonClient.h>
# include <RegistrarDefs.h>
# include <RosterPrivate.h>
#endif


Expand Down Expand Up @@ -225,6 +227,74 @@ BPackageRoster::GetActivePackages(BPackageInstallationLocation location,
}


status_t
BPackageRoster::StartWatching(const BMessenger& target, uint32 eventMask)
{
// This method makes sense only on an installed Haiku, but not for the build
// tools.
#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
// compose the registrar request
BMessage request(::BPrivate::B_REG_PACKAGE_START_WATCHING);
status_t error;
if ((error = request.AddMessenger("target", target)) != B_OK
|| (error = request.AddUInt32("events", eventMask)) != B_OK) {
return error;
}

// send it
BMessage reply;
error = BRoster::Private().SendTo(&request, &reply, false);
if (error != B_OK)
return error;

// get result
if (reply.what != ::BPrivate::B_REG_SUCCESS) {
int32 result;
if (reply.FindInt32("error", &result) != B_OK)
result = B_ERROR;
return (status_t)error;
}

return B_OK;
#else
return B_NOT_SUPPORTED;
#endif
}


status_t
BPackageRoster::StopWatching(const BMessenger& target)
{
// This method makes sense only on an installed Haiku, but not for the build
// tools.
#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
// compose the registrar request
BMessage request(::BPrivate::B_REG_PACKAGE_STOP_WATCHING);
status_t error = request.AddMessenger("target", target);
if (error != B_OK)
return error;

// send it
BMessage reply;
error = BRoster::Private().SendTo(&request, &reply, false);
if (error != B_OK)
return error;

// get result
if (reply.what != ::BPrivate::B_REG_SUCCESS) {
int32 result;
if (reply.FindInt32("error", &result) != B_OK)
result = B_ERROR;
return (status_t)error;
}

return B_OK;
#else
return B_NOT_SUPPORTED;
#endif
}


status_t
BPackageRoster::_GetRepositoryPath(BPath* path, bool create,
directory_which whichDir) const
Expand Down
17 changes: 17 additions & 0 deletions src/servers/package/Volume.cpp
Expand Up @@ -22,8 +22,10 @@
#include <MessageRunner.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <Roster.h>

#include <package/CommitTransactionResult.h>
#include <package/PackageRoster.h>
#include <package/solver/Solver.h>
#include <package/solver/SolverPackage.h>
#include <package/solver/SolverProblem.h>
Expand All @@ -35,12 +37,14 @@
#include <AutoLocker.h>
#include <NotOwningEntryRef.h>
#include <package/DaemonDefs.h>
#include <RosterPrivate.h>

#include "CommitTransactionHandler.h"
#include "Constants.h"
#include "DebugSupport.h"
#include "Exception.h"
#include "PackageFileManager.h"
#include "Root.h"
#include "VolumeState.h"


Expand Down Expand Up @@ -1193,6 +1197,19 @@ Volume::_SetLatestState(VolumeState* state, bool isActive)
delete fLatestState;
fLatestState = state;
fChangeCount++;

locker.Unlock();

// Send a notification, if this is a system root volume.
if (fRoot->IsSystemRoot()) {
BMessage message(B_PACKAGE_UPDATE);
if (message.AddInt32("event",
(int32)B_INSTALLATION_LOCATION_PACKAGES_CHANGED) == B_OK
&& message.AddInt32("location", (int32)Location()) == B_OK
&& message.AddInt64("change count", fChangeCount) == B_OK) {
BRoster::Private().SendTo(&message, NULL, false);
}
}
}


Expand Down
1 change: 1 addition & 0 deletions src/servers/registrar/Jamfile
Expand Up @@ -27,6 +27,7 @@ Server registrar
MessageRunnerManager.cpp
MessagingService.cpp
MIMEManager.cpp
PackageWatchingManager.cpp
PriorityMessageQueue.cpp
RecentApps.cpp
RecentEntries.cpp
Expand Down
107 changes: 107 additions & 0 deletions src/servers/registrar/PackageWatchingManager.cpp
@@ -0,0 +1,107 @@
/*
* Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/


#include "PackageWatchingManager.h"

#include <new>

#include <package/PackageRoster.h>

#include <RegistrarDefs.h>

#include "Debug.h"
#include "EventMaskWatcher.h"


using namespace BPackageKit;
using namespace BPrivate;


PackageWatchingManager::PackageWatchingManager()
{
}


PackageWatchingManager::~PackageWatchingManager()
{
}


void
PackageWatchingManager::HandleStartStopWatching(BMessage* request)
{
status_t error = request->what == B_REG_PACKAGE_START_WATCHING
? _AddWatcher(request) : _RemoveWatcher(request);

if (error == B_OK) {
BMessage reply(B_REG_SUCCESS);
request->SendReply(&reply);
} else {
BMessage reply(B_REG_ERROR);
reply.AddInt32("error", error);
request->SendReply(&reply);
}
}


void
PackageWatchingManager::NotifyWatchers(BMessage* message)
{
int32 event;
if (message->FindInt32("event", &event) != B_OK) {
WARNING("No event field in notification message\n");
return;
}

uint32 eventMask;
switch (event) {
case B_INSTALLATION_LOCATION_PACKAGES_CHANGED:
eventMask = B_WATCH_PACKAGE_INSTALLATION_LOCATIONS;
break;
default:
WARNING("Invalid event: %" B_PRId32 "\n", event);
return;
}

EventMaskWatcherFilter filter(eventMask);
fWatchingService.NotifyWatchers(message, &filter);
}


status_t
PackageWatchingManager::_AddWatcher(const BMessage* request)
{
BMessenger target;
uint32 eventMask;
status_t error;
if ((error = request->FindMessenger("target", &target)) != B_OK
|| (error = request->FindUInt32("events", &eventMask)) != B_OK) {
return error;
}

Watcher* watcher = new(std::nothrow) EventMaskWatcher(target, eventMask);
if (watcher == NULL || !fWatchingService.AddWatcher(watcher)) {
delete watcher;
return B_NO_MEMORY;
}

return B_OK;
}


status_t
PackageWatchingManager::_RemoveWatcher(const BMessage* request)
{
BMessenger target;
status_t error;
if ((error = request->FindMessenger("target", &target)) != B_OK)
return error;

if (!fWatchingService.RemoveWatcher(target))
return B_BAD_VALUE;

return B_OK;
}
29 changes: 29 additions & 0 deletions src/servers/registrar/PackageWatchingManager.h
@@ -0,0 +1,29 @@
/*
* Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef PACKAGE_WATCHING_MANAGER_H
#define PACKAGE_WATCHING_MANAGER_H


#include "WatchingService.h"


class PackageWatchingManager {
public:
PackageWatchingManager();
~PackageWatchingManager();

void HandleStartStopWatching(BMessage* request);
void NotifyWatchers(BMessage* message);

private:
status_t _AddWatcher(const BMessage* request);
status_t _RemoveWatcher(const BMessage* request);

private:
WatchingService fWatchingService;
};


#endif // PACKAGE_WATCHING_MANAGER_H

0 comments on commit 5c9672e

Please sign in to comment.