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:
Ingo Weinhold
2003-02-04 23:54:03 +00:00
parent e42e3be9c8
commit 8cd6a1c0f8
3 changed files with 380 additions and 0 deletions
+9
View File
@@ -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 ;
+145
View File
@@ -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;
}
+226
View File
@@ -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;
}