// Copyright (c) 2011 The LevelDB Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. See the AUTHORS file for names of contributors. #ifndef STORAGE_LEVELDB_DB_SNAPSHOT_H_ #define STORAGE_LEVELDB_DB_SNAPSHOT_H_ #include "db/dbformat.h" #include "leveldb/db.h" namespace leveldb { class SnapshotList; // Snapshots are kept in a doubly-linked list in the DB. // Each SnapshotImpl corresponds to a particular sequence number. class SnapshotImpl : public Snapshot { public: SnapshotImpl(SequenceNumber sequence_number) : sequence_number_(sequence_number) {} SequenceNumber sequence_number() const { return sequence_number_; } private: friend class SnapshotList; // SnapshotImpl is kept in a doubly-linked circular list. The SnapshotList // implementation operates on the next/previous fields directly. SnapshotImpl* prev_; SnapshotImpl* next_; const SequenceNumber sequence_number_; #if !defined(NDEBUG) SnapshotList* list_ = nullptr; #endif // !defined(NDEBUG) }; class SnapshotList { public: SnapshotList() : head_(0) { head_.prev_ = &head_; head_.next_ = &head_; } bool empty() const { return head_.next_ == &head_; } SnapshotImpl* oldest() const { assert(!empty()); return head_.next_; } SnapshotImpl* newest() const { assert(!empty()); return head_.prev_; } // Creates a SnapshotImpl and appends it to the end of the list. SnapshotImpl* New(SequenceNumber sequence_number) { assert(empty() || newest()->sequence_number_ <= sequence_number); SnapshotImpl* snapshot = new SnapshotImpl(sequence_number); #if !defined(NDEBUG) snapshot->list_ = this; #endif // !defined(NDEBUG) snapshot->next_ = &head_; snapshot->prev_ = head_.prev_; snapshot->prev_->next_ = snapshot; snapshot->next_->prev_ = snapshot; return snapshot; } // Removes a SnapshotImpl from this list. // // The snapshot must have been created by calling New() on this list. // // The snapshot pointer should not be const, because its memory is // deallocated. However, that would force us to change DB::ReleaseSnapshot(), // which is in the API, and currently takes a const Snapshot. void Delete(const SnapshotImpl* snapshot) { #if !defined(NDEBUG) assert(snapshot->list_ == this); #endif // !defined(NDEBUG) snapshot->prev_->next_ = snapshot->next_; snapshot->next_->prev_ = snapshot->prev_; delete snapshot; } private: // Dummy head of doubly-linked list of snapshots SnapshotImpl head_; }; } // namespace leveldb #endif // STORAGE_LEVELDB_DB_SNAPSHOT_H_