| // 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 IMPALA_UTIL_FILESYSTEM_UTIL_H |
| #define IMPALA_UTIL_FILESYSTEM_UTIL_H |
| |
| #include <dirent.h> |
| #include "common/status.h" |
| |
| namespace impala { |
| |
| /// Utility class for common local file system operations such as file creation and |
| /// deletion. This class should NOT be used to read or write data (DiskIoMgr is used |
| /// for that). Errors are indicated by the status code RUNTIME_ERROR, and are not |
| /// handled via exceptions. |
| class FileSystemUtil { |
| public: |
| /// Create the specified directory and any ancestor directories that do not exist yet. |
| /// The directory and its contents are destroyed if it already exists. |
| /// Returns Status::OK if successful, or a runtime error with a message otherwise. |
| static Status RemoveAndCreateDirectory(const std::string& directory) WARN_UNUSED_RESULT; |
| |
| /// Create a file at the specified path. |
| static Status CreateFile(const std::string& file_path) WARN_UNUSED_RESULT; |
| |
| /// Remove the specified paths and their enclosing files/directories. |
| static Status RemovePaths( |
| const std::vector<std::string>& directories) WARN_UNUSED_RESULT; |
| |
| /// Verify that the specified path is an existing directory. |
| /// Returns Status::OK if it is, or a runtime error with a message otherwise. |
| static Status VerifyIsDirectory(const std::string& directory_path) WARN_UNUSED_RESULT; |
| |
| /// Returns the space available on the file system containing 'directory_path' |
| /// in 'available_bytes' |
| static Status GetSpaceAvailable( |
| const std::string& directory_path, uint64_t* available_bytes) WARN_UNUSED_RESULT; |
| |
| /// Returns the currently allowed maximum of possible file descriptors. In case of an |
| /// error returns 0. |
| static uint64_t MaxNumFileHandles(); |
| |
| /// Finds the canonicalized absolute pathname for 'file_path' and returns it in |
| /// *canonical_path. |
| static Status GetCanonicalPath( |
| const std::string& file_path, std::string* canonical_path) WARN_UNUSED_RESULT; |
| |
| /// Checks if 'file_path' is a symbolic link. If it is, 'is_symbolic_link' is set to |
| /// 'true' and *canonical_path is set to the resolved canonicalized path. |
| static Status IsSymbolicLink(const std::string& file_path, bool* is_symbolic_link, |
| std::string* canonical_path) WARN_UNUSED_RESULT; |
| |
| /// Returns 'true' iff 'path' is a canonicalized path. 'path' doesn't have to be an |
| /// existing path. |
| /// Always returns 'true' for the *canonical_path returned by GetCanonicalPath() and |
| /// IsSymbolicLink(). |
| static bool IsCanonicalPath(const std::string& path); |
| |
| /// Returns 'true' iff path 'prefix' is a non-empty prefix of path 'path'. |
| /// This is a string computation: the filesystem is not accessed to confirm the |
| /// existance of 'path' or 'prefix'. It is assumed that 'prefix' and 'path' are both |
| /// canonicalized paths. |
| static bool IsPrefixPath(const std::string& prefix, const std::string& path); |
| |
| /// - If 'start' is a prefix of 'path', it constructs relative filepath to 'path' from |
| /// the 'start' directory and sets 'relpath' to the resulting path. 'true' is returned. |
| /// - Otherwise, 'relpath' is left intact and 'false' is returned. |
| /// This is a string computation: the filesystem is not accessed to confirm the |
| /// existance of 'path' or 'start'. It is assumed that 'path' and 'start' are both |
| /// canonicalized paths. |
| static bool GetRelativePath(const std::string& path, const std::string& start, |
| std::string* relpath); |
| |
| /// Ext filesystem on certain kernel versions may result in inconsistent metadata after |
| /// punching holes in files. The filesystem may require fsck repair on next reboot. |
| /// See KUDU-1508 for details. This function checks if the filesystem at 'path' resides |
| /// in a ext filesystem and the kernel version is affected by KUDU-1058. If so, return |
| /// error status; Returns OK otherwise. |
| static Status CheckForBuggyExtFS(const std::string& path); |
| |
| /// Checks if the filesystem at the directory 'path' supports hole punching (i.e. |
| /// calling fallocate with FALLOC_FL_PUNCH_HOLE). |
| /// |
| /// Return error status if: |
| /// - 'path' resides in a ext filesystem and the kernel version is vulnerable to |
| /// KUDU-1508. |
| /// - creating a test file at 'path' failed. |
| /// - punching holes in test file failed. |
| /// - reading the test file's size failed. |
| /// |
| /// Returns OK otherwise. |
| static Status CheckHolePunch(const std::string& path); |
| |
| class Directory { |
| public: |
| // Different types of entry in the directory |
| enum EntryType { |
| DIR_ENTRY_ANY = 0, |
| DIR_ENTRY_REG, // regular file (DT_REG in readdir() result) |
| DIR_ENTRY_DIR, // directory (DT_DIR in readdir() result) |
| DIR_ENTRY_NUM_TYPES |
| }; |
| |
| /// Opens 'path' directory for iteration. Directory entries "." and ".." will be |
| /// skipped while iterating through the entries. |
| Directory(const string& path); |
| |
| /// Closes the directory. |
| ~Directory(); |
| |
| /// Reads the next directory entry and sets 'entry_name' to the entry name. |
| /// Returns false if an error occured or no more entries were found in the directory. |
| /// If 'type' is specified and filesystem supports returning the types of directory |
| /// entries, only entries of 'type' will be included. Otherwise, it may return |
| /// entries of all types. Return 'true' on success. |
| bool GetNextEntryName(std::string* entry_name, EntryType type = DIR_ENTRY_ANY); |
| |
| /// Returns the status of the previous directory operation. |
| const Status& GetLastStatus() const { return status_; } |
| |
| /// Reads no more than 'max_result_size' directory entries from 'path' and returns |
| /// their names in 'entry_names' vector. If 'max_result_size' <= 0, every directory |
| /// entry is returned. Directory entries "." and ".." will be skipped. If 'type' is |
| /// specified and filesystem of 'path' supports returning type of directory entries, |
| /// only entries of 'type' will be included in 'entry_names'. Otherwise, it will |
| /// include entries of all types. |
| static Status GetEntryNames(const string& path, std::vector<std::string>* entry_names, |
| int max_result_size = 0, EntryType type = DIR_ENTRY_ANY); |
| |
| private: |
| DIR* dir_stream_; |
| std::string dir_path_; |
| Status status_; |
| |
| // Do not allow making copies. |
| Directory(const Directory&); |
| Directory& operator=(const Directory&); |
| }; |
| |
| private: |
| |
| /// This function returns true iff the kernel version Impala is running on |
| /// is affected by KUDU-1508. |
| static bool IsBuggyEl6Kernel(); |
| }; |
| |
| } |
| |
| #endif |