-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathjournal.cpp
More file actions
174 lines (141 loc) · 5.78 KB
/
Copy pathjournal.cpp
File metadata and controls
174 lines (141 loc) · 5.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include "drive.hpp"
#include "block.hpp"
#include "fast_hash.hpp"
#include "logic_error.hpp"
#include <cstring>
namespace AppenDB {
/*
FIXME: the following implementation is not durable or performant.
*/
void Drive::begin_next_transaction(UserData user_data){
//assert(!current_transaction_begin());
current_transaction_begin() = 1;
current_transaction_write_pointer() = user_data;
}
void Drive::write_data(const char *data, size_t data_size, size_t target_disk_offset){
//assert(current_transaction_begin());
::std::memcpy(disk() + target_disk_offset, data, data_size);
}
void Drive::write_data_pointer(size_t data_size, size_t target_disk_offset, char*& target_pointer, size_t& target_pointer_capacity){
//assert(current_transaction_begin());
target_pointer = disk() + target_disk_offset;
target_pointer_capacity = data_size;
}
void Drive::get_next_pointer(char*& target_pointer, size_t& target_pointer_capacity){
emit_logic_error("Should not be used");
}
void Drive::commit_transaction(){
//assert(current_transaction_begin());
current_transaction_begin() = 0;
on_commit(current_transaction_write_pointer());
}
void Drive::cancel_transaction(){
emit_logic_error("Not Implemented");
// TODO: if this gets implemented, it will need to account for the changes to the block index properly
}
void Drive::initialize_journal(){
current_transaction_begin() = 0;
current_transaction_write_pointer() = 0;
}
void Drive::apply_journal(char* disk, const char *journal_start, const char *journal_end){}
/*
ASSUMPTIONS:
operations on 16 byte chunks are atomic
JOURNAL HEADER (bytes 128 - 4096):
USED ENTRY (4 bytes) {
32 bits: block index
}
UNUSED ENTRY (4 bytes) {
32 bits: 0xFFFFFFFF
}
Note that any blocks referenced in the journal will automatically be converted to a special journaling block on restart
They will also be written that way in memory, but that won't be synced because it is implicit in the journal
In order to free these, the change back to a free block should be journalled and written to that spot on disk
JOURNAL BLOCK
HEADER:
32 bits: end transaction magic number
32 bits: begin transaction magic number
32 bits: offset to the first transaction on this block
32 bits: reserved (0)
TRANSACTION[]:
HEADER:
32 bits: begin transaction magic number
1 bit: possibly needs to be written (note that this is also used for transactions that aren't ready to commit)
31 bits: transaction length (counting header & footer)
64 bits: user data
ENTRY[]:
1 bit: reserved (0)
31 bits: data to write length
48 bits: disk offset
n bytes: data
FOOTER:
n bytes: to pad to an 8-byte boundary
1 bit: reserved (0)
31 bits: transaction length (counting header & footer)
32 bits: end transaction magic number
FOOTER (only used when the end of the block is reached):
32 bits: end transaction magic number
32 bits: begin transaction magic number
NOTE:
the magic numbers should be picked such that the particular value isn't present on
the drive at the time that it is picked. However, it can appear in the middle
of a transaction. It just can't accidentally fall at the key spot that
corresponds to the beginning or end of a transaction because that will mean
an incompletely written transaction might get marked as completed causing
garbage data to be written.
*/
/*
The size_t properties for tracking drive position are in this form:
32 bits: the offset into the block (starting from the beginning of the block, not the end of the header)
32 bits: block index
char* disk() const;
size_t& current_transaction_flushed_begin();
size_t& current_transaction_committed_begin();
size_t& current_transaction_begin();
size_t& current_transaction_write_pointer();
char* drive_journal_start() const;
char* drive_journal_end() const;
*/
/*
unsigned int get_journal_block_index_from_size_t(size_t s){
return s >> 32;
}
uint32_t get_block_index_from_journal_block_index(const char *journal_start, unsigned int index){
assert(index < 248);
return reinterpret_cast<const uint32_t*>(journal_start)[index];
}
uint32_t get_block_index_from_size_t(const char *journal_start, size_t s){
return get_block_index_from_journal_block_index(journal_start, get_journal_block_index_from_size_t(s));
}
const size_t JOURNAL_HEADER_LENGTH = 16;
const size_t JOURNAL_HEADER_OFFSET = 0;
const size_t JOURNAL_HEADER_OFFSET_END = JOURNAL_HEADER_LENGTH;
const size_t JOURNAL_FOOTER_LENGTH = 8;
const size_t JOURNAL_FOOTER_OFFSET = DRIVE_BLOCK_SIZE - JOURNAL_FOOTER_LENGTH;
const size_t JOURNAL_FOOTER_OFFSET_END = DRIVE_BLOCK_SIZE;
void Drive::apply_journal(char* __restrict disk, const char * __restrict journal_start, const char * __restrict journal_end){
...
}
void Drive::begin_next_transaction(uint64_t user_data){
assert(!current_transaction_begin());
assert(!(current_transaction_write_pointer() & 0x7));
current_transaction_begin() = current_transaction_write_pointer();
const uint32_t block = get_block_index_from_journal_block_index(drive_journal_start(), current_transaction_write_pointer());
char* block_begin = blocks() +
...
}
void Drive::write_data(const char *data, size_t data_size, size_t target_disk_offset){
assert(current_transaction_begin());
...
}
void Drive::commit_transaction(){
assert(current_transaction_begin());
...
}
void Drive::cancel_transaction(){
assert(current_transaction_begin());
current_transaction_write_pointer() = current_transaction_begin();
current_transaction_begin() = 0;
}
*/
}