将大量文件写入EFS(10k左右)的一系列文件夹后。 Readdir停止返回每个目录中的所有文件。
我有一个C ++应用程序,它在其进程的一部分中生成大量文件,每个文件都有一个符号链接。之后,我需要获取文件夹中的文件列表,然后选择要重命名的子集。当我运行获取文件列表的函数时,它不会返回实际存在的所有文件。此代码在我的本地计算机上运行正常,但在安装了EFS驱动器的AWS服务器上,它会在一段时间后停止工作。
为了解决这个问题,我让我的代码一次只写一个文件。我还设置了我的代码,使用getFiles()来计算每批文件(大约17个文件)后文件夹中有多少文件。当文件数达到~950个文件时,getFiles()开始列出~910个文件,不再增加。当它的文件写入时,文件变化但相当小(2字节 - 300K),并且每秒写入大约200个文件。每个文件还有一个创建的符号链接。
在读取和写入文件时,我使用的是posix open(),write(),read()和close()。我已经确认我确实在阅读或写作后关闭了所有文件。
我想弄明白: 1.为什么readdir不工作?或者为什么不列出所有文件? 2. EFS可能导致问题的不同之处是什么?
这些是我用来获取文件夹中文件列表的函数:
DIR * FileUtil::getDirStream(std::string path) {
bool success = false;
if (!folderExists(path)){
return NULL;
}
DIR * dir = opendir(path.c_str());
success = dir != NULL;
int count = 0;
while(!success){
int fileRetryDelay = BlazingConfig::getInstance()->getFileRetryDelay();
const int sleep_milliseconds = (count+1)*fileRetryDelay;
std::this_thread::sleep_for(std::chrono::milliseconds(sleep_milliseconds));
std::cout<<"Was unable to get Dir stream for "<<path<<std::endl;
dir = opendir(path.c_str());
success = dir != NULL;
count++;
if(count > 6){
break;
}
}
if(success == -1){
std::cout<<"Can't get Dir stream for "<<path<<". Error was: "<<errno<<std::endl;
}
return dir;
}
int FileUtil::getDirEntry(DIR * dirp, struct dirent * & prevDirEntry, struct dirent * & dirEntry){
bool success = false;
if (dirp == NULL){
return -1;
}
int returnCode = readdir_r(dirp, prevDirEntry, &dirEntry);
success = (dirEntry == NULL && returnCode == 0) || dirEntry != NULL;
int count = 0;
while(!success){
int fileRetryDelay = BlazingConfig::getInstance()->getFileRetryDelay();
const int sleep_milliseconds = (count+1)*fileRetryDelay;
std::this_thread::sleep_for(std::chrono::milliseconds(sleep_milliseconds));
std::cout<<"Was unable to get dirent with readdir"<<std::endl;
returnCode = readdir_r(dirp, prevDirEntry, &dirEntry);
success = (dirEntry == NULL && returnCode == 0) || dirEntry != NULL;
count++;
if(count > 6){
break;
}
}
if(success == -1){
std::cout<<"Can't get dirent with readdir. Error was: "<<errno<<std::endl;
}
return returnCode;
}
std::vector<std::string> FileUtil::getFiles(std::string baseFolder){
DIR *dir = getDirStream(baseFolder);
std::vector <std::string> subFolders;
if (dir != NULL) {
struct dirent *prevDirEntry = NULL;
struct dirent *dirEntry = NULL;
int len_entry = offsetof(struct dirent, d_name) + fpathconf(dirfd(dir), _PC_NAME_MAX) + 1;
prevDirEntry = (struct dirent *)malloc(len_entry);
int returnCode = getDirEntry(dir, prevDirEntry, dirEntry);
while (dirEntry != NULL) {
if( dirEntry->d_type == DT_REG || dirEntry->d_type == DT_LNK){
std::string name(dirEntry->d_name);
subFolders.push_back(name);
}
returnCode = getDirEntry(dir, prevDirEntry, dirEntry);
}
free(prevDirEntry);
closedir (dir);
} else {
std::cout<<"Could not open directory err num is"<<errno<<std::endl;
/* could not open directory */
perror ("");
}
return subFolders;
}
这些函数以这种方式编写,以尽可能地保持健壮,因为可以有许多线程执行文件操作,我希望能够在出现任何故障时重试代码。不幸的是,当getFiles()返回错误的结果时,它不会给我任何失败的迹象。
注意:当我使用readdir而不是readdir_r时,我仍然遇到同样的问题。