#include <new>
#include <errno.h>
#include <sys/resource.h>
#include <AutoLocker.h>
#include <Message.h>
#include <Node.h>
#include <NodeMonitor.h>
#include "DebugSupport.h"
#include "NodeMonitor.h"
#include "NodeMonitoringEvent.h"
static const int32 kDefaultNodeMonitorLimit = 4096;
static const int32 kNodeMonitorLimitIncrement = 512;
NodeMonitor::NodeMonitor(NodeMonitorListener* listener)
: BLooper("node monitor", B_DISPLAY_PRIORITY, 1000),
fListener(listener),
fCurrentNodeMonitorLimit(kDefaultNodeMonitorLimit)
{
struct rlimit rl;
rl.rlim_cur = fCurrentNodeMonitorLimit;
rl.rlim_max = RLIM_SAVED_MAX;
setrlimit(RLIMIT_NOVMON, &rl);
watch_node(NULL, B_WATCH_MOUNT, this);
}
NodeMonitor::~NodeMonitor()
{
stop_watching(this);
}
void
NodeMonitor::MessageReceived(BMessage* message)
{
switch (message->what) {
case B_NODE_MONITOR:
{
NodeMonitoringEvent* event = NULL;
int32 opcode;
if (message->FindInt32("opcode", &opcode) == B_OK) {
switch (opcode) {
case B_ENTRY_CREATED:
event = new(std::nothrow) EntryCreatedEvent;
break;
case B_ENTRY_REMOVED:
event = new(std::nothrow) EntryRemovedEvent;
break;
case B_ENTRY_MOVED:
event = new(std::nothrow) EntryMovedEvent;
break;
case B_STAT_CHANGED:
event = new(std::nothrow) StatChangedEvent;
break;
case B_ATTR_CHANGED:
event = new(std::nothrow) AttributeChangedEvent;
break;
case B_DEVICE_MOUNTED:
event = new(std::nothrow) VolumeMountedEvent;
break;
case B_DEVICE_UNMOUNTED:
event = new(std::nothrow) VolumeUnmountedEvent;
break;
}
}
if (event) {
if (event->Init(message) == B_OK)
fListener->ProcessNodeMonitoringEvent(event);
else
delete event;
}
break;
}
default:
BLooper::MessageReceived(message);
}
}
status_t
NodeMonitor::StartWatching(const node_ref& ref)
{
uint32 flags = B_WATCH_ALL;
status_t error = watch_node(&ref, flags, this);
if (error != B_OK) {
error = _IncreaseLimit();
if (error == B_OK)
error = watch_node(&ref, flags, this);
}
if (error == B_OK) {
PRINT("NodeMonitor: started watching node: "
"(%" B_PRIdDEV ", %" B_PRIdINO ")\n", ref.device, ref.node);
}
return error;
}
status_t
NodeMonitor::StopWatching(const node_ref& ref)
{
PRINT("NodeMonitor: stopped watching node: "
"(%" B_PRIdDEV ", %" B_PRIdINO ")\n", ref.device, ref.node);
return watch_node(&ref, B_STOP_WATCHING, this);
}
status_t
NodeMonitor::_IncreaseLimit()
{
AutoLocker<BLooper> _(this);
int32 newLimit = fCurrentNodeMonitorLimit + kNodeMonitorLimitIncrement;
struct rlimit rl;
rl.rlim_cur = newLimit;
rl.rlim_max = RLIM_SAVED_MAX;
if (setrlimit(RLIMIT_NOVMON, &rl) < 0)
return errno;
fCurrentNodeMonitorLimit = newLimit;
return B_OK;
}
NodeMonitorListener::NodeMonitorListener()
{
}
NodeMonitorListener::~NodeMonitorListener()
{
}