AWS EFS上的readdir不会返回目录

时间:2017-06-01 21:24:37

标签: c++ linux amazon-web-services readdir aws-elasticfilesystem

将大量文件写入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时,我仍然遇到同样的问题。

0 个答案:

没有答案