blob: 5471baa2d2bfe767d1553a86ee1199abfeb41ecd [file] [log] [blame]
// 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