xref: /haiku/src/add-ons/kernel/file_systems/netfs/server/NodeMonitor.cpp (revision ebb21bd1486152acf792f4b069339d14ef6e1896)
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