readdir в AWS EFS не возвращает все файлы в каталоге

После записи большого количества файлов в ряд папок на EFS (10k или около того). Readdir прекращает возвращать все файлы в каждом каталоге.

У меня есть приложение C++, которое в одной части своего процесса генерирует много файлов, и каждому файлу дается символическая ссылка. После этого мне нужно получить список файлов в папке, а затем выбрать подмножество для переименования. Когда я запускаю функцию, которая получает список файлов, она не возвращает все файлы, которые на самом деле там. Этот код отлично работает на моей локальной машине, но на сервере AWS с подключенным диском EFS через некоторое время он перестает работать.

Чтобы устранить эту проблему, я сделал так, чтобы мой код записывал только один файл за раз. Я также настроил свой код для использования getFiles(), чтобы подсчитывать, сколько файлов в папке после записи каждого пакета файлов (около 17 файлов). Когда количество файлов достигает ~950 файлов, getFiles() начинает перечислять ~910 файлов и больше не увеличивается. Когда он записывает файлы, файлы различаются, но довольно малы (2 байта - 300 КБ) и записывают около 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 ответов

Другие вопросы по тегам