levaldb写入数据(6)
来源:互联网 发布:白夜追凶剧情分析知乎 编辑:程序博客网 时间:2024/06/09 20:30
前言
数据库只有增删改查,我们在以前写了很多废话,这里就不一一叙述,进入增加数据库内容的代码部分,这里依赖上一篇的初始化,不过我们需要的数据结构,再来提示一下,
正文
这里主要介绍增删改查的一些操作,可是这里有一些奇怪的问题,比如数据过长时候灰产生的bug等等,这里暂时不介绍,主要关注主要流程,具体参数等以后一一介绍。
先看增加,
db_->Put(leveldb::WriteOptions(),"love","life");
这个是增加,我们可以很简单的找到是DBIMP中的write()
函数实现了写入操作,具体代码如下:
Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) { Writer w(&mutex_); w.batch = my_batch; w.sync = options.sync; w.done = false; MutexLock l(&mutex_); writers_.push_back(&w); while (!w.done && &w != writers_.front()) { //一直等到w加入成功,或者w是对列的第一个。就不在等待,这存储过程是同步的。 w.cv.Wait(); } if (w.done) { //如果是存入完成,就不存入了,直接退出,这其实是前面的一种情况。 return w.status; } // May temporarily unlock and wait. Status status = MakeRoomForWrite(my_batch == NULL); // uint64_t last_sequence = versions_->LastSequence(); Writer* last_writer = &w; if (status.ok() && my_batch != NULL) { // NULL batch is for compactions WriteBatch* updates = BuildBatchGroup(&last_writer); WriteBatchInternal::SetSequence(updates, last_sequence + 1); last_sequence += WriteBatchInternal::Count(updates); // Add to log and apply to memtable. We can release the lock // during this phase since &w is currently responsible for logging // and protects against concurrent loggers and concurrent writes // into mem_. { mutex_.Unlock(); status = log_->AddRecord(WriteBatchInternal::Contents(updates)); bool sync_error = false; if (status.ok() && options.sync) { status = logfile_->Sync(); if (!status.ok()) { sync_error = true; } } //写到log文件中, if (status.ok()) { status = WriteBatchInternal::InsertInto(updates, mem_); //写入到内存中mem_ } mutex_.Lock(); if (sync_error) { // The state of the log file is indeterminate: the log record we // just added may or may not show up when the DB is re-opened. // So we force the DB into a mode where all future writes fail. RecordBackgroundError(status); } } if (updates == tmp_batch_) tmp_batch_->Clear(); versions_->SetLastSequence(last_sequence); }
这里写入操作为了实现异步,也是费尽了心机,这里稍加解释,吧所有要写入的内容写入到一个list中,等待前面没内容或者这条内容已经写入(其他线程给写入了),就不在等待。MakeRoomForWrite()
这个其实内容挺多的,但是这里写入少量数据,基本不会出错的,这里就暂时不用搞出空间,开始真正的写入,
log_->AddRecord(WriteBatchInternal::Contents(updates));
这个是写入到log文件中,其实也就是特定的一个文件,用来下次恢复内容,这里设计有点奇怪,但是我也说不清楚,不想深入研究这个东东,写入内存是
WriteBatchInternal::InsertInto(updates, mem_);Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* memtable) { MemTableInserter inserter; inserter.sequence_ = WriteBatchInternal::Sequence(b); inserter.mem_ = memtable; return b->Iterate(&inserter);}Status WriteBatch::Iterate(Handler* handler) const {......handler->Put(key, value);....} virtual void Put(const Slice& key, const Slice& value) { mem_->Add(sequence_, kTypeValue, key, value); //其实这里才是添加到内存中。 sequence_++; } void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key, const Slice& value) { // Format of an entry is concatenation of: // key_size : varint32 of internal_key.size() // key bytes : char[internal_key.size()] // value_size : varint32 of value.size() // value bytes : char[value.size()] size_t key_size = key.size(); size_t val_size = value.size(); size_t internal_key_size = key_size + 8; const size_t encoded_len = VarintLength(internal_key_size) + internal_key_size + VarintLength(val_size) + val_size; char* buf = arena_.Allocate(encoded_len); char* p = EncodeVarint32(buf, internal_key_size); memcpy(p, key.data(), key_size); p += key_size; EncodeFixed64(p, (s << 8) | type); p += 8; p = EncodeVarint32(p, val_size); memcpy(p, value.data(), val_size); assert((p + val_size) - buf == encoded_len); table_.Insert(buf);}typedef SkipList<const char*, KeyComparator> Table;Table table_;
这里废了好大劲,就是这种,关于SKipList,到底是啥,这里暂时不去介绍,我们现在默认他是一个list即可。
Status DBImpl::Get(const ReadOptions& options, const Slice& key, std::string* value) { ... mem->Get(lkey, value, &s) ...}
关于MemberTable的Get这里暂时也不详细介绍,主要流程大概就是这样,所有的数据都保存在mem_中
关于删除
Status DB::Delete(const WriteOptions& opt, const Slice& key) { WriteBatch batch; batch.Delete(key); return Write(opt, &batch);Status WriteBatch::Iterate(Handler* handler) const { ...... case kTypeDeletion: if (GetLengthPrefixedSlice(&input, &key)) { handler->Delete(key); ......} virtual void Delete(const Slice& key) { mem_->Add(sequence_, kTypeDeletion, key, Slice()); sequence_++; }
其他部分这里不介绍了,等着下一篇完全解析mem_的结构,好好看看增删改查如何实现,
后记
这里等了好久,终于读完了DBIMP的主要流程,发现又遇到一个坑,这里我们慢慢踩,这些代码,我总有一天,可以啃完,以后可以慢慢分析一下指针和引用等一些知识,
阅读全文
0 0
- levaldb写入数据(6)
- 简单的数据写入(质数写入文件)
- Writestring无法写入数据(中文文本)
- 写入结构数据 (Write from structure)
- mybatis中批量写入(insert)数据
- 打开文件,写入数据(文件操作)
- AVAssetWriter写入char*数据(video)
- 写入image类型数据
- 图片数据写入SQL
- java写入大量数据
- C++ 数据写入文件
- 数据页的写入
- Datagridview数据写入DataTable
- 数据写入流量控制
- ofstream写入数据
- 将数据写入文件
- HBase数据写入测试
- QQWry.dat 数据写入
- Centos6、7安装Java(jdk+mysql+tomcat)环境傻瓜式教程
- 新文档
- 死锁
- Codeforces Round #424 E. Cards Sorting 线段树/数据结构瞎搞/模拟
- 基础编程题目集-厘米换算英尺英寸
- levaldb写入数据(6)
- java多线程中wait()和sleep()方法的区别
- poj 3320
- C++实现第一个Windows程序设计Hello World
- Memcache的使用与安全
- 《计算机操作系统原理—linux实例分析》_肖竞华_第二章_知识点
- [POJ 1062]昂贵的聘礼
- 《计算机操作系统-linux实例分析》_肖劲华_第三章_知识点
- CoreJava day02