blob: 4e9c4ac671e489209bb8792a6a02375588ede03d [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_INDEXED_DB_LEVELDB_TRANSACTIONAL_LEVELDB_ITERATOR_H_
#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_TRANSACTIONAL_LEVELDB_ITERATOR_H_
#include <memory>
#include <tuple>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
namespace leveldb {
class Comparator;
class Iterator;
} // namespace leveldb
namespace content {
class TransactionalLevelDBDatabase;
class TransactionalLevelDBTransaction;
class LevelDBSnapshot;
namespace indexed_db {
class DefaultLevelDBFactory;
}
// This iterator is meant to stay 'live' to the data on disk for a given
// transaction, and be evict-able for saving memory. Specifically, it supports:
// * Staying up to date with the data on disk as long as the NotifyModified
// method is called for every change, and
// * detaching itself (unloading it's leveldb::Iterator) to reduce memory when
// EvictLevelDBIterator is called.
// Note: the returned base::StringPiece from Key or Value can become
// invalidated when EvictLevelDBIterator, OnDatabaseKeyModified, or
// OnDatabaseRangeModified are called.
class CONTENT_EXPORT TransactionalLevelDBIterator {
public:
virtual ~TransactionalLevelDBIterator();
virtual bool IsValid() const;
virtual leveldb::Status SeekToLast();
virtual leveldb::Status Seek(const base::StringPiece& target);
virtual leveldb::Status Next();
virtual leveldb::Status Prev();
// The returned base::StringPiece can be invalidated when
// EvictLevelDBIterator is called.
virtual base::StringPiece Key() const;
// The returned base::StringPiece can be invalidated when
// EvictLevelDBIterator is called.
virtual base::StringPiece Value() const;
// Evicts the internal leveldb::Iterator, which helps save memory at the
// performance expense of reloading and seeking later if the iterator is
// needed again for |Seek*|, |Next|, or |Prev|.
void EvictLevelDBIterator();
bool IsEvicted() const { return iterator_state_ != IteratorState::kActive; }
protected:
friend class indexed_db::DefaultLevelDBFactory;
TransactionalLevelDBIterator(
std::unique_ptr<leveldb::Iterator> iterator,
base::WeakPtr<TransactionalLevelDBDatabase> db,
base::WeakPtr<TransactionalLevelDBTransaction> txn,
std::unique_ptr<LevelDBSnapshot> snapshot);
private:
enum class Direction { kNext, kPrev };
enum class IteratorState { kActive, kEvictedAndValid, kEvictedAndInvalid };
leveldb::Status WrappedIteratorStatus() WARN_UNUSED_RESULT;
// Notifies the database of iterator usage and recreates iterator if needed.
// If the iterator was previously evicted, this method returns the key that
// was used, the status of reloading the iterator.
std::tuple<std::string, leveldb::Status> WillUseDBIterator(bool perform_seek)
WARN_UNUSED_RESULT;
// If this method fails, then iterator_ will be nullptr.
leveldb::Status ReloadIterator() WARN_UNUSED_RESULT;
void NextPastScopesMetadata();
void PrevPastScopesMetadata();
void CheckState() const;
// WeakPtr to allow lazy destruction order. This is assumed to be valid for
// all other Iterator operations.
base::WeakPtr<TransactionalLevelDBDatabase> db_;
const std::vector<uint8_t>& scopes_metadata_prefix_;
base::WeakPtr<TransactionalLevelDBTransaction> txn_;
// State used to facilitate memory purging.
IteratorState iterator_state_ = IteratorState::kActive;
// Non-null iff |iterator_state_| is kActive.
std::unique_ptr<leveldb::Iterator> iterator_;
// Empty if |iterator_state_| is kActive.
std::string key_before_eviction_;
// Empty if |iterator_state_| is kActive.
std::string value_before_eviction_;
// Non-null iff |iterator_state_| is kActive.
std::unique_ptr<LevelDBSnapshot> snapshot_;
const leveldb::Comparator* const comparator_;
DISALLOW_COPY_AND_ASSIGN(TransactionalLevelDBIterator);
};
} // namespace content
#endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_TRANSACTIONAL_LEVELDB_ITERATOR_H_