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
|
||||
MessageRunnerManager.cpp
|
||||
MIMEManager.cpp
|
||||
NodeMonitoring.cpp
|
||||
RDiskDevice.cpp
|
||||
RDiskDeviceList.cpp
|
||||
RecentApps.cpp
|
||||
@@ -29,6 +30,7 @@ Server obos_registrar :
|
||||
RosterSettingsCharStream.cpp
|
||||
RPartition.cpp
|
||||
RSession.cpp
|
||||
RVolumeList.cpp
|
||||
TRoster.cpp
|
||||
Watcher.cpp
|
||||
WatchingService.cpp
|
||||
@@ -42,3 +44,10 @@ LinkSharedOSLibs obos_registrar :
|
||||
stdc++.r4
|
||||
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