1 // FDManager.cpp
2
3 #include <new>
4
5 #include <dirent.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <sys/resource.h>
9
10 #include <Directory.h>
11 #include <Entry.h>
12 #include <File.h>
13 #include <fs_attr.h>
14
15 #include "AutoLocker.h"
16 #include "FDManager.h"
17
18 // FD constants
19 static const int32 kDefaultFDLimit = 512;
20 static const int32 kFDLimitIncrement = 128;
21
22
23 // constructor
FDManager()24 FDManager::FDManager()
25 : fLock("FD manager"),
26 fFDLimit(kDefaultFDLimit)
27 {
28 }
29
30 // destructor
~FDManager()31 FDManager::~FDManager()
32 {
33 }
34
35 // Init
36 status_t
Init()37 FDManager::Init()
38 {
39 // ask for a bunch more file descriptors
40 struct rlimit rl;
41 rl.rlim_cur = fFDLimit;
42 rl.rlim_max = RLIM_SAVED_MAX;
43 if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
44 return errno;
45
46 return B_OK;
47 }
48
49 // CreateDefault
50 status_t
CreateDefault()51 FDManager::CreateDefault()
52 {
53 if (sManager)
54 return B_OK;
55
56 FDManager* manager = new(std::nothrow) FDManager;
57 if (!manager)
58 return B_NO_MEMORY;
59
60 status_t error = manager->Init();
61 if (error != B_OK) {
62 delete manager;
63 return error;
64 }
65
66 sManager = manager;
67 return B_OK;
68 }
69
70 // DeleteDefault
71 void
DeleteDefault()72 FDManager::DeleteDefault()
73 {
74 if (sManager) {
75 delete sManager;
76 sManager = NULL;
77 }
78 }
79
80 // GetDefault
81 FDManager*
GetDefault()82 FDManager::GetDefault()
83 {
84 return sManager;
85 }
86
87 // SetDirectory
88 status_t
SetDirectory(BDirectory * directory,const node_ref * ref)89 FDManager::SetDirectory(BDirectory* directory, const node_ref* ref)
90 {
91 status_t error = directory->SetTo(ref);
92
93 if (error == B_NO_MORE_FDS) {
94 GetDefault()->_IncreaseLimit();
95 error = directory->SetTo(ref);
96 }
97
98 return error;
99 }
100
101 // SetEntry
102 status_t
SetEntry(BEntry * entry,const entry_ref * ref)103 FDManager::SetEntry(BEntry* entry, const entry_ref* ref)
104 {
105 status_t error = entry->SetTo(ref);
106
107 if (error == B_NO_MORE_FDS) {
108 GetDefault()->_IncreaseLimit();
109 error = entry->SetTo(ref);
110 }
111
112 return error;
113 }
114
115 // SetEntry
116 status_t
SetEntry(BEntry * entry,const char * path)117 FDManager::SetEntry(BEntry* entry, const char* path)
118 {
119 status_t error = entry->SetTo(path);
120
121 if (error == B_NO_MORE_FDS) {
122 GetDefault()->_IncreaseLimit();
123 error = entry->SetTo(path);
124 }
125
126 return error;
127 }
128
129 // SetFile
130 status_t
SetFile(BFile * file,const char * path,uint32 openMode)131 FDManager::SetFile(BFile* file, const char* path, uint32 openMode)
132 {
133 status_t error = file->SetTo(path, openMode);
134
135 if (error == B_NO_MORE_FDS) {
136 GetDefault()->_IncreaseLimit();
137 error = file->SetTo(path, openMode);
138 }
139
140 return error;
141 }
142
143 // SetNode
144 status_t
SetNode(BNode * node,const entry_ref * ref)145 FDManager::SetNode(BNode* node, const entry_ref* ref)
146 {
147 status_t error = node->SetTo(ref);
148
149 if (error == B_NO_MORE_FDS) {
150 GetDefault()->_IncreaseLimit();
151 error = node->SetTo(ref);
152 }
153
154 return error;
155 }
156
157 // Open
158 status_t
Open(const char * path,uint32 openMode,mode_t mode,int & fd)159 FDManager::Open(const char* path, uint32 openMode, mode_t mode, int& fd)
160 {
161 status_t error = B_OK;
162 fd = open(path, openMode, mode);
163 if (fd < 0)
164 error = errno;
165
166 if (error == B_NO_MORE_FDS) {
167 GetDefault()->_IncreaseLimit();
168
169 error = B_OK;
170 fd = open(path, openMode, mode);
171 if (fd < 0)
172 error = errno;
173 }
174
175 return error;
176 }
177
178 // OpenDir
179 status_t
OpenDir(const char * path,DIR * & dir)180 FDManager::OpenDir(const char* path, DIR*& dir)
181 {
182 status_t error = B_OK;
183 dir = opendir(path);
184 if (!dir)
185 error = errno;
186
187 if (error == B_NO_MORE_FDS) {
188 GetDefault()->_IncreaseLimit();
189
190 error = B_OK;
191 dir = opendir(path);
192 if (!dir)
193 error = errno;
194 }
195
196 return error;
197 }
198
199 // OpenAttrDir
200 status_t
OpenAttrDir(const char * path,DIR * & dir)201 FDManager::OpenAttrDir(const char* path, DIR*& dir)
202 {
203 status_t error = B_OK;
204 dir = fs_open_attr_dir(path);
205 if (!dir)
206 error = errno;
207
208 if (error == B_NO_MORE_FDS) {
209 GetDefault()->_IncreaseLimit();
210
211 error = B_OK;
212 dir = fs_open_attr_dir(path);
213 if (!dir)
214 error = errno;
215 }
216
217 return error;
218 }
219
220 // _IncreaseLimit
221 status_t
_IncreaseLimit()222 FDManager::_IncreaseLimit()
223 {
224 AutoLocker<Locker> _(fLock);
225
226 int32 newLimit = fFDLimit + kFDLimitIncrement;
227
228 struct rlimit rl;
229 rl.rlim_cur = newLimit;
230 rl.rlim_max = RLIM_SAVED_MAX;
231 if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
232 return errno;
233
234 fFDLimit = newLimit;
235
236 return B_OK;
237 }
238
239
240 // sManager
241 FDManager* FDManager::sManager = NULL;
242