|
|
|
// Copyright (c) 2011-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).
|
|
|
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
|
|
//
|
|
|
|
// An Env is an interface used by the rocksdb implementation to access
|
|
|
|
// operating system functionality like the filesystem etc. Callers
|
|
|
|
// may wish to provide a custom Env object when opening a database to
|
|
|
|
// get fine gain control; e.g., to rate limit file system operations.
|
|
|
|
//
|
|
|
|
// All Env implementations are safe for concurrent access from
|
|
|
|
// multiple threads without any external synchronization.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
#include <mutex>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "env/composite_env_wrapper.h"
|
|
|
|
#include "port/port.h"
|
|
|
|
#include "rocksdb/env.h"
|
|
|
|
#include "rocksdb/file_system.h"
|
|
|
|
#include "rocksdb/system_clock.h"
|
|
|
|
#include "util/threadpool_imp.h"
|
|
|
|
|
|
|
|
#undef GetCurrentTime
|
|
|
|
#undef DeleteFile
|
|
|
|
#undef LoadLibrary
|
|
|
|
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
|
|
namespace port {
|
|
|
|
|
|
|
|
// Currently not designed for inheritance but rather a replacement
|
|
|
|
class WinEnvThreads {
|
|
|
|
public:
|
|
|
|
explicit WinEnvThreads(Env* hosted_env);
|
|
|
|
|
|
|
|
~WinEnvThreads();
|
|
|
|
|
|
|
|
WinEnvThreads(const WinEnvThreads&) = delete;
|
|
|
|
WinEnvThreads& operator=(const WinEnvThreads&) = delete;
|
|
|
|
|
|
|
|
void Schedule(void (*function)(void*), void* arg, Env::Priority pri,
|
|
|
|
void* tag, void (*unschedFunction)(void* arg));
|
|
|
|
|
|
|
|
int UnSchedule(void* arg, Env::Priority pri);
|
|
|
|
|
|
|
|
void StartThread(void (*function)(void* arg), void* arg);
|
|
|
|
|
|
|
|
void WaitForJoin();
|
|
|
|
|
|
|
|
unsigned int GetThreadPoolQueueLen(Env::Priority pri) const;
|
|
|
|
|
|
|
|
static uint64_t gettid();
|
|
|
|
|
|
|
|
uint64_t GetThreadID() const;
|
|
|
|
|
|
|
|
// Allow increasing the number of worker threads.
|
|
|
|
void SetBackgroundThreads(int num, Env::Priority pri);
|
|
|
|
int GetBackgroundThreads(Env::Priority pri);
|
|
|
|
|
|
|
|
void IncBackgroundThreadsIfNeeded(int num, Env::Priority pri);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Env* hosted_env_;
|
|
|
|
mutable std::mutex mu_;
|
|
|
|
std::vector<ThreadPoolImpl> thread_pools_;
|
|
|
|
std::vector<Thread> threads_to_join_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class WinClock : public SystemClock {
|
|
|
|
public:
|
|
|
|
WinClock();
|
|
|
|
virtual ~WinClock() {}
|
|
|
|
|
|
|
|
static const char* kClassName() { return "WindowsClock"; }
|
|
|
|
const char* Name() const override { return kClassName(); }
|
|
|
|
const char* NickName() const override { return kDefaultName(); }
|
|
|
|
|
|
|
|
uint64_t NowMicros() override;
|
|
|
|
|
|
|
|
uint64_t NowNanos() override;
|
|
|
|
|
|
|
|
// 0 indicates not supported
|
|
|
|
uint64_t CPUMicros() override { return 0; }
|
|
|
|
void SleepForMicroseconds(int micros) override;
|
|
|
|
|
|
|
|
Status GetCurrentTime(int64_t* unix_time) override;
|
|
|
|
// Converts seconds-since-Jan-01-1970 to a printable string
|
|
|
|
virtual std::string TimeToString(uint64_t time);
|
|
|
|
|
|
|
|
uint64_t GetPerfCounterFrequency() const { return perf_counter_frequency_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
using FnGetSystemTimePreciseAsFileTime = VOID(WINAPI*)(LPFILETIME);
|
|
|
|
|
|
|
|
uint64_t perf_counter_frequency_;
|
|
|
|
uint64_t nano_seconds_per_period_;
|
|
|
|
FnGetSystemTimePreciseAsFileTime GetSystemTimePreciseAsFileTime_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class WinFileSystem : public FileSystem {
|
|
|
|
public:
|
|
|
|
static const std::shared_ptr<WinFileSystem>& Default();
|
|
|
|
WinFileSystem(const std::shared_ptr<SystemClock>& clock);
|
|
|
|
~WinFileSystem() {}
|
|
|
|
static const char* kClassName() { return "WinFS"; }
|
|
|
|
const char* Name() const override { return kClassName(); }
|
|
|
|
const char* NickName() const { return kDefaultName(); }
|
|
|
|
|
|
|
|
static size_t GetSectorSize(const std::string& fname);
|
|
|
|
size_t GetPageSize() const { return page_size_; }
|
|
|
|
size_t GetAllocationGranularity() const { return allocation_granularity_; }
|
|
|
|
|
|
|
|
IOStatus DeleteFile(const std::string& fname, const IOOptions& options,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
|
|
|
|
// Truncate the named file to the specified size.
|
|
|
|
IOStatus Truncate(const std::string& /*fname*/, size_t /*size*/,
|
|
|
|
const IOOptions& /*options*/,
|
|
|
|
IODebugContext* /*dbg*/) override;
|
|
|
|
IOStatus NewSequentialFile(const std::string& fname,
|
|
|
|
const FileOptions& file_opts,
|
|
|
|
std::unique_ptr<FSSequentialFile>* result,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
|
|
|
|
IOStatus NewRandomAccessFile(const std::string& fname,
|
|
|
|
const FileOptions& options,
|
|
|
|
std::unique_ptr<FSRandomAccessFile>* result,
|
|
|
|
IODebugContext* /*dbg*/) override;
|
|
|
|
IOStatus NewWritableFile(const std::string& f, const FileOptions& file_opts,
|
|
|
|
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 NewRandomRWFile(const std::string& fname,
|
|
|
|
const FileOptions& file_opts,
|
|
|
|
std::unique_ptr<FSRandomRWFile>* result,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus NewMemoryMappedFileBuffer(
|
|
|
|
const std::string& fname,
|
|
|
|
std::unique_ptr<MemoryMappedFileBuffer>* result) override;
|
|
|
|
|
|
|
|
IOStatus NewDirectory(const std::string& name, const IOOptions& io_opts,
|
|
|
|
std::unique_ptr<FSDirectory>* result,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus FileExists(const std::string& f, const IOOptions& io_opts,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus GetChildren(const std::string& dir, const IOOptions& io_opts,
|
|
|
|
std::vector<std::string>* r,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus CreateDir(const std::string& dirname, const IOOptions& options,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
|
|
|
|
// Creates directory if missing. Return Ok if it exists, or successful in
|
|
|
|
// Creating.
|
|
|
|
IOStatus CreateDirIfMissing(const std::string& dirname,
|
|
|
|
const IOOptions& options,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
|
|
|
|
// Delete the specified directory.
|
|
|
|
IOStatus DeleteDir(const std::string& dirname, const IOOptions& options,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
// Store the size of fname in *file_size.
|
|
|
|
IOStatus GetFileSize(const std::string& fname, const IOOptions& options,
|
|
|
|
uint64_t* file_size, IODebugContext* dbg) override;
|
|
|
|
// Store the last modification time of fname in *file_mtime.
|
|
|
|
IOStatus GetFileModificationTime(const std::string& fname,
|
|
|
|
const IOOptions& options,
|
|
|
|
uint64_t* file_mtime,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
// Rename file src to target.
|
|
|
|
IOStatus RenameFile(const std::string& src, const std::string& target,
|
|
|
|
const IOOptions& options, IODebugContext* dbg) override;
|
|
|
|
|
|
|
|
// Hard Link file src to target.
|
|
|
|
IOStatus LinkFile(const std::string& /*src*/, const std::string& /*target*/,
|
|
|
|
const IOOptions& /*options*/,
|
|
|
|
IODebugContext* /*dbg*/) override;
|
|
|
|
IOStatus NumFileLinks(const std::string& /*fname*/,
|
|
|
|
const IOOptions& /*options*/, uint64_t* /*count*/,
|
|
|
|
IODebugContext* /*dbg*/) override;
|
|
|
|
IOStatus AreFilesSame(const std::string& /*first*/,
|
|
|
|
const std::string& /*second*/,
|
|
|
|
const IOOptions& /*options*/, bool* /*res*/,
|
|
|
|
IODebugContext* /*dbg*/) override;
|
|
|
|
IOStatus LockFile(const std::string& fname, const IOOptions& options,
|
|
|
|
FileLock** lock, IODebugContext* dbg) override;
|
|
|
|
IOStatus UnlockFile(FileLock* lock, const IOOptions& options,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus GetTestDirectory(const IOOptions& options, std::string* path,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
|
|
|
|
// Create and returns a default logger (an instance of EnvLogger) for storing
|
|
|
|
// informational messages. Derived classes can overide to provide custom
|
|
|
|
// logger.
|
|
|
|
IOStatus NewLogger(const std::string& fname, const IOOptions& io_opts,
|
|
|
|
std::shared_ptr<Logger>* result,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
// Get full directory name for this db.
|
|
|
|
IOStatus GetAbsolutePath(const std::string& db_path, const IOOptions& options,
|
|
|
|
std::string* output_path,
|
|
|
|
IODebugContext* dbg) override;
|
|
|
|
IOStatus IsDirectory(const std::string& /*path*/, const IOOptions& options,
|
|
|
|
bool* is_dir, IODebugContext* /*dgb*/) override;
|
|
|
|
// This seems to clash with a macro on Windows, so #undef it here
|
|
|
|
#undef GetFreeSpace
|
|
|
|
IOStatus GetFreeSpace(const std::string& /*path*/,
|
|
|
|
const IOOptions& /*options*/, uint64_t* /*diskfree*/,
|
|
|
|
IODebugContext* /*dbg*/) override;
|
|
|
|
FileOptions OptimizeForLogWrite(const FileOptions& file_options,
|
|
|
|
const DBOptions& db_options) const override;
|
|
|
|
FileOptions OptimizeForManifestRead(
|
|
|
|
const FileOptions& file_options) const override;
|
|
|
|
FileOptions OptimizeForManifestWrite(
|
|
|
|
const FileOptions& file_options) const override;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
static uint64_t FileTimeToUnixTime(const FILETIME& ftTime);
|
|
|
|
// Returns true iff the named directory exists and is a directory.
|
|
|
|
|
|
|
|
virtual bool DirExists(const std::string& dname);
|
|
|
|
// Helper for NewWritable and ReopenWritableFile
|
|
|
|
virtual IOStatus OpenWritableFile(const std::string& fname,
|
|
|
|
const FileOptions& options,
|
|
|
|
std::unique_ptr<FSWritableFile>* result,
|
|
|
|
bool reopen);
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::shared_ptr<SystemClock> clock_;
|
|
|
|
size_t page_size_;
|
|
|
|
size_t allocation_granularity_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Designed for inheritance so can be re-used
|
|
|
|
// but certain parts replaced
|
|
|
|
class WinEnvIO {
|
|
|
|
public:
|
|
|
|
explicit WinEnvIO(Env* hosted_env);
|
|
|
|
|
|
|
|
virtual ~WinEnvIO();
|
|
|
|
|
|
|
|
virtual Status GetHostName(char* name, uint64_t len);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Env* hosted_env_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class WinEnv : public CompositeEnv {
|
|
|
|
public:
|
|
|
|
WinEnv();
|
|
|
|
|
|
|
|
~WinEnv();
|
|
|
|
|
|
|
|
Status GetHostName(char* name, uint64_t len) override;
|
|
|
|
|
|
|
|
Status GetThreadList(std::vector<ThreadStatus>* thread_list) override;
|
|
|
|
|
|
|
|
void Schedule(void (*function)(void*), void* arg, Env::Priority pri,
|
|
|
|
void* tag, void (*unschedFunction)(void* arg)) override;
|
|
|
|
|
|
|
|
int UnSchedule(void* arg, Env::Priority pri) override;
|
|
|
|
|
|
|
|
void StartThread(void (*function)(void* arg), void* arg) override;
|
|
|
|
|
|
|
|
void WaitForJoin() override;
|
|
|
|
|
|
|
|
unsigned int GetThreadPoolQueueLen(Env::Priority pri) const override;
|
|
|
|
|
|
|
|
uint64_t GetThreadID() const override;
|
|
|
|
|
|
|
|
// Allow increasing the number of worker threads.
|
|
|
|
void SetBackgroundThreads(int num, Env::Priority pri) override;
|
|
|
|
int GetBackgroundThreads(Env::Priority pri) override;
|
|
|
|
|
|
|
|
void IncBackgroundThreadsIfNeeded(int num, Env::Priority pri) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
WinEnvIO winenv_io_;
|
|
|
|
WinEnvThreads winenv_threads_;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace port
|
|
|
|
} // namespace ROCKSDB_NAMESPACE
|