Storage Engine API
durable_mapped_file.h
Go to the documentation of this file.
1 // durable_mapped_file.h
2 
3 /*
4 *
5 * Copyright (C) 2008 10gen Inc.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License, version 3,
9 * as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * As a special exception, the copyright holders give permission to link the
20 * code of portions of this program with the OpenSSL library under certain
21 * conditions as described in each individual source file and distribute
22 * linked combinations including the program with the OpenSSL library. You
23 * must comply with the GNU Affero General Public License in all respects for
24 * all of the code used other than as permitted herein. If you modify file(s)
25 * with this exception, you may extend this exception to your version of the
26 * file(s), but you are not obligated to do so. If you do not wish to do so,
27 * delete this exception statement from your version. If you delete this
28 * exception statement from all source files in the program, then also delete
29 * it in the license file.
30 */
31 
32 #pragma once
33 
34 #include "mongo/base/static_assert.h"
35 #include "mongo/db/operation_context.h"
38 #include "mongo/stdx/mutex.h"
39 
40 namespace mongo {
41 
48 protected:
49  virtual void* viewForFlushing() {
50  return _view_write;
51  }
52 
53 public:
54  explicit DurableMappedFile(OperationContext* opCtx, OptionSet options = NONE);
55  virtual ~DurableMappedFile();
56 
60  virtual void close(OperationContext* opCtx);
61 
63  bool open(OperationContext* opCtx, const std::string& fname);
64 
66  unsigned long long length() const {
67  return MemoryMappedFile::length();
68  }
69 
70  std::string filename() const {
72  }
73 
74  void flush(bool sync) {
76  }
77 
78  /* Creates with length if DNE, otherwise uses existing file length,
79  passed length.
80  @return true for ok
81  */
82  bool create(OperationContext* opCtx, const std::string& fname, unsigned long long& len);
83 
84  /* Get the "standard" view (which is the private one).
85  @return the private view.
86  */
87  void* getView() const {
88  return _view_private;
89  }
90 
91  /* Get the "write" view (which is required for writing).
92  @return the write view.
93  */
94  void* view_write() const {
95  return _view_write;
96  }
97 
103  const RelativePath& relativePath() const {
104  DEV verify(!_p._p.empty());
105  return _p;
106  }
107 
108  int fileSuffixNo() const {
109  return _fileSuffixNo;
110  }
112  return MemoryMappedFile::getFd();
113  }
114 
119  bool willNeedRemap() {
120  return _willNeedRemap;
121  }
123  _willNeedRemap = true;
124  }
125 
126  void remapThePrivateView(OperationContext* opCtx);
127 
128  virtual bool isDurableMappedFile() {
129  return true;
130  }
131 
132 private:
133  void* _view_write;
136  RelativePath _p; // e.g. "somepath/dbname"
137  int _fileSuffixNo; // e.g. 3. -1="ns"
138 
139  void setPath(const std::string& pathAndFileName);
140  bool finishOpening();
141 };
142 
143 
144 #ifdef _WIN32
145 // Simple array based bitset to track COW chunks in memory mapped files on Windows
146 // A chunk is a 64MB granular region in virtual memory that we mark as COW everytime we need
147 // to write to a memory mapped files on Windows
148 //
149 class MemoryMappedCOWBitset {
150  MONGO_DISALLOW_COPYING(MemoryMappedCOWBitset);
151 
152 public:
153  // Size of the chunks we mark Copy-On-Write with VirtualProtect
154  static const unsigned long long ChunkSize = 64 * 1024 * 1024;
155 
156  // Number of chunks we store in our bitset which are really 32-bit ints
157  static const unsigned long long NChunks = 64 * 1024;
158 
159  // Total Virtual Memory space we can cover with the bitset
160  static const unsigned long long MaxChunkMemory = ChunkSize * NChunks * sizeof(unsigned int) * 8;
161 
162  // Size in bytes of the bitset we allocate
163  static const unsigned long long MaxChunkBytes = NChunks * sizeof(unsigned int);
164 
165  // 128 TB Virtual Memory space in Windows 8.1/2012 R2, 8TB before
166  static const unsigned long long MaxWinMemory = 128ULL * 1024 * 1024 * 1024 * 1024;
167 
168  // Make sure that the chunk memory covers the Max Windows user process VM space
169  MONGO_STATIC_ASSERT_MSG(MaxChunkMemory == MaxWinMemory,
170  "Need a larger bitset to cover max process VM space");
171 
172 public:
173  MemoryMappedCOWBitset() {
174  MONGO_STATIC_ASSERT_MSG(MemoryMappedCOWBitset::MaxChunkBytes == sizeof(bits),
175  "Validate our predicted bitset size is correct");
176  }
177 
178  bool get(uintptr_t i) const {
179  uintptr_t x = i / 32;
180  verify(x < MemoryMappedCOWBitset::NChunks);
181  return (bits[x].loadRelaxed() & (1 << (i % 32))) != 0;
182  }
183 
184  // Note: assumes caller holds privateViews.mutex
185  void set(uintptr_t i) {
186  uintptr_t x = i / 32;
187  verify(x < MemoryMappedCOWBitset::NChunks);
188  bits[x].store(bits[x].loadRelaxed() | (1 << (i % 32)));
189  }
190 
191  // Note: assumes caller holds privateViews.mutex
192  void clear(uintptr_t i) {
193  uintptr_t x = i / 32;
194  verify(x < MemoryMappedCOWBitset::NChunks);
195  bits[x].store(bits[x].loadRelaxed() & ~(1 << (i % 32)));
196  }
197 
198 private:
199  // atomic as we are doing double check locking
200  AtomicUInt32 bits[MemoryMappedCOWBitset::NChunks];
201 };
202 #endif
203 
208 
209 public:
211 
215  void add_inlock(void* view, DurableMappedFile* f);
216 
220  void remove(void* view, size_t length);
221 
227  DurableMappedFile* find(void* p, /*out*/ size_t& ofs);
228 
230  stdx::mutex& _mutex() {
231  return _m;
232  }
233 
235  DurableMappedFile* find_inlock(void* p, /*out*/ size_t& ofs);
236 
238  unsigned numberOfViews_inlock() const {
239  return _views.size();
240  }
241 
243  void makeWritable(void*, unsigned len);
244 
245  void clearWritableBits(void* privateView, size_t len);
246 
247 private:
248  void clearWritableBits_inlock(void* privateView, size_t len);
249 
250 #ifdef _WIN32
251  void makeChunkWritable(size_t chunkno);
252 #endif
253 
254 private:
255  // PointerToDurableMappedFile Mutex
256  //
257  // Protects:
258  // Protects internal consistency of data structure
259  // Lock Ordering:
260  // Must be taken before MapViewMutex if both are taken to prevent deadlocks
261  stdx::mutex _m;
262  std::map<void*, DurableMappedFile*> _views;
263 
264 #ifdef _WIN32
265  // Tracks which memory mapped regions are marked as Copy on Write
266  MemoryMappedCOWBitset writable;
267 #endif
268 };
269 
270 #ifdef _WIN32
271 inline void PointerToDurableMappedFile::makeWritable(void* privateView, unsigned len) {
272  size_t p = reinterpret_cast<size_t>(privateView);
273  unsigned a = p / MemoryMappedCOWBitset::ChunkSize;
274  unsigned b = (p + len) / MemoryMappedCOWBitset::ChunkSize;
275 
276  for (unsigned i = a; i <= b; i++) {
277  if (!writable.get(i)) {
278  makeChunkWritable(i);
279  }
280  }
281 }
282 #else
283 inline void PointerToDurableMappedFile::makeWritable(void* _p, unsigned len) {}
284 #endif
285 
286 // allows a pointer into any private view of a DurableMappedFile to be resolved to the
287 // DurableMappedFile object
289 }
unsigned long long len
Definition: mmap.h:289
unsigned long long length() const
Definition: mmap.h:262
std::map< void *, DurableMappedFile * > _views
Definition: durable_mapped_file.h:262
int ofs
Definition: btree_interface.cpp:337
Definition: mmap.h:220
bool _willNeedRemap
Definition: durable_mapped_file.h:135
bool willNeedRemap()
true if we have written.
Definition: durable_mapped_file.h:119
int fileSuffixNo() const
Definition: durable_mapped_file.h:108
Copyright (C) 2014 MongoDB Inc.
Definition: bson_collection_catalog_entry.cpp:38
std::string _p
Definition: paths.h:50
void * view_write() const
Definition: durable_mapped_file.h:94
void flush(bool sync)
Definition: mmap_posix.cpp:269
PointerToDurableMappedFile privateViews
Definition: durable_mapped_file.cpp:226
Definition: mmap.h:121
void * _view_write
Definition: durable_mapped_file.h:133
bool create(OperationContext *opCtx, const std::string &fname, unsigned long long &len)
Definition: durable_mapped_file.cpp:254
HANDLE getFd() const
Definition: mmap.h:265
void setWillNeedRemap()
Definition: durable_mapped_file.h:122
void setPath(const std::string &pathAndFileName)
Definition: durable_mapped_file.cpp:229
std::underlying_type< Options >::type OptionSet
Definition: mmap.h:127
int HANDLE
Definition: mmap.h:42
stdx::mutex & _mutex()
for doing many finds in a row with one lock operation
Definition: durable_mapped_file.h:230
void * _view_private
Definition: durable_mapped_file.h:134
virtual void * viewForFlushing()
Definition: durable_mapped_file.h:49
virtual bool isDurableMappedFile()
Definition: durable_mapped_file.h:128
stdx::mutex _m
Definition: durable_mapped_file.h:261
bool finishOpening()
Definition: durable_mapped_file.cpp:266
HANDLE getFd()
Definition: durable_mapped_file.h:111
int _fileSuffixNo
Definition: durable_mapped_file.h:137
unsigned numberOfViews_inlock() const
not-threadsafe, caller must hold _mutex()
Definition: durable_mapped_file.h:238
DurableMappedFile adds some layers atop memory mapped files - specifically our handling of private vi...
Definition: durable_mapped_file.h:47
DurableMappedFile(OperationContext *opCtx, OptionSet options=NONE)
Definition: durable_mapped_file.cpp:307
virtual ~DurableMappedFile()
Definition: durable_mapped_file.cpp:312
void * getView() const
Definition: durable_mapped_file.h:87
MONGO_DISALLOW_COPYING(MongoFile)
RelativePath _p
Definition: durable_mapped_file.h:136
std::string filename() const
Definition: durable_mapped_file.h:70
unsigned long long length() const
Definition: durable_mapped_file.h:66
OperationContext Database StringData BSONObj options
Definition: database_impl.cpp:949
std::string filename() const
Definition: mmap.h:151
bool open(OperationContext *opCtx, const std::string &fname)
Definition: durable_mapped_file.cpp:244
Collection *const OperationContext *const opCtx
Definition: collection_impl.cpp:80
virtual void close(OperationContext *opCtx)
Callers must be holding a LockMongoFilesExclusive.
Definition: durable_mapped_file.cpp:288
const RelativePath & relativePath() const
for a filename a/b/c.3 filePath() is "a/b/c" fileSuffixNo() is 3 if the suffix is "ns"...
Definition: durable_mapped_file.h:103
void remapThePrivateView(OperationContext *opCtx)
Definition: durable_mapped_file.cpp:64
this is very much like a boost::path.
Definition: paths.h:49
void flush(bool sync)
Definition: durable_mapped_file.h:74
for durability support we want to be able to map pointers to specific DurableMappedFile objects...
Definition: durable_mapped_file.h:206
void makeWritable(void *, unsigned len)
make the private map range writable (necessary for our windows implementation)
Definition: durable_mapped_file.h:283