blob: 4d4a90db69782649e77f8527d27f05f058837f38 [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_FILE_BLOCK_MANAGER_H
#define KUDU_FS_FILE_BLOCK_MANAGER_H
#include <map>
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
#include "kudu/fs/block_id.h"
#include "kudu/fs/block_manager.h"
#include "kudu/util/locks.h"
#include "kudu/util/random.h"
namespace kudu {
class Env;
class MemTracker;
class MetricEntity;
class WritableFile;
namespace fs {
class PathInstanceMetadataFile;
namespace internal {
class FileBlockLocation;
class FileReadableBlock;
class FileWritableBlock;
struct BlockManagerMetrics;
} // namespace internal
// A file-backed block storage implementation.
//
// This is a naive block implementation which maps each block to its own
// file on disk. To prevent the block directory from becoming too large,
// blocks are aggregated into a 3-level directory hierarchy.
//
// The block manager can take advantage of multiple filesystem paths. A block
// written to a given path will be assigned an ID that includes enough
// information to uniquely identify the path's underlying disk. The ID is
// resolved back into a filesystem path when the block is opened for reading.
// The structure of this ID limits the block manager to at most 65,536 disks.
//
// When creating blocks, the block manager will round robin through the
// available filesystem paths.
//
// TODO: Support path-based block placement hints.
// The file-backed block manager.
class FileBlockManager : public BlockManager {
public:
// Creates a new in-memory instance of a FileBlockManager.
//
// 'env' should remain alive for the lifetime of the block manager.
FileBlockManager(Env* env, const BlockManagerOptions& opts);
virtual ~FileBlockManager();
virtual Status Create() OVERRIDE;
virtual Status Open() OVERRIDE;
virtual Status CreateBlock(const CreateBlockOptions& opts,
gscoped_ptr<WritableBlock>* block) OVERRIDE;
virtual Status CreateBlock(gscoped_ptr<WritableBlock>* block) OVERRIDE;
virtual Status OpenBlock(const BlockId& block_id,
gscoped_ptr<ReadableBlock>* block) OVERRIDE;
virtual Status DeleteBlock(const BlockId& block_id) OVERRIDE;
virtual Status CloseBlocks(const std::vector<WritableBlock*>& blocks) OVERRIDE;
private:
friend class internal::FileBlockLocation;
friend class internal::FileReadableBlock;
friend class internal::FileWritableBlock;
// Synchronizes the metadata for a block with the given id.
Status SyncMetadata(const internal::FileBlockLocation& block_id);
// Looks up the path of the file backing a particular block ID.
//
// On success, overwrites 'path' with the file's path.
bool FindBlockPath(const BlockId& block_id,
std::string* root_path) const;
Env* env() const { return env_; }
// For manipulating files.
Env* env_;
// If true, only read operations are allowed.
const bool read_only_;
// Filesystem paths where all block directories are found.
const std::vector<std::string> root_paths_;
// Maps path indices their instance files.
//
// There's no need to synchronize access to the map as it is only written
// to during Create() and Open(); all subsequent accesses are reads.
typedef std::map<uint16_t, PathInstanceMetadataFile*> PathMap;
PathMap root_paths_by_idx_;
// For generating block IDs.
ThreadSafeRandom rand_;
// Protects 'dirty_dirs_' and 'next_root_path_'.
mutable simple_spinlock lock_;
// Tracks the block directories which are dirty from block creation. This
// lets us perform some simple coalescing when synchronizing metadata.
std::unordered_set<std::string> dirty_dirs_;
// Points to the filesystem path to be used when creating the next block.
PathMap::iterator next_root_path_;
// Metric container for the block manager.
// May be null if instantiated without metrics.
gscoped_ptr<internal::BlockManagerMetrics> metrics_;
// Tracks memory consumption of any allocations numerous enough to be
// interesting.
std::shared_ptr<MemTracker> mem_tracker_;
DISALLOW_COPY_AND_ASSIGN(FileBlockManager);
};
} // namespace fs
} // namespace kudu
#endif