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
NodeMonitor(NodeMonitorListener * listener)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
~NodeMonitor()38 NodeMonitor::~NodeMonitor()
39 {
40 // stop volume watching
41 stop_watching(this);
42 }
43
44 // MessageReceived
45 void
MessageReceived(BMessage * message)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
StartWatching(const node_ref & ref)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
StopWatching(const node_ref & ref)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
_IncreaseLimit()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
NodeMonitorListener()142 NodeMonitorListener::NodeMonitorListener()
143 {
144 }
145
146 // destructor
~NodeMonitorListener()147 NodeMonitorListener::~NodeMonitorListener()
148 {
149 }
150