1// NodeMonitor.cpp 2 3#include <new> 4 5#include <errno.h> 6#include <sys/resource.h> 7 8#include <AutoLocker.h> 9#include <Message.h> 10#include <Node.h> 11#include <NodeMonitor.h> 12 13#include "DebugSupport.h" 14#include "NodeMonitor.h" 15#include "NodeMonitoringEvent.h" 16 17// node monitor constants 18static const int32 kDefaultNodeMonitorLimit = 4096; 19static const int32 kNodeMonitorLimitIncrement = 512; 20 21// constructor 22NodeMonitor::NodeMonitor(NodeMonitorListener* listener) 23 : BLooper("node monitor", B_DISPLAY_PRIORITY, 1000), 24 fListener(listener), 25 fCurrentNodeMonitorLimit(kDefaultNodeMonitorLimit) 26{ 27 // set the initial limit -- just to be sure 28 struct rlimit rl; 29 rl.rlim_cur = fCurrentNodeMonitorLimit; 30 rl.rlim_max = RLIM_SAVED_MAX; 31 setrlimit(RLIMIT_NOVMON, &rl); 32 33 // start volume watching 34 watch_node(NULL, B_WATCH_MOUNT, this); 35} 36 37// destructor 38NodeMonitor::~NodeMonitor() 39{ 40 // stop volume watching 41 stop_watching(this); 42} 43 44// MessageReceived 45void 46NodeMonitor::MessageReceived(BMessage* message) 47{ 48 switch (message->what) { 49 case B_NODE_MONITOR: 50 { 51 NodeMonitoringEvent* event = NULL; 52 int32 opcode; 53 if (message->FindInt32("opcode", &opcode) == B_OK) { 54 switch (opcode) { 55 case B_ENTRY_CREATED: 56 event = new(std::nothrow) EntryCreatedEvent; 57 break; 58 case B_ENTRY_REMOVED: 59 event = new(std::nothrow) EntryRemovedEvent; 60 break; 61 case B_ENTRY_MOVED: 62 event = new(std::nothrow) EntryMovedEvent; 63 break; 64 case B_STAT_CHANGED: 65 event = new(std::nothrow) StatChangedEvent; 66 break; 67 case B_ATTR_CHANGED: 68 event = new(std::nothrow) AttributeChangedEvent; 69 break; 70 case B_DEVICE_MOUNTED: 71 event = new(std::nothrow) VolumeMountedEvent; 72 break; 73 case B_DEVICE_UNMOUNTED: 74 event = new(std::nothrow) VolumeUnmountedEvent; 75 break; 76 } 77 } 78 if (event) { 79 if (event->Init(message) == B_OK) 80 fListener->ProcessNodeMonitoringEvent(event); 81 else 82 delete event; 83 } 84 break; 85 } 86 default: 87 BLooper::MessageReceived(message); 88 } 89} 90 91// StartWatching 92status_t 93NodeMonitor::StartWatching(const node_ref& ref) 94{ 95 uint32 flags = B_WATCH_ALL; 96 status_t error = watch_node(&ref, flags, this); 97 // If starting to watch the node fail, we allocate more node 98 // monitoring slots and try again. 99 if (error != B_OK) { 100 error = _IncreaseLimit(); 101 if (error == B_OK) 102 error = watch_node(&ref, flags, this); 103 } 104 if (error == B_OK) { 105 PRINT("NodeMonitor: started watching node: " 106 "(%" B_PRIdDEV ", %" B_PRIdINO ")\n", ref.device, ref.node); 107 } 108 return error; 109} 110 111// StopWatching 112status_t 113NodeMonitor::StopWatching(const node_ref& ref) 114{ 115 PRINT("NodeMonitor: stopped watching node: " 116 "(%" B_PRIdDEV ", %" B_PRIdINO ")\n", ref.device, ref.node); 117 return watch_node(&ref, B_STOP_WATCHING, this); 118} 119 120// _IncreaseLimit 121status_t 122NodeMonitor::_IncreaseLimit() 123{ 124 AutoLocker<BLooper> _(this); 125 126 int32 newLimit = fCurrentNodeMonitorLimit + kNodeMonitorLimitIncrement; 127 struct rlimit rl; 128 rl.rlim_cur = newLimit; 129 rl.rlim_max = RLIM_SAVED_MAX; 130 if (setrlimit(RLIMIT_NOVMON, &rl) < 0) 131 return errno; 132 133 fCurrentNodeMonitorLimit = newLimit; 134 135 return B_OK; 136} 137 138 139// #pragma mark - 140 141// constructor 142NodeMonitorListener::NodeMonitorListener() 143{ 144} 145 146// destructor 147NodeMonitorListener::~NodeMonitorListener() 148{ 149} 150