Added a work-around for the problem, that we can't use libbe's node monitoring functions, when linked against libopenbeos. An application NodeMonitor acts as a mediator. Not an optimal solution, but the only one I have for now -- if someone told me which parameters _k{start,stop}_watching_vnode_() have, things looked much nicer. The work-around is currently only used for the registrar; for other places the code that get the path of NodeMonitor needs to be adjusted.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2633 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -20,6 +20,7 @@ Server obos_registrar :
|
|||||||
MessageEvent.cpp
|
MessageEvent.cpp
|
||||||
MessageRunnerManager.cpp
|
MessageRunnerManager.cpp
|
||||||
MIMEManager.cpp
|
MIMEManager.cpp
|
||||||
|
NodeMonitoring.cpp
|
||||||
RDiskDevice.cpp
|
RDiskDevice.cpp
|
||||||
RDiskDeviceList.cpp
|
RDiskDeviceList.cpp
|
||||||
RecentApps.cpp
|
RecentApps.cpp
|
||||||
@@ -29,6 +30,7 @@ Server obos_registrar :
|
|||||||
RosterSettingsCharStream.cpp
|
RosterSettingsCharStream.cpp
|
||||||
RPartition.cpp
|
RPartition.cpp
|
||||||
RSession.cpp
|
RSession.cpp
|
||||||
|
RVolumeList.cpp
|
||||||
TRoster.cpp
|
TRoster.cpp
|
||||||
Watcher.cpp
|
Watcher.cpp
|
||||||
WatchingService.cpp
|
WatchingService.cpp
|
||||||
@@ -42,3 +44,10 @@ LinkSharedOSLibs obos_registrar :
|
|||||||
stdc++.r4
|
stdc++.r4
|
||||||
be
|
be
|
||||||
;
|
;
|
||||||
|
|
||||||
|
# Helper needed for node watching
|
||||||
|
#
|
||||||
|
BinCommand NodeMonitor : NodeMonitor.cpp : be ;
|
||||||
|
|
||||||
|
Depends obos_registrar : NodeMonitor ;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
//----------------------------------------------------------------------
|
||||||
|
// This software is part of the OpenBeOS distribution and is covered
|
||||||
|
// by the OpenBeOS license.
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Message.h>
|
||||||
|
#include <Messenger.h>
|
||||||
|
#include <NodeMonitor.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
|
// Monitor
|
||||||
|
class Monitor : public BHandler {
|
||||||
|
public:
|
||||||
|
Monitor(BMessenger target);
|
||||||
|
virtual ~Monitor();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage *message);
|
||||||
|
|
||||||
|
BMessenger Target() const { return fTarget; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMessenger fTarget;
|
||||||
|
};
|
||||||
|
|
||||||
|
// NodeMonitorApp
|
||||||
|
class NodeMonitorApp : public BApplication {
|
||||||
|
public:
|
||||||
|
NodeMonitorApp();
|
||||||
|
virtual ~NodeMonitorApp();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage *message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BObjectList<Monitor> fMonitors;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Monitor
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Monitor::Monitor(BMessenger target)
|
||||||
|
: BHandler(),
|
||||||
|
fTarget(target)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
Monitor::~Monitor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageReceived
|
||||||
|
void
|
||||||
|
Monitor::MessageReceived(BMessage *message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case B_NODE_MONITOR:
|
||||||
|
fTarget.SendMessage(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NodeMonitorApp
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
NodeMonitorApp::NodeMonitorApp()
|
||||||
|
: BApplication("application/x-vnd.obos-NodeMonitor"),
|
||||||
|
fMonitors(10, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
NodeMonitorApp::~NodeMonitorApp()
|
||||||
|
{
|
||||||
|
Lock();
|
||||||
|
for (int32 i = 0; Monitor *monitor = fMonitors.ItemAt(i); i++)
|
||||||
|
RemoveHandler(monitor);
|
||||||
|
Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageReceived
|
||||||
|
void
|
||||||
|
NodeMonitorApp::MessageReceived(BMessage *message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case 'wtch':
|
||||||
|
{
|
||||||
|
status_t error = B_BAD_VALUE;
|
||||||
|
node_ref ref;
|
||||||
|
BMessenger target;
|
||||||
|
uint32 flags;
|
||||||
|
if (message->FindInt32("device", &ref.device) == B_OK
|
||||||
|
&& message->FindInt64("node", &ref.node) == B_OK
|
||||||
|
&& message->FindMessenger("target", &target) == B_OK
|
||||||
|
&& message->FindInt32("flags", (int32*)&flags) == B_OK) {
|
||||||
|
Monitor *monitor = new Monitor(target);
|
||||||
|
fMonitors.AddItem(monitor);
|
||||||
|
AddHandler(monitor);
|
||||||
|
error = watch_node(&ref, flags, monitor);
|
||||||
|
if (error != B_OK) {
|
||||||
|
RemoveHandler(monitor);
|
||||||
|
fMonitors.RemoveItem(monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BMessage reply(B_SIMPLE_DATA);
|
||||||
|
reply.AddInt32("result", error);
|
||||||
|
message->SendReply(&reply);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'hctw':
|
||||||
|
{
|
||||||
|
status_t error = B_BAD_VALUE;
|
||||||
|
BMessenger target;
|
||||||
|
if (message->FindMessenger("target", &target) == B_OK) {
|
||||||
|
error = B_OK;
|
||||||
|
for (int32 i = fMonitors.CountItems();
|
||||||
|
Monitor *monitor = fMonitors.ItemAt(i);
|
||||||
|
i--) {
|
||||||
|
if (monitor->Target() == target) {
|
||||||
|
error = stop_watching(monitor->Target());
|
||||||
|
RemoveHandler(monitor);
|
||||||
|
delete fMonitors.RemoveItemAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BMessage reply(B_SIMPLE_DATA);
|
||||||
|
reply.AddInt32("result", error);
|
||||||
|
message->SendReply(&reply);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// main
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
NodeMonitorApp app;
|
||||||
|
app.Run();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
//----------------------------------------------------------------------
|
||||||
|
// This software is part of the OpenBeOS distribution and is covered
|
||||||
|
// by the OpenBeOS license.
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
// A fake implementation of the node monitoring functions.
|
||||||
|
// They start a remote application that functions as an adapter for the
|
||||||
|
// functions in libbe.so.
|
||||||
|
// Note: We can't use the node monitoring provided by libbe directly, since
|
||||||
|
// it makes sure, that the target is local using BMessenger::Target(), which
|
||||||
|
// can't work.
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <AppMisc.h>
|
||||||
|
#include <image.h>
|
||||||
|
#include <Locker.h>
|
||||||
|
#include <Message.h>
|
||||||
|
#include <Messenger.h>
|
||||||
|
#include <NodeMonitor.h>
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include "Debug.h"
|
||||||
|
|
||||||
|
// NodeMonitor
|
||||||
|
class NodeMonitor {
|
||||||
|
public:
|
||||||
|
NodeMonitor();
|
||||||
|
~NodeMonitor();
|
||||||
|
|
||||||
|
status_t GetMessenger(BMessenger &monitor);
|
||||||
|
status_t WatchingRequest(const node_ref *node, uint32 flags,
|
||||||
|
BMessenger target, bool start);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool fInitialized;
|
||||||
|
status_t fStatus;
|
||||||
|
thread_id fThread;
|
||||||
|
team_id fTeam;
|
||||||
|
BMessenger fMessenger;
|
||||||
|
BLocker fLock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static NodeMonitor gNodeMonitor;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
NodeMonitor::NodeMonitor()
|
||||||
|
: fInitialized(false),
|
||||||
|
fStatus(B_ERROR),
|
||||||
|
fThread(-1),
|
||||||
|
fTeam(-1),
|
||||||
|
fMessenger(),
|
||||||
|
fLock()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
NodeMonitor::~NodeMonitor()
|
||||||
|
{
|
||||||
|
fLock.Lock();
|
||||||
|
if (fInitialized) {
|
||||||
|
if (fMessenger.IsValid())
|
||||||
|
fMessenger.SendMessage(B_QUIT_REQUESTED);
|
||||||
|
else if (fThread >= 0)
|
||||||
|
kill_thread(fThread);
|
||||||
|
}
|
||||||
|
fLock.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMessenger
|
||||||
|
status_t
|
||||||
|
NodeMonitor::GetMessenger(BMessenger &monitor)
|
||||||
|
{
|
||||||
|
fLock.Lock();
|
||||||
|
if (!fInitialized) {
|
||||||
|
fInitialized = true;
|
||||||
|
// get NodeMonitor path
|
||||||
|
char path[B_PATH_NAME_LENGTH];
|
||||||
|
fStatus = BPrivate::get_app_path(path);
|
||||||
|
if (fStatus == B_OK) {
|
||||||
|
if (char *leaf = strstr(path, "obos_registrar")) {
|
||||||
|
strcpy(leaf, "../../bin/NodeMonitor");
|
||||||
|
} else
|
||||||
|
fStatus = B_ERROR;
|
||||||
|
}
|
||||||
|
// start the NodeMonitor
|
||||||
|
if (fStatus == B_OK) {
|
||||||
|
const char *argv[] = { path, NULL };
|
||||||
|
fThread = load_image(1, argv,
|
||||||
|
const_cast<const char**>(environ));
|
||||||
|
if (fThread >= 0) {
|
||||||
|
resume_thread(fThread);
|
||||||
|
thread_info info;
|
||||||
|
fStatus = get_thread_info(fThread, &info);
|
||||||
|
if (fStatus == B_OK)
|
||||||
|
fTeam = info.team;
|
||||||
|
} else
|
||||||
|
fStatus = fThread;
|
||||||
|
}
|
||||||
|
// find the app looper port
|
||||||
|
port_id port = -1;
|
||||||
|
if (fStatus == B_OK) {
|
||||||
|
snooze(200000);
|
||||||
|
port_info info;
|
||||||
|
int32 cookie = 0;
|
||||||
|
fStatus = B_ERROR;
|
||||||
|
while (get_next_port_info(fTeam, &cookie, &info) == B_OK) {
|
||||||
|
if (!strcmp(info.name, "AppLooperPort")) {
|
||||||
|
fStatus = B_OK;
|
||||||
|
port = info.port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// get a messenger
|
||||||
|
if (fStatus == B_OK) {
|
||||||
|
struct {
|
||||||
|
port_id fPort;
|
||||||
|
int32 fHandlerToken;
|
||||||
|
team_id fTeam;
|
||||||
|
int32 extra0;
|
||||||
|
int32 extra1;
|
||||||
|
bool fPreferredTarget;
|
||||||
|
bool extra2;
|
||||||
|
bool extra3;
|
||||||
|
bool extra4;
|
||||||
|
} fakeMessenger;
|
||||||
|
fakeMessenger.fPort = port;
|
||||||
|
fakeMessenger.fHandlerToken = -1;
|
||||||
|
fakeMessenger.fTeam = fTeam;
|
||||||
|
fakeMessenger.fPreferredTarget = true;
|
||||||
|
fMessenger = *(BMessenger*)&fakeMessenger;
|
||||||
|
if (!fMessenger.IsValid())
|
||||||
|
fStatus = B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// set result
|
||||||
|
if (fStatus == B_OK)
|
||||||
|
monitor = fMessenger;
|
||||||
|
fLock.Unlock();
|
||||||
|
return fStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchingRequest
|
||||||
|
status_t
|
||||||
|
NodeMonitor::WatchingRequest(const node_ref *node, uint32 flags,
|
||||||
|
BMessenger target, bool start)
|
||||||
|
{
|
||||||
|
BMessenger monitor;
|
||||||
|
status_t error = GetMessenger(monitor);
|
||||||
|
// prepare request message
|
||||||
|
BMessage request;
|
||||||
|
if (error == B_OK) {
|
||||||
|
if (start) {
|
||||||
|
request.what = 'wtch';
|
||||||
|
request.AddInt32("device", node->device);
|
||||||
|
request.AddInt64("node", node->node);
|
||||||
|
request.AddInt32("flags", (int32)flags);
|
||||||
|
} else {
|
||||||
|
request.what = 'hctw';
|
||||||
|
}
|
||||||
|
request.AddMessenger("target", target);
|
||||||
|
}
|
||||||
|
// send request
|
||||||
|
BMessage reply;
|
||||||
|
if (error == B_OK)
|
||||||
|
error = monitor.SendMessage(&request, &reply);
|
||||||
|
// analyze reply
|
||||||
|
if (error == B_OK) {
|
||||||
|
status_t result;
|
||||||
|
error = reply.FindInt32("result", &result);
|
||||||
|
if (error == B_OK)
|
||||||
|
error = result;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// watch_node
|
||||||
|
status_t
|
||||||
|
watch_node(const node_ref *node, uint32 flags, BMessenger target)
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
if (flags == B_STOP_WATCHING)
|
||||||
|
error = stop_watching(target);
|
||||||
|
else {
|
||||||
|
node_ref fakeNode;
|
||||||
|
if (!node)
|
||||||
|
node = &fakeNode;
|
||||||
|
error = gNodeMonitor.WatchingRequest(node, flags, target, true);
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// watch_node
|
||||||
|
status_t
|
||||||
|
watch_node(const node_ref *node, uint32 flags, const BHandler *handler,
|
||||||
|
const BLooper *looper)
|
||||||
|
{
|
||||||
|
status_t error = (handler || looper ? B_OK : B_BAD_VALUE);
|
||||||
|
if (error == B_OK) {
|
||||||
|
BMessenger target(handler, looper);
|
||||||
|
error = watch_node(node, flags, target);
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop_watching
|
||||||
|
status_t
|
||||||
|
stop_watching(BMessenger target)
|
||||||
|
{
|
||||||
|
return gNodeMonitor.WatchingRequest(NULL, 0, target, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop_watching
|
||||||
|
status_t
|
||||||
|
stop_watching(const BHandler *handler, const BLooper *looper)
|
||||||
|
{
|
||||||
|
status_t error = (handler || looper ? B_OK : B_BAD_VALUE);
|
||||||
|
if (error == B_OK) {
|
||||||
|
BMessenger target(handler, looper);
|
||||||
|
error = stop_watching(target);
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user