2011-03-18 22:37:00 +00:00
|
|
|
// 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_
|
|
|
|
|
2014-12-11 08:02:45 -08:00
|
|
|
#include "db/dbformat.h"
|
2011-03-30 18:35:40 +00:00
|
|
|
#include "leveldb/db.h"
|
2011-03-18 22:37:00 +00:00
|
|
|
|
|
|
|
namespace leveldb {
|
|
|
|
|
|
|
|
class SnapshotList;
|
|
|
|
|
|
|
|
// Snapshots are kept in a doubly-linked list in the DB.
|
2011-05-21 02:17:43 +00:00
|
|
|
// Each SnapshotImpl corresponds to a particular sequence number.
|
|
|
|
class SnapshotImpl : public Snapshot {
|
2011-03-18 22:37:00 +00:00
|
|
|
public:
|
2018-04-30 15:11:03 -07:00
|
|
|
SnapshotImpl(SequenceNumber sequence_number)
|
|
|
|
: sequence_number_(sequence_number) {}
|
|
|
|
|
|
|
|
SequenceNumber sequence_number() const { return sequence_number_; }
|
2011-03-18 22:37:00 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
friend class SnapshotList;
|
|
|
|
|
2018-04-30 15:11:03 -07:00
|
|
|
// SnapshotImpl is kept in a doubly-linked circular list. The SnapshotList
|
|
|
|
// implementation operates on the next/previous fields direcly.
|
2011-05-21 02:17:43 +00:00
|
|
|
SnapshotImpl* prev_;
|
|
|
|
SnapshotImpl* next_;
|
2011-03-18 22:37:00 +00:00
|
|
|
|
2018-04-30 15:11:03 -07:00
|
|
|
const SequenceNumber sequence_number_;
|
|
|
|
|
|
|
|
#if !defined(NDEBUG)
|
|
|
|
SnapshotList* list_ = nullptr;
|
|
|
|
#endif // !defined(NDEBUG)
|
2011-03-18 22:37:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class SnapshotList {
|
|
|
|
public:
|
2018-04-30 15:11:03 -07:00
|
|
|
SnapshotList() : head_(0) {
|
|
|
|
head_.prev_ = &head_;
|
|
|
|
head_.next_ = &head_;
|
2011-03-18 22:37:00 +00:00
|
|
|
}
|
|
|
|
|
2018-04-30 15:11:03 -07:00
|
|
|
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;
|
2011-03-18 22:37:00 +00:00
|
|
|
}
|
|
|
|
|
2018-04-30 15:11:03 -07:00
|
|
|
// 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;
|
2011-03-18 22:37:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Dummy head of doubly-linked list of snapshots
|
2018-04-30 15:11:03 -07:00
|
|
|
SnapshotImpl head_;
|
2011-03-18 22:37:00 +00:00
|
|
|
};
|
|
|
|
|
2011-10-31 17:22:06 +00:00
|
|
|
} // namespace leveldb
|
2011-03-18 22:37:00 +00:00
|
|
|
|
|
|
|
#endif // STORAGE_LEVELDB_DB_SNAPSHOT_H_
|