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 
6 #pragma once
7 
8 #include <memory>
9 #include <string>
10 
11 #include "rocksdb/status.h"
12 #include "rocksdb/utilities/env_mirror.h"
13 
14 #include <rados/librados.hpp>
15 
16 namespace ROCKSDB_NAMESPACE {
17 class LibradosWritableFile;
18 
19 class EnvLibrados : public EnvWrapper {
20  public:
21   // Create a brand new sequentially-readable file with the specified name.
22   // On success, stores a pointer to the new file in *result and returns OK.
23   // On failure stores nullptr in *result and returns non-OK.  If the file does
24   // not exist, returns a non-OK status.
25   //
26   // The returned file will only be accessed by one thread at a time.
27   Status NewSequentialFile(const std::string& fname,
28                            std::unique_ptr<SequentialFile>* result,
29                            const EnvOptions& options) override;
30 
31   // Create a brand new random access read-only file with the
32   // specified name.  On success, stores a pointer to the new file in
33   // *result and returns OK.  On failure stores nullptr in *result and
34   // returns non-OK.  If the file does not exist, returns a non-OK
35   // status.
36   //
37   // The returned file may be concurrently accessed by multiple threads.
38   Status NewRandomAccessFile(const std::string& fname,
39                              std::unique_ptr<RandomAccessFile>* result,
40                              const EnvOptions& options) override;
41 
42   // Create an object that writes to a new file with the specified
43   // name.  Deletes any existing file with the same name and creates a
44   // new file.  On success, stores a pointer to the new file in
45   // *result and returns OK.  On failure stores nullptr in *result and
46   // returns non-OK.
47   //
48   // The returned file will only be accessed by one thread at a time.
49   Status NewWritableFile(const std::string& fname,
50                          std::unique_ptr<WritableFile>* result,
51                          const EnvOptions& options) override;
52 
53   // Reuse an existing file by renaming it and opening it as writable.
54   Status ReuseWritableFile(const std::string& fname,
55                            const std::string& old_fname,
56                            std::unique_ptr<WritableFile>* result,
57                            const EnvOptions& options) override;
58 
59   // Create an object that represents a directory. Will fail if directory
60   // doesn't exist. If the directory exists, it will open the directory
61   // and create a new Directory object.
62   //
63   // On success, stores a pointer to the new Directory in
64   // *result and returns OK. On failure stores nullptr in *result and
65   // returns non-OK.
66   Status NewDirectory(const std::string& name,
67                       std::unique_ptr<Directory>* result) override;
68 
69   // Returns OK if the named file exists.
70   //         NotFound if the named file does not exist,
71   //                  the calling process does not have permission to determine
72   //                  whether this file exists, or if the path is invalid.
73   //         IOError if an IO Error was encountered
74   Status FileExists(const std::string& fname) override;
75 
76   // Store in *result the names of the children of the specified directory.
77   // The names are relative to "dir".
78   // Original contents of *results are dropped.
79   Status GetChildren(const std::string& dir, std::vector<std::string>* result);
80 
81   // Delete the named file.
82   Status DeleteFile(const std::string& fname) override;
83 
84   // Create the specified directory. Returns error if directory exists.
85   Status CreateDir(const std::string& dirname) override;
86 
87   // Creates directory if missing. Return Ok if it exists, or successful in
88   // Creating.
89   Status CreateDirIfMissing(const std::string& dirname) override;
90 
91   // Delete the specified directory.
92   Status DeleteDir(const std::string& dirname) override;
93 
94   // Store the size of fname in *file_size.
95   Status GetFileSize(const std::string& fname, uint64_t* file_size) override;
96 
97   // Store the last modification time of fname in *file_mtime.
98   Status GetFileModificationTime(const std::string& fname,
99                                  uint64_t* file_mtime) override;
100   // Rename file src to target.
101   Status RenameFile(const std::string& src, const std::string& target) override;
102   // Hard Link file src to target.
103   Status LinkFile(const std::string& src, const std::string& target) override;
104 
105   // Lock the specified file.  Used to prevent concurrent access to
106   // the same db by multiple processes.  On failure, stores nullptr in
107   // *lock and returns non-OK.
108   //
109   // On success, stores a pointer to the object that represents the
110   // acquired lock in *lock and returns OK.  The caller should call
111   // UnlockFile(*lock) to release the lock.  If the process exits,
112   // the lock will be automatically released.
113   //
114   // If somebody else already holds the lock, finishes immediately
115   // with a failure.  I.e., this call does not wait for existing locks
116   // to go away.
117   //
118   // May create the named file if it does not already exist.
119   Status LockFile(const std::string& fname, FileLock** lock);
120 
121   // Release the lock acquired by a previous successful call to LockFile.
122   // REQUIRES: lock was returned by a successful LockFile() call
123   // REQUIRES: lock has not already been unlocked.
124   Status UnlockFile(FileLock* lock);
125 
126   // Get full directory name for this db.
127   Status GetAbsolutePath(const std::string& db_path, std::string* output_path);
128 
129   // Generate unique id
130   std::string GenerateUniqueId();
131 
132   // Get default EnvLibrados
133   static EnvLibrados* Default();
134 
135   explicit EnvLibrados(const std::string& db_name,
136                        const std::string& config_path,
137                        const std::string& db_pool);
138 
139   explicit EnvLibrados(
140       const std::string& client_name,  // first 3 parameters are
141                                        // for RADOS client init
142       const std::string& cluster_name, const uint64_t flags,
143       const std::string& db_name, const std::string& config_path,
144       const std::string& db_pool, const std::string& wal_dir,
145       const std::string& wal_pool, const uint64_t write_buffer_size);
~EnvLibrados()146   ~EnvLibrados() { _rados.shutdown(); }
147 
148  private:
149   std::string _client_name;
150   std::string _cluster_name;
151   uint64_t _flags;
152   std::string _db_name;  // get from user, readable string; Also used as db_id
153                          // for db metadata
154   std::string _config_path;
155   librados::Rados _rados;  // RADOS client
156   std::string _db_pool_name;
157   librados::IoCtx _db_pool_ioctx;  // IoCtx for connecting db_pool
158   std::string _wal_dir;            // WAL dir path
159   std::string _wal_pool_name;
160   librados::IoCtx _wal_pool_ioctx;  // IoCtx for connecting wal_pool
161   uint64_t _write_buffer_size;      // WritableFile buffer max size
162 
163   /* private function to communicate with rados */
164   std::string _CreateFid();
165   Status _GetFid(const std::string& fname, std::string& fid);
166   Status _GetFid(const std::string& fname, std::string& fid, int fid_len);
167   Status _RenameFid(const std::string& old_fname, const std::string& new_fname);
168   Status _AddFid(const std::string& fname, const std::string& fid);
169   Status _DelFid(const std::string& fname);
170   Status _GetSubFnames(const std::string& dirname,
171                        std::vector<std::string>* result);
172   librados::IoCtx* _GetIoctx(const std::string& prefix);
173   friend class LibradosWritableFile;
174 };
175 }  // namespace ROCKSDB_NAMESPACE
176