mirror of
https://github.com/facebook/rocksdb.git
synced 2024-11-30 13:41:46 +00:00
65893ad959
Summary: Currently, the DB directory file descriptor is left open until the deconstruction process (`DB::Close()` does not close the file descriptor). To verify this, comment out the lines between `db_ = nullptr` and `db_->Close()` (line 512, 513, 514, 515 in ldb_cmd.cc) to leak the ``db_'' object, build `ldb` tool and run ``` strace --trace=open,openat,close ./ldb --db=$TEST_TMPDIR --ignore_unknown_options put K1 V1 --create_if_missing ``` There is one directory file descriptor that is not closed in the strace log. Pull Request resolved: https://github.com/facebook/rocksdb/pull/10049 Test Plan: Add a new unit test DBBasicTest.DBCloseAllDirectoryFDs: Open a database with different WAL directory and three different data directories, and all directory file descriptors should be closed after calling Close(). Explicitly call Close() after a directory file descriptor is not used so that the counter of directory open and close should be equivalent. Reviewed By: ajkr, hx235 Differential Revision: D36722135 Pulled By: littlepig2013 fbshipit-source-id: 07bdc2abc417c6b30997b9bbef1f79aa757b21ff
159 lines
4.7 KiB
C++
159 lines
4.7 KiB
C++
// Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
|
|
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <memory>
|
|
|
|
#include "rocksdb/file_system.h"
|
|
#include "rocksdb/io_status.h"
|
|
#include "rocksdb/rocksdb_namespace.h"
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
class Logger;
|
|
|
|
struct OpCounter {
|
|
std::atomic<int> ops;
|
|
std::atomic<uint64_t> bytes;
|
|
|
|
OpCounter() : ops(0), bytes(0) {}
|
|
|
|
void Reset() {
|
|
ops = 0;
|
|
bytes = 0;
|
|
}
|
|
void RecordOp(const IOStatus& io_s, size_t added_bytes) {
|
|
if (!io_s.IsNotSupported()) {
|
|
ops.fetch_add(1, std::memory_order_relaxed);
|
|
}
|
|
if (io_s.ok()) {
|
|
bytes.fetch_add(added_bytes, std::memory_order_relaxed);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct FileOpCounters {
|
|
static const char* kName() { return "FileOpCounters"; }
|
|
|
|
std::atomic<int> opens;
|
|
std::atomic<int> closes;
|
|
std::atomic<int> deletes;
|
|
std::atomic<int> renames;
|
|
std::atomic<int> flushes;
|
|
std::atomic<int> syncs;
|
|
std::atomic<int> dsyncs;
|
|
std::atomic<int> fsyncs;
|
|
std::atomic<int> dir_opens;
|
|
std::atomic<int> dir_closes;
|
|
OpCounter reads;
|
|
OpCounter writes;
|
|
|
|
FileOpCounters()
|
|
: opens(0),
|
|
closes(0),
|
|
deletes(0),
|
|
renames(0),
|
|
flushes(0),
|
|
syncs(0),
|
|
dsyncs(0),
|
|
fsyncs(0),
|
|
dir_opens(0),
|
|
dir_closes(0) {}
|
|
|
|
void Reset() {
|
|
opens = 0;
|
|
closes = 0;
|
|
deletes = 0;
|
|
renames = 0;
|
|
flushes = 0;
|
|
syncs = 0;
|
|
dsyncs = 0;
|
|
fsyncs = 0;
|
|
dir_opens = 0;
|
|
dir_closes = 0;
|
|
reads.Reset();
|
|
writes.Reset();
|
|
}
|
|
std::string PrintCounters() const;
|
|
};
|
|
|
|
// A FileSystem class that counts operations (reads, writes, opens, closes, etc)
|
|
class CountedFileSystem : public FileSystemWrapper {
|
|
public:
|
|
private:
|
|
FileOpCounters counters_;
|
|
|
|
public:
|
|
explicit CountedFileSystem(const std::shared_ptr<FileSystem>& base);
|
|
static const char* kClassName() { return "CountedFileSystem"; }
|
|
const char* Name() const override { return kClassName(); }
|
|
|
|
IOStatus NewSequentialFile(const std::string& f, const FileOptions& options,
|
|
std::unique_ptr<FSSequentialFile>* r,
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus NewRandomAccessFile(const std::string& f,
|
|
const FileOptions& file_opts,
|
|
std::unique_ptr<FSRandomAccessFile>* r,
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus NewWritableFile(const std::string& f, const FileOptions& options,
|
|
std::unique_ptr<FSWritableFile>* r,
|
|
IODebugContext* dbg) override;
|
|
IOStatus ReopenWritableFile(const std::string& fname,
|
|
const FileOptions& options,
|
|
std::unique_ptr<FSWritableFile>* result,
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus ReuseWritableFile(const std::string& fname,
|
|
const std::string& old_fname,
|
|
const FileOptions& file_opts,
|
|
std::unique_ptr<FSWritableFile>* result,
|
|
IODebugContext* dbg) override;
|
|
IOStatus NewRandomRWFile(const std::string& name, const FileOptions& options,
|
|
std::unique_ptr<FSRandomRWFile>* result,
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus NewDirectory(const std::string& name, const IOOptions& io_opts,
|
|
std::unique_ptr<FSDirectory>* result,
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus DeleteFile(const std::string& fname, const IOOptions& options,
|
|
IODebugContext* dbg) override {
|
|
IOStatus s = target()->DeleteFile(fname, options, dbg);
|
|
if (s.ok()) {
|
|
counters_.deletes++;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
IOStatus RenameFile(const std::string& s, const std::string& t,
|
|
const IOOptions& options, IODebugContext* dbg) override {
|
|
IOStatus st = target()->RenameFile(s, t, options, dbg);
|
|
if (st.ok()) {
|
|
counters_.renames++;
|
|
}
|
|
return st;
|
|
}
|
|
|
|
const FileOpCounters* counters() const { return &counters_; }
|
|
|
|
FileOpCounters* counters() { return &counters_; }
|
|
|
|
const void* GetOptionsPtr(const std::string& name) const override {
|
|
if (name == FileOpCounters::kName()) {
|
|
return counters();
|
|
} else {
|
|
return FileSystemWrapper::GetOptionsPtr(name);
|
|
}
|
|
}
|
|
|
|
// Prints the counters to a string
|
|
std::string PrintCounters() const { return counters_.PrintCounters(); }
|
|
void ResetCounters() { counters_.Reset(); }
|
|
};
|
|
} // namespace ROCKSDB_NAMESPACE
|