Storage Engine API
record_store_v1_base.h
Go to the documentation of this file.
1 
29 #pragma once
30 
31 #include "mongo/stdx/unordered_set.h"
32 #include "mongo/util/concurrency/spin_lock.h"
33 
36 
37 namespace mongo {
38 
39 class DeletedRecord;
40 class ExtentManager;
41 class MmapV1RecordHeader;
42 class OperationContext;
43 
44 struct Extent;
45 
47 public:
49 
50  virtual const DiskLoc& capExtent() const = 0;
51  virtual void setCapExtent(OperationContext* opCtx, const DiskLoc& loc) = 0;
52 
53  virtual const DiskLoc& capFirstNewRecord() const = 0;
54  virtual void setCapFirstNewRecord(OperationContext* opCtx, const DiskLoc& loc) = 0;
55 
56  bool capLooped() const {
57  return capFirstNewRecord().isValid();
58  }
59 
60  virtual long long dataSize() const = 0;
61  virtual long long numRecords() const = 0;
62 
63  virtual void incrementStats(OperationContext* opCtx,
64  long long dataSizeIncrement,
65  long long numRecordsIncrement) = 0;
66 
67  virtual void setStats(OperationContext* opCtx, long long dataSize, long long numRecords) = 0;
68 
69  virtual DiskLoc deletedListEntry(int bucket) const = 0;
70  virtual void setDeletedListEntry(OperationContext* opCtx, int bucket, const DiskLoc& loc) = 0;
71 
72  virtual DiskLoc deletedListLegacyGrabBag() const = 0;
73  virtual void setDeletedListLegacyGrabBag(OperationContext* opCtx, const DiskLoc& loc) = 0;
74 
75  virtual void orphanDeletedList(OperationContext* opCtx) = 0;
76 
77  virtual const DiskLoc& firstExtent(OperationContext* opCtx) const = 0;
78  virtual void setFirstExtent(OperationContext* opCtx, const DiskLoc& loc) = 0;
79 
80  virtual const DiskLoc& lastExtent(OperationContext* opCtx) const = 0;
81  virtual void setLastExtent(OperationContext* opCtx, const DiskLoc& loc) = 0;
82 
83  virtual bool isCapped() const = 0;
84 
85  virtual bool isUserFlagSet(int flag) const = 0;
86  virtual int userFlags() const = 0;
87  virtual bool setUserFlag(OperationContext* opCtx, int flag) = 0;
88  virtual bool clearUserFlag(OperationContext* opCtx, int flag) = 0;
89  virtual bool replaceUserFlags(OperationContext* opCtx, int flags) = 0;
90 
91  virtual int lastExtentSize(OperationContext* opCtx) const = 0;
92  virtual void setLastExtentSize(OperationContext* opCtx, int newMax) = 0;
93 
94  virtual long long maxCappedDocs() const = 0;
95 };
96 
105 public:
110  struct SavedCursor {
111  SavedCursor() : _registry(NULL) {}
112  virtual ~SavedCursor() {
113  if (_registry)
115  }
117  BSONObj key;
119 
120  private:
121  friend class SavedCursorRegistry;
122  // Non-null iff registered. Accessed by owner or writer with MODE_X collection lock
124  };
125 
127 
131  void registerCursor(SavedCursor* cursor);
132 
137  bool unregisterCursor(SavedCursor* cursor);
138 
144 
145 private:
146  SpinLock _mutex;
147  typedef stdx::unordered_set<SavedCursor*>
148  SavedCursorSet; // SavedCursor pointers not owned here
150 };
151 
153 public:
154  static const int Buckets = 26;
155  static const int MaxAllowedAllocation = 16 * 1024 * 1024 + 512 * 1024;
156 
157  static const int bucketSizes[];
158 
159  // ------------
160 
161  class IntraExtentIterator;
162 
167  RecordStoreV1Base(StringData ns,
169  ExtentManager* em,
170  bool isSystemIndexes);
171 
172  virtual ~RecordStoreV1Base();
173 
174  const std::string& getIdent() const override {
175  MONGO_UNREACHABLE;
176  }
177 
178  virtual long long dataSize(OperationContext* opCtx) const {
179  return _details->dataSize();
180  }
181  virtual long long numRecords(OperationContext* opCtx) const {
182  return _details->numRecords();
183  }
184 
185  virtual int64_t storageSize(OperationContext* opCtx,
186  BSONObjBuilder* extraInfo = NULL,
187  int level = 0) const;
188 
189  virtual RecordData dataFor(OperationContext* opCtx, const RecordId& loc) const;
190 
191  virtual bool findRecord(OperationContext* opCtx, const RecordId& loc, RecordData* rd) const;
192 
193  void deleteRecord(OperationContext* opCtx, const RecordId& dl);
194 
196  OperationContext* opCtx, const char* data, int len, Timestamp, bool enforceQuota);
197 
198  Status insertRecordsWithDocWriter(OperationContext* opCtx,
199  const DocWriter* const* docs,
200  const Timestamp*,
201  size_t nDocs,
202  RecordId* idsOut) final;
203 
204  virtual Status updateRecord(OperationContext* opCtx,
205  const RecordId& oldLocation,
206  const char* data,
207  int len,
208  bool enforceQuota,
209  UpdateNotifier* notifier);
210 
211  virtual bool updateWithDamagesSupported() const;
212 
213  virtual StatusWith<RecordData> updateWithDamages(OperationContext* opCtx,
214  const RecordId& loc,
215  const RecordData& oldRec,
216  const char* damageSource,
217  const mutablebson::DamageVector& damages);
218 
219  virtual std::unique_ptr<RecordCursor> getCursorForRepair(OperationContext* opCtx) const;
220 
221  void increaseStorageSize(OperationContext* opCtx, int size, bool enforceQuota);
222 
223  virtual Status validate(OperationContext* opCtx,
224  ValidateCmdLevel level,
225  ValidateAdaptor* adaptor,
226  ValidateResults* results,
227  BSONObjBuilder* output);
228 
229  virtual void appendCustomStats(OperationContext* opCtx,
230  BSONObjBuilder* result,
231  double scale) const;
232 
233  virtual Status touch(OperationContext* opCtx, BSONObjBuilder* output) const;
234 
236  return _details.get();
237  }
238 
239  // This keeps track of cursors saved during yielding, for invalidation purposes.
241 
242  DiskLoc getExtentLocForRecord(OperationContext* opCtx, const DiskLoc& loc) const;
243 
244  DiskLoc getNextRecord(OperationContext* opCtx, const DiskLoc& loc) const;
245  DiskLoc getPrevRecord(OperationContext* opCtx, const DiskLoc& loc) const;
246 
247  DiskLoc getNextRecordInExtent(OperationContext* opCtx, const DiskLoc& loc) const;
248  DiskLoc getPrevRecordInExtent(OperationContext* opCtx, const DiskLoc& loc) const;
249 
253  static int quantizeAllocationSpace(int minSize);
254 
255  static bool isQuantized(int recordSize);
256 
257  /* return which "deleted bucket" for this size object */
258  static int bucket(int size);
259 
260  void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) const override {}
261 
262  virtual void updateStatsAfterRepair(OperationContext* opCtx,
263  long long numRecords,
264  long long dataSize) {
265  MONGO_UNREACHABLE; // MMAPv1 has its own repair which doesn't call this.
266  }
267 
268 protected:
269  virtual MmapV1RecordHeader* recordFor(const DiskLoc& loc) const;
270 
271  const DeletedRecord* deletedRecordFor(const DiskLoc& loc) const;
272 
273  virtual bool isCapped() const = 0;
274 
275  virtual bool shouldPadInserts() const = 0;
276 
277  virtual StatusWith<DiskLoc> allocRecord(OperationContext* opCtx,
278  int lengthWithHeaders,
279  bool enforceQuota) = 0;
280 
281  // TODO: document, remove, what have you
282  virtual void addDeletedRec(OperationContext* opCtx, const DiskLoc& dloc) = 0;
283 
284  // TODO: another sad one
285  virtual DeletedRecord* drec(const DiskLoc& loc) const;
286 
287  // just a wrapper for _extentManager->getExtent( loc );
288  Extent* _getExtent(OperationContext* opCtx, const DiskLoc& loc) const;
289 
290  DiskLoc _getExtentLocForRecord(OperationContext* opCtx, const DiskLoc& loc) const;
291 
292  DiskLoc _getNextRecord(OperationContext* opCtx, const DiskLoc& loc) const;
293  DiskLoc _getPrevRecord(OperationContext* opCtx, const DiskLoc& loc) const;
294 
295  DiskLoc _getNextRecordInExtent(OperationContext* opCtx, const DiskLoc& loc) const;
296  DiskLoc _getPrevRecordInExtent(OperationContext* opCtx, const DiskLoc& loc) const;
297 
302  DiskLoc _findFirstSpot(OperationContext* opCtx, const DiskLoc& extDiskLoc, Extent* e);
303 
307  void _addRecordToRecListInExtent(OperationContext* opCtx, MmapV1RecordHeader* r, DiskLoc loc);
308 
313  StatusWith<RecordId> _insertRecord(OperationContext* opCtx,
314  const char* data,
315  int len,
316  bool enforceQuota);
317 
318  std::unique_ptr<RecordStoreV1MetaData> _details;
321 
323 };
324 
331 public:
332  IntraExtentIterator(OperationContext* opCtx,
333  DiskLoc start,
334  const RecordStoreV1Base* rs,
335  bool forward = true)
336  : _opCtx(opCtx), _curr(start), _rs(rs), _forward(forward) {}
337 
338  boost::optional<Record> next() final;
339  void invalidate(OperationContext* opCtx, const RecordId& dl) final;
340  void save() final {}
341  bool restore() final {
342  return true;
343  }
345  _opCtx = nullptr;
346  }
347  void reattachToOperationContext(OperationContext* opCtx) final {
348  _opCtx = opCtx;
349  }
350  std::unique_ptr<RecordFetcher> fetcherForNext() const final;
351 
352 private:
353  virtual const MmapV1RecordHeader* recordFor(const DiskLoc& loc) const {
354  return _rs->recordFor(loc);
355  }
356 
357  void advance();
358 
359  OperationContext* _opCtx;
362  bool _forward;
363 };
364 } // namespace mongo
void registerCursor(SavedCursor *cursor)
Adds given saved cursor to SavedCursorRegistry.
Definition: record_store_v1_base.cpp:102
Status insertRecordsWithDocWriter(OperationContext *opCtx, const DocWriter *const *docs, const Timestamp *, size_t nDocs, RecordId *idsOut) final
Inserts nDocs documents into this RecordStore using the DocWriter interface.
Definition: record_store_v1_base.cpp:302
virtual std::unique_ptr< RecordCursor > getCursorForRepair(OperationContext *opCtx) const
Constructs a cursor over a potentially corrupted store, which can be used to salvage damaged records.
Definition: record_store_v1_base.cpp:497
ValidateCmdLevel
Definition: record_store.h:93
StatusWith< RecordId > _insertRecord(OperationContext *opCtx, const char *data, int len, bool enforceQuota)
internal doesn't check inputs or change padding
Definition: record_store_v1_base.cpp:356
virtual ~RecordStoreV1Base()
Definition: record_store_v1_base.cpp:140
stdx::unordered_set< SavedCursor * > SavedCursorSet
Definition: record_store_v1_base.h:148
IntraExtentIterator(OperationContext *opCtx, DiskLoc start, const RecordStoreV1Base *rs, bool forward=true)
Definition: record_store_v1_base.h:332
DiskLoc _curr
Definition: record_store_v1_base.h:360
Definition: record_store.h:673
virtual bool setUserFlag(OperationContext *opCtx, int flag)=0
Definition: extent.h:50
virtual void setStats(OperationContext *opCtx, long long dataSize, long long numRecords)=0
~SavedCursorRegistry()
Definition: record_store_v1_base.cpp:96
DiskLoc getNextRecord(OperationContext *opCtx, const DiskLoc &loc) const
Definition: record_store_v1_base.cpp:216
virtual bool isCapped() const =0
virtual Status updateRecord(OperationContext *opCtx, const RecordId &oldLocation, const char *data, int len, bool enforceQuota, UpdateNotifier *notifier)
Definition: record_store_v1_base.cpp:382
virtual const DiskLoc & firstExtent(OperationContext *opCtx) const =0
Copyright (C) 2014 MongoDB Inc.
Definition: bson_collection_catalog_entry.cpp:38
virtual long long numRecords(OperationContext *opCtx) const
Total number of record in the RecordStore.
Definition: record_store_v1_base.h:181
virtual void updateStatsAfterRepair(OperationContext *opCtx, long long numRecords, long long dataSize)
Called after a repair operation is run with the recomputed numRecords and dataSize.
Definition: record_store_v1_base.h:262
DiskLoc loc
Definition: record_store_v1_base.h:118
virtual const MmapV1RecordHeader * recordFor(const DiskLoc &loc) const
Definition: record_store_v1_base.h:353
virtual Status validate(OperationContext *opCtx, ValidateCmdLevel level, ValidateAdaptor *adaptor, ValidateResults *results, BSONObjBuilder *output)
Definition: record_store_v1_base.cpp:554
Definition: record_store_v1_base.h:152
bool unregisterCursor(SavedCursor *cursor)
Removes given saved cursor.
Definition: record_store_v1_base.cpp:109
virtual const DiskLoc & capExtent() const =0
const std::string & getIdent() const override
Definition: record_store_v1_base.h:174
void _addRecordToRecListInExtent(OperationContext *opCtx, MmapV1RecordHeader *r, DiskLoc loc)
add a record to the end of the linked list chain within this extent.
Definition: record_store_v1_base.cpp:501
virtual void setDeletedListEntry(OperationContext *opCtx, int bucket, const DiskLoc &loc)=0
A replacement for the Record class.
Definition: record_data.h:43
virtual DiskLoc deletedListEntry(int bucket) const =0
void invalidate(OperationContext *opCtx, const RecordId &dl) final
Inform the cursor that this id is being invalidated.
Definition: record_store_v1_base.cpp:915
virtual StatusWith< RecordData > updateWithDamages(OperationContext *opCtx, const RecordId &loc, const RecordData &oldRec, const char *damageSource, const mutablebson::DamageVector &damages)
Updates the record positioned at 'loc' in-place using the deltas described by 'damages'.
Definition: record_store_v1_base.cpp:412
virtual int64_t storageSize(OperationContext *opCtx, BSONObjBuilder *extraInfo=NULL, int level=0) const
Definition: record_store_v1_base.cpp:143
void save() final
Prepares for state changes in underlying data in a way that allows the cursor's current position to b...
Definition: record_store_v1_base.h:340
DiskLoc _getPrevRecordInExtent(OperationContext *opCtx, const DiskLoc &loc) const
void invalidateCursorsForBucket(DiskLoc bucket)
When a btree-bucket disappears due to merge/split or similar, this invalidates all cursors that point...
Definition: record_store_v1_base.cpp:120
virtual const DiskLoc & lastExtent(OperationContext *opCtx) const =0
DiskLoc getPrevRecord(OperationContext *opCtx, const DiskLoc &loc) const
Definition: record_store_v1_base.cpp:236
This is so when a RecordStore is validating all records it can call back to someone to check if a rec...
Definition: record_store.h:687
virtual void setLastExtent(OperationContext *opCtx, const DiskLoc &loc)=0
Definition: record_store.h:78
represents a disk location/offset on disk in a database.
Definition: diskloc.h:53
virtual long long maxCappedDocs() const =0
static const int bucketSizes[]
Definition: record_store_v1_base.h:157
DiskLoc _getNextRecordInExtent(OperationContext *opCtx, const DiskLoc &loc) const
SavedCursorSet _cursors
Definition: record_store_v1_base.h:149
static bool isQuantized(int recordSize)
Definition: record_store_v1_base.cpp:941
Definition: record.h:58
ExtentManager * _extentManager
Definition: record_store_v1_base.h:319
Allows inserting a Record "in-place" without creating a copy ahead of time.
Definition: record_store.h:62
static const int MaxAllowedAllocation
Definition: record_store_v1_base.h:155
Definition: record.h:150
std::shared_ptr< void > data
Definition: ephemeral_for_test_record_store_test.cpp:74
std::unique_ptr< RecordStore > rs
Definition: kv_engine_test_timestamps.cpp:207
virtual DiskLoc deletedListLegacyGrabBag() const =0
virtual StatusWith< DiskLoc > allocRecord(OperationContext *opCtx, int lengthWithHeaders, bool enforceQuota)=0
virtual void setCapFirstNewRecord(OperationContext *opCtx, const DiskLoc &loc)=0
SpinLock _mutex
Definition: record_store_v1_base.h:146
Iterates over all records within a single extent.
Definition: record_store_v1_base.h:330
DiskLoc bucket
Definition: record_store_v1_base.h:116
The destructor ensures the cursor is unregistered when an exception is thrown.
Definition: record_store_v1_base.h:110
OperationContext Database StringData CollectionOptions bool const BSONObj &idIndex Status
Definition: database_impl.cpp:955
virtual MmapV1RecordHeader * recordFor(const DiskLoc &loc) const
Definition: record_store_v1_base.cpp:192
const RecordStoreV1Base * _rs
Definition: record_store_v1_base.h:361
bool capLooped() const
Definition: record_store_v1_base.h:56
DiskLoc _findFirstSpot(OperationContext *opCtx, const DiskLoc &extDiskLoc, Extent *e)
finds the first suitable DiskLoc for data will return the DiskLoc of a newly created DeletedRecord
Definition: record_store_v1_base.cpp:256
DiskLoc _getExtentLocForRecord(OperationContext *opCtx, const DiskLoc &loc) const
Definition: record_store_v1_base.cpp:210
SavedCursor()
Definition: record_store_v1_base.h:111
virtual void setDeletedListLegacyGrabBag(OperationContext *opCtx, const DiskLoc &loc)=0
bool _isSystemIndexes
Definition: record_store_v1_base.h:320
Definition: index_key_validate.h:40
virtual bool isCapped() const =0
std::unique_ptr< RecordStoreV1MetaData > _details
Definition: record_store_v1_base.h:318
static int quantizeAllocationSpace(int minSize)
Quantize 'minSize' to the nearest allocation size.
Definition: record_store_v1_base.cpp:930
BSONObj key
Definition: record_store_v1_base.h:117
RecordStoreV1Base(StringData ns, RecordStoreV1MetaData *details, ExtentManager *em, bool isSystemIndexes)
Definition: record_store_v1_base.cpp:134
virtual RecordData dataFor(OperationContext *opCtx, const RecordId &loc) const
Get the RecordData at loc, which must exist.
Definition: record_store_v1_base.cpp:174
virtual long long dataSize(OperationContext *opCtx) const
The dataSize is an approximation of the sum of the sizes (in bytes) of the documents or entries in th...
Definition: record_store_v1_base.h:178
virtual bool replaceUserFlags(OperationContext *opCtx, int flags)=0
This iterator will go over the collection twice - once going forward (first extent -> last extent) an...
Definition: record_store_v1_repair_iterator.h:43
virtual void orphanDeletedList(OperationContext *opCtx)=0
OperationContext * _opCtx
Definition: record_store_v1_base.h:359
Retrieves Records from a RecordStore.
Definition: record_store.h:141
virtual bool clearUserFlag(OperationContext *opCtx, int flag)=0
An abstraction used for storing documents in a collection or entries in an index.
Definition: record_store.h:282
DiskLoc bucket
Definition: btree_interface.cpp:336
void reattachToOperationContext(OperationContext *opCtx) final
Reattaches to the OperationContext and reacquires any storage-engine state.
Definition: record_store_v1_base.h:347
virtual bool isUserFlagSet(int flag) const =0
DiskLoc getNextRecordInExtent(OperationContext *opCtx, const DiskLoc &loc) const
Definition: record_store_v1_base.cpp:278
bool isValid() const
Definition: diskloc.h:115
virtual const std::string & ns() const
Definition: record_store.h:295
virtual ~RecordStoreV1MetaData()
Definition: record_store_v1_base.h:48
bool _forward
Definition: record_store_v1_base.h:362
virtual long long dataSize() const =0
virtual void incrementStats(OperationContext *opCtx, long long dataSizeIncrement, long long numRecordsIncrement)=0
DiskLoc _getNextRecord(OperationContext *opCtx, const DiskLoc &loc) const
virtual const DiskLoc & capFirstNewRecord() const =0
std::unique_ptr< RecordFetcher > fetcherForNext() const final
Returns a RecordFetcher if needed for a call to next() or none if unneeded.
Definition: record_store_v1_base.cpp:926
DiskLoc getExtentLocForRecord(OperationContext *opCtx, const DiskLoc &loc) const
void increaseStorageSize(OperationContext *opCtx, int size, bool enforceQuota)
Definition: record_store_v1_base.cpp:520
StatusWith< RecordId > insertRecord(OperationContext *opCtx, const char *data, int len, Timestamp, bool enforceQuota)
Definition: record_store_v1_base.cpp:343
virtual long long numRecords() const =0
Extent * _getExtent(OperationContext *opCtx, const DiskLoc &loc) const
Definition: record_store_v1_base.cpp:206
virtual bool findRecord(OperationContext *opCtx, const RecordId &loc, RecordData *rd) const
Definition: record_store_v1_base.cpp:178
void advance()
Definition: record_store_v1_base.cpp:906
virtual int lastExtentSize(OperationContext *opCtx) const =0
const RecordStoreV1MetaData * details() const
Definition: record_store_v1_base.h:235
ExtentManager basics.
Definition: extent_manager.h:64
const DeletedRecord * deletedRecordFor(const DiskLoc &loc) const
Definition: record_store_v1_base.cpp:196
static int bucket(int size)
Definition: record_store_v1_base.cpp:948
virtual void appendCustomStats(OperationContext *opCtx, BSONObjBuilder *result, double scale) const
Definition: record_store_v1_base.cpp:831
SavedCursorRegistry savedCursors
Definition: record_store_v1_base.h:240
static const int Buckets
Definition: record_store_v1_base.h:154
DiskLoc getPrevRecordInExtent(OperationContext *opCtx, const DiskLoc &loc) const
Definition: record_store_v1_base.cpp:290
Definition: record_store_v1_base.h:46
virtual Status touch(OperationContext *opCtx, BSONObjBuilder *output) const
Load all data into cache.
Definition: record_store_v1_base.cpp:856
void waitForAllEarlierOplogWritesToBeVisible(OperationContext *opCtx) const override
Waits for all writes that completed before this call to be visible to forward scans.
Definition: record_store_v1_base.h:260
void detachFromOperationContext() final
Detaches from the OperationContext and releases any storage-engine state.
Definition: record_store_v1_base.h:344
virtual void setCapExtent(OperationContext *opCtx, const DiskLoc &loc)=0
Collection *const OperationContext *const opCtx
Definition: collection_impl.cpp:80
virtual int userFlags() const =0
void deleteRecord(OperationContext *opCtx, const RecordId &dl)
Definition: record_store_v1_base.cpp:434
Class that stores active cursors that have been saved (as part of yielding) to allow them to be inval...
Definition: record_store_v1_base.h:104
virtual bool updateWithDamagesSupported() const
Definition: record_store_v1_base.cpp:408
virtual void setFirstExtent(OperationContext *opCtx, const DiskLoc &loc)=0
virtual DeletedRecord * drec(const DiskLoc &loc) const
Definition: record_store_v1_base.cpp:201
DiskLoc _getPrevRecord(OperationContext *opCtx, const DiskLoc &loc) const
virtual bool shouldPadInserts() const =0
boost::optional< Record > next() final
Moves forward and returns the new data or boost::none if there is no more data.
Definition: record_store_v1_base.cpp:898
virtual void addDeletedRec(OperationContext *opCtx, const DiskLoc &dloc)=0
bool restore() final
Recovers from potential state changes in underlying data.
Definition: record_store_v1_base.h:341
SavedCursorRegistry * _registry
Definition: record_store_v1_base.h:123
virtual ~SavedCursor()
Definition: record_store_v1_base.h:112
virtual void setLastExtentSize(OperationContext *opCtx, int newMax)=0