blob: 3c4420aa3ba9c8e9213f9155d2fe766f1dc97080 [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 KUDU_FS_FS_MANAGER_H
#define KUDU_FS_FS_MANAGER_H
#include <boost/none.hpp>
#include <boost/optional/optional.hpp>
#include <gtest/gtest_prod.h>
#include <iosfwd>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "kudu/gutil/gscoped_ptr.h"
#include "kudu/gutil/ref_counted.h"
#include "kudu/util/env.h"
#include "kudu/util/path_util.h"
DECLARE_bool(enable_data_block_fsync);
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
namespace kudu {
class MemTracker;
class MetricEntity;
namespace fs {
class BlockManager;
class ReadableBlock;
class WritableBlock;
} // namespace fs
namespace itest {
class ExternalMiniClusterFsInspector;
}
class BlockId;
class InstanceMetadataPB;
struct FsManagerOpts {
FsManagerOpts();
~FsManagerOpts();
// The entity under which all metrics should be grouped. If NULL, metrics
// will not be produced.
//
// Defaults to NULL.
scoped_refptr<MetricEntity> metric_entity;
// The memory tracker under which all new memory trackers will be parented.
// If NULL, new memory trackers will be parented to the root tracker.
std::shared_ptr<MemTracker> parent_mem_tracker;
// The path where WALs will be stored. Cannot be empty.
std::string wal_path;
// The paths where data blocks will be stored. Cannot be empty.
std::vector<std::string> data_paths;
// Whether or not read-write operations should be allowed. Defaults to false.
bool read_only;
};
// FsManager provides helpers to read data and metadata files,
// and it's responsible for abstracting the file-system layout.
//
// The user should not be aware of where files are placed,
// but instead should interact with the storage in terms of "open the block xyz"
// or "write a new schema metadata file for table kwz".
//
// The current layout is:
// <kudu.root.dir>/data/
// <kudu.root.dir>/data/<prefix-0>/<prefix-2>/<prefix-4>/<name>
class FsManager {
public:
static const char *kWalFileNamePrefix;
static const char *kWalsRecoveryDirSuffix;
// Only for unit tests.
FsManager(Env* env, const std::string& root_path);
FsManager(Env* env, const FsManagerOpts& opts);
~FsManager();
// Initialize and load the basic filesystem metadata.
// If the file system has not been initialized, returns NotFound.
// In that case, CreateInitialFileSystemLayout may be used to initialize
// the on-disk structures.
Status Open();
// Create the initial filesystem layout. If 'uuid' is provided, uses it as
// uuid of the filesystem. Otherwise generates one at random.
//
// Returns an error if the file system is already initialized.
Status CreateInitialFileSystemLayout(
boost::optional<std::string> uuid = boost::none);
void DumpFileSystemTree(std::ostream& out);
// Return the UUID persisted in the local filesystem. If Open()
// has not been called, this will crash.
const std::string& uuid() const;
// ==========================================================================
// Data read/write interfaces
// ==========================================================================
// Creates a new anonymous block.
//
// Block will be synced on close.
Status CreateNewBlock(gscoped_ptr<fs::WritableBlock>* block);
Status OpenBlock(const BlockId& block_id,
gscoped_ptr<fs::ReadableBlock>* block);
Status DeleteBlock(const BlockId& block_id);
bool BlockExists(const BlockId& block_id) const;
// ==========================================================================
// on-disk path
// ==========================================================================
std::vector<std::string> GetDataRootDirs() const;
std::string GetWalsRootDir() const {
DCHECK(initted_);
return JoinPathSegments(canonicalized_wal_fs_root_, kWalDirName);
}
std::string GetTabletWalDir(const std::string& tablet_id) const {
return JoinPathSegments(GetWalsRootDir(), tablet_id);
}
std::string GetTabletWalRecoveryDir(const std::string& tablet_id) const;
std::string GetWalSegmentFileName(const std::string& tablet_id,
uint64_t sequence_number) const;
// Return the directory where tablet superblocks should be stored.
std::string GetTabletMetadataDir() const;
// Return the path for a specific tablet's superblock.
std::string GetTabletMetadataPath(const std::string& tablet_id) const;
// List the tablet IDs in the metadata directory.
Status ListTabletIds(std::vector<std::string>* tablet_ids);
// Return the path where InstanceMetadataPB is stored.
std::string GetInstanceMetadataPath(const std::string& root) const;
// Return the directory where the consensus metadata is stored.
std::string GetConsensusMetadataDir() const {
DCHECK(initted_);
return JoinPathSegments(canonicalized_metadata_fs_root_, kConsensusMetadataDirName);
}
// Return the path where ConsensusMetadataPB is stored.
std::string GetConsensusMetadataPath(const std::string& tablet_id) const {
return JoinPathSegments(GetConsensusMetadataDir(), tablet_id);
}
Env *env() { return env_; }
bool read_only() const {
return read_only_;
}
// ==========================================================================
// file-system helpers
// ==========================================================================
bool Exists(const std::string& path) const {
return env_->FileExists(path);
}
Status ListDir(const std::string& path, std::vector<std::string> *objects) const {
return env_->GetChildren(path, objects);
}
Status CreateDirIfMissing(const std::string& path, bool* created = NULL);
fs::BlockManager* block_manager() {
return block_manager_.get();
}
private:
FRIEND_TEST(FsManagerTestBase, TestDuplicatePaths);
friend class itest::ExternalMiniClusterFsInspector; // for access to directory names
// Initializes, sanitizes, and canonicalizes the filesystem roots.
Status Init();
// Select and create an instance of the appropriate block manager.
//
// Does not actually perform any on-disk operations.
void InitBlockManager();
// Create a new InstanceMetadataPB.
Status CreateInstanceMetadata(boost::optional<std::string> uuid,
InstanceMetadataPB* metadata);
// Save a InstanceMetadataPB to the filesystem.
// Does not mutate the current state of the fsmanager.
Status WriteInstanceMetadata(const InstanceMetadataPB& metadata,
const std::string& root);
// Checks if 'path' is an empty directory.
//
// Returns an error if it's not a directory. Otherwise, sets 'is_empty'
// accordingly.
Status IsDirectoryEmpty(const std::string& path, bool* is_empty);
// ==========================================================================
// file-system helpers
// ==========================================================================
void DumpFileSystemTree(std::ostream& out,
const std::string& prefix,
const std::string& path,
const std::vector<std::string>& objects);
static const char *kDataDirName;
static const char *kTabletMetadataDirName;
static const char *kWalDirName;
static const char *kCorruptedSuffix;
static const char *kInstanceMetadataFileName;
static const char *kInstanceMetadataMagicNumber;
static const char *kTabletSuperBlockMagicNumber;
static const char *kConsensusMetadataDirName;
Env *env_;
// If false, operations that mutate on-disk state are prohibited.
const bool read_only_;
// These roots are the constructor input verbatim. None of them are used
// as-is; they are first canonicalized during Init().
const std::string wal_fs_root_;
const std::vector<std::string> data_fs_roots_;
scoped_refptr<MetricEntity> metric_entity_;
std::shared_ptr<MemTracker> parent_mem_tracker_;
// Canonicalized forms of 'wal_fs_root_ and 'data_fs_roots_'. Constructed
// during Init().
//
// - The first data root is used as the metadata root.
// - Common roots in the collections have been deduplicated.
std::string canonicalized_wal_fs_root_;
std::string canonicalized_metadata_fs_root_;
std::set<std::string> canonicalized_data_fs_roots_;
std::set<std::string> canonicalized_all_fs_roots_;
gscoped_ptr<InstanceMetadataPB> metadata_;
gscoped_ptr<fs::BlockManager> block_manager_;
bool initted_;
DISALLOW_COPY_AND_ASSIGN(FsManager);
};
} // namespace kudu
#endif