From e55018a8ce0b83e3f1dbe17d0632062924e119ad Mon Sep 17 00:00:00 2001 From: bbkot <97723937+bbkot@users.noreply.github.com> Date: Wed, 30 Mar 2022 15:55:31 -0700 Subject: [PATCH] fixing issue #8345 RocksDB does not work when using UNC network paths (#9384) Summary: Fix https://github.com/facebook/rocksdb/issues/8345 RocksDB does not work with network filesystem paths on Windows, e.g. "\\hostname\folder\..." Pull Request resolved: https://github.com/facebook/rocksdb/pull/9384 Reviewed By: mrambacher Differential Revision: D33830622 Pulled By: riversand963 fbshipit-source-id: 2a99dc3c94415eb1460e110784b97d71600218f1 --- HISTORY.md | 1 + db/filename_test.cc | 63 +++++++++++++++++++++++++++++++++++++++++++++ file/filename.cc | 6 +++++ 3 files changed, 70 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index a406fea4a..154ee23f1 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,7 @@ # Rocksdb Change Log ## Unreleased ### Bug Fixes +* Fixed bug which caused rocksdb failure in the situation when rocksdb was accessible using UNC path * Fixed a race condition when 2PC is disabled and WAL tracking in the MANIFEST is enabled. The race condition is between two background flush threads trying to install flush results, causing a WAL deletion not tracked in the MANIFEST. A future DB open may fail. * Fixed a heap use-after-free race with DropColumnFamily. * Fixed a bug that `rocksdb.read.block.compaction.micros` cannot track compaction stats (#9722). diff --git a/db/filename_test.cc b/db/filename_test.cc index d166876ba..23f6974b1 100644 --- a/db/filename_test.cc +++ b/db/filename_test.cc @@ -171,6 +171,69 @@ TEST_F(FileNameTest, Construction) { ASSERT_EQ(kMetaDatabase, type); } +TEST_F(FileNameTest, NormalizePath) { + // No leading slash + const std::string sep = std::string(1, kFilePathSeparator); + + std::string expected = "FOLDER" + sep + "filename.ext"; + std::string given = "FOLDER" + sep + "filename.ext"; + + ASSERT_EQ(expected, NormalizePath(given)); + + // Two chars /a + + expected = sep + "a"; + given = expected; + ASSERT_EQ(expected, NormalizePath(given)); + + // Two chars a/ + expected = "a" + sep; + given = expected; + ASSERT_EQ(expected, NormalizePath(given)); + + // Server only + expected = sep + sep + "a"; + given = expected; + ASSERT_EQ(expected, NormalizePath(given)); + + // Two slashes after character + expected = "a" + sep; + given = "a" + sep + sep; + + ASSERT_EQ(expected, NormalizePath(given)); + + // slash only / + expected = sep; + given = expected; + ASSERT_EQ(expected, NormalizePath(given)); + + // UNC only // + expected = sep; + given = sep + sep; + + ASSERT_EQ(expected, NormalizePath(given)); + + // 3 slashesy // + expected = sep + sep; + given = sep + sep + sep; + ASSERT_EQ(expected, NormalizePath(given)); + + // 3 slashes // + expected = sep + sep + "a" + sep; + given = sep + sep + sep + "a" + sep; + ASSERT_EQ(expected, NormalizePath(given)); + + // 2 separators in the middle + expected = "a" + sep + "b"; + given = "a" + sep + sep + "b"; + ASSERT_EQ(expected, NormalizePath(given)); + + // UNC with duplicate slashes + expected = sep + sep + "SERVER" + sep + "a" + sep + "b" + sep + "c"; + given = sep + sep + "SERVER" + sep + "a" + sep + sep + "b" + sep + "c"; + ASSERT_EQ(expected, NormalizePath(given)); +} + } // namespace ROCKSDB_NAMESPACE int main(int argc, char** argv) { diff --git a/file/filename.cc b/file/filename.cc index 358f88cf0..f63a469dd 100644 --- a/file/filename.cc +++ b/file/filename.cc @@ -491,6 +491,12 @@ Status GetInfoLogFiles(const std::shared_ptr& fs, std::string NormalizePath(const std::string& path) { std::string dst; + + if (path.length() > 2 && path[0] == kFilePathSeparator && + path[1] == kFilePathSeparator) { // Handle UNC names + dst.append(2, kFilePathSeparator); + } + for (auto c : path) { if (!dst.empty() && (c == kFilePathSeparator || c == '/') && (dst.back() == kFilePathSeparator || dst.back() == '/')) {