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