YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/rocksdb/env.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
// This source code is licensed under the BSD-style license found in the
3
// LICENSE file in the root directory of this source tree. An additional grant
4
// of patent rights can be found in the PATENTS file in the same 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
// The following only applies to changes made to this file as part of YugaByte development.
10
//
11
// Portions Copyright (c) YugaByte, Inc.
12
//
13
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
14
// in compliance with the License.  You may obtain a copy of the License at
15
//
16
// http://www.apache.org/licenses/LICENSE-2.0
17
//
18
// Unless required by applicable law or agreed to in writing, software distributed under the License
19
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
20
// or implied.  See the License for the specific language governing permissions and limitations
21
// under the License.
22
//
23
// An Env is an interface used by the rocksdb implementation to access
24
// operating system functionality like the filesystem etc.  Callers
25
// may wish to provide a custom Env object when opening a database to
26
// get fine gain control; e.g., to rate limit file system operations.
27
//
28
// All Env implementations are safe for concurrent access from
29
// multiple threads without any external synchronization.
30
31
#ifndef YB_ROCKSDB_ENV_H
32
#define YB_ROCKSDB_ENV_H
33
34
#include <stdint.h>
35
36
#include <limits>
37
#include <memory>
38
#include <string>
39
#include <vector>
40
41
#include "yb/util/status_fwd.h"
42
#include "yb/util/file_system.h"
43
#include "yb/util/slice.h"
44
45
#ifdef _WIN32
46
// Windows API macro interference
47
#undef DeleteFile
48
#undef GetCurrentTime
49
#endif
50
51
5.42M
#define RLOG(...) LogWithContext(__FILE__, __LINE__, ##
__VA_ARGS__103k
)
52
1.13M
#define RHEADER(...) HeaderWithContext(__FILE__, __LINE__, ##
__VA_ARGS__141k
)
53
97.5k
#define RDEBUG(...) DebugWithContext(__FILE__, __LINE__, ##
__VA_ARGS__304
)
54
2.79k
#define RINFO(...) InfoWithContext(__FILE__, __LINE__, ##__VA_ARGS__)
55
454
#define RWARN(...) WarnWithContext(__FILE__, __LINE__, ##__VA_ARGS__)
56
0
#define RERROR(...) ErrorWithContext(__FILE__, __LINE__, ##__VA_ARGS__)
57
#define RFATAL(...) FatalWithContext(__FILE__, __LINE__, ##__VA_ARGS__)
58
59
#ifdef NDEBUG
60
// TODO: it should also fail in release under tests: https://yugabyte.atlassian.net/browse/ENG-1453.
61
// Idea is to fail in both release and debug builds under tests, but don't fail in production.
62
// This is useful when some secondary functionality is broken and we don't want to fail the whole
63
// server, we can just turn that functionality off. But under tests and in debug mode we need to
64
// fail to be able to catch bugs quickly. One of examples of such functionality is bloom filters.
65
#define FAIL_IF_NOT_PRODUCTION() do {} while (false)
66
#else
67
281
#define FAIL_IF_NOT_PRODUCTION() assert(false)
68
#endif
69
70
71
namespace rocksdb {
72
73
class FileLock;
74
class Logger;
75
class WritableFile;
76
class Directory;
77
struct DBOptions;
78
class RateLimiter;
79
80
typedef yb::SequentialFile SequentialFile;
81
typedef yb::RandomAccessFile RandomAccessFile;
82
83
using std::unique_ptr;
84
using std::shared_ptr;
85
86
using Status = yb::Status;
87
88
// Options while opening a file to read/write
89
struct EnvOptions : public yb::FileSystemOptions {
90
91
  // construct with default Options
92
  EnvOptions();
93
94
  // construct from Options
95
  explicit EnvOptions(const DBOptions& options);
96
97
  // If true, then use mmap to write data
98
  bool use_mmap_writes = true;
99
100
  // If false, fallocate() calls are bypassed
101
  bool allow_fallocate = true;
102
103
  // If true, set the FD_CLOEXEC on open fd.
104
  bool set_fd_cloexec = true;
105
106
  // Allows OS to incrementally sync files to disk while they are being
107
  // written, in the background. Issue one request for every bytes_per_sync
108
  // written. 0 turns it off.
109
  // Default: 0
110
  uint64_t bytes_per_sync = 0;
111
112
  // If true, we will preallocate the file with FALLOC_FL_KEEP_SIZE flag, which
113
  // means that file size won't change as part of preallocation.
114
  // If false, preallocation will also change the file size. This option will
115
  // improve the performance in workloads where you sync the data on every
116
  // write. By default, we set it to true for MANIFEST writes and false for
117
  // WAL writes
118
  bool fallocate_with_keep_size = true;
119
120
  // See DBOPtions doc
121
  size_t compaction_readahead_size;
122
123
  // See DBOPtions doc
124
  size_t random_access_max_buffer_size;
125
126
  // See DBOptions doc
127
  size_t writable_file_max_buffer_size = 1024 * 1024;
128
129
  // If not nullptr, write rate limiting is enabled for flush and compaction
130
  RateLimiter* rate_limiter = nullptr;
131
};
132
133
// RocksDBFileFactory is the implementation of all NewxxxFile Env methods as well as any methods
134
// that are used to create new files. This class is created to allow easy definition of how we
135
// create new files without inheriting the whole env.
136
class RocksDBFileFactory {
137
 public:
138
1.57k
  virtual ~RocksDBFileFactory() {}
139
  virtual CHECKED_STATUS NewSequentialFile(const std::string& f, unique_ptr<SequentialFile>* r,
140
                                           const EnvOptions& options) = 0;
141
  virtual CHECKED_STATUS NewRandomAccessFile(const std::string& f,
142
                                             unique_ptr<RandomAccessFile>* r,
143
                                             const EnvOptions& options) = 0;
144
  virtual CHECKED_STATUS NewWritableFile(const std::string& f, unique_ptr<WritableFile>* r,
145
                                         const EnvOptions& options) = 0;
146
  virtual CHECKED_STATUS ReuseWritableFile(const std::string& fname,
147
                                   const std::string& old_fname,
148
                                   unique_ptr<WritableFile>* result,
149
                                   const EnvOptions& options) = 0;
150
  virtual CHECKED_STATUS GetFileSize(const std::string& fname, uint64_t* size) = 0;
151
152
  // Does the file factory produce plaintext files.
153
  virtual bool IsPlainText() const = 0;
154
};
155
156
class RocksDBFileFactoryWrapper : public rocksdb::RocksDBFileFactory {
157
 public:
158
9.28k
  explicit RocksDBFileFactoryWrapper(rocksdb::RocksDBFileFactory* t) : target_(t) {}
159
160
165
  virtual ~RocksDBFileFactoryWrapper() {}
161
162
  // The following text is boilerplate that forwards all methods to target()
163
  Status NewSequentialFile(const std::string& f, unique_ptr<SequentialFile>* r,
164
                           const rocksdb::EnvOptions& options) override;
165
  Status NewRandomAccessFile(const std::string& f,
166
                             unique_ptr <rocksdb::RandomAccessFile>* r,
167
                             const EnvOptions& options) override;
168
  Status NewWritableFile(const std::string& f, unique_ptr <rocksdb::WritableFile>* r,
169
                         const EnvOptions& options) override;
170
171
  Status ReuseWritableFile(const std::string& fname,
172
                           const std::string& old_fname,
173
                           unique_ptr<WritableFile>* result,
174
                           const EnvOptions& options) override;
175
176
  Status GetFileSize(const std::string& fname, uint64_t* size) override;
177
178
0
  bool IsPlainText() const override {
179
0
    return target_->IsPlainText();
180
0
  }
181
182
 private:
183
  rocksdb::RocksDBFileFactory* target_;
184
};
185
186
class Env {
187
 public:
188
  struct FileAttributes {
189
    // File name
190
    std::string name;
191
192
    // Size of file in bytes
193
    uint64_t size_bytes;
194
  };
195
196
26.9k
  Env() {}
197
198
  virtual ~Env();
199
200
  // Return a default environment suitable for the current operating
201
  // system.  Sophisticated users may wish to provide their own Env
202
  // implementation instead of relying on this default environment.
203
  //
204
  // The result of Default() belongs to rocksdb and must never be deleted.
205
  static Env* Default();
206
207
  static RocksDBFileFactory* DefaultFileFactory();
208
209
  static std::unique_ptr<Env> NewRocksDBDefaultEnv(
210
      std::unique_ptr<RocksDBFileFactory> file_factory);
211
212
  // Create a brand new sequentially-readable file with the specified name.
213
  // On success, stores a pointer to the new file in *result and returns OK.
214
  // On failure stores nullptr in *result and returns non-OK.  If the file does
215
  // not exist, returns a non-OK status.
216
  //
217
  // The returned file will only be accessed by one thread at a time.
218
  virtual Status NewSequentialFile(const std::string& fname,
219
                                   std::unique_ptr<SequentialFile>* result,
220
                                   const EnvOptions& options)
221
                                   = 0;
222
223
  // Create a brand new random access read-only file with the
224
  // specified name.  On success, stores a pointer to the new file in
225
  // *result and returns OK.  On failure stores nullptr in *result and
226
  // returns non-OK.  If the file does not exist, returns a non-OK
227
  // status.
228
  //
229
  // The returned file may be concurrently accessed by multiple threads.
230
  virtual Status NewRandomAccessFile(const std::string& fname,
231
                                     std::unique_ptr<RandomAccessFile>* result,
232
                                     const EnvOptions& options)
233
                                     = 0;
234
235
  // Create an object that writes to a new file with the specified
236
  // name.  Deletes any existing file with the same name and creates a
237
  // new file.  On success, stores a pointer to the new file in
238
  // *result and returns OK.  On failure stores nullptr in *result and
239
  // returns non-OK.
240
  //
241
  // The returned file will only be accessed by one thread at a time.
242
  virtual Status NewWritableFile(const std::string& fname,
243
                                 unique_ptr<WritableFile>* result,
244
                                 const EnvOptions& options) = 0;
245
246
  // Reuse an existing file by renaming it and opening it as writable.
247
  virtual Status ReuseWritableFile(const std::string& fname,
248
                                   const std::string& old_fname,
249
                                   unique_ptr<WritableFile>* result,
250
                                   const EnvOptions& options);
251
252
  // Create an object that represents a directory. Will fail if directory
253
  // doesn't exist. If the directory exists, it will open the directory
254
  // and create a new Directory object.
255
  //
256
  // On success, stores a pointer to the new Directory in
257
  // *result and returns OK. On failure stores nullptr in *result and
258
  // returns non-OK.
259
  virtual Status NewDirectory(const std::string& name,
260
                              unique_ptr<Directory>* result) = 0;
261
262
  // Returns OK if the named file exists.
263
  //         NotFound if the named file does not exist,
264
  //                  the calling process does not have permission to determine
265
  //                  whether this file exists, or if the path is invalid.
266
  //         IOError if an IO Error was encountered
267
  virtual Status FileExists(const std::string& fname) = 0;
268
269
0
  virtual bool DirExists(const std::string& fname) { return false; }
270
271
  // Store in *result the names of the children of the specified directory.
272
  // The names are relative to "dir".
273
  // Original contents of *results are dropped.
274
  virtual Status GetChildren(const std::string& dir,
275
                             std::vector<std::string>* result) = 0;
276
277
  void GetChildrenWarnNotOk(const std::string& dir,
278
                            std::vector<std::string>* result);
279
280
  // Store in *result the attributes of the children of the specified directory.
281
  // In case the implementation lists the directory prior to iterating the files
282
  // and files are concurrently deleted, the deleted files will be omitted from
283
  // result.
284
  // The name attributes are relative to "dir".
285
  // Original contents of *results are dropped.
286
  virtual Status GetChildrenFileAttributes(const std::string& dir,
287
                                           std::vector<FileAttributes>* result);
288
289
  // Delete the named file.
290
  virtual Status DeleteFile(const std::string& fname) = 0;
291
292
  // Delete file, print warning on failure.
293
  void CleanupFile(const std::string& fname);
294
295
  // Create the specified directory. Returns error if directory exists.
296
  virtual Status CreateDir(const std::string& dirname) = 0;
297
298
  // Creates directory if missing. Return Ok if it exists, or successful in
299
  // Creating.
300
  virtual Status CreateDirIfMissing(const std::string& dirname) = 0;
301
302
  // Delete the specified directory.
303
  virtual Status DeleteDir(const std::string& dirname) = 0;
304
305
  // Store the size of fname in *file_size.
306
  virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) = 0;
307
308
  yb::Result<uint64_t> GetFileSize(const std::string& fname);
309
310
  // Store the last modification time of fname in *file_mtime.
311
  virtual Status GetFileModificationTime(const std::string& fname,
312
                                         uint64_t* file_mtime) = 0;
313
  // Rename file src to target.
314
  virtual Status RenameFile(const std::string& src,
315
                            const std::string& target) = 0;
316
317
  // Hard Link file src to target.
318
  virtual Status LinkFile(const std::string& src, const std::string& target);
319
320
  // Lock the specified file.  Used to prevent concurrent access to
321
  // the same db by multiple processes.  On failure, stores nullptr in
322
  // *lock and returns non-OK.
323
  //
324
  // On success, stores a pointer to the object that represents the
325
  // acquired lock in *lock and returns OK.  The caller should call
326
  // UnlockFile(*lock) to release the lock.  If the process exits,
327
  // the lock will be automatically released.
328
  //
329
  // If somebody else already holds the lock, finishes immediately
330
  // with a failure.  I.e., this call does not wait for existing locks
331
  // to go away.
332
  //
333
  // May create the named file if it does not already exist.
334
  virtual Status LockFile(const std::string& fname, FileLock** lock) = 0;
335
336
  // Release the lock acquired by a previous successful call to LockFile.
337
  // REQUIRES: lock was returned by a successful LockFile() call
338
  // REQUIRES: lock has not already been unlocked.
339
  virtual Status UnlockFile(FileLock* lock) = 0;
340
341
  // Priority for scheduling job in thread pool
342
  enum Priority { LOW, HIGH, TOTAL };
343
344
  // Priority for requesting bytes in rate limiter scheduler
345
  enum IOPriority {
346
    IO_LOW = 0,
347
    IO_HIGH = 1,
348
    IO_TOTAL = 2
349
  };
350
351
  // Arrange to run "(*function)(arg)" once in a background thread, in
352
  // the thread pool specified by pri. By default, jobs go to the 'LOW'
353
  // priority thread pool.
354
355
  // "function" may run in an unspecified thread.  Multiple functions
356
  // added to the same Env may run concurrently in different threads.
357
  // I.e., the caller may not assume that background work items are
358
  // serialized.
359
  // When the UnSchedule function is called, the unschedFunction
360
  // registered at the time of Schedule is invoked with arg as a parameter.
361
  virtual void Schedule(void (*function)(void* arg), void* arg,
362
                        Priority pri = LOW, void* tag = nullptr,
363
                        void (*unschedFunction)(void* arg) = 0) = 0;
364
365
  // Arrange to remove jobs for given arg from the queue_ if they are not
366
  // already scheduled. Caller is expected to have exclusive lock on arg.
367
0
  virtual int UnSchedule(void* arg, Priority pri) { return 0; }
368
369
  // Start a new thread, invoking "function(arg)" within the new thread.
370
  // When "function(arg)" returns, the thread will be destroyed.
371
  virtual void StartThread(void (*function)(void* arg), void* arg) = 0;
372
373
  // Wait for all threads started by StartThread to terminate.
374
0
  virtual void WaitForJoin() {}
375
376
  // Get thread pool queue length for specific thrad pool.
377
0
  virtual unsigned int GetThreadPoolQueueLen(Priority pri = LOW) const {
378
0
    return 0;
379
0
  }
380
381
  // *path is set to a temporary directory that can be used for testing. It may
382
  // or many not have just been created. The directory may or may not differ
383
  // between runs of the same process, but subsequent calls will return the
384
  // same directory.
385
  virtual Status GetTestDirectory(std::string* path) = 0;
386
387
  // Create and return a log file for storing informational messages.
388
  virtual Status NewLogger(const std::string& fname,
389
                           shared_ptr<Logger>* result) = 0;
390
391
  // Returns the number of micro-seconds since some fixed point in time. Only
392
  // useful for computing deltas of time.
393
  // However, it is often used as system time such as in GenericRateLimiter
394
  // and other places so a port needs to return system time in order to work.
395
  virtual uint64_t NowMicros() = 0;
396
397
  // Returns the number of nano-seconds since some fixed point in time. Only
398
  // useful for computing deltas of time in one run.
399
  // Default implementation simply relies on NowMicros
400
86
  virtual uint64_t NowNanos() {
401
86
    return NowMicros() * 1000;
402
86
  }
403
404
  // Sleep/delay the thread for the perscribed number of micro-seconds.
405
  virtual void SleepForMicroseconds(int micros) = 0;
406
407
  // Get the current host name.
408
  virtual Status GetHostName(char* name, uint64_t len) = 0;
409
410
  // Get the number of seconds since the Epoch, 1970-01-01 00:00:00 (UTC).
411
  virtual Status GetCurrentTime(int64_t* unix_time) = 0;
412
413
  // Get full directory name for this db.
414
  virtual Status GetAbsolutePath(const std::string& db_path,
415
      std::string* output_path) = 0;
416
417
  // The number of background worker threads of a specific thread pool
418
  // for this environment. 'LOW' is the default pool.
419
  // default number: 1
420
  virtual void SetBackgroundThreads(int number, Priority pri = LOW) = 0;
421
422
  // Enlarge number of background worker threads of a specific thread pool
423
  // for this environment if it is smaller than specified. 'LOW' is the default
424
  // pool.
425
  virtual void IncBackgroundThreadsIfNeeded(int number, Priority pri) = 0;
426
427
  // Lower IO priority for threads from the specified pool.
428
0
  virtual void LowerThreadPoolIOPriority(Priority pool = LOW) {}
429
430
  // Converts seconds-since-Jan-01-1970 to a printable string
431
  virtual std::string TimeToString(uint64_t time) = 0;
432
433
  // Generates a unique id that can be used to identify a db
434
  virtual std::string GenerateUniqueId();
435
436
  // OptimizeForLogWrite will create a new EnvOptions object that is a copy of
437
  // the EnvOptions in the parameters, but is optimized for writing log files.
438
  // Default implementation returns the copy of the same object.
439
  virtual EnvOptions OptimizeForLogWrite(const EnvOptions& env_options,
440
                                         const DBOptions& db_options) const;
441
  // OptimizeForManifestWrite will create a new EnvOptions object that is a copy
442
  // of the EnvOptions in the parameters, but is optimized for writing manifest
443
  // files. Default implementation returns the copy of the same object.
444
  virtual EnvOptions OptimizeForManifestWrite(const EnvOptions& env_options)
445
      const;
446
447
0
  virtual bool IsPlainText() const {
448
0
    return true;
449
0
  }
450
451
  // Returns the ID of the current thread.
452
  virtual uint64_t GetThreadID() const;
453
454
 private:
455
  // No copying allowed
456
  Env(const Env&);
457
  void operator=(const Env&);
458
};
459
460
// A file abstraction for sequential writing.  The implementation
461
// must provide buffering since callers may append small fragments
462
// at a time to the file.
463
class WritableFile : public yb::FileWithUniqueId {
464
 public:
465
  WritableFile()
466
    : last_preallocated_block_(0),
467
      preallocation_block_size_(0),
468
3.86M
      io_priority_(Env::IO_TOTAL) {
469
3.86M
  }
470
  virtual ~WritableFile();
471
472
  // Indicates if the class makes use of unbuffered I/O
473
1.31M
  virtual bool UseOSBuffer() const {
474
1.31M
    return true;
475
1.31M
  }
476
477
  const size_t c_DefaultPageSize = 4 * 1024;
478
479
  // This is needed when you want to allocate
480
  // AlignedBuffer for use with file I/O classes
481
  // Used for unbuffered file I/O when UseOSBuffer() returns false
482
1.31M
  virtual size_t GetRequiredBufferAlignment() const {
483
1.31M
    return c_DefaultPageSize;
484
1.31M
  }
485
486
  virtual Status Append(const Slice& data) = 0;
487
488
  // Positioned write for unbuffered access default forward
489
  // to simple append as most of the tests are buffered by default
490
  virtual Status PositionedAppend(const Slice& /* data */, uint64_t /* offset */);
491
492
  // Truncate is necessary to trim the file to the correct size
493
  // before closing. It is not always possible to keep track of the file
494
  // size due to whole pages writes. The behavior is undefined if called
495
  // with other writes to follow.
496
  virtual Status Truncate(uint64_t size);
497
  virtual Status Close() = 0;
498
  virtual Status Flush() = 0;
499
  virtual Status Sync() = 0; // sync data
500
501
  /*
502
   * Sync data and/or metadata as well.
503
   * By default, sync only data.
504
   * Override this method for environments where we need to sync
505
   * metadata as well.
506
   */
507
  virtual Status Fsync();
508
509
  // true if Sync() and Fsync() are safe to call concurrently with Append()
510
  // and Flush().
511
0
  virtual bool IsSyncThreadSafe() const {
512
0
    return false;
513
0
  }
514
515
  // Indicates the upper layers if the current WritableFile implementation
516
  // uses direct IO.
517
1.31M
  virtual bool UseDirectIO() const { return false; }
518
519
  /*
520
   * Change the priority in rate limiter if rate limiting is enabled.
521
   * If rate limiting is not enabled, this call has no effect.
522
   */
523
106k
  virtual void SetIOPriority(Env::IOPriority pri) {
524
106k
    io_priority_ = pri;
525
106k
  }
526
527
2.20M
  virtual Env::IOPriority GetIOPriority() { return io_priority_; }
528
529
  /*
530
   * Get the size of valid data in the file.
531
   */
532
0
  virtual uint64_t GetFileSize() {
533
0
    return 0;
534
0
  }
535
536
  /*
537
   * Get and set the default pre-allocation block size for writes to
538
   * this file.  If non-zero, then Allocate will be used to extend the
539
   * underlying storage of a file (generally via fallocate) if the Env
540
   * instance supports it.
541
   */
542
1.18M
  void SetPreallocationBlockSize(size_t size) {
543
1.18M
    preallocation_block_size_ = size;
544
1.18M
  }
545
546
  virtual void GetPreallocationStatus(size_t* block_size,
547
3.66M
                                      size_t* last_allocated_block) {
548
3.66M
    *last_allocated_block = last_preallocated_block_;
549
3.66M
    *block_size = preallocation_block_size_;
550
3.66M
  }
551
552
  // For documentation, refer to File::GetUniqueId()
553
1.42k
  virtual size_t GetUniqueId(char* id) const override {
554
1.42k
    return 0; // Default implementation to prevent issues with backwards
555
1.42k
  }
556
557
  // Remove any kind of caching of data from the offset to offset+length
558
  // of this file. If the length is 0, then it refers to the end of file.
559
  // If the system is not caching the file contents, then this is a noop.
560
  // This call has no effect on dirty pages in the cache.
561
  virtual Status InvalidateCache(size_t offset, size_t length);
562
563
  // Sync a file range with disk.
564
  // offset is the starting byte of the file range to be synchronized.
565
  // nbytes specifies the length of the range to be synchronized.
566
  // This asks the OS to initiate flushing the cached data to disk,
567
  // without waiting for completion.
568
  // Default implementation does nothing.
569
  virtual Status RangeSync(uint64_t offset, uint64_t nbytes);
570
571
  // PrepareWrite performs any necessary preparation for a write
572
  // before the write actually occurs.  This allows for pre-allocation
573
  // of space on devices where it can result in less file
574
  // fragmentation and/or less waste from over-zealous filesystem
575
  // pre-allocation.
576
  void PrepareWrite(size_t offset, size_t len);
577
578
 protected:
579
  /*
580
   * Pre-allocate space for a file.
581
   */
582
  virtual Status Allocate(uint64_t offset, uint64_t len);
583
584
97.0k
  size_t preallocation_block_size() { return preallocation_block_size_; }
585
586
 private:
587
  size_t last_preallocated_block_;
588
  size_t preallocation_block_size_;
589
  // No copying allowed
590
  WritableFile(const WritableFile&);
591
  void operator=(const WritableFile&);
592
593
 protected:
594
  friend class WritableFileWrapper;
595
  friend class WritableFileMirror;
596
597
  Env::IOPriority io_priority_;
598
};
599
600
// Directory object represents collection of files and implements
601
// filesystem operations that can be executed on directories.
602
class Directory {
603
 public:
604
399k
  virtual ~Directory() {}
605
  // Fsync directory. Can be called concurrently from multiple threads.
606
  virtual Status Fsync() = 0;
607
};
608
609
enum InfoLogLevel : unsigned char {
610
  DEBUG_LEVEL = 0,
611
  INFO_LEVEL,
612
  WARN_LEVEL,
613
  ERROR_LEVEL,
614
  FATAL_LEVEL,
615
  HEADER_LEVEL,
616
  NUM_INFO_LOG_LEVELS,
617
};
618
619
// An interface for writing log messages.
620
class Logger {
621
 public:
622
  size_t kDoNotSupportGetLogFileSize = std::numeric_limits<size_t>::max();
623
624
  explicit Logger(const InfoLogLevel log_level = InfoLogLevel::INFO_LEVEL)
625
694k
      : log_level_(log_level) {
626
627
694k
  }
628
  virtual ~Logger();
629
630
  // Write a header to the log file with the specified format
631
  // It is recommended that you log all header information at the start of the
632
  // application. But it is not enforced.
633
  virtual void LogHeaderWithContext(const char* file, const int line,
634
1.13M
      const char *format, va_list ap) {
635
    // Default implementation does a simple INFO level log write.
636
    // Please override as per the logger class requirement.
637
1.13M
    LogvWithContext(file, line, InfoLogLevel::HEADER_LEVEL, format, ap);
638
1.13M
  }
639
640
  // Write an entry to the log file with the specified format.
641
  virtual void Logv(const char* format, va_list ap) = 0;
642
643
  // Write an entry to the log file with the specified log level
644
  // and format.  Any log with level under the internal log level
645
  // of *this (see @SetInfoLogLevel and @GetInfoLogLevel) will not be
646
  // printed.
647
  virtual void Logv(const rocksdb::InfoLogLevel log_level, const char* format, va_list ap);
648
649
  // A version of the Logv function that takes the file and line number of the caller.
650
  // Accomplished by the RLOG() macro with the __FILE__ and __LINE__ attributes.
651
  virtual void LogvWithContext(const char* file,
652
                               const int line,
653
                               const InfoLogLevel log_level,
654
                               const char* format,
655
                               va_list ap);
656
657
0
  virtual size_t GetLogFileSize() const { return kDoNotSupportGetLogFileSize; }
658
  // Flush to the OS buffers
659
3.03M
  virtual void Flush() {}
660
1.74M
  virtual InfoLogLevel GetInfoLogLevel() const { return log_level_; }
661
21.0k
  virtual void SetInfoLogLevel(const InfoLogLevel log_level) {
662
21.0k
    log_level_ = log_level;
663
21.0k
  }
664
665
14.2k
  virtual const std::string& Prefix() const {
666
14.2k
    static const std::string kEmptyString;
667
14.2k
    return kEmptyString;
668
14.2k
  }
669
670
 private:
671
  // No copying allowed
672
  Logger(const Logger&);
673
  void operator=(const Logger&);
674
  InfoLogLevel log_level_;
675
};
676
677
678
// Identifies a locked file.
679
class FileLock {
680
 public:
681
855k
  FileLock() { }
682
  virtual ~FileLock();
683
 private:
684
  // No copying allowed
685
  FileLock(const FileLock&);
686
  void operator=(const FileLock&);
687
};
688
689
extern void LogFlush(const shared_ptr<Logger>& info_log);
690
691
extern void LogWithContext(const char* file,
692
                           const int line,
693
                           const InfoLogLevel log_level,
694
                           const shared_ptr<Logger>& info_log,
695
                           const char* format,
696
                           ...);
697
698
// a set of log functions with different log levels.
699
extern void HeaderWithContext(
700
    const char* file,
701
    const int line,
702
    const shared_ptr<Logger> &info_log,
703
    const char *format, ...);
704
extern void DebugWithContext(
705
    const char* file,
706
    const int line,
707
    const shared_ptr<Logger> &info_log,
708
    const char *format, ...);
709
extern void InfoWithContext(
710
    const char* file,
711
    const int line,
712
    const shared_ptr<Logger> &info_log,
713
    const char *format, ...);
714
extern void WarnWithContext(
715
    const char* file,
716
    const int line,
717
    const shared_ptr<Logger> &info_log,
718
    const char *format, ...);
719
extern void ErrorWithContext(
720
    const char* file,
721
    const int line,
722
    const shared_ptr<Logger> &info_log,
723
    const char *format, ...);
724
extern void FatalWithContext(
725
    const char* file,
726
    const int line,
727
    const shared_ptr<Logger> &info_log,
728
    const char *format, ...);
729
730
// Log the specified data to *info_log if info_log is non-nullptr.
731
// The default info log level is InfoLogLevel::ERROR.
732
extern void LogWithContext(const char* file,
733
                           const int line,
734
                           const shared_ptr<Logger>& info_log,
735
                           const char* format,
736
                           ...)
737
#   if defined(__GNUC__) || defined(__clang__)
738
    __attribute__((__format__ (__printf__, 4, 5)))
739
#   endif
740
    ; // NOLINT(whitespace/semicolon)
741
742
extern void LogFlush(Logger *info_log);
743
744
extern void LogWithContext(const char* file,
745
                           const int line,
746
                           const InfoLogLevel log_level,
747
                           Logger* info_log,
748
                           const char* format,
749
                           ...);
750
751
// The default info log level is InfoLogLevel::ERROR.
752
extern void LogWithContext(const char* file,
753
                           const int line,
754
                           Logger* info_log,
755
                           const char* format,
756
                           ...)
757
#   if defined(__GNUC__) || defined(__clang__)
758
    __attribute__((__format__ (__printf__, 4, 5)))
759
#   endif
760
    ; // NOLINT(whitespace/semicolon)
761
762
// a set of log functions with different log levels.
763
extern void HeaderWithContext(const char* file, const int line,
764
    Logger *info_log, const char *format, ...);
765
extern void DebugWithContext(const char* file, const int line,
766
    Logger *info_log, const char *format, ...);
767
extern void InfoWithContext(const char* file, const int line,
768
    Logger *info_log, const char *format, ...);
769
extern void WarnWithContext(const char* file, const int line,
770
    Logger *info_log, const char *format, ...);
771
extern void ErrorWithContext(const char* file, const int line,
772
    Logger *info_log, const char *format, ...);
773
extern void FatalWithContext(const char* file, const int line,
774
    Logger *info_log, const char *format, ...);
775
776
// A utility routine: write "data" to the named file.
777
extern Status WriteStringToFile(Env* env, const Slice& data,
778
                                const std::string& fname,
779
                                bool should_sync = false);
780
781
// A utility routine: read contents of named file into *data
782
extern Status ReadFileToString(Env* env, const std::string& fname,
783
                               std::string* data);
784
785
// An implementation of Env that forwards all calls to another Env.
786
// May be useful to clients who wish to override just part of the
787
// functionality of another Env.
788
class EnvWrapper : public Env {
789
 public:
790
  // Initialize an EnvWrapper that delegates all calls to *t
791
672
  explicit EnvWrapper(Env* t) : target_(t) { }
792
  virtual ~EnvWrapper();
793
794
  // Return the target to which this Env forwards all calls
795
3.16M
  Env* target() const { return target_; }
796
797
  // The following text is boilerplate that forwards all methods to target()
798
  Status NewSequentialFile(const std::string& f, std::unique_ptr<SequentialFile>* r,
799
                           const EnvOptions& options) override;
800
  Status NewRandomAccessFile(const std::string& f,
801
                             unique_ptr<RandomAccessFile>* r,
802
                             const EnvOptions& options) override;
803
  Status NewWritableFile(const std::string& f, unique_ptr<WritableFile>* r,
804
                         const EnvOptions& options) override;
805
  Status ReuseWritableFile(const std::string& fname,
806
                           const std::string& old_fname,
807
                           unique_ptr<WritableFile>* r,
808
                           const EnvOptions& options) override;
809
  virtual Status NewDirectory(const std::string& name,
810
                              unique_ptr<Directory>* result) override;
811
  Status FileExists(const std::string& f) override;
812
813
15.9k
  bool DirExists(const std::string& f) override {
814
15.9k
    return target_->DirExists(f);
815
15.9k
  }
816
817
  Status GetChildren(const std::string& dir,
818
                     std::vector<std::string>* r) override;
819
  Status GetChildrenFileAttributes(
820
      const std::string& dir, std::vector<FileAttributes>* result) override;
821
  Status DeleteFile(const std::string& f) override;
822
  Status CreateDir(const std::string& d) override;
823
  Status CreateDirIfMissing(const std::string& d) override;
824
  Status DeleteDir(const std::string& d) override;
825
  Status GetFileSize(const std::string& f, uint64_t* s) override;
826
827
  Status GetFileModificationTime(const std::string& fname,
828
                                 uint64_t* file_mtime) override;
829
830
  Status RenameFile(const std::string& s, const std::string& t) override;
831
832
  Status LinkFile(const std::string& s, const std::string& t) override;
833
834
  Status LockFile(const std::string& f, FileLock** l) override;
835
836
  Status UnlockFile(FileLock* l) override;
837
838
  void Schedule(void (*f)(void* arg), void* a, Priority pri,
839
128k
                void* tag = nullptr, void (*u)(void* arg) = 0) override {
840
128k
    return target_->Schedule(f, a, pri, tag, u);
841
128k
  }
842
843
18.2k
  int UnSchedule(void* tag, Priority pri) override {
844
18.2k
    return target_->UnSchedule(tag, pri);
845
18.2k
  }
846
847
412
  void StartThread(void (*f)(void*), void* a) override {
848
412
    return target_->StartThread(f, a);
849
412
  }
850
0
  void WaitForJoin() override { return target_->WaitForJoin(); }
851
  virtual unsigned int GetThreadPoolQueueLen(
852
9
      Priority pri = LOW) const override {
853
9
    return target_->GetThreadPoolQueueLen(pri);
854
9
  }
855
  virtual Status GetTestDirectory(std::string* path) override;
856
  virtual Status NewLogger(const std::string& fname,
857
                           shared_ptr<Logger>* result) override;
858
20.3k
  uint64_t NowMicros() override { return target_->NowMicros(); }
859
37
  void SleepForMicroseconds(int micros) override {
860
37
    target_->SleepForMicroseconds(micros);
861
37
  }
862
  Status GetHostName(char* name, uint64_t len) override;
863
  Status GetCurrentTime(int64_t* unix_time) override;
864
  Status GetAbsolutePath(const std::string& db_path,
865
                         std::string* output_path) override;
866
1.14k
  void SetBackgroundThreads(int num, Priority pri) override {
867
1.14k
    return target_->SetBackgroundThreads(num, pri);
868
1.14k
  }
869
870
25.0k
  void IncBackgroundThreadsIfNeeded(int num, Priority pri) override {
871
25.0k
    return target_->IncBackgroundThreadsIfNeeded(num, pri);
872
25.0k
  }
873
874
0
  void LowerThreadPoolIOPriority(Priority pool = LOW) override {
875
0
    target_->LowerThreadPoolIOPriority(pool);
876
0
  }
877
878
0
  std::string TimeToString(uint64_t time) override {
879
0
    return target_->TimeToString(time);
880
0
  }
881
882
201
  uint64_t GetThreadID() const override {
883
201
    return target_->GetThreadID();
884
201
  }
885
886
5.51k
  bool IsPlainText() const override {
887
5.51k
    return target_->IsPlainText();
888
5.51k
  }
889
890
 private:
891
  Env* target_;
892
};
893
894
// An implementation of WritableFile that forwards all calls to another
895
// WritableFile. May be useful to clients who wish to override just part of the
896
// functionality of another WritableFile.
897
// It's declared as friend of WritableFile to allow forwarding calls to
898
// protected virtual methods.
899
class WritableFileWrapper : public WritableFile {
900
 public:
901
40
  explicit WritableFileWrapper(std::unique_ptr<WritableFile> t) : target_(std::move(t)) { }
902
903
  Status Append(const Slice& data) override;
904
  Status PositionedAppend(const Slice& data, uint64_t offset) override;
905
  Status Truncate(uint64_t size) override;
906
  Status Close() override;
907
  Status Flush() override;
908
  Status Sync() override;
909
  Status Fsync() override;
910
0
  bool IsSyncThreadSafe() const override { return target_->IsSyncThreadSafe(); }
911
5
  void SetIOPriority(Env::IOPriority pri) override {
912
5
    target_->SetIOPriority(pri);
913
5
  }
914
0
  Env::IOPriority GetIOPriority() override { return target_->GetIOPriority(); }
915
99.6k
  uint64_t GetFileSize() override { return target_->GetFileSize(); }
916
  void GetPreallocationStatus(size_t* block_size,
917
1
                              size_t* last_allocated_block) override {
918
1
    target_->GetPreallocationStatus(block_size, last_allocated_block);
919
1
  }
920
1
  size_t GetUniqueId(char* id) const override {
921
1
    return target_->GetUniqueId(id);
922
1
  }
923
  Status InvalidateCache(size_t offset, size_t length) override;
924
925
 protected:
926
  Status Allocate(uint64_t offset, uint64_t len) override;
927
  Status RangeSync(uint64_t offset, uint64_t nbytes) override;
928
929
 private:
930
  std::unique_ptr<WritableFile> target_;
931
};
932
933
// Returns a new environment that stores its data in memory and delegates
934
// all non-file-storage tasks to base_env. The caller must delete the result
935
// when it is no longer needed.
936
// *base_env must remain live while the result is in use.
937
Env* NewMemEnv(Env* base_env);
938
939
// Returns a new environment that is used for HDFS environment.
940
// This is a factory method for HdfsEnv declared in hdfs/env_hdfs.h
941
Status NewHdfsEnv(Env** hdfs_env, const std::string& fsname);
942
943
}  // namespace rocksdb
944
945
#endif // YB_ROCKSDB_ENV_H