Skip to content

Commit 45bdd37

Browse files
committed
fixes to binary serialization caused by overloaded operators
1 parent aa2a693 commit 45bdd37

File tree

6 files changed

+131
-50
lines changed

6 files changed

+131
-50
lines changed

libraries/chain/include/eosio/chain/database_utils.hpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ namespace eosio { namespace chain {
6262
}
6363
};
6464

65+
template<typename DataStream>
66+
DataStream& operator << ( DataStream& ds, const shared_blob& b ) {
67+
fc::raw::pack(ds, static_cast<const shared_string&>(b));
68+
return ds;
69+
}
70+
71+
template<typename DataStream>
72+
DataStream& operator >> ( DataStream& ds, shared_blob& b ) {
73+
fc::raw::unpack(ds, static_cast<shared_string &>(b));
74+
return ds;
75+
}
6576
} }
6677

6778
namespace fc {
@@ -131,30 +142,18 @@ namespace fc {
131142
from_variant(v, _v);
132143
sv = eosio::chain::shared_vector<T>(_v.begin(), _v.end(), sv.get_allocator());
133144
}
134-
135-
template<typename DataStream>
136-
DataStream& operator << ( DataStream& ds, const eosio::chain::shared_blob& b ) {
137-
fc::raw::pack(ds, static_cast<const eosio::chain::shared_string&>(b));
138-
return ds;
139-
}
140-
141-
template<typename DataStream>
142-
DataStream& operator >> ( DataStream& ds, eosio::chain::shared_blob& b ) {
143-
fc::raw::unpack(ds, static_cast<eosio::chain::shared_string &>(b));
144-
return ds;
145-
}
146145
}
147146

148147
namespace chainbase {
149148
// overloads for OID packing
150149
template<typename DataStream, typename OidType>
151-
DataStream& operator << ( DataStream& ds, const chainbase::oid<OidType>& oid ) {
150+
DataStream& operator << ( DataStream& ds, const oid<OidType>& oid ) {
152151
fc::raw::pack(ds, oid._id);
153152
return ds;
154153
}
155154

156155
template<typename DataStream, typename OidType>
157-
DataStream& operator >> ( DataStream& ds, chainbase::oid<OidType>& oid ) {
156+
DataStream& operator >> ( DataStream& ds, oid<OidType>& oid ) {
158157
fc::raw::unpack(ds, oid._id);
159158
return ds;
160159
}
@@ -169,7 +168,7 @@ DataStream& operator << ( DataStream& ds, const float64_t& v ) {
169168

170169
template<typename DataStream>
171170
DataStream& operator >> ( DataStream& ds, float64_t& v ) {
172-
fc::raw::unpack(ds, *reinterpret_cast<const double *>(&v));
171+
fc::raw::unpack(ds, *reinterpret_cast<double *>(&v));
173172
return ds;
174173
}
175174

@@ -181,7 +180,7 @@ DataStream& operator << ( DataStream& ds, const float128_t& v ) {
181180

182181
template<typename DataStream>
183182
DataStream& operator >> ( DataStream& ds, float128_t& v ) {
184-
fc::raw::unpack(ds, *reinterpret_cast<const eosio::chain::uint128_t*>(&v));
183+
fc::raw::unpack(ds, *reinterpret_cast<eosio::chain::uint128_t*>(&v));
185184
return ds;
186185
}
187186

libraries/chain/include/eosio/chain/permission_object.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
#pragma once
66
#include <eosio/chain/authority.hpp>
7+
#include <eosio/chain/database_utils.hpp>
78

89
#include "multi_index_includes.hpp"
910

@@ -112,5 +113,4 @@ CHAINBASE_SET_INDEX_TYPE(eosio::chain::permission_usage_object, eosio::chain::pe
112113

113114
FC_REFLECT(eosio::chain::permission_object, (usage_id)(parent)(owner)(name)(last_updated)(auth))
114115

115-
FC_REFLECT(chainbase::oid<eosio::chain::permission_usage_object>, (_id))
116116
FC_REFLECT(eosio::chain::permission_usage_object, (id)(last_used))

libraries/chain/include/eosio/chain/snapshot.hpp

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,55 @@ namespace eosio { namespace chain {
4040
value = row;
4141
}
4242

43+
/**
44+
* Due to a pattern in our code of overloading `operator << ( std::ostream&, ... )` to provide
45+
* human-readable string forms of data, we cannot directly use ostream as those operators will
46+
* be used instead of the expected operators. In otherwords:
47+
* fc::raw::pack(fc::datastream...)
48+
* will end up calling _very_ different operators than
49+
* fc::raw::pack(std::ostream...)
50+
*/
51+
struct ostream_wrapper {
52+
explicit ostream_wrapper(std::ostream& s)
53+
:inner(s) {
54+
55+
}
56+
57+
ostream_wrapper(ostream_wrapper &&) = default;
58+
ostream_wrapper(const ostream_wrapper& ) = default;
59+
60+
auto& write( const char* d, size_t s ) {
61+
return inner.write(d, s);
62+
}
63+
64+
auto& put(char c) {
65+
return inner.put(c);
66+
}
67+
68+
auto tellp() const {
69+
return inner.tellp();
70+
}
71+
72+
auto& seekp(std::ostream::pos_type p) {
73+
return inner.seekp(p);
74+
}
75+
76+
std::ostream& inner;
77+
};
78+
79+
4380
struct abstract_snapshot_row_writer {
44-
virtual void write(std::ostream& out) const = 0;
81+
virtual void write(ostream_wrapper& out) const = 0;
4582
virtual variant to_variant() const = 0;
83+
virtual std::string row_type_name() const = 0;
4684
};
4785

4886
template<typename T>
4987
struct snapshot_row_writer : abstract_snapshot_row_writer {
5088
explicit snapshot_row_writer( const T& data )
5189
:data(data) {}
5290

53-
void write(std::ostream& out) const override {
91+
void write(ostream_wrapper& out) const override {
5492
fc::raw::pack(out, data);
5593
}
5694

@@ -60,6 +98,10 @@ namespace eosio { namespace chain {
6098
return var;
6199
}
62100

101+
std::string row_type_name() const override {
102+
return boost::core::demangle( typeid( T ).name() );
103+
}
104+
63105
const T& data;
64106
};
65107

@@ -110,6 +152,7 @@ namespace eosio { namespace chain {
110152
struct abstract_snapshot_row_reader {
111153
virtual void provide(std::istream& in) const = 0;
112154
virtual void provide(const fc::variant&) const = 0;
155+
virtual std::string row_type_name() const = 0;
113156
};
114157

115158
template<typename T>
@@ -125,6 +168,10 @@ namespace eosio { namespace chain {
125168
fc::from_variant(var, data);
126169
}
127170

171+
std::string row_type_name() const override {
172+
return boost::core::demangle( typeid( T ).name() );
173+
}
174+
128175
T& data;
129176
};
130177

@@ -231,11 +278,10 @@ namespace eosio { namespace chain {
231278
static const uint32_t magic_number = 0x30510550;
232279

233280
private:
234-
235-
std::ostream& snapshot;
236-
std::streampos header_pos;
237-
std::streampos section_pos;
238-
uint64_t row_count;
281+
detail::ostream_wrapper snapshot;
282+
std::streampos header_pos;
283+
std::streampos section_pos;
284+
uint64_t row_count;
239285

240286
};
241287

libraries/chain/snapshot.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ void istream_snapshot_reader::set_section( const string& section_name ) {
263263
if (match && snapshot.get() == 0) {
264264
cur_row = 0;
265265
num_rows = row_count;
266+
267+
// leave the stream at the right point
268+
restore_pos.cancel();
266269
return;
267270
}
268271
}

unittests/snapshot_tests.cpp

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -67,49 +67,82 @@ struct variant_snapshot_suite {
6767
using writer_t = variant_snapshot_writer;
6868
using reader_t = variant_snapshot_reader;
6969
using write_storage_t = fc::mutable_variant_object;
70-
using read_storage_t = fc::variant;
70+
using snapshot_t = fc::variant;
71+
72+
struct writer : public writer_t {
73+
writer( const std::shared_ptr<write_storage_t>& storage )
74+
:writer_t(*storage)
75+
,storage(storage)
76+
{
77+
78+
}
79+
80+
std::shared_ptr<write_storage_t> storage;
81+
};
82+
83+
struct reader : public reader_t {
84+
explicit reader(const snapshot_t& storage)
85+
:reader_t(storage)
86+
{}
87+
};
88+
89+
90+
static auto get_writer() {
91+
return std::make_shared<writer>(std::make_shared<write_storage_t>());
92+
}
93+
94+
static auto finalize(const std::shared_ptr<writer>& w) {
95+
w->finalize();
96+
return snapshot_t(*w->storage);
97+
}
98+
99+
static auto get_reader( const snapshot_t& buffer) {
100+
return std::make_shared<reader>(buffer);
101+
}
102+
71103
};
72104

73105
struct buffered_snapshot_suite {
74106
using writer_t = ostream_snapshot_writer;
75107
using reader_t = istream_snapshot_reader;
76-
using write_storage_t = std::stringstream;
77-
using read_storage_t = write_storage_t;
78-
79-
};
108+
using write_storage_t = std::ostringstream;
109+
using snapshot_t = std::string;
110+
using read_storage_t = std::istringstream;
80111

81-
template<typename SUITE>
82-
struct suite_funcs {
83-
struct writer : public SUITE::writer_t {
84-
writer( const std::shared_ptr<typename SUITE::write_storage_t>& storage )
85-
:SUITE::writer_t(*storage)
112+
struct writer : public writer_t {
113+
writer( const std::shared_ptr<write_storage_t>& storage )
114+
:writer_t(*storage)
86115
,storage(storage)
87116
{
88117

89118
}
90119

91-
std::shared_ptr<typename SUITE::write_storage_t> storage;
120+
std::shared_ptr<write_storage_t> storage;
92121
};
93122

94-
struct reader : public SUITE::reader_t {
95-
explicit reader(typename SUITE::read_storage_t& buffer)
96-
:SUITE::reader_t(buffer)
123+
struct reader : public reader_t {
124+
explicit reader(const std::shared_ptr<read_storage_t>& storage)
125+
:reader_t(*storage)
126+
,storage(storage)
97127
{}
98128

129+
std::shared_ptr<read_storage_t> storage;
99130
};
100131

132+
101133
static auto get_writer() {
102-
return std::make_shared<writer>(std::make_shared<typename SUITE::write_storage_t>());
134+
return std::make_shared<writer>(std::make_shared<write_storage_t>());
103135
}
104136

105137
static auto finalize(const std::shared_ptr<writer>& w) {
106138
w->finalize();
107-
return typename SUITE::read_storage_t(std::move(*w->storage));
139+
return w->storage->str();
108140
}
109141

110-
static auto get_reader( typename SUITE::read_storage_t& buffer) {
111-
return std::make_shared<reader>(buffer);
142+
static auto get_reader( const snapshot_t& buffer) {
143+
return std::make_shared<reader>(std::make_shared<read_storage_t>(buffer));
112144
}
145+
113146
};
114147

115148
BOOST_AUTO_TEST_SUITE(snapshot_tests)
@@ -132,12 +165,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_exhaustive_snapshot, SNAPSHOT_SUITE, snapshot
132165

133166
for (int generation = 0; generation < generation_count; generation++) {
134167
// create a new snapshot child
135-
auto writer = suite_funcs<SNAPSHOT_SUITE>::get_writer();
168+
auto writer = SNAPSHOT_SUITE::get_writer();
136169
chain.control->write_snapshot(writer);
137-
auto snapshot = suite_funcs<SNAPSHOT_SUITE>::finalize(writer);
170+
auto snapshot = SNAPSHOT_SUITE::finalize(writer);
138171

139172
// create a new child at this snapshot
140-
sub_testers.emplace_back(chain.get_config(), suite_funcs<SNAPSHOT_SUITE>::get_reader(snapshot), generation);
173+
sub_testers.emplace_back(chain.get_config(), SNAPSHOT_SUITE::get_reader(snapshot), generation);
141174

142175
// increment the test contract
143176
chain.push_action(N(snapshot), N(increment), N(snapshot), mutable_variant_object()
@@ -188,12 +221,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_replay_over_snapshot, SNAPSHOT_SUITE, snapsho
188221
auto expected_pre_integrity_hash = chain.control->calculate_integrity_hash();
189222

190223
// create a new snapshot child
191-
auto writer = suite_funcs<SNAPSHOT_SUITE>::get_writer();
224+
auto writer = SNAPSHOT_SUITE::get_writer();
192225
chain.control->write_snapshot(writer);
193-
auto snapshot = suite_funcs<SNAPSHOT_SUITE>::finalize(writer);
226+
auto snapshot = SNAPSHOT_SUITE::finalize(writer);
194227

195228
// create a new child at this snapshot
196-
snapshotted_tester snap_chain(chain.get_config(), suite_funcs<SNAPSHOT_SUITE>::get_reader(snapshot), 1);
229+
snapshotted_tester snap_chain(chain.get_config(), SNAPSHOT_SUITE::get_reader(snapshot), 1);
197230
BOOST_REQUIRE_EQUAL(expected_pre_integrity_hash.str(), snap_chain.control->calculate_integrity_hash().str());
198231

199232
// push more blocks to build up a block log
@@ -213,7 +246,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_replay_over_snapshot, SNAPSHOT_SUITE, snapsho
213246
BOOST_REQUIRE_EQUAL(expected_post_integrity_hash.str(), snap_chain.control->calculate_integrity_hash().str());
214247

215248
// replay the block log from the snapshot child, from the snapshot
216-
snapshotted_tester replay_chain(chain.get_config(), suite_funcs<SNAPSHOT_SUITE>::get_reader(snapshot), 2, 1);
249+
snapshotted_tester replay_chain(chain.get_config(), SNAPSHOT_SUITE::get_reader(snapshot), 2, 1);
217250
BOOST_REQUIRE_EQUAL(expected_post_integrity_hash.str(), snap_chain.control->calculate_integrity_hash().str());
218251
}
219252

0 commit comments

Comments
 (0)