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 18 static const int32 kDefaultNodeMonitorLimit = 4096; 19 static const int32 kNodeMonitorLimitIncrement = 512; 20 21 // constructor 22 NodeMonitor::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 38 NodeMonitor::~NodeMonitor() 39 { 40 // stop volume watching 41 stop_watching(this); 42 } 43 44 // MessageReceived 45 void 46 NodeMonitor::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 92 status_t 93 NodeMonitor::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 112 status_t 113 NodeMonitor::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 121 status_t 122 NodeMonitor::_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 142 NodeMonitorListener::NodeMonitorListener() 143 { 144 } 145 146 // destructor 147 NodeMonitorListener::~NodeMonitorListener() 148 { 149 } 150