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 19static const int32 kDefaultFDLimit = 512; 20static const int32 kFDLimitIncrement = 128; 21 22 23// constructor 24FDManager::FDManager() 25 : fLock("FD manager"), 26 fFDLimit(kDefaultFDLimit) 27{ 28} 29 30// destructor 31FDManager::~FDManager() 32{ 33} 34 35// Init 36status_t 37FDManager::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 50status_t 51FDManager::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 71void 72FDManager::DeleteDefault() 73{ 74 if (sManager) { 75 delete sManager; 76 sManager = NULL; 77 } 78} 79 80// GetDefault 81FDManager* 82FDManager::GetDefault() 83{ 84 return sManager; 85} 86 87// SetDirectory 88status_t 89FDManager::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 102status_t 103FDManager::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 116status_t 117FDManager::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 130status_t 131FDManager::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 144status_t 145FDManager::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 158status_t 159FDManager::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 179status_t 180FDManager::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 200status_t 201FDManager::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 221status_t 222FDManager::_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 241FDManager* FDManager::sManager = NULL; 242