1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 // Use of this source code is governed by a BSD-style license that can be 7 // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 // 9 // An Env is an interface used by the rocksdb implementation to access 10 // operating system functionality like the filesystem etc. Callers 11 // may wish to provide a custom Env object when opening a database to 12 // get fine gain control; e.g., to rate limit file system operations. 13 // 14 // All Env implementations are safe for concurrent access from 15 // multiple threads without any external synchronization. 16 17 #pragma once 18 19 #include "port/win/win_thread.h" 20 #include <rocksdb/env.h> 21 #include "util/threadpool_imp.h" 22 23 #include <stdint.h> 24 #include <windows.h> 25 26 #include <mutex> 27 #include <vector> 28 #include <string> 29 30 31 #undef GetCurrentTime 32 #undef DeleteFile 33 #undef GetTickCount 34 35 namespace rocksdb { 36 namespace port { 37 38 // Currently not designed for inheritance but rather a replacement 39 class WinEnvThreads { 40 public: 41 42 explicit WinEnvThreads(Env* hosted_env); 43 44 ~WinEnvThreads(); 45 46 WinEnvThreads(const WinEnvThreads&) = delete; 47 WinEnvThreads& operator=(const WinEnvThreads&) = delete; 48 49 void Schedule(void(*function)(void*), void* arg, Env::Priority pri, 50 void* tag, void(*unschedFunction)(void* arg)); 51 52 int UnSchedule(void* arg, Env::Priority pri); 53 54 void StartThread(void(*function)(void* arg), void* arg); 55 56 void WaitForJoin(); 57 58 unsigned int GetThreadPoolQueueLen(Env::Priority pri) const; 59 60 static uint64_t gettid(); 61 62 uint64_t GetThreadID() const; 63 64 void SleepForMicroseconds(int micros); 65 66 // Allow increasing the number of worker threads. 67 void SetBackgroundThreads(int num, Env::Priority pri); 68 int GetBackgroundThreads(Env::Priority pri); 69 70 void IncBackgroundThreadsIfNeeded(int num, Env::Priority pri); 71 72 private: 73 74 Env* hosted_env_; 75 mutable std::mutex mu_; 76 std::vector<ThreadPoolImpl> thread_pools_; 77 std::vector<WindowsThread> threads_to_join_; 78 79 }; 80 81 // Designed for inheritance so can be re-used 82 // but certain parts replaced 83 class WinEnvIO { 84 public: 85 explicit WinEnvIO(Env* hosted_env); 86 87 virtual ~WinEnvIO(); 88 89 virtual Status DeleteFile(const std::string& fname); 90 91 Status Truncate(const std::string& fname, size_t size); 92 93 virtual Status GetCurrentTime(int64_t* unix_time); 94 95 virtual Status NewSequentialFile(const std::string& fname, 96 std::unique_ptr<SequentialFile>* result, 97 const EnvOptions& options); 98 99 // Helper for NewWritable and ReopenWritableFile 100 virtual Status OpenWritableFile(const std::string& fname, 101 std::unique_ptr<WritableFile>* result, 102 const EnvOptions& options, 103 bool reopen); 104 105 virtual Status NewRandomAccessFile(const std::string& fname, 106 std::unique_ptr<RandomAccessFile>* result, 107 const EnvOptions& options); 108 109 // The returned file will only be accessed by one thread at a time. 110 virtual Status NewRandomRWFile(const std::string& fname, 111 std::unique_ptr<RandomRWFile>* result, 112 const EnvOptions& options); 113 114 virtual Status NewMemoryMappedFileBuffer( 115 const std::string& fname, 116 std::unique_ptr<MemoryMappedFileBuffer>* result); 117 118 virtual Status NewDirectory(const std::string& name, 119 std::unique_ptr<Directory>* result); 120 121 virtual Status FileExists(const std::string& fname); 122 123 virtual Status GetChildren(const std::string& dir, 124 std::vector<std::string>* result); 125 126 virtual Status CreateDir(const std::string& name); 127 128 virtual Status CreateDirIfMissing(const std::string& name); 129 130 virtual Status DeleteDir(const std::string& name); 131 132 virtual Status GetFileSize(const std::string& fname, uint64_t* size); 133 134 static uint64_t FileTimeToUnixTime(const FILETIME& ftTime); 135 136 virtual Status GetFileModificationTime(const std::string& fname, 137 uint64_t* file_mtime); 138 139 virtual Status RenameFile(const std::string& src, const std::string& target); 140 141 virtual Status LinkFile(const std::string& src, const std::string& target); 142 143 virtual Status NumFileLinks(const std::string& /*fname*/, 144 uint64_t* /*count*/); 145 146 virtual Status AreFilesSame(const std::string& first, 147 const std::string& second, bool* res); 148 149 virtual Status LockFile(const std::string& lockFname, FileLock** lock); 150 151 virtual Status UnlockFile(FileLock* lock); 152 153 virtual Status GetTestDirectory(std::string* result); 154 155 virtual Status NewLogger(const std::string& fname, 156 std::shared_ptr<Logger>* result); 157 158 virtual uint64_t NowMicros(); 159 160 virtual uint64_t NowNanos(); 161 162 virtual Status GetHostName(char* name, uint64_t len); 163 164 virtual Status GetAbsolutePath(const std::string& db_path, 165 std::string* output_path); 166 167 // This seems to clash with a macro on Windows, so #undef it here 168 #undef GetFreeSpace 169 170 // Get the amount of free disk space 171 virtual Status GetFreeSpace(const std::string& path, uint64_t* diskfree); 172 173 virtual std::string TimeToString(uint64_t secondsSince1970); 174 175 virtual EnvOptions OptimizeForLogWrite(const EnvOptions& env_options, 176 const DBOptions& db_options) const; 177 178 virtual EnvOptions OptimizeForManifestWrite( 179 const EnvOptions& env_options) const; 180 181 virtual EnvOptions OptimizeForManifestRead( 182 const EnvOptions& env_options) const; 183 GetPageSize()184 size_t GetPageSize() const { return page_size_; } 185 GetAllocationGranularity()186 size_t GetAllocationGranularity() const { return allocation_granularity_; } 187 GetPerfCounterFrequency()188 uint64_t GetPerfCounterFrequency() const { return perf_counter_frequency_; } 189 190 static size_t GetSectorSize(const std::string& fname); 191 192 private: 193 // Returns true iff the named directory exists and is a directory. 194 virtual bool DirExists(const std::string& dname); 195 196 typedef VOID(WINAPI * FnGetSystemTimePreciseAsFileTime)(LPFILETIME); 197 198 Env* hosted_env_; 199 size_t page_size_; 200 size_t allocation_granularity_; 201 uint64_t perf_counter_frequency_; 202 uint64_t nano_seconds_per_period_; 203 FnGetSystemTimePreciseAsFileTime GetSystemTimePreciseAsFileTime_; 204 }; 205 206 class WinEnv : public Env { 207 public: 208 WinEnv(); 209 210 ~WinEnv(); 211 212 Status DeleteFile(const std::string& fname) override; 213 214 Status Truncate(const std::string& fname, size_t size) override; 215 216 Status GetCurrentTime(int64_t* unix_time) override; 217 218 Status NewSequentialFile(const std::string& fname, 219 std::unique_ptr<SequentialFile>* result, 220 const EnvOptions& options) override; 221 222 Status NewRandomAccessFile(const std::string& fname, 223 std::unique_ptr<RandomAccessFile>* result, 224 const EnvOptions& options) override; 225 226 Status NewWritableFile(const std::string& fname, 227 std::unique_ptr<WritableFile>* result, 228 const EnvOptions& options) override; 229 230 // Create an object that writes to a new file with the specified 231 // name. Deletes any existing file with the same name and creates a 232 // new file. On success, stores a pointer to the new file in 233 // *result and returns OK. On failure stores nullptr in *result and 234 // returns non-OK. 235 // 236 // The returned file will only be accessed by one thread at a time. 237 Status ReopenWritableFile(const std::string& fname, 238 std::unique_ptr<WritableFile>* result, 239 const EnvOptions& options) override; 240 241 // The returned file will only be accessed by one thread at a time. 242 Status NewRandomRWFile(const std::string& fname, 243 std::unique_ptr<RandomRWFile>* result, 244 const EnvOptions& options) override; 245 246 Status NewMemoryMappedFileBuffer( 247 const std::string& fname, 248 std::unique_ptr<MemoryMappedFileBuffer>* result) override; 249 250 Status NewDirectory(const std::string& name, 251 std::unique_ptr<Directory>* result) override; 252 253 Status FileExists(const std::string& fname) override; 254 255 Status GetChildren(const std::string& dir, 256 std::vector<std::string>* result) override; 257 258 Status CreateDir(const std::string& name) override; 259 260 Status CreateDirIfMissing(const std::string& name) override; 261 262 Status DeleteDir(const std::string& name) override; 263 264 Status GetFileSize(const std::string& fname, 265 uint64_t* size) override; 266 267 Status GetFileModificationTime(const std::string& fname, 268 uint64_t* file_mtime) override; 269 270 Status RenameFile(const std::string& src, 271 const std::string& target) override; 272 273 Status LinkFile(const std::string& src, 274 const std::string& target) override; 275 276 Status NumFileLinks(const std::string& fname, uint64_t* count) override; 277 278 Status AreFilesSame(const std::string& first, 279 const std::string& second, bool* res) override; 280 281 Status LockFile(const std::string& lockFname, FileLock** lock) override; 282 283 Status UnlockFile(FileLock* lock) override; 284 285 Status GetTestDirectory(std::string* result) override; 286 287 Status NewLogger(const std::string& fname, 288 std::shared_ptr<Logger>* result) override; 289 290 uint64_t NowMicros() override; 291 292 uint64_t NowNanos() override; 293 294 Status GetHostName(char* name, uint64_t len) override; 295 296 Status GetAbsolutePath(const std::string& db_path, 297 std::string* output_path) override; 298 299 std::string TimeToString(uint64_t secondsSince1970) override; 300 301 Status GetThreadList(std::vector<ThreadStatus>* thread_list) override; 302 303 void Schedule(void(*function)(void*), void* arg, Env::Priority pri, 304 void* tag, void(*unschedFunction)(void* arg)) override; 305 306 int UnSchedule(void* arg, Env::Priority pri) override; 307 308 void StartThread(void(*function)(void* arg), void* arg) override; 309 310 void WaitForJoin(); 311 312 unsigned int GetThreadPoolQueueLen(Env::Priority pri) const override; 313 314 uint64_t GetThreadID() const override; 315 316 // This seems to clash with a macro on Windows, so #undef it here 317 #undef GetFreeSpace 318 319 // Get the amount of free disk space 320 Status GetFreeSpace(const std::string& path, uint64_t* diskfree) override; 321 322 void SleepForMicroseconds(int micros) override; 323 324 // Allow increasing the number of worker threads. 325 void SetBackgroundThreads(int num, Env::Priority pri) override; 326 int GetBackgroundThreads(Env::Priority pri) override; 327 328 void IncBackgroundThreadsIfNeeded(int num, Env::Priority pri) override; 329 330 EnvOptions OptimizeForManifestRead( 331 const EnvOptions& env_options) const override; 332 333 EnvOptions OptimizeForLogWrite(const EnvOptions& env_options, 334 const DBOptions& db_options) const override; 335 336 EnvOptions OptimizeForManifestWrite( 337 const EnvOptions& env_options) const override; 338 339 340 private: 341 342 WinEnvIO winenv_io_; 343 WinEnvThreads winenv_threads_; 344 }; 345 346 } // namespace port 347 } // namespace rocksdb 348