-
Notifications
You must be signed in to change notification settings - Fork 9.2k
HDFS-16463. Make dirent cross platform compatible #4370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
GauthamBanasandra
merged 26 commits into
apache:trunk
from
GauthamBanasandra:dirent-x-platform
Jun 10, 2022
Merged
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
1625759
Add dirent for XPlatform
GauthamBanasandra ac14466
Do not return ref type in variant
GauthamBanasandra af99d8e
Add C API for dirent
GauthamBanasandra f0154ca
Fix compilation issue
GauthamBanasandra 433cbca
Add unit test for dirent
GauthamBanasandra 3c907b4
Fix compilation issue
GauthamBanasandra 14a024f
Add unit test for dirent C API
GauthamBanasandra 43f5956
Fix unit test failure
GauthamBanasandra cc17069
Fix memory leak
GauthamBanasandra c6396c2
Throw exception instead of assertion
GauthamBanasandra 3773c8f
Clear d_name buffer for reuse
GauthamBanasandra b75e312
Return absolute paths
GauthamBanasandra a8a17c0
Add dirent example
GauthamBanasandra d48336b
Remove extern since it's not needed
GauthamBanasandra deb38e6
Add USE_X_PLATFORM_DIRENT def
GauthamBanasandra c6de53f
Use XPlatform dirent appropriately
GauthamBanasandra c1ffa2a
Declare listdir as a project
GauthamBanasandra e65788a
Add extern and other fixes
GauthamBanasandra 3f516f1
Add extern "C" only for Windows
GauthamBanasandra adaff0c
Remove whitespace
GauthamBanasandra 9785856
Remove const
GauthamBanasandra 09cf9a5
Add documentation
GauthamBanasandra a39772d
Remove dirent example
GauthamBanasandra 33292fa
Implement non-Windows approach first
GauthamBanasandra 8cc389d
Do not wrap impl with extern "C"
GauthamBanasandra 946251e
Modularize dirent.h header file
GauthamBanasandra File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
...roject/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/c-api/dirent.cc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| /** | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #include <algorithm> | ||
| #include <cerrno> | ||
| #include <iostream> | ||
| #include <iterator> | ||
| #include <system_error> | ||
| #include <variant> | ||
|
|
||
| #include "x-platform/c-api/dirent.h" | ||
| #include "x-platform/dirent.h" | ||
|
|
||
| #if defined(WIN32) && defined(__cplusplus) | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| DIR *opendir(const char *dir_path) { | ||
| const auto dir = new DIR; | ||
| dir->x_platform_dirent_ptr = new XPlatform::Dirent(dir_path); | ||
| return dir; | ||
| } | ||
|
|
||
| struct dirent *readdir(DIR *dir) { | ||
| /* | ||
| * We will use a static variable to hold the dirent, so that we align with the | ||
| * readdir's implementation in dirent.h header file in Linux. | ||
| */ | ||
| static struct dirent static_dir_entry; | ||
|
|
||
| // Get the XPlatform::Dirent instance and move the iterator. | ||
| const auto x_platform_dirent = | ||
| static_cast<XPlatform::Dirent *>(dir->x_platform_dirent_ptr); | ||
| const auto dir_entry = x_platform_dirent->NextFile(); | ||
|
|
||
| // End of iteration. | ||
| if (std::holds_alternative<std::monostate>(dir_entry)) { | ||
| return nullptr; | ||
| } | ||
|
|
||
| // Error in iteration. | ||
| if (std::holds_alternative<std::error_code>(dir_entry)) { | ||
| const auto err = std::get<std::error_code>(dir_entry); | ||
| errno = err.value(); | ||
|
|
||
| #ifdef X_PLATFORM_C_API_DIRENT_DEBUG | ||
| std::cerr << "Error in listing directory: " << err.message() << std::endl; | ||
GauthamBanasandra marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| #endif | ||
|
|
||
| return nullptr; | ||
| } | ||
|
|
||
| // Return the current child file/folder's name. | ||
| if (std::holds_alternative<std::filesystem::directory_entry>(dir_entry)) { | ||
| const auto entry = std::get<std::filesystem::directory_entry>(dir_entry); | ||
| const auto filename = entry.path().filename().string(); | ||
|
|
||
| // The file name's length shouldn't exceed 256. | ||
| if (filename.length() >= 256) { | ||
| errno = 1; | ||
| return nullptr; | ||
| } | ||
|
|
||
| std::fill(std::begin(static_dir_entry.d_name), | ||
| std::end(static_dir_entry.d_name), '\0'); | ||
| std::copy(filename.begin(), filename.end(), | ||
| std::begin(static_dir_entry.d_name)); | ||
| } | ||
| return &static_dir_entry; | ||
| } | ||
|
|
||
| int closedir(DIR *dir) { | ||
| const auto x_platform_dirent = | ||
| static_cast<XPlatform::Dirent *>(dir->x_platform_dirent_ptr); | ||
| delete x_platform_dirent; | ||
| delete dir; | ||
|
|
||
| // We can't use the void return type for closedir since we want to align the | ||
| // closedir method's signature in dirent.h header file in Linux. | ||
| return 0; | ||
| } | ||
|
|
||
| #if defined(WIN32) && defined(__cplusplus) | ||
| } | ||
| #endif | ||
93 changes: 93 additions & 0 deletions
93
...project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/c-api/dirent.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| /** | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #ifndef NATIVE_LIBHDFSPP_LIB_CROSS_PLATFORM_C_API_DIRENT_H | ||
| #define NATIVE_LIBHDFSPP_LIB_CROSS_PLATFORM_C_API_DIRENT_H | ||
|
|
||
| /* | ||
| * We will use XPlatform's dirent on Windows or when the macro | ||
| * USE_X_PLATFORM_DIRENT is defined. | ||
| */ | ||
| #if defined(WIN32) || defined(USE_X_PLATFORM_DIRENT) | ||
|
|
||
| /* | ||
| * We will use extern "C" only on Windows. | ||
| */ | ||
| #if defined(WIN32) && defined(__cplusplus) | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /** | ||
GauthamBanasandra marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| * DIR struct holds the pointer to XPlatform::Dirent instance. Since this will | ||
| * be used in C, we can't hold the pointer to XPlatform::Dirent. We're working | ||
| * around this by using a void pointer and casting it to XPlatform::Dirent when | ||
| * needed in C++. | ||
| */ | ||
| typedef struct DIR { | ||
| void *x_platform_dirent_ptr; | ||
| } DIR; | ||
|
|
||
| /** | ||
| * dirent struct contains the name of the file/folder while iterating through | ||
| * the directory's children. | ||
| */ | ||
| struct dirent { | ||
| char d_name[256]; | ||
| }; | ||
|
|
||
| /** | ||
| * Opens a directory for iteration. Internally, it instantiates DIR struct for | ||
| * the given path. closedir must be called on the returned pointer to DIR struct | ||
| * when done. | ||
| * | ||
| * @param dir_path The path to the directory to iterate through. | ||
| * @return A pointer to the DIR struct. | ||
| */ | ||
| DIR *opendir(const char *dir_path); | ||
|
|
||
| /** | ||
| * For iterating through the children of the directory pointed to by the DIR | ||
| * struct pointer. | ||
| * | ||
| * @param dir The pointer to the DIR struct. | ||
| * @return A pointer to dirent struct containing the name of the current child | ||
| * file/folder. | ||
| */ | ||
| struct dirent *readdir(DIR *dir); | ||
|
|
||
| /** | ||
| * De-allocates the XPlatform::Dirent instance pointed to by the DIR pointer. | ||
| * | ||
| * @param dir The pointer to DIR struct to close. | ||
| * @return 0 if successful. | ||
| */ | ||
| int closedir(DIR *dir); | ||
|
|
||
| #if defined(WIN32) && defined(__cplusplus) | ||
| } | ||
| #endif | ||
|
|
||
| #else | ||
| /* | ||
| * For non-Windows environments, we use the dirent.h header itself. | ||
| */ | ||
| #include <dirent.h> | ||
GauthamBanasandra marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| #endif | ||
|
|
||
| #endif | ||
38 changes: 38 additions & 0 deletions
38
...hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/dirent.cc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| /** | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #include <filesystem> | ||
| #include <system_error> | ||
| #include <variant> | ||
|
|
||
| #include "dirent.h" | ||
|
|
||
| std::variant<std::monostate, std::filesystem::directory_entry, std::error_code> | ||
| XPlatform::Dirent::NextFile() { | ||
| if (dir_it_err_) { | ||
| return dir_it_err_; | ||
| } | ||
|
|
||
| if (dir_it_ == std::filesystem::end(dir_it_)) { | ||
| return std::monostate(); | ||
| } | ||
|
|
||
| const std::filesystem::directory_entry dir_entry = *dir_it_; | ||
| dir_it_ = dir_it_.increment(dir_it_err_); | ||
| return dir_entry; | ||
| } |
77 changes: 77 additions & 0 deletions
77
...-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/dirent.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| /** | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #ifndef NATIVE_LIBHDFSPP_LIB_CROSS_PLATFORM_DIRENT | ||
| #define NATIVE_LIBHDFSPP_LIB_CROSS_PLATFORM_DIRENT | ||
|
|
||
| #include <filesystem> | ||
| #include <string> | ||
| #include <system_error> | ||
| #include <variant> | ||
|
|
||
| namespace XPlatform { | ||
| /** | ||
| * {@class XPlatform::Dirent} provides the functionality to perform a one-time | ||
| * iteration per {@link XPlatform::Dirent} through the child files or folders | ||
| * under a given path. | ||
| */ | ||
| class Dirent { | ||
| public: | ||
| Dirent(const std::string &path) | ||
| : dir_it_{std::filesystem::path{path}, dir_it_err_} {} | ||
|
|
||
| // Abiding to the Rule of 5 | ||
| Dirent(const Dirent &) = default; | ||
| Dirent(Dirent &&) = default; | ||
| Dirent &operator=(const Dirent &) = default; | ||
| Dirent &operator=(Dirent &&) = default; | ||
| ~Dirent() = default; | ||
|
|
||
| /** | ||
| * Advances the iterator {@link XPlatform::Dirent#dir_it_} to the next file in | ||
| * the given path. | ||
| * | ||
| * @return An {@link std::variant} comprising of any one of the following | ||
| * types: | ||
| * 1. {@link std::monostate} which indicates the end of iteration of all the | ||
| * files in the given path. | ||
| * 2. {@link std::filesystem::directory_entry} which is the directory entry of | ||
| * the current file. | ||
| * 3. {@link std::error_code} which corresponds to the error in retrieving the | ||
| * file. | ||
| */ | ||
| std::variant<std::monostate, std::filesystem::directory_entry, | ||
| std::error_code> | ||
| NextFile(); | ||
|
|
||
| private: | ||
| /** | ||
| * Indicates the error corresponding to the most recent invocation of | ||
| * directory iteration by {@link XPlatform::Dirent#dir_it_}. | ||
| */ | ||
| std::error_code dir_it_err_{}; | ||
|
|
||
| /** | ||
| * The iterator used for iterating through the files or folders under the | ||
| * given path. | ||
| */ | ||
| std::filesystem::directory_iterator dir_it_; | ||
| }; | ||
| } // namespace XPlatform | ||
|
|
||
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.