This repository has been archived by the owner on Oct 4, 2019. It is now read-only.
forked from steemit/steem
-
Notifications
You must be signed in to change notification settings - Fork 35
/
operation_dump_visitor.hpp
223 lines (165 loc) · 6.81 KB
/
operation_dump_visitor.hpp
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#pragma once
#include <golos/plugins/operation_dump/operation_dump_container.hpp>
#include <golos/protocol/operations.hpp>
#include <golos/chain/comment_object.hpp>
#include <golos/plugins/follow/follow_operations.hpp>
#include <golos/plugins/tags/tag_visitor.hpp>
#include <queue>
namespace golos { namespace plugins { namespace operation_dump {
using namespace golos::plugins::follow;
#define COMMENT_ID(OP) hash_id(std::string(OP.author) + "/" + OP.permlink)
#define TAGS_NUMBER 15
#define TAG_MAX_LENGTH 512
class operation_dump_visitor {
public:
using result_type = void;
dump_buffers& _buffers;
const signed_block& _block;
uint16_t& _op_in_block;
database& _db;
operation_dump_visitor(dump_buffers& buffers, const signed_block& block, uint16_t& op_in_block, database& db)
: _buffers(buffers), _block(block), _op_in_block(op_in_block), _db(db) {
}
uint64_t hash_id(const std::string& id) {
return fc::hash64(id.c_str(), id.length());
}
dump_buffer& write_op_header(const std::string& file_name, uint64_t op_related_id) {
auto& b = _buffers[file_name];
b.write(operation_number(_block.block_num(), _op_in_block));
fc::raw::pack(b, op_related_id);
return b;
}
template<typename T>
auto operator()(const T&) -> result_type {
}
auto operator()(const transfer_operation& op) -> result_type {
auto& b = write_op_header("transfers", 0);
fc::raw::pack(b, op);
fc::raw::pack(b, _block.timestamp);
}
auto operator()(const comment_operation& op) -> result_type {
auto& b = write_op_header("comments", COMMENT_ID(op));
fc::raw::pack(b, op.parent_author);
fc::raw::pack(b, op.parent_permlink);
fc::raw::pack(b, op.author);
fc::raw::pack(b, op.permlink);
fc::raw::pack(b, op.title);
fc::raw::pack(b, op.body);
auto meta = golos::plugins::tags::get_metadata(op.json_metadata, TAGS_NUMBER, TAG_MAX_LENGTH);
fc::raw::pack(b, meta);
fc::raw::pack(b, _block.timestamp);
}
auto operator()(const delete_comment_operation& op) -> result_type {
if (_db.find_comment(op.author, op.permlink)) {
return;
}
write_op_header("delete_comments", COMMENT_ID(op));
}
auto operator()(const comment_benefactor_reward_operation& op) -> result_type {
auto& b = write_op_header("benefactor_rewards", COMMENT_ID(op));
fc::raw::pack(b, op);
}
auto operator()(const author_reward_operation& op) -> result_type {
auto& b = write_op_header("author_rewards", COMMENT_ID(op));
fc::raw::pack(b, op);
}
auto operator()(const curation_reward_operation& op) -> result_type {
auto& b = write_op_header("curation_rewards", hash_id(std::string(op.comment_author) + "/" + op.comment_permlink));
fc::raw::pack(b, op);
}
auto operator()(const auction_window_reward_operation& op) -> result_type {
auto& b = write_op_header("auction_window_rewards", hash_id(std::string(op.comment_author) + "/" + op.comment_permlink));
fc::raw::pack(b, op);
}
auto operator()(const total_comment_reward_operation& op) -> result_type {
auto& b = write_op_header("total_comment_rewards", COMMENT_ID(op));
fc::raw::pack(b, op);
}
auto operator()(const vote_rshares_operation& op) -> result_type {
auto& b = write_op_header("votes", COMMENT_ID(op));
fc::raw::pack(b, op);
fc::raw::pack(b, _block.timestamp);
}
// Not logs if operation failed in plugin, but logs if plugin not exists
auto operator()(const custom_json_operation& op) -> result_type {
if (op.id != "follow") { // follows, reblogs, delete_reblogs
return;
}
std::vector<follow_plugin_operation> fpops;
auto v = fc::json::from_string(op.json);
try {
if (v.is_array() && v.size() > 0 && v.get_array()[0].is_array()) {
fc::from_variant(v, fpops);
} else {
fpops.emplace_back();
fc::from_variant(v, fpops[0]);
}
} catch (...) {
// Normal cases failed, try this strange case from follow-plugin
try {
auto fop = v.as<follow_operation>();
fpops.emplace_back(fop);
} catch (...) {
}
}
for (const follow_plugin_operation& fpop : fpops) {
fpop.visit(*this);
}
}
auto operator()(const follow_operation& op) -> result_type {
auto& b = write_op_header("follows", hash_id(std::string(op.follower) + "/" + op.following));
fc::raw::pack(b, op.follower);
fc::raw::pack(b, op.following);
uint16_t what = 0;
for (const auto& target : op.what) {
if (target == "blog") {
what |= 1 << blog;
} else if (target == "ignore") {
what |= 1 << ignore;
}
}
fc::raw::pack(b, what);
}
auto operator()(const reblog_operation& op) -> result_type {
auto& b = write_op_header("reblogs", COMMENT_ID(op));
fc::raw::pack(b, op.account);
fc::raw::pack(b, op.author);
fc::raw::pack(b, op.permlink);
fc::raw::pack(b, op.title); // Usually empty, but no problems to dump
fc::raw::pack(b, op.body);
// Usually it is:
// {"app": "golos.io/0.1", "format": "text"}
// Not seems to be need
//fc::raw::pack(b, op.json_metadata);
fc::raw::pack(b, _block.timestamp);
}
auto operator()(const delete_reblog_operation& op) -> result_type {
auto& b = write_op_header("delete_reblogs", COMMENT_ID(op));
fc::raw::pack(b, op.account);
}
// TODO: Remove mandatory hash from header to save 8 bytes on each record
auto operator()(const account_create_operation& op) -> result_type {
auto& b = write_op_header("account_metas", 0);
fc::raw::pack(b, op.new_account_name);
fc::raw::pack(b, op.json_metadata);
}
auto operator()(const account_create_with_delegation_operation& op) -> result_type {
auto& b = write_op_header("account_metas", 0);
fc::raw::pack(b, op.new_account_name);
fc::raw::pack(b, op.json_metadata);
}
auto operator()(const account_update_operation& op) -> result_type {
if (op.json_metadata.size() == 0) {
return;
}
auto& b = write_op_header("account_metas", 0);
fc::raw::pack(b, op.account);
fc::raw::pack(b, op.json_metadata);
}
auto operator()(const account_metadata_operation& op) -> result_type {
auto& b = write_op_header("account_metas", 0);
fc::raw::pack(b, op.account);
fc::raw::pack(b, op.json_metadata);
}
};
} } } // golos::plugins::operation_dump