Add watching support for installation location package changes

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".
This commit is contained in:
Ingo Weinhold 2014-06-17 09:46:48 +02:00
parent 3f91ba29d9
commit 5c9672edeb
11 changed files with 271 additions and 3 deletions

View File

@ -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',

View File

@ -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_
@ -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();
@ -68,6 +85,10 @@ public:
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;

View File

@ -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

View File

@ -1,6 +1,7 @@
SubDir HAIKU_TOP src kits package ;
UsePrivateHeaders
app
kernel
shared
storage

View File

@ -31,6 +31,8 @@
#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
# include <package/DaemonClient.h>
# include <RegistrarDefs.h>
# include <RosterPrivate.h>
#endif
@ -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

View File

@ -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>
@ -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"
@ -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);
}
}
}

View File

@ -27,6 +27,7 @@ Server registrar
MessageRunnerManager.cpp
MessagingService.cpp
MIMEManager.cpp
PackageWatchingManager.cpp
PriorityMessageQueue.cpp
RecentApps.cpp
RecentEntries.cpp

View File

@ -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;
}

View File

@ -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

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2009, Haiku, Inc. All Rights Reserved.
* Copyright 2001-2014, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -29,6 +29,7 @@
#include "MessageRunnerManager.h"
#include "MessagingService.h"
#include "MIMEManager.h"
#include "PackageWatchingManager.h"
#include "ShutdownProcess.h"
#include "TRoster.h"
@ -64,7 +65,8 @@ Registrar::Registrar(status_t *error)
fMessageRunnerManager(NULL),
fSanityEvent(NULL),
fShutdownProcess(NULL),
fAuthenticationManager(NULL)
fAuthenticationManager(NULL),
fPackageWatchingManager(NULL)
{
FUNCTION_START();
@ -83,6 +85,7 @@ Registrar::~Registrar()
Lock();
fEventQueue->Die();
delete fAuthenticationManager;
delete fPackageWatchingManager;
delete fMessageRunnerManager;
delete fEventQueue;
delete fSanityEvent;
@ -166,6 +169,9 @@ Registrar::ReadyToRun()
"(that's by design when running under R5): %s\n", strerror(error));
}
// create the package watching manager
fPackageWatchingManager = new PackageWatchingManager;
// create and schedule the sanity message event
fSanityEvent = new MessageEvent(system_time() + kRosterSanityEventInterval,
this, B_REG_ROSTER_SANITY_EVENT);
@ -336,6 +342,15 @@ Registrar::_MessageReceived(BMessage *message)
fMessageRunnerManager->HandleGetRunnerInfo(message);
break;
// package watching requests
case B_REG_PACKAGE_START_WATCHING:
case B_REG_PACKAGE_STOP_WATCHING:
fPackageWatchingManager->HandleStartStopWatching(message);
break;
case B_PACKAGE_UPDATE:
fPackageWatchingManager->NotifyWatchers(message);
break;
// internal messages
case B_REG_ROSTER_SANITY_EVENT:
fRoster->CheckSanity();

View File

@ -36,6 +36,7 @@ class EventQueue;
class MessageEvent;
class MessageRunnerManager;
class MIMEManager;
class PackageWatchingManager;
class ShutdownProcess;
class TRoster;
@ -66,6 +67,7 @@ private:
MessageEvent *fSanityEvent;
ShutdownProcess *fShutdownProcess;
AuthenticationManager *fAuthenticationManager;
PackageWatchingManager *fPackageWatchingManager;
};
#endif // REGISTRAR_H