aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2022-06-24 14:10:09 +0200
committerGitHub <noreply@github.com>2022-06-24 14:10:09 +0200
commitaa244b000fe8ef9db2e8c8fea7921b7cd1a71d84 (patch)
treebd818f0eb396a2038b8d7b4c9a16327bed68bf59
parent9b15271f6d4cb16772ddebeef8a690bb34737623 (diff)
parent54741a65578269abf9cd515f4246320162e8713e (diff)
Merge pull request #23233 from vespa-engine/toregge/remove-unused-directory-traverse-create-and-remove-code
Remove unused code for creating / removing directories and
-rw-r--r--fastos/src/tests/filetest.cpp195
-rw-r--r--fastos/src/vespa/fastos/file.cpp78
-rw-r--r--fastos/src/vespa/fastos/file.h47
-rw-r--r--fastos/src/vespa/fastos/unix_file.cpp18
-rw-r--r--fastos/src/vespa/fastos/unix_file.h2
-rw-r--r--searchlib/src/vespa/searchlib/util/dirtraverse.cpp282
-rw-r--r--searchlib/src/vespa/searchlib/util/dirtraverse.h48
7 files changed, 52 insertions, 618 deletions
diff --git a/fastos/src/tests/filetest.cpp b/fastos/src/tests/filetest.cpp
index a3470810e2e..88e81c2bbaf 100644
--- a/fastos/src/tests/filetest.cpp
+++ b/fastos/src/tests/filetest.cpp
@@ -5,6 +5,7 @@
#include <memory>
#include <cassert>
#include <sys/mman.h>
+#include <filesystem>
namespace {
@@ -46,176 +47,6 @@ public:
const std::string woFilename = "generated/writeonlytest.txt";
const std::string rwFilename = "generated/readwritetest.txt";
- void DirectoryTest()
- {
- TestHeader ("Directory management (remove & empty) test");
-
- const char *dirName = "tmpTestDir";
- char file1[1024];
- char file2[1024];
- char file3[1024];
- char file4[1024];
- char file5[1024];
- char subdir1[512];
- char subdir2[512];
- sprintf(file1, "%s%sfile1", dirName, FastOS_File::GetPathSeparator());
- sprintf(file2, "%s%sfile2", dirName, FastOS_File::GetPathSeparator());
- sprintf(file3, "%s%sfile2", dirName, FastOS_File::GetPathSeparator());
- sprintf(subdir1, "%s%sdir1", dirName, FastOS_File::GetPathSeparator());
- sprintf(subdir2, "%s%sdir2", dirName, FastOS_File::GetPathSeparator());
- sprintf(file4, "%s%sfile4", subdir2, FastOS_File::GetPathSeparator());
- sprintf(file5, "%s%sfile5", subdir2, FastOS_File::GetPathSeparator());
-
- FastOS_StatInfo statInfo;
-
- bool success = false;
-
- // Don't run at all if the directory already exists
- assert(!FastOS_File::Stat(dirName, &statInfo));
-
- FastOS_File::MakeDirectory(dirName);
-
- // Verify that we succeed with an empty directory
- FastOS_File::EmptyDirectory(dirName);
- success = FastOS_File::Stat(dirName, &statInfo);
- Progress(success, "Removing empty directory.");
-
- // Verify that we can empty a directory with files in it
- createFile(file1);
- createFile(file2);
- createFile(file3);
- FastOS_File::EmptyDirectory(dirName);
- success =
- !FastOS_File::Stat(file1, &statInfo) &&
- !FastOS_File::Stat(file2, &statInfo) &&
- !FastOS_File::Stat(file3, &statInfo) &&
- FastOS_File::Stat(dirName, &statInfo);
- Progress(success, "Deleting dir with files in it.");
-
- // Verify that we can empty a directory with files and directories in it
- createFile(file1);
- createFile(file2);
- createFile(file3);
- FastOS_File::MakeDirectory(subdir1);
- FastOS_File::MakeDirectory(subdir2);
- createFile(file4);
- createFile(file5);
- FastOS_File::EmptyDirectory(dirName);
- success = FastOS_File::Stat(dirName, &statInfo) &&
- !FastOS_File::Stat(file1, &statInfo) &&
- !FastOS_File::Stat(file2, &statInfo) &&
- !FastOS_File::Stat(file3, &statInfo) &&
- !FastOS_File::Stat(file4, &statInfo) &&
- !FastOS_File::Stat(file5, &statInfo) &&
- !FastOS_File::Stat(subdir1, &statInfo) &&
- !FastOS_File::Stat(subdir2, &statInfo);
- Progress(success, "Emptying directory with files and folders in it.");
-
- // Verify that we don't empty the directory if we find a file to keep
- createFile(file1);
- createFile(file2);
- createFile(file3);
- FastOS_File::MakeDirectory(subdir1);
- FastOS_File::MakeDirectory(subdir2);
- createFile(file4);
- createFile(file5);
- FastOS_File::EmptyDirectory(dirName, "file1");
- success = FastOS_File::Stat(dirName, &statInfo);
- Progress(success, "Emptying dir with keepfile in it.");
- // Verify that all but the file to keep are removed
- success = FastOS_File::Stat(file1, &statInfo) &&
- !FastOS_File::Stat(file2, &statInfo) &&
- !FastOS_File::Stat(file3, &statInfo) &&
- !FastOS_File::Stat(file4, &statInfo) &&
- !FastOS_File::Stat(file5, &statInfo) &&
- !FastOS_File::Stat(subdir1, &statInfo) &&
- !FastOS_File::Stat(subdir2, &statInfo);
- Progress(success, "Looking for keepfile.");
-
- // Verify that we don't empty the sub-directory if we find a file to keep
- createFile(file1);
- createFile(file2);
- createFile(file3);
- FastOS_File::MakeDirectory(subdir1);
- FastOS_File::MakeDirectory(subdir2);
- createFile(file4);
- createFile(file5);
- FastOS_File::EmptyDirectory(dirName, "file4");
- success = FastOS_File::Stat(dirName, &statInfo);
- Progress(success, "Emptying file with nested keepfile.");
- // Verify that all but the file to keep are removed
- success = !FastOS_File::Stat(file1, &statInfo) &&
- !FastOS_File::Stat(file2, &statInfo) &&
- !FastOS_File::Stat(file3, &statInfo) &&
- FastOS_File::Stat(file4, &statInfo) &&
- !FastOS_File::Stat(file5, &statInfo) &&
- !FastOS_File::Stat(subdir1, &statInfo) &&
- FastOS_File::Stat(subdir2, &statInfo);
- // Progress(success, "Looking for nested keepfile."); // Unsupported for now.
-
-
- FastOS_File::EmptyAndRemoveDirectory(dirName);
-
- FastOS_File::MakeDirectory(dirName);
-
- // Verify that we can remove an empty directory
- FastOS_File::EmptyAndRemoveDirectory(dirName);
- success = !FastOS_File::Stat(dirName, &statInfo);
- Progress(success, "Deleting empty directory.");
-
- // Verify that we can remove a directory with files in it
- FastOS_File::MakeDirectory(dirName);
- createFile(file1);
- createFile(file2);
- createFile(file3);
- FastOS_File::EmptyAndRemoveDirectory(dirName);
- success = !FastOS_File::Stat(dirName, &statInfo);
- Progress(success, "Deleting a directory with files in it.");
-
- // Verify that we can remove a directory with files and directories in it
- FastOS_File::MakeDirectory(dirName);
- createFile(file1);
- createFile(file2);
- createFile(file3);
- FastOS_File::MakeDirectory(subdir1);
- FastOS_File::MakeDirectory(subdir2);
- createFile(file4);
- createFile(file5);
- FastOS_File::EmptyAndRemoveDirectory(dirName);
- success = !FastOS_File::Stat(dirName, &statInfo);
- Progress(success, "Deleting directory with files and directories in it.");
-
- }
-
- void MoveFileTest() {
- TestHeader ("Moving files (across volumes too) test");
-
- const char *dirName = "tmpTestDir";
- char file1[1024];
- char file2[1024];
- char file3[1024];
- sprintf(file1, "%s%sfile1", dirName, FastOS_File::GetPathSeparator());
- sprintf(file2, "%s%sfile2", dirName, FastOS_File::GetPathSeparator());
- sprintf(file3, "%stmp%sfile3", FastOS_File::GetPathSeparator(),
- FastOS_File::GetPathSeparator());
-
- FastOS_File::MakeDirectory(dirName);
- createFile(file1);
-
- FastOS_StatInfo statInfo;
- // Move file to new name in same dir.
- FastOS_File::MoveFile(file1, file2);
- Progress(FastOS_File::Stat(file2, &statInfo), "Moving one within a directory.");
-
- // Move file to /tmp.
- FastOS_File::MoveFile(file2, file3);
- Progress(FastOS_File::Stat(file3, &statInfo), "Moving to /tmp/");
-
- // Clean up
- FastOS_File::Delete(file3);
- FastOS_File::EmptyAndRemoveDirectory(dirName);
- }
-
void GetCurrentDirTest ()
{
TestHeader ("Get Current Directory Test");
@@ -252,7 +83,7 @@ public:
int i;
const int bufSize = 1000;
- FastOS_File::MakeDirectory("generated");
+ std::filesystem::create_directory(std::filesystem::path("generated"));
FastOS_File file("generated/memorymaptest");
bool rc = file.OpenReadWrite();
@@ -294,7 +125,7 @@ public:
}
delete [] buffer;
}
- FastOS_File::EmptyAndRemoveDirectory("generated");
+ std::filesystem::remove_all(std::filesystem::path("generated"));
PrintSeparator();
}
@@ -305,7 +136,7 @@ public:
int i;
const int bufSize = 40000;
- FastOS_File::MakeDirectory("generated");
+ std::filesystem::create_directory(std::filesystem::path("generated"));
FastOS_File file("generated/diotest");
bool rc = file.OpenWriteOnly();
@@ -429,7 +260,7 @@ public:
delete [] buffer;
}
- FastOS_File::EmptyAndRemoveDirectory("generated");
+ std::filesystem::remove_all(std::filesystem::path("generated"));
PrintSeparator();
}
@@ -483,7 +314,7 @@ public:
void WriteOnlyTest ()
{
TestHeader("Write-Only Test");
- FastOS_File::MakeDirectory("generated");
+ std::filesystem::create_directory(std::filesystem::path("generated"));
FastOS_File *myFile = new FastOS_File(woFilename.c_str());
@@ -541,14 +372,14 @@ public:
Progress(deleteResult, "Delete file '%s'.", woFilename.c_str());
delete(myFile);
- FastOS_File::EmptyAndRemoveDirectory("generated");
+ std::filesystem::remove_all(std::filesystem::path("generated"));
PrintSeparator();
}
void ReadWriteTest ()
{
TestHeader("Read/Write Test");
- FastOS_File::MakeDirectory("generated");
+ std::filesystem::create_directory(std::filesystem::path("generated"));
FastOS_File *myFile = new FastOS_File(rwFilename.c_str());
@@ -637,7 +468,7 @@ public:
Progress(deleteResult, "Delete file '%s'.", rwFilename.c_str());
delete(myFile);
- FastOS_File::EmptyAndRemoveDirectory("generated");
+ std::filesystem::remove_all(std::filesystem::path("generated"));
PrintSeparator();
}
@@ -731,8 +562,8 @@ public:
sprintf(file4, "%s%sfile4", dirName, FastOS_File::GetPathSeparator());
sprintf(file5, "%s%sfile5", dirName, FastOS_File::GetPathSeparator());
- FastOS_File::EmptyAndRemoveDirectory(dirName);
- FastOS_File::MakeDirectory(dirName);
+ std::filesystem::remove_all(std::filesystem::path(dirName));
+ std::filesystem::create_directory(std::filesystem::path(dirName));
printf("Creating files to copy. Some of them are quite large...\n\n");
createFile(file1);
createFile(file3, 20*1024*1024); // 20MB file.
@@ -789,7 +620,7 @@ public:
"Size of copied file should be %u bytes.", sizeOfFile5);
- FastOS_File::EmptyAndRemoveDirectory("./tmpDir");
+ std::filesystem::remove_all(std::filesystem::path("tmpDir"));
PrintSeparator();
}
@@ -798,8 +629,6 @@ public:
printf("This test should be run in the 'tests' directory.\n\n");
printf("grep for the string '%s' to detect failures.\n\n", failString);
- DirectoryTest();
- MoveFileTest();
CopyFileTest();
GetCurrentDirTest();
DirectIOTest();
diff --git a/fastos/src/vespa/fastos/file.cpp b/fastos/src/vespa/fastos/file.cpp
index ca109d831a8..2857f45e3de 100644
--- a/fastos/src/vespa/fastos/file.cpp
+++ b/fastos/src/vespa/fastos/file.cpp
@@ -260,84 +260,6 @@ FastOS_FileInterface::CopyFile( const char *src, const char *dst )
}
-bool
-FastOS_FileInterface::MoveFile(const char* src, const char* dst)
-{
- bool rc = FastOS_File::Rename(src, dst);
- if (!rc) {
- // Try copy and remove.
- if (CopyFile(src, dst)) {
- rc = FastOS_File::Delete(src);
- }
- }
- return rc;
-}
-
-
-void
-FastOS_FileInterface::EmptyDirectory( const char *dir,
- const char *keepFile /* = nullptr */ )
-{
- FastOS_StatInfo statInfo;
- if (!FastOS_File::Stat(dir, &statInfo))
- return; // Fail if the directory does not exist
- FastOS_DirectoryScan dirScan( dir );
-
- while (dirScan.ReadNext()) {
- if (strcmp(dirScan.GetName(), ".") != 0 &&
- strcmp(dirScan.GetName(), "..") != 0 &&
- (keepFile == nullptr || strcmp(dirScan.GetName(), keepFile) != 0))
- {
- std::string name = dir;
- name += GetPathSeparator();
- name += dirScan.GetName();
- if (dirScan.IsDirectory()) {
- EmptyAndRemoveDirectory(name.c_str());
- } else {
- if ( ! FastOS_File::Delete(name.c_str()) ) {
- std::ostringstream os;
- os << "Failed deleting file '" << name << "' due to " << getLastErrorString();
- throw std::runtime_error(os.str().c_str());
- }
- }
- }
- }
-}
-
-
-void
-FastOS_FileInterface::EmptyAndRemoveDirectory(const char *dir)
-{
- EmptyDirectory(dir);
- FastOS_File::RemoveDirectory(dir);
-}
-
-void
-FastOS_FileInterface::MakeDirIfNotPresentOrExit(const char *name)
-{
- FastOS_StatInfo statInfo;
-
- if (FastOS_File::Stat(name, &statInfo)) {
- if (statInfo._isDirectory)
- return;
-
- fprintf(stderr, "%s is not a directory\n", name);
- std::_Exit(1);
- }
-
- if (statInfo._error != FastOS_StatInfo::FileNotFound) {
- std::error_code ec(errno, std::system_category());
- fprintf(stderr, "Could not stat %s: %s\n", name, ec.message().c_str());
- std::_Exit(1);
- }
-
- if (!FastOS_File::MakeDirectory(name)) {
- std::error_code ec(errno, std::system_category());
- fprintf(stderr, "Could not mkdir(\"%s\", 0775): %s\n", name, ec.message().c_str());
- std::_Exit(1);
- }
-}
-
void
FastOS_FileInterface::SetFileName(const char *filename)
{
diff --git a/fastos/src/vespa/fastos/file.h b/fastos/src/vespa/fastos/file.h
index b5e1add3529..b52b7e787fa 100644
--- a/fastos/src/vespa/fastos/file.h
+++ b/fastos/src/vespa/fastos/file.h
@@ -109,53 +109,6 @@ public:
static bool CopyFile( const char *src, const char *dst );
/**
- * Move a file from src to dst. Has the same semantics as
- * FastOS_File::Rename, except that it works across different
- * volumes / disks as well (Via copy and remove).
- *
- * @author Terje Loken
- * @return success / failure
- * @param src a 'const char *' value with the file to move from
- * @param dst a 'const char *' value with the name of the resulting filename
- */
- static bool MoveFile( const char *src, const char *dst);
-
- /**
- * Remove a directory, even if it is non-empty. Missing directory does not cause error.
- *
- * @author Terje Loken
- * @throws std::runtime_error if there are errors.
- * @param dir a 'const char *' valuem, with the path to the directory we
- * want to remove.
- */
- static void EmptyAndRemoveDirectory(const char *dir);
-
- /**
- * Empty a directory. Delete all files and directories within the
- * dir, with the exception of files matching a specific name
- * (optional). The exception does not apply files in
- * subdirectories.
- *
- * @author Terje Loken
- * @throws std::runtime_error if there are errors.
- * @param dir a 'const char *' value with the directory to empty.
- * @param keepFile a 'const char *' value. If supplied, leave files with
- * this name alone.
- */
- static void EmptyDirectory( const char *dir, const char *keepFile = nullptr);
-
- /**
- * Make a directory (special compatibility version)
- * Succeed if the directory already exists. A stat is performed
- * to check the directory before attempting to create the
- * directory.
- * If the procedure fails, an error is printed to stderr and
- * the program exits.
- * @param name Name of directory
- */
- static void MakeDirIfNotPresentOrExit(const char *name);
-
- /**
* Return path separator string. This will yield "/" on UNIX systems.
* @return pointer to path separator character string
*/
diff --git a/fastos/src/vespa/fastos/unix_file.cpp b/fastos/src/vespa/fastos/unix_file.cpp
index 39e31c87702..71a9f6e6faa 100644
--- a/fastos/src/vespa/fastos/unix_file.cpp
+++ b/fastos/src/vespa/fastos/unix_file.cpp
@@ -128,24 +128,6 @@ int FastOS_UNIX_File::GetMaximumPathLength(const char *pathName)
return pathconf(pathName, _PC_PATH_MAX);
}
-bool
-FastOS_UNIX_File::MakeDirectory (const char *name)
-{
- return (mkdir(name, 0775) == 0);
-}
-
-
-void
-FastOS_UNIX_File::RemoveDirectory (const char *name)
-{
- if ((rmdir(name) != 0) && (ERR_ENOENT != GetLastError())) {
- std::ostringstream os;
- os << "Remove of directory '" << name << "' failed with error :'" << getLastErrorString() << "'";
- throw std::runtime_error(os.str());
- }
-}
-
-
std::string
FastOS_UNIX_File::getCurrentDirectory(void)
{
diff --git a/fastos/src/vespa/fastos/unix_file.h b/fastos/src/vespa/fastos/unix_file.h
index 70a8db5036e..368d3c5aca5 100644
--- a/fastos/src/vespa/fastos/unix_file.h
+++ b/fastos/src/vespa/fastos/unix_file.h
@@ -39,8 +39,6 @@ public:
}
static bool Stat(const char *filename, FastOS_StatInfo *statInfo);
- static bool MakeDirectory(const char *name);
- static void RemoveDirectory(const char *name);
static std::string getCurrentDirectory();
diff --git a/searchlib/src/vespa/searchlib/util/dirtraverse.cpp b/searchlib/src/vespa/searchlib/util/dirtraverse.cpp
index 07dbc9a247d..c1e8b6b7396 100644
--- a/searchlib/src/vespa/searchlib/util/dirtraverse.cpp
+++ b/searchlib/src/vespa/searchlib/util/dirtraverse.cpp
@@ -2,275 +2,63 @@
#include "dirtraverse.h"
#include <vespa/vespalib/util/size_literals.h>
-#include <vespa/fastos/file.h>
-#include <cassert>
-#include <cstring>
+#include <filesystem>
+#include <system_error>
namespace search {
-extern "C" {
-static int cmpname(const void *av, const void *bv)
-{
- const DirectoryTraverse::Name *const a =
- *(const DirectoryTraverse::Name *const *) av;
- const DirectoryTraverse::Name *const b =
- *(const DirectoryTraverse::Name *const *) bv;
- return a->_name.compare(b->_name.c_str());
-}
-}
-
-DirectoryTraverse::Name::Name(const char *name)
- : _name(name),
- _next(nullptr)
-{
-}
-DirectoryTraverse::Name::~Name() = default;
-
-DirectoryTraverse::Name *
-DirectoryTraverse::Name::sort(Name *head, int count)
-{
- Name *nl;
- Name **names;
- int i;
-
- names = new Name *[count];
- i = 0;
- for(nl = head; nl != nullptr; nl = nl->_next)
- names[i++] = nl;
- assert(i == count);
- qsort(names, count, sizeof(Name *), cmpname);
- for (i = 0; i < count; i++) {
- if (i + 1 < count)
- names[i]->_next = names[i + 1];
- else
- names[i]->_next = nullptr;
- }
- head = names[0];
- delete [] names;
- return head;
-}
-
-
-void
-DirectoryTraverse::QueueDir(const char *name)
-{
- Name *n = new Name(name);
- if (_dirTail == nullptr)
- _dirHead = n;
- else
- _dirTail->_next = n;
- _dirTail = n;
-}
+namespace fs = std::filesystem;
+namespace {
-void
-DirectoryTraverse::PushDir(const char *name)
-{
- Name *n = new Name(name);
- n->_next = _pdirHead;
- _pdirHead = n;
-}
-
-
-void
-DirectoryTraverse::PushRemoveDir(const char *name)
-{
- Name *n = new Name(name);
- n->_next = _rdirHead;
- _rdirHead = n;
-}
-
-
-void
-DirectoryTraverse::PushPushedDirs()
-{
- Name *n;
- while (_pdirHead != nullptr) {
- n = _pdirHead;
- _pdirHead = n->_next;
- n->_next = _dirHead;
- _dirHead = n;
- if (_dirTail == nullptr)
- _dirTail = n;
- }
-}
-
-
-DirectoryTraverse::Name *
-DirectoryTraverse::UnQueueDir()
-{
- Name *n;
- PushPushedDirs();
- if (_dirHead == nullptr)
- return nullptr;
- n = _dirHead;
- _dirHead = n->_next;
- n->_next = nullptr;
- if (_dirHead == nullptr)
- _dirTail = nullptr;
- return n;
-}
-
-DirectoryTraverse::Name *
-DirectoryTraverse::UnQueueName()
-{
- Name *n;
- if (_nameHead == nullptr)
- return nullptr;
- n = _nameHead;
- _nameHead = n->_next;
- n->_next = nullptr;
- _nameCount--;
- return n;
-}
-
-
-void
-DirectoryTraverse::ScanSingleDir()
+uint64_t
+try_get_tree_size(const std::string& base_dir)
{
- assert(_nameHead == nullptr);
- assert(_nameCount == 0);
- delete _curDir;
- _fullDirName.clear();
- _curDir = UnQueueDir();
- if (_curDir == nullptr)
- return;
- _fullDirName = _baseDir;
- if ( ! _curDir->_name.empty()) {
- _fullDirName += "/" + _curDir->_name;
+ fs::path path(base_dir);
+ std::error_code ec;
+ fs::recursive_directory_iterator dir_itr(path, fs::directory_options::skip_permission_denied, ec);
+ if (ec) {
+ return 0;
}
- FastOS_DirectoryScan *dirscan = new FastOS_DirectoryScan(_fullDirName.c_str());
- while (dirscan->ReadNext()) {
- const char *name = dirscan->GetName();
- if (strcmp(name, ".") == 0 ||
- strcmp(name, "..") == 0)
- continue;
- Name *nl = new Name(name);
- nl->_next = _nameHead;
- _nameHead = nl;
- _nameCount++;
- }
- if (_nameCount > 1)
- _nameHead = _nameHead->sort(_nameHead, _nameCount);
- delete dirscan;
-}
-
-
-bool
-DirectoryTraverse::NextName()
-{
- delete _curName;
- _curName = nullptr;
- while (_nameHead == nullptr && (_dirHead != nullptr || _pdirHead != nullptr))
- ScanSingleDir();
- if (_nameHead == nullptr)
- return false;
- _curName = UnQueueName();
- _fullName = _fullDirName + "/" + _curName->_name;
- _relName = _fullName.c_str() + (_baseDir.size() + 1);
- return true;
-}
-
-
-bool
-DirectoryTraverse::NextRemoveDir()
-{
- Name *curName;
- delete _curName;
- _curName = nullptr;
- if (_rdirHead == nullptr)
- return false;
- curName = _rdirHead;
- _rdirHead = curName->_next;
- _fullName = _baseDir + "/" + curName->_name;
- _relName = _fullName.c_str() + _baseDir.size() + 1;
- delete curName;
- return true;
-}
-
-
-bool
-DirectoryTraverse::RemoveTree()
-{
- FastOS_StatInfo statInfo;
-
- while (NextName()) {
- const char *relname = GetRelName();
- const char *fullname = GetFullName();
- if (FastOS_File::Stat(fullname, &statInfo)) {
- if (statInfo._isDirectory) {
- PushDir(relname);
- PushRemoveDir(relname);
- } else {
- FastOS_File::Delete(fullname);
+ uint64_t total_size = 0;
+ constexpr uint64_t block_size = 4_Ki;
+ for (const auto &elem : dir_itr) {
+ if (fs::is_regular_file(elem.path()) && !fs::is_symlink(elem.path())) {
+ const auto size = elem.file_size(ec);
+ if (!ec) {
+ // round up size to file system block size (assumed to be 4 KiB)
+ auto adj_size = ((size + block_size - 1) / block_size) * block_size;
+ total_size += adj_size;
}
}
}
- while (NextRemoveDir()) {
- const char *fullname = GetFullName();
- FastOS_File::RemoveDirectory(fullname);
- }
- FastOS_File::RemoveDirectory(_baseDir.c_str());
- return true;
+ return total_size;
+}
+
}
uint64_t
DirectoryTraverse::GetTreeSize()
{
- FastOS_StatInfo statInfo;
- uint64_t size = 0;
- const uint64_t blockSize = 4_Ki;
-
- while (NextName()) {
- const char *relname = GetRelName();
- const char *fullname = GetFullName();
- if (FastOS_File::Stat(fullname, &statInfo)) {
- uint64_t adjSize = ((statInfo._size + blockSize - 1) / blockSize) * blockSize;
- size += adjSize;
- if (statInfo._isDirectory) {
- PushDir(relname);
- }
+ // Since try_get_tree_size may throw on concurrent directory
+ // modifications, immediately retry a bounded number of times if this
+ // happens. Number of retries chosen randomly by counting fingers.
+ for (int i = 0; i < 10; ++i) {
+ try {
+ return try_get_tree_size(_base_dir);
+ } catch (const fs::filesystem_error&) {
+ // Go around for another spin that hopefully won't race.
}
}
- return size;
+ return 0;
}
-DirectoryTraverse::DirectoryTraverse(const char *baseDir)
- : _baseDir(baseDir),
- _nameHead(nullptr),
- _nameCount(0),
- _dirHead(nullptr),
- _dirTail(nullptr),
- _pdirHead(nullptr),
- _rdirHead(nullptr),
- _curDir(nullptr),
- _curName(nullptr),
- _fullDirName(),
- _fullName(),
- _relName(nullptr)
+DirectoryTraverse::DirectoryTraverse(const std::string& base_dir)
+ : _base_dir(base_dir)
{
- QueueDir("");
- ScanSingleDir();
}
-
-DirectoryTraverse::~DirectoryTraverse()
-{
- delete _curDir;
- delete _curName;
- PushPushedDirs();
- while (_dirHead != nullptr)
- delete UnQueueDir();
- while (_nameHead != nullptr)
- delete UnQueueName();
- while (_rdirHead != nullptr) {
- Name *n;
- n = _rdirHead;
- _rdirHead = n->_next;
- n->_next = nullptr;
- delete n;
- }
-}
+DirectoryTraverse::~DirectoryTraverse() = default;
} // namespace search
diff --git a/searchlib/src/vespa/searchlib/util/dirtraverse.h b/searchlib/src/vespa/searchlib/util/dirtraverse.h
index 4a96ad0935d..c26246e2596 100644
--- a/searchlib/src/vespa/searchlib/util/dirtraverse.h
+++ b/searchlib/src/vespa/searchlib/util/dirtraverse.h
@@ -7,54 +7,16 @@
namespace search {
+/*
+ * Class used to get size of directory tree on disk.
+ */
class DirectoryTraverse
{
private:
- DirectoryTraverse(const DirectoryTraverse &);
- DirectoryTraverse& operator=(const DirectoryTraverse &);
-
-public:
- class Name
- {
- private:
- Name(const Name &);
- Name& operator=(const Name &);
-
- public:
- std::string _name;
- Name *_next;
- explicit Name(const char *name);
- ~Name();
- static Name *sort(Name *head, int count);
- };
-private:
- std::string _baseDir;
- Name *_nameHead;
- int _nameCount;
- Name *_dirHead;
- Name *_dirTail;
- Name *_pdirHead;
- Name *_rdirHead;
- Name *_curDir;
- Name *_curName;
- std::string _fullDirName;
- std::string _fullName;
- const char *_relName;
+ std::string _base_dir;
public:
- const char *GetFullName() const { return _fullName.c_str(); }
- const char *GetRelName() const { return _relName; }
- void QueueDir(const char *name);
- void PushDir(const char *name);
- void PushRemoveDir(const char *name);
- void PushPushedDirs();
- Name *UnQueueDir();
- Name *UnQueueName();
- void ScanSingleDir();
- bool NextName();
- bool NextRemoveDir();
- bool RemoveTree();
uint64_t GetTreeSize(); // Returns size of directory in bytes
- explicit DirectoryTraverse(const char *baseDir);
+ explicit DirectoryTraverse(const std::string& base_dir);
~DirectoryTraverse();
};