fork of https://github.com/oxigraph/rocksdb and https://github.com/facebook/rocksdb for nextgraph and oxigraph
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
5.1 KiB
172 lines
5.1 KiB
11 years ago
|
#include "db/transaction_log_impl.h"
|
||
12 years ago
|
#include "db/write_batch_internal.h"
|
||
12 years ago
|
|
||
12 years ago
|
namespace leveldb {
|
||
|
|
||
|
TransactionLogIteratorImpl::TransactionLogIteratorImpl(
|
||
12 years ago
|
const std::string& dbname,
|
||
|
const Options* options,
|
||
12 years ago
|
const EnvOptions& soptions,
|
||
11 years ago
|
const SequenceNumber seq,
|
||
|
std::unique_ptr<VectorLogPtr> files,
|
||
12 years ago
|
SequenceNumber const * const lastFlushedSequence) :
|
||
11 years ago
|
dbname_(dbname),
|
||
|
options_(options),
|
||
|
soptions_(soptions),
|
||
|
startingSequenceNumber_(seq),
|
||
|
files_(std::move(files)),
|
||
|
started_(false),
|
||
|
isValid_(false),
|
||
|
currentFileIndex_(0),
|
||
|
lastFlushedSequence_(lastFlushedSequence) {
|
||
|
assert(startingSequenceNumber_ <= *lastFlushedSequence_);
|
||
12 years ago
|
assert(files_.get() != nullptr);
|
||
12 years ago
|
|
||
12 years ago
|
reporter_.env = options_->env;
|
||
|
reporter_.info_log = options_->info_log.get();
|
||
12 years ago
|
}
|
||
|
|
||
12 years ago
|
Status TransactionLogIteratorImpl::OpenLogFile(
|
||
11 years ago
|
const LogFile* logFile,
|
||
12 years ago
|
unique_ptr<SequentialFile>* file) {
|
||
12 years ago
|
Env* env = options_->env;
|
||
11 years ago
|
if (logFile->Type() == kArchivedLogFile) {
|
||
|
std::string fname = ArchivedLogFileName(dbname_, logFile->LogNumber());
|
||
12 years ago
|
return env->NewSequentialFile(fname, file, soptions_);
|
||
12 years ago
|
} else {
|
||
11 years ago
|
std::string fname = LogFileName(dbname_, logFile->LogNumber());
|
||
12 years ago
|
Status status = env->NewSequentialFile(fname, file, soptions_);
|
||
12 years ago
|
if (!status.ok()) {
|
||
|
// If cannot open file in DB directory.
|
||
|
// Try the archive dir, as it could have moved in the meanwhile.
|
||
11 years ago
|
fname = ArchivedLogFileName(dbname_, logFile->LogNumber());
|
||
12 years ago
|
status = env->NewSequentialFile(fname, file, soptions_);
|
||
12 years ago
|
if (!status.ok()) {
|
||
|
return Status::IOError(" Requested file not present in the dir");
|
||
|
}
|
||
|
}
|
||
|
return status;
|
||
|
}
|
||
|
}
|
||
|
|
||
12 years ago
|
BatchResult TransactionLogIteratorImpl::GetBatch() {
|
||
12 years ago
|
assert(isValid_); // cannot call in a non valid state.
|
||
12 years ago
|
BatchResult result;
|
||
|
result.sequence = currentSequence_;
|
||
|
result.writeBatchPtr = std::move(currentBatch_);
|
||
|
return result;
|
||
12 years ago
|
}
|
||
|
|
||
|
Status TransactionLogIteratorImpl::status() {
|
||
|
return currentStatus_;
|
||
|
}
|
||
|
|
||
|
bool TransactionLogIteratorImpl::Valid() {
|
||
|
return started_ && isValid_;
|
||
|
}
|
||
|
|
||
|
void TransactionLogIteratorImpl::Next() {
|
||
11 years ago
|
LogFile* currentLogFile = files_.get()->at(currentFileIndex_).get();
|
||
12 years ago
|
|
||
|
// First seek to the given seqNo. in the current file.
|
||
12 years ago
|
std::string scratch;
|
||
|
Slice record;
|
||
|
if (!started_) {
|
||
12 years ago
|
started_ = true; // this piece only runs onced.
|
||
12 years ago
|
isValid_ = false;
|
||
12 years ago
|
if (startingSequenceNumber_ > *lastFlushedSequence_) {
|
||
12 years ago
|
currentStatus_ = Status::IOError("Looking for a sequence, "
|
||
|
"which is not flushed yet.");
|
||
|
return;
|
||
|
}
|
||
12 years ago
|
Status s = OpenLogReader(currentLogFile);
|
||
|
if (!s.ok()) {
|
||
|
currentStatus_ = s;
|
||
|
isValid_ = false;
|
||
12 years ago
|
return;
|
||
|
}
|
||
12 years ago
|
while (currentLogReader_->ReadRecord(&record, &scratch)) {
|
||
12 years ago
|
if (record.size() < 12) {
|
||
12 years ago
|
reporter_.Corruption(
|
||
12 years ago
|
record.size(), Status::Corruption("log record too small"));
|
||
|
continue;
|
||
|
}
|
||
12 years ago
|
UpdateCurrentWriteBatch(record);
|
||
12 years ago
|
if (currentSequence_ >= startingSequenceNumber_) {
|
||
12 years ago
|
assert(currentSequence_ <= *lastFlushedSequence_);
|
||
12 years ago
|
isValid_ = true;
|
||
|
break;
|
||
12 years ago
|
} else {
|
||
|
isValid_ = false;
|
||
12 years ago
|
}
|
||
|
}
|
||
12 years ago
|
if (isValid_) {
|
||
|
// Done for this iteration
|
||
|
return;
|
||
12 years ago
|
}
|
||
12 years ago
|
}
|
||
|
bool openNextFile = true;
|
||
|
while(openNextFile) {
|
||
12 years ago
|
assert(currentLogReader_);
|
||
12 years ago
|
if (currentSequence_ < *lastFlushedSequence_) {
|
||
|
if (currentLogReader_->IsEOF()) {
|
||
|
currentLogReader_->UnmarkEOF();
|
||
|
}
|
||
|
while (currentLogReader_->ReadRecord(&record, &scratch)) {
|
||
|
if (record.size() < 12) {
|
||
12 years ago
|
reporter_.Corruption(
|
||
12 years ago
|
record.size(), Status::Corruption("log record too small"));
|
||
|
continue;
|
||
|
} else {
|
||
|
UpdateCurrentWriteBatch(record);
|
||
|
openNextFile = false;
|
||
|
break;
|
||
|
}
|
||
12 years ago
|
}
|
||
|
}
|
||
|
|
||
|
if (openNextFile) {
|
||
12 years ago
|
if (currentFileIndex_ < files_.get()->size() - 1) {
|
||
12 years ago
|
++currentFileIndex_;
|
||
11 years ago
|
Status status =OpenLogReader(files_.get()->at(currentFileIndex_).get());
|
||
12 years ago
|
if (!status.ok()) {
|
||
|
isValid_ = false;
|
||
|
currentStatus_ = status;
|
||
|
return;
|
||
|
}
|
||
|
} else {
|
||
|
isValid_ = false;
|
||
12 years ago
|
openNextFile = false;
|
||
|
if (currentSequence_ == *lastFlushedSequence_) {
|
||
|
currentStatus_ = Status::OK();
|
||
|
} else {
|
||
|
currentStatus_ = Status::IOError(" NO MORE DATA LEFT");
|
||
|
}
|
||
12 years ago
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
12 years ago
|
void TransactionLogIteratorImpl::UpdateCurrentWriteBatch(const Slice& record) {
|
||
|
WriteBatch* batch = new WriteBatch();
|
||
|
WriteBatchInternal::SetContents(batch, record);
|
||
|
currentSequence_ = WriteBatchInternal::Sequence(batch);
|
||
|
currentBatch_.reset(batch);
|
||
12 years ago
|
isValid_ = true;
|
||
12 years ago
|
currentStatus_ = Status::OK();
|
||
12 years ago
|
}
|
||
|
|
||
11 years ago
|
Status TransactionLogIteratorImpl::OpenLogReader(const LogFile* logFile) {
|
||
12 years ago
|
unique_ptr<SequentialFile> file;
|
||
|
Status status = OpenLogFile(logFile, &file);
|
||
|
if (!status.ok()) {
|
||
|
return status;
|
||
|
}
|
||
|
assert(file);
|
||
|
currentLogReader_.reset(
|
||
12 years ago
|
new log::Reader(std::move(file), &reporter_, true, 0)
|
||
12 years ago
|
);
|
||
|
return Status::OK();
|
||
|
}
|
||
12 years ago
|
} // namespace leveldb
|