Skip to content

Commit 0efabfe

Browse files
添加write batch事务的实现
1 parent 0f9172c commit 0efabfe

14 files changed

+214
-23
lines changed

demo/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
cmake_minimum_required(VERSION 3.9)
22
# Keep the version below in sync with the one in db.h
3-
project(leveldb VERSION 1.23.0 LANGUAGES C CXX)
43

54

65

@@ -19,4 +18,8 @@ target_link_libraries(test
1918
PUBLIC leveldb)
2019

2120
target_include_directories(test
22-
PUBLIC ${PROJECT_SOURCE_DIR}/../include)
21+
PUBLIC ${PROJECT_SOURCE_DIR}/include)
22+
23+
24+
# 添加各个算法测试代码
25+
add_subdirectory(batch_test)

demo/batch_test/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
cmake_minimum_required(VERSION 3.9)
2+
# Keep the version below in sync with the one in db.h
3+
# 这里一旦指定project那么下面所有的 ${PROJECT_SOURCE_DIR} 都会变成当前目录
4+
#project(leveldb VERSION 1.23.0 LANGUAGES C CXX)
5+
6+
7+
add_executable(write_batch
8+
write_batch_main.cpp
9+
write_batch_demo.cpp)
10+
11+
#target_link_libraries(test
12+
# PUBLIC leveldb)
13+
14+
target_include_directories(write_batch
15+
PUBLIC ${PROJECT_SOURCE_DIR}/include)
16+

demo/batch_test/write_batch_demo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//
2+
// Created by wangyz38535 on 2023/12/5.
3+
//
4+
5+
#include "write_batch_demo.h"

demo/batch_test/write_batch_demo.h

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//
2+
// Created by wangyz38535 on 2023/12/5.
3+
//
4+
5+
#ifndef LEVELDB_WRITE_BATCH_DEMO_H
6+
#define LEVELDB_WRITE_BATCH_DEMO_H
7+
8+
#include <algorithm>
9+
#include <string>
10+
#include "leveldb/slice.h"
11+
#include "leveldb/export.h"
12+
#include "leveldb/status.h"
13+
14+
/*
15+
* 对write_bach 进行重新实现,一般理解里面的实现原理
16+
*
17+
* */
18+
namespace WRITE_BATCH_DEMO {
19+
20+
21+
class WriteBatch {
22+
public:
23+
class LEVELDB_EXPORT Handler {
24+
public:
25+
virtual ~Handler();
26+
27+
virtual void Put(const leveldb::Slice &key, const leveldb::Slice &value) = 0;
28+
29+
virtual void Delete(const leveldb::Slice &key) = 0;
30+
};
31+
32+
WriteBatch();
33+
34+
// Intentionally copyable.
35+
WriteBatch(const WriteBatch &) = default;
36+
37+
WriteBatch &operator=(const WriteBatch &) = default;
38+
39+
~WriteBatch();
40+
41+
// Store the mapping "key->value" in the database.
42+
void Put(const leveldb::Slice &key, const leveldb::Slice &value);
43+
44+
// If the database contains a mapping for "key", erase it. Else do nothing.
45+
void Delete(const leveldb::Slice &key);
46+
47+
// Clear all updates buffered in this batch.
48+
void Clear();
49+
50+
// The size of the database changes caused by this batch.
51+
//
52+
// This number is tied to implementation details, and may change across
53+
// releases. It is intended for LevelDB usage metrics.
54+
size_t ApproximateSize() const;
55+
56+
// Copies the operations in "source" to this batch.
57+
//
58+
// This runs in O(source size) time. However, the constant factor is better
59+
// than calling Iterate() over the source batch with a Handler that replicates
60+
// the operations into this batch.
61+
void Append(const WriteBatch &source);
62+
63+
// Support for iterating over the contents of a batch.
64+
leveldb::Status Iterate(Handler *handler) const;
65+
66+
private:
67+
friend class WriteBatchInternal;
68+
69+
std::string rep_; // See comment in write_batch.cc for the format of rep_
70+
};
71+
72+
}
73+
74+
class write_batch_demo {
75+
76+
};
77+
78+
79+
#endif //LEVELDB_WRITE_BATCH_DEMO_H
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//
2+
// Created by wangyz38535 on 2023/12/5.
3+
//
4+
5+
#include "write_batch_internal_demo.h"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//
2+
// Created by wangyz38535 on 2023/12/5.
3+
//
4+
5+
#ifndef LEVELDB_WRITE_BATCH_INTERNAL_DEMO_H
6+
#define LEVELDB_WRITE_BATCH_INTERNAL_DEMO_H
7+
8+
9+
class write_batch_internal_demo {
10+
11+
};
12+
13+
14+
#endif //LEVELDB_WRITE_BATCH_INTERNAL_DEMO_H

demo/batch_test/write_batch_main.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// Created by wangyz38535 on 2023/12/5.
3+
//
4+
#include <iostream>
5+
6+
#include "write_batch_demo.h"
7+
8+
9+
int main(int argc, char **argv) {
10+
11+
12+
13+
return 0;
14+
}
15+
16+

demo/leveldb_exec.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ int main(int argc, char *argv[]) {
2121
// 数据库的读写
2222
std::string value = "value";
2323
std::string key1 = "key1";
24+
leveldb::WriteOptions write_options;
25+
write_options.sync = true;
2426

25-
auto s = db->Put(leveldb::WriteOptions(), key1, value);
27+
auto s = db->Put(write_options, key1, value);
2628

2729
for (int i = 0; i < 100; ++i) {
2830
std::string key = to_string(i);

demo/test.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,37 @@
1414
#include <set>
1515
#include <iostream>
1616
#include <cassert>
17+
#include <functional>
1718
#include "leveldb/write_batch.h"
1819
#include "leveldb/db.h"
1920

2021
using namespace std;
2122

23+
template<int max>
24+
class A {
25+
26+
private:
27+
int m_a;
28+
};
29+
30+
class B {
31+
public:
32+
33+
34+
private:
35+
int m_b;
36+
};
37+
2238

23-
const uint64_t CREATE_SQL_STR_LEN = 1024 * 1024;
2439

2540
int main(int argc, char *argv[]) {
2641

27-
int *lpData = nullptr;
28-
std::cout << sizeof(*lpData) << std::endl;
42+
const std::set<int32_t> data1;
43+
const std::set<int32_t> &data = data1;
44+
45+
46+
47+
std::end(data);
2948

3049

3150
return 0;

doc/index.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ ____
3131

3232

3333
include::instruction/readme.adoc[readme]
34+
// impl中进行总体介绍,在后面跟着对应的实现
3435
include::instruction/impl.adoc[impl]
36+
include::instruction/write_batch_impl.adoc[write_batch_impl]
3537

3638
include::persistence/log_format.adoc[log_format]
3739

doc/instruction/impl.adoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,12 @@ endif::rootpath[]
2626

2727

2828

29+
=== write batch
30+
levelDB虽然只是一个简单的键值对数据库,但是其中关于数据的处理特别是对slice的使用,简直是玩出花来了,非常值的参考,write batch的实现就是一个例子。
31+
32+
33+
34+
35+
36+
37+

doc/instruction/readme.adoc

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -208,29 +208,18 @@ if (s.ok()) {
208208

209209
WriteBatch将一些列动作封装成一个原子操作,当需要对数据库进行多次修改时,可以将这些操作封装成一个batch,这样能有效加快这些更改。
210210

211-
== Synchronous Writes
211+
== 同步写
212212

213-
By default, each write to leveldb is asynchronous: it returns after pushing the
214-
write from the process into the operating system. The transfer from operating
215-
system memory to the underlying persistent storage happens asynchronously. The
216-
sync flag can be turned on for a particular write to make the write operation
217-
not return until the data being written has been pushed all the way to
218-
persistent storage. (On Posix systems, this is implemented by calling either
219-
`fsync(...)` or `fdatasync(...)` or `msync(..., MS_SYNC)` before the write
220-
operation returns.)
213+
每次levelDB的写操作其实都是异步的,当调用完系统接口之后接口就会返回,这时文件只是到系统内存并没有进行持久化,但是系统内存到真正的持久化之间是异步执行的。当需要接口同步写时可以将sync flag设置给put的WriteOptions,这样就能保证接口返回之前已经将值都写入到持久化文件里了。(在UNIX系统上是通过在写操作返回之前调用`fsync(...)` or `fdatasync(...)` or `msync(..., MS_SYNC)`等接口实现。)
221214

222-
```c++
215+
[source,c++]
216+
----
223217
leveldb::WriteOptions write_options;
224218
write_options.sync = true;
225219
db->Put(write_options, ...);
226-
```
220+
----
227221

228-
Asynchronous writes are often more than a thousand times as fast as synchronous
229-
writes. The downside of asynchronous writes is that a crash of the machine may
230-
cause the last few updates to be lost. Note that a crash of just the writing
231-
process (i.e., not a reboot) will not cause any loss since even when sync is
232-
false, an update is pushed from the process memory into the operating system
233-
before it is considered done.
222+
异步写的速度是同步写的千倍左右,异步写的问题就是系统崩溃时可能会丢失部分数据。
234223

235224
Asynchronous writes can often be used safely. For example, when loading a large
236225
amount of data into the database you can handle lost updates by restarting the

doc/instruction/write_batch_impl.adoc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
:toc:
2+
3+
:icons: font
4+
5+
// 保证所有的目录层级都可以正常显示图片
6+
:path: instruction/
7+
:imagesdir: ../image/
8+
:srcdir: ../src
9+
10+
11+
// 只有book调用的时候才会走到这里
12+
ifdef::rootpath[]
13+
:imagesdir: {rootpath}{path}{imagesdir}
14+
:srcdir: {rootpath}../src/
15+
endif::rootpath[]
16+
17+
ifndef::rootpath[]
18+
:rootpath: ../
19+
:srcdir: {rootpath}{path}../src/
20+
endif::rootpath[]
21+
22+
23+
== write batch
24+
25+

doc/persistence/log_format.adoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,10 @@ bytes free in the third block, which will be left empty as the trailer.
101101
2. No compression. Again, this could be fixed by adding new record types.
102102

103103

104+
105+
106+
107+
108+
109+
110+

0 commit comments

Comments
 (0)