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 24 FDManager::FDManager() 25 : fLock("FD manager"), 26 fFDLimit(kDefaultFDLimit) 27 { 28 } 29 30 // destructor 31 FDManager::~FDManager() 32 { 33 } 34 35 // Init 36 status_t 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 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 72 FDManager::DeleteDefault() 73 { 74 if (sManager) { 75 delete sManager; 76 sManager = NULL; 77 } 78 } 79 80 // GetDefault 81 FDManager* 82 FDManager::GetDefault() 83 { 84 return sManager; 85 } 86 87 // SetDirectory 88 status_t 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 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 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 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 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 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 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 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 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