void DirectoryTree::TraverseBreadthFirst(Directory& dir, const DirectoryEntryVisitor& visitor) { if (!dir) { return; } Aws::Queue<DirectoryEntry> queue; while (DirectoryEntry&& entry = dir.Next()) { queue.push(std::move(entry)); } while (queue.size() > 0) { auto entry = queue.front(); queue.pop(); if(visitor(this, entry)) { if(entry.fileType == FileType::Directory) { auto currentDir = dir.Descend(entry); while (DirectoryEntry&& dirEntry = currentDir->Next()) { queue.push(std::move(dirEntry)); } } } else { return; } } }
/** * Process the history directory and maintain the history file map * * Only handle rotated history files, those history.* that are not an * index. For each one that is not in the history file map, create a * new HistoryFile, poll it for entries to process, and add it to the * map. */ void aviary::history::processHistoryDirectory() { const char *file = NULL; // each time through we rebuild our set of inodes if (force_reset) { m_historyFiles.clear(); } Directory dir ( m_path.Value() ); dir.Rewind(); while ( ( file = dir.Next() ) ) { // Skip all non-history files, e.g. history and history.*.idx if ( strncmp ( file, "history.", 8 ) || !strncmp ( file + ( strlen ( file ) - 4 ), HISTORY_INDEX_SUFFIX, 4 ) ) continue; HistoryFile h_file ( ( m_path + DIR_DELIM_STRING + file ).Value() ); CondorError errstack; if ( !h_file.init ( errstack ) ) { dprintf ( D_ALWAYS, "%s\n", errstack.getFullText().c_str() ); return; } errstack.clear(); long unsigned int id; ASSERT ( h_file.getId ( id ) ); HistoryFileListType::iterator entry = m_historyFiles.find ( id ); if ( m_historyFiles.end() == entry ) { HistoryFile::HistoryEntriesTypeIterators ij = h_file.poll ( errstack ); for ( HistoryFile::HistoryEntriesTypeIterator i = ij.first; i != ij.second; i++ ) { process ( ( *i ) ); } m_historyFiles.insert ( id ); } } }
/** * Process orphaned index files, those that exist but do not have a * corresponding history file. * * Process all .idx files looking for the corresponding HistoryFile in * the history file map. */ void aviary::history::processOrphanedIndices() { const char *file = NULL; Directory dir ( m_path.Value() ); dir.Rewind(); while ( ( file = dir.Next() ) ) { // Skip all non-history index files, e.g. history and history.* if ( strncmp ( file, "history.", 8 ) || strncmp ( file + ( strlen ( file ) - 4 ), HISTORY_INDEX_SUFFIX, 4 ) ) continue; // XXX: This is ugly because it indicates we know details // of how HistoryFile implements index files. // The index file is "history.%ld.idx" where %ld is the id // of the history file the index is for. long unsigned int id; int count = sscanf ( file, "history.%ld.idx", &id ); if ( 1 != count ) { dprintf ( D_ALWAYS, "Error parsing %s, skipping.\n", file ); continue; } HistoryFileListType::iterator entry = m_historyFiles.find ( id ); if ( m_historyFiles.end() == entry ) { // The index is dangling, remove it. if ( !dir.Remove_Current_File() ) { dprintf ( D_ALWAYS, "Failed to remove: %s\n", file ); } } } }
bool DirectoryTree::TraverseDepthFirst(Directory& dir, const DirectoryEntryVisitor& visitor, bool postOrder) { if (!dir) { return true; } bool exitTraversal(false); DirectoryEntry entry; while ((entry = dir.Next()) && !exitTraversal) { if(!postOrder) { if(!visitor(this, entry)) { return false; } } if (entry.fileType == FileType::Directory) { auto subDir = dir.Descend(entry); exitTraversal = !TraverseDepthFirst(*subDir, visitor, postOrder); } if (postOrder) { if (!visitor(this, entry)) { return false; } } } return !exitTraversal; }