// FDManager.cpp #include #include #include #include #include #include #include #include #include #include "AutoLocker.h" #include "FDManager.h" // FD constants static const int32 kDefaultFDLimit = 512; static const int32 kFDLimitIncrement = 128; // constructor FDManager::FDManager() : fLock("FD manager"), fFDLimit(kDefaultFDLimit) { } // destructor FDManager::~FDManager() { } // Init status_t FDManager::Init() { // ask for a bunch more file descriptors struct rlimit rl; rl.rlim_cur = fFDLimit; rl.rlim_max = RLIM_SAVED_MAX; if (setrlimit(RLIMIT_NOFILE, &rl) < 0) return errno; return B_OK; } // CreateDefault status_t FDManager::CreateDefault() { if (sManager) return B_OK; FDManager* manager = new(std::nothrow) FDManager; if (!manager) return B_NO_MEMORY; status_t error = manager->Init(); if (error != B_OK) { delete manager; return error; } sManager = manager; return B_OK; } // DeleteDefault void FDManager::DeleteDefault() { if (sManager) { delete sManager; sManager = NULL; } } // GetDefault FDManager* FDManager::GetDefault() { return sManager; } // SetDirectory status_t FDManager::SetDirectory(BDirectory* directory, const node_ref* ref) { status_t error = directory->SetTo(ref); if (error == B_NO_MORE_FDS) { GetDefault()->_IncreaseLimit(); error = directory->SetTo(ref); } return error; } // SetEntry status_t FDManager::SetEntry(BEntry* entry, const entry_ref* ref) { status_t error = entry->SetTo(ref); if (error == B_NO_MORE_FDS) { GetDefault()->_IncreaseLimit(); error = entry->SetTo(ref); } return error; } // SetEntry status_t FDManager::SetEntry(BEntry* entry, const char* path) { status_t error = entry->SetTo(path); if (error == B_NO_MORE_FDS) { GetDefault()->_IncreaseLimit(); error = entry->SetTo(path); } return error; } // SetFile status_t FDManager::SetFile(BFile* file, const char* path, uint32 openMode) { status_t error = file->SetTo(path, openMode); if (error == B_NO_MORE_FDS) { GetDefault()->_IncreaseLimit(); error = file->SetTo(path, openMode); } return error; } // SetNode status_t FDManager::SetNode(BNode* node, const entry_ref* ref) { status_t error = node->SetTo(ref); if (error == B_NO_MORE_FDS) { GetDefault()->_IncreaseLimit(); error = node->SetTo(ref); } return error; } // Open status_t FDManager::Open(const char* path, uint32 openMode, mode_t mode, int& fd) { status_t error = B_OK; fd = open(path, openMode, mode); if (fd < 0) error = errno; if (error == B_NO_MORE_FDS) { GetDefault()->_IncreaseLimit(); error = B_OK; fd = open(path, openMode, mode); if (fd < 0) error = errno; } return error; } // OpenDir status_t FDManager::OpenDir(const char* path, DIR*& dir) { status_t error = B_OK; dir = opendir(path); if (!dir) error = errno; if (error == B_NO_MORE_FDS) { GetDefault()->_IncreaseLimit(); error = B_OK; dir = opendir(path); if (!dir) error = errno; } return error; } // OpenAttrDir status_t FDManager::OpenAttrDir(const char* path, DIR*& dir) { status_t error = B_OK; dir = fs_open_attr_dir(path); if (!dir) error = errno; if (error == B_NO_MORE_FDS) { GetDefault()->_IncreaseLimit(); error = B_OK; dir = fs_open_attr_dir(path); if (!dir) error = errno; } return error; } // _IncreaseLimit status_t FDManager::_IncreaseLimit() { AutoLocker _(fLock); int32 newLimit = fFDLimit + kFDLimitIncrement; struct rlimit rl; rl.rlim_cur = newLimit; rl.rlim_max = RLIM_SAVED_MAX; if (setrlimit(RLIMIT_NOFILE, &rl) < 0) return errno; fFDLimit = newLimit; return B_OK; } // sManager FDManager* FDManager::sManager = NULL;