Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
daed208b
Y
YTBP
项目概览
YottaChain
/
YTBP
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
YTBP
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
daed208b
编写于
8月 15, 2017
作者:
B
Bart Wyatt
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
changes to resolve review feedback
上级
b05922ea
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
141 addition
and
143 deletion
+141
-143
libraries/chain/block_schedule.cpp
libraries/chain/block_schedule.cpp
+34
-34
libraries/chain/chain_controller.cpp
libraries/chain/chain_controller.cpp
+12
-14
libraries/chain/include/eos/chain/block_schedule.hpp
libraries/chain/include/eos/chain/block_schedule.hpp
+8
-57
tests/common/expect.hpp
tests/common/expect.hpp
+15
-15
tests/tests/block_schedule_tests.cpp
tests/tests/block_schedule_tests.cpp
+72
-23
未找到文件。
libraries/chain/block_schedule.cpp
浏览文件 @
daed208b
...
...
@@ -46,7 +46,7 @@ typedef std::hash<decltype(AccountName::value)> account_hash;
static
account_hash
account_hasher
;
struct
schedule_entry
{
schedule_entry
(
uint
_cycle
,
uint
_thread
,
pending_transaction
const
*
_transaction
)
schedule_entry
(
uint
_cycle
,
uint
_thread
,
const
pending_transaction
&
_transaction
)
:
cycle
(
_cycle
)
,
thread
(
_thread
)
,
transaction
(
_transaction
)
...
...
@@ -54,9 +54,9 @@ struct schedule_entry {
uint
cycle
;
uint
thread
;
pending_transaction
const
*
transaction
;
std
::
reference_wrapper
<
const
pending_transaction
>
transaction
;
friend
bool
operator
<
(
schedule_entry
const
&
l
,
schedule_entry
const
&
r
)
{
friend
bool
operator
<
(
const
schedule_entry
&
l
,
const
schedule_entry
&
r
)
{
if
(
l
.
cycle
<
r
.
cycle
)
{
return
true
;
}
else
if
(
l
.
cycle
==
r
.
cycle
)
{
...
...
@@ -67,18 +67,18 @@ struct schedule_entry {
}
};
static
block_schedule
from_entries
(
vector
<
schedule_entry
>
&
entries
)
{
static
block_schedule
from_entries
(
vector
<
schedule_entry
>
&
entries
)
{
// sort in reverse to save allocations, this should put the highest thread index
// for the highest cycle index first meaning the naive resize in the loop below
// is usually the largest and only resize
auto
reverse
=
[](
schedule_entry
const
&
l
,
schedule_entry
const
&
r
)
{
auto
reverse
=
[](
const
schedule_entry
&
l
,
const
schedule_entry
&
r
)
{
return
!
(
l
<
r
);
};
std
::
sort
(
entries
.
begin
(),
entries
.
end
(),
reverse
);
block_schedule
result
;
for
(
auto
const
&
entry
:
entries
)
{
for
(
const
auto
&
entry
:
entries
)
{
if
(
result
.
cycles
.
size
()
<=
entry
.
cycle
)
{
result
.
cycles
.
resize
(
entry
.
cycle
+
1
);
}
...
...
@@ -93,18 +93,18 @@ static block_schedule from_entries(vector<schedule_entry> &entries) {
// allocations, we cannot emplace_back as that would reverse
// the transactions in a thread
auto
&
thread
=
cycle
.
at
(
entry
.
thread
);
thread
.
transactions
.
emplace
(
thread
.
transactions
.
begin
(),
*
entry
.
transaction
);
thread
.
transactions
.
emplace
(
thread
.
transactions
.
begin
(),
entry
.
transaction
.
get
()
);
}
return
result
;
}
template
<
typename
C
ONTAINER
>
auto
initialize_
pointer_vector
(
CONTAINER
const
&
c
)
{
vector
<
pending_transaction
const
*
>
result
;
template
<
typename
C
ontainer
>
auto
initialize_
ref_vector
(
const
Container
&
c
)
{
vector
<
std
::
reference_wrapper
<
const
pending_transaction
>
>
result
;
result
.
reserve
(
c
.
size
());
for
(
auto
const
&
t
:
c
)
{
result
.
emplace_back
(
&
t
);
for
(
const
auto
&
t
:
c
)
{
result
.
emplace_back
(
t
);
}
return
result
;
...
...
@@ -113,8 +113,8 @@ auto initialize_pointer_vector(CONTAINER const &c) {
struct
transaction_size_visitor
:
public
fc
::
visitor
<
size_t
>
{
template
<
typename
T
>
size_t
operator
()(
const
T
&
trx_p
)
const
{
return
fc
::
raw
::
pack_size
(
*
trx_p
);
size_t
operator
()(
std
::
reference_wrapper
<
const
T
>
trx
)
const
{
return
fc
::
raw
::
pack_size
(
trx
.
get
()
);
}
};
...
...
@@ -122,8 +122,8 @@ struct block_size_skipper {
size_t
current_size
;
size_t
const
max_size
;
bool
should_skip
(
pending_transaction
const
*
t
)
const
{
size_t
transaction_size
=
t
->
visit
(
transaction_size_visitor
());
bool
should_skip
(
const
pending_transaction
&
t
)
const
{
size_t
transaction_size
=
t
.
visit
(
transaction_size_visitor
());
// postpone transaction if it would make block too big
if
(
transaction_size
+
current_size
>
max_size
)
{
return
true
;
...
...
@@ -132,21 +132,21 @@ struct block_size_skipper {
}
}
void
apply
(
pending_transaction
const
*
t
)
{
size_t
transaction_size
=
t
->
visit
(
transaction_size_visitor
());
void
apply
(
const
pending_transaction
&
t
)
{
size_t
transaction_size
=
t
.
visit
(
transaction_size_visitor
());
current_size
+=
transaction_size
;
}
};
auto
make_skipper
(
const
global_property_object
&
properties
)
{
auto
make_skipper
(
const
global_property_object
&
properties
)
{
static
const
size_t
max_block_header_size
=
fc
::
raw
::
pack_size
(
signed_block_header
()
)
+
4
;
auto
maximum_block_size
=
properties
.
configuration
.
maxBlockSize
;
return
block_size_skipper
{
max_block_header_size
,
(
size_t
)
maximum_block_size
};
}
block_schedule
block_schedule
::
by_threading_conflicts
(
vector
<
pending_transaction
>
const
&
transactions
,
const
global_property_object
&
properties
const
vector
<
pending_transaction
>&
transactions
,
const
global_property_object
&
properties
)
{
static
uint
const
MAX_TXS_PER_THREAD
=
4
;
...
...
@@ -158,8 +158,8 @@ block_schedule block_schedule::by_threading_conflicts(
vector
<
schedule_entry
>
schedule
;
schedule
.
reserve
(
transactions
.
size
());
auto
current
=
initialize_
pointer
_vector
(
transactions
);
vector
<
pending_transaction
const
*>
postponed
;
auto
current
=
initialize_
ref
_vector
(
transactions
);
decltype
(
current
)
postponed
;
postponed
.
reserve
(
transactions
.
size
());
vector
<
uint
>
txs_per_thread
;
...
...
@@ -179,7 +179,7 @@ block_schedule block_schedule::by_threading_conflicts(
auto
assigned_to
=
optional
<
uint
>
();
bool
postpone
=
false
;
auto
scopes
=
t
->
visit
(
scope_extracting_visitor
());
auto
scopes
=
t
.
get
().
visit
(
scope_extracting_visitor
());
for
(
const
auto
&
a
:
scopes
)
{
uint
hash_index
=
account_hasher
(
a
)
%
HASH_SIZE
;
...
...
@@ -218,9 +218,9 @@ block_schedule block_schedule::by_threading_conflicts(
}
}
current
.
resize
(
0
);
txs_per_thread
.
resize
(
0
);
assigned_threads
.
resize
(
0
);
current
.
clear
(
);
txs_per_thread
.
clear
(
);
assigned_threads
.
clear
(
);
assigned_threads
.
resize
(
HASH_SIZE
);
std
::
swap
(
current
,
postponed
);
++
cycle
;
...
...
@@ -230,8 +230,8 @@ block_schedule block_schedule::by_threading_conflicts(
}
block_schedule
block_schedule
::
by_cycling_conflicts
(
vector
<
pending_transaction
>
const
&
transactions
,
const
global_property_object
&
properties
const
vector
<
pending_transaction
>&
transactions
,
const
global_property_object
&
properties
)
{
auto
skipper
=
make_skipper
(
properties
);
...
...
@@ -240,8 +240,8 @@ block_schedule block_schedule::by_cycling_conflicts(
vector
<
schedule_entry
>
schedule
;
schedule
.
reserve
(
transactions
.
size
());
auto
current
=
initialize_
pointer
_vector
(
transactions
);
vector
<
pending_transaction
const
*>
postponed
;
auto
current
=
initialize_
ref
_vector
(
transactions
);
decltype
(
current
)
postponed
;
postponed
.
reserve
(
transactions
.
size
());
int
cycle
=
0
;
...
...
@@ -256,7 +256,7 @@ block_schedule block_schedule::by_cycling_conflicts(
continue
;
}
auto
scopes
=
t
->
visit
(
scope_extracting_visitor
());
auto
scopes
=
t
.
get
().
visit
(
scope_extracting_visitor
());
bool
u
=
false
;
for
(
const
auto
&
a
:
scopes
)
{
uint
hash_index
=
account_hasher
(
a
)
%
HASH_SIZE
;
...
...
@@ -279,8 +279,8 @@ block_schedule block_schedule::by_cycling_conflicts(
}
}
current
.
resize
(
0
);
used
.
resize
(
0
);
current
.
clear
(
);
used
.
clear
(
);
used
.
resize
(
HASH_SIZE
);
std
::
swap
(
current
,
postponed
);
++
cycle
;
...
...
libraries/chain/chain_controller.cpp
浏览文件 @
daed208b
...
...
@@ -303,12 +303,12 @@ signed_block chain_controller::_generate_block(
vector
<
pending_transaction
>
pending
;
pending
.
reserve
(
generated
.
size
()
+
_pending_transactions
.
size
());
for
(
auto
const
&
gt
:
generated
)
{
pending
.
emplace_back
(
pending_transaction
{
&
gt
.
trx
});
for
(
const
auto
&
gt
:
generated
)
{
pending
.
emplace_back
(
std
::
reference_wrapper
<
const
GeneratedTransaction
>
{
gt
.
trx
});
}
for
(
auto
const
&
st
:
_pending_transactions
)
{
pending
.
emplace_back
(
pending_transaction
{
&
st
});
for
(
const
auto
&
st
:
_pending_transactions
)
{
pending
.
emplace_back
(
std
::
reference_wrapper
<
const
SignedTransaction
>
{
st
});
}
auto
schedule
=
scheduler
(
pending
,
get_global_properties
());
...
...
@@ -345,15 +345,14 @@ signed_block chain_controller::_generate_block(
try
{
auto
temp_session
=
_db
.
start_undo_session
(
true
);
if
(
trx
.
contains
<
SignedTransaction
const
*
>
())
{
auto
const
&
t
=
*
trx
.
get
<
SignedTransaction
const
*>
();
if
(
trx
.
contains
<
std
::
reference_wrapper
<
const
SignedTransaction
>
>
())
{
const
auto
&
t
=
trx
.
get
<
std
::
reference_wrapper
<
const
SignedTransaction
>>
().
get
();
validate_referenced_accounts
(
t
);
check_transaction_authorization
(
t
);
auto
processed
=
_apply_transaction
(
t
);
block_thread
.
user_input
.
emplace_back
(
processed
);
}
else
if
(
trx
.
contains
<
GeneratedTransaction
const
*>
())
{
#warning TODO: Process generated transaction
// auto processed = _apply_transaction(*trx.get<GeneratedTransaction const *>());
}
else
if
(
trx
.
contains
<
std
::
reference_wrapper
<
const
GeneratedTransaction
>>
())
{
// auto processed = _apply_transaction(trx.get<std::reference_wrapper<const GeneratedTransaction>>().get());
// block_thread.generated_input.emplace_back(processed);
}
else
{
FC_THROW_EXCEPTION
(
tx_scheduling_exception
,
"Unknown transaction type in block_schedule"
);
...
...
@@ -366,10 +365,10 @@ signed_block chain_controller::_generate_block(
{
// Do nothing, transaction will not be re-applied
wlog
(
"Transaction was not processed while generating block due to ${e}"
,
(
"e"
,
e
)
);
if
(
trx
.
contains
<
SignedTransaction
const
*
>
())
{
wlog
(
"The transaction was ${t}"
,
(
"t"
,
*
trx
.
get
<
SignedTransaction
const
*>
())
);
}
else
if
(
trx
.
contains
<
GeneratedTransaction
const
*
>
())
{
wlog
(
"The transaction was ${t}"
,
(
"t"
,
*
trx
.
get
<
GeneratedTransaction
const
*>
())
);
if
(
trx
.
contains
<
std
::
reference_wrapper
<
const
SignedTransaction
>
>
())
{
wlog
(
"The transaction was ${t}"
,
(
"t"
,
trx
.
get
<
std
::
reference_wrapper
<
const
SignedTransaction
>>
().
get
())
);
}
else
if
(
trx
.
contains
<
std
::
reference_wrapper
<
const
GeneratedTransaction
>
>
())
{
wlog
(
"The transaction was ${t}"
,
(
"t"
,
trx
.
get
<
std
::
reference_wrapper
<
const
GeneratedTransaction
>>
().
get
())
);
}
invalid_transaction_count
++
;
}
...
...
@@ -503,7 +502,6 @@ void chain_controller::_apply_block(const signed_block& next_block)
for
(
const
auto
&
cycle
:
next_block
.
cycles
)
{
for
(
const
auto
&
thread
:
cycle
)
{
for
(
const
auto
&
trx
:
thread
.
generated_input
)
{
#warning TODO: Process generated transaction
}
for
(
const
auto
&
trx
:
thread
.
user_input
)
{
_apply_transaction
(
trx
);
...
...
libraries/chain/include/eos/chain/block_schedule.hpp
浏览文件 @
daed208b
...
...
@@ -29,7 +29,7 @@
#include <set>
namespace
eos
{
namespace
chain
{
using
pending_transaction
=
static_variant
<
SignedTransaction
const
*
,
GeneratedTransaction
const
*
>
;
using
pending_transaction
=
static_variant
<
std
::
reference_wrapper
<
const
SignedTransaction
>
,
std
::
reference_wrapper
<
const
GeneratedTransaction
>
>
;
struct
thread_schedule
{
vector
<
pending_transaction
>
transactions
;
...
...
@@ -43,7 +43,7 @@ namespace eos { namespace chain {
*/
struct
block_schedule
{
typedef
block_schedule
(
*
factory
)(
vector
<
pending_transaction
>
const
&
,
const
global_property_object
&
);
typedef
block_schedule
(
*
factory
)(
const
vector
<
pending_transaction
>
&
,
const
global_property_object
&
);
vector
<
cycle_schedule
>
cycles
;
// Algorithms
...
...
@@ -53,70 +53,21 @@ namespace eos { namespace chain {
* falling back on cycles
* @return the block scheduler
*/
static
block_schedule
by_threading_conflicts
(
vector
<
pending_transaction
>
const
&
transactions
,
const
global_property_object
&
properties
);
static
block_schedule
by_threading_conflicts
(
const
vector
<
pending_transaction
>&
transactions
,
const
global_property_object
&
properties
);
/**
* A greedy scheduler that attempts uses future cycles to resolve scope contention
* @return the block scheduler
*/
static
block_schedule
by_cycling_conflicts
(
vector
<
pending_transaction
>
const
&
transactions
,
const
global_property_object
&
properties
);
/*
* templated meta schedulers for fuzzing
*/
template
<
typename
NEXT
>
struct
shuffled_functor
{
shuffled_functor
(
NEXT
&&
_next
)
:
next
(
_next
){};
block_schedule
operator
()(
vector
<
pending_transaction
>
const
&
transactions
,
const
global_property_object
&
properties
)
{
std
::
random_device
rd
;
std
::
mt19937
rng
(
rd
());
auto
copy
=
std
::
vector
<
pending_transaction
>
(
transactions
);
std
::
shuffle
(
copy
.
begin
(),
copy
.
end
(),
rng
);
return
next
(
copy
,
properties
);
}
NEXT
&&
next
;
};
template
<
typename
NEXT
>
static
shuffled_functor
<
NEXT
>
shuffled
(
NEXT
&&
next
)
{
return
shuffled_functor
<
NEXT
>
(
next
);
}
template
<
int
NUM
,
int
DEN
,
typename
NEXT
>
struct
lossy_functor
{
lossy_functor
(
NEXT
&&
_next
)
:
next
(
_next
){};
block_schedule
operator
()(
vector
<
pending_transaction
>
const
&
transactions
,
const
global_property_object
&
properties
)
{
std
::
random_device
rd
;
std
::
mt19937
rng
(
rd
());
std
::
uniform_real_distribution
<>
dist
(
0
,
1
);
double
const
cutoff
=
(
double
)
NUM
/
(
double
)
DEN
;
auto
copy
=
std
::
vector
<
pending_transaction
>
();
copy
.
reserve
(
transactions
.
size
());
std
::
copy_if
(
transactions
.
begin
(),
transactions
.
end
(),
copy
.
begin
(),
[
&
](
pending_transaction
const
&
trx
){
return
dist
(
rng
)
>=
cutoff
;
});
return
next
(
copy
,
properties
);
}
NEXT
&&
next
;
};
template
<
int
NUM
,
int
DEN
,
typename
NEXT
>
static
lossy_functor
<
NUM
,
DEN
,
NEXT
>
lossy
(
NEXT
&&
next
)
{
return
lossy_functor
<
NUM
,
DEN
,
NEXT
>
(
next
);
}
static
block_schedule
by_cycling_conflicts
(
const
vector
<
pending_transaction
>&
transactions
,
const
global_property_object
&
properties
);
};
struct
scope_extracting_visitor
:
public
fc
::
visitor
<
std
::
set
<
AccountName
>>
{
template
<
typename
T
>
std
::
set
<
AccountName
>
operator
()(
const
T
&
trx_p
)
const
{
std
::
set
<
AccountName
>
unique_names
(
trx_p
->
scope
.
begin
(),
trx_p
->
scope
.
end
());
for
(
auto
const
&
m
:
trx_p
->
messages
)
{
std
::
set
<
AccountName
>
operator
()(
std
::
reference_wrapper
<
const
T
>
trx
)
const
{
const
auto
&
t
=
trx
.
get
();
std
::
set
<
AccountName
>
unique_names
(
t
.
scope
.
begin
(),
t
.
scope
.
end
());
for
(
const
auto
&
m
:
t
.
messages
)
{
unique_names
.
insert
(
m
.
code
);
}
...
...
tests/common/expect.hpp
浏览文件 @
daed208b
...
...
@@ -25,40 +25,40 @@
namespace
eos
{
namespace
test
{
template
<
typename
P
RED
,
typename
EVAL
,
typename
T
>
template
<
typename
P
red
,
typename
Eval
,
typename
T
>
struct
expector
{
expector
(
E
VAL
_eval
,
T
const
&
_expected
,
char
const
*
const
_msg
)
expector
(
E
val
_eval
,
const
T
&
_expected
,
const
char
*
const
_msg
)
:
expected
(
_expected
)
,
eval
(
_eval
)
,
msg
(
_msg
)
{}
template
<
typename
I
NPUT
>
void
operator
()
(
INPUT
const
&
input
)
{
template
<
typename
I
nput
>
void
operator
()
(
const
Input
&
input
)
{
BOOST_TEST_INFO
(
msg
);
auto
actual
=
eval
(
input
);
BOOST_CHECK_EQUAL
(
P
RED
()(
actual
,
expected
),
true
);
BOOST_CHECK_EQUAL
(
P
red
()(
actual
,
expected
),
true
);
}
T
expected
;
E
VAL
eval
;
E
val
eval
;
char
const
*
const
msg
;
};
template
<
typename
P
RED
,
typename
EVAL
,
typename
T
>
auto
expect
(
E
VAL
&&
eval
,
T
expected
,
char
const
*
const
msg
)
{
return
expector
<
P
RED
,
EVAL
,
T
>
(
eval
,
expected
,
msg
);
template
<
typename
P
red
,
typename
Eval
,
typename
T
>
auto
expect
(
E
val
&&
eval
,
T
expected
,
char
const
*
const
msg
)
{
return
expector
<
P
red
,
Eval
,
T
>
(
eval
,
expected
,
msg
);
}
template
<
typename
E
VAL
,
typename
T
>
auto
expect
(
E
VAL
&&
eval
,
T
expected
,
char
const
*
const
msg
)
{
return
expector
<
std
::
equal_to
<
T
>
,
E
VAL
,
T
>
(
eval
,
expected
,
msg
);
template
<
typename
E
val
,
typename
T
>
auto
expect
(
E
val
&&
eval
,
T
expected
,
char
const
*
const
msg
)
{
return
expector
<
std
::
equal_to
<
T
>
,
E
val
,
T
>
(
eval
,
expected
,
msg
);
}
template
<
typename
E
VAL
>
auto
expect
(
E
VAL
&&
eval
,
char
const
*
const
msg
)
{
return
expector
<
std
::
equal_to
<
bool
>
,
E
VAL
,
bool
>
(
eval
,
true
,
msg
);
template
<
typename
E
val
>
auto
expect
(
E
val
&&
eval
,
char
const
*
const
msg
)
{
return
expector
<
std
::
equal_to
<
bool
>
,
E
val
,
bool
>
(
eval
,
true
,
msg
);
}
#define _NUM_ARGS(A,B,C,N, ...) N
...
...
tests/tests/block_schedule_tests.cpp
浏览文件 @
daed208b
...
...
@@ -30,24 +30,74 @@
using
namespace
eos
;
using
namespace
chain
;
/*
* templated meta schedulers for fuzzing
*/
template
<
typename
NEXT
>
struct
shuffled_functor
{
shuffled_functor
(
NEXT
&&
_next
)
:
next
(
_next
){};
block_schedule
operator
()(
const
vector
<
pending_transaction
>&
transactions
,
const
global_property_object
&
properties
)
{
std
::
random_device
rd
;
std
::
mt19937
rng
(
rd
());
auto
copy
=
std
::
vector
<
pending_transaction
>
(
transactions
);
std
::
shuffle
(
copy
.
begin
(),
copy
.
end
(),
rng
);
return
next
(
copy
,
properties
);
}
NEXT
&&
next
;
};
template
<
typename
NEXT
>
static
shuffled_functor
<
NEXT
>
shuffled
(
NEXT
&&
next
)
{
return
shuffled_functor
<
NEXT
>
(
next
);
}
template
<
int
NUM
,
int
DEN
,
typename
NEXT
>
struct
lossy_functor
{
lossy_functor
(
NEXT
&&
_next
)
:
next
(
_next
){};
block_schedule
operator
()(
const
vector
<
pending_transaction
>&
transactions
,
const
global_property_object
&
properties
)
{
std
::
random_device
rd
;
std
::
mt19937
rng
(
rd
());
std
::
uniform_real_distribution
<>
dist
(
0
,
1
);
double
const
cutoff
=
(
double
)
NUM
/
(
double
)
DEN
;
auto
copy
=
std
::
vector
<
pending_transaction
>
();
copy
.
reserve
(
transactions
.
size
());
std
::
copy_if
(
transactions
.
begin
(),
transactions
.
end
(),
copy
.
begin
(),
[
&
](
const
pending_transaction
&
trx
){
return
dist
(
rng
)
>=
cutoff
;
});
return
next
(
copy
,
properties
);
}
NEXT
&&
next
;
};
template
<
int
NUM
,
int
DEN
,
typename
NEXT
>
static
lossy_functor
<
NUM
,
DEN
,
NEXT
>
lossy
(
NEXT
&&
next
)
{
return
lossy_functor
<
NUM
,
DEN
,
NEXT
>
(
next
);
}
/*
* Policy based Fixtures for chain properties
*/
class
common_fixture
{
public:
struct
test_transaction
{
test_transaction
(
std
::
initializer_list
<
AccountName
>
const
&
_scopes
)
test_transaction
(
const
std
::
initializer_list
<
AccountName
>&
_scopes
)
:
scopes
(
_scopes
)
{
}
std
::
initializer_list
<
AccountName
>
const
&
scopes
;
const
std
::
initializer_list
<
AccountName
>&
scopes
;
};
protected:
auto
create_transactions
(
std
::
initializer_list
<
test_transaction
>
const
&
transactions
)
{
auto
create_transactions
(
const
std
::
initializer_list
<
test_transaction
>&
transactions
)
{
std
::
vector
<
SignedTransaction
>
result
;
for
(
auto
const
&
t
:
transactions
)
{
for
(
const
auto
&
t
:
transactions
)
{
SignedTransaction
st
;
st
.
scope
.
reserve
(
t
.
scopes
.
size
());
st
.
scope
.
insert
(
st
.
scope
.
end
(),
t
.
scopes
.
begin
(),
t
.
scopes
.
end
());
...
...
@@ -56,11 +106,10 @@ protected:
return
result
;
}
auto
create_pending
(
std
::
vector
<
SignedTransaction
>
const
&
transactions
)
{
auto
create_pending
(
const
std
::
vector
<
SignedTransaction
>&
transactions
)
{
std
::
vector
<
pending_transaction
>
result
;
for
(
auto
const
&
t
:
transactions
)
{
auto
const
*
ptr
=
&
t
;
result
.
emplace_back
(
ptr
);
for
(
const
auto
&
t
:
transactions
)
{
result
.
emplace_back
(
std
::
reference_wrapper
<
SignedTransaction
const
>
{
t
});
}
return
result
;
}
...
...
@@ -70,7 +119,7 @@ template<typename PROPERTIES_POLICY>
class
compose_fixture
:
public
common_fixture
{
public:
template
<
typename
SCHED_FN
,
typename
...
VALIDATORS
>
void
schedule_and_validate
(
SCHED_FN
sched_fn
,
std
::
initializer_list
<
test_transaction
>
const
&
transactions
,
VALIDATORS
...
validators
)
{
void
schedule_and_validate
(
SCHED_FN
sched_fn
,
const
std
::
initializer_list
<
test_transaction
>&
transactions
,
VALIDATORS
...
validators
)
{
try
{
auto
signed_transactions
=
create_transactions
(
transactions
);
auto
pending
=
create_pending
(
signed_transactions
);
...
...
@@ -81,12 +130,12 @@ public:
private:
template
<
typename
VALIDATOR
>
void
validate
(
block_schedule
const
&
schedule
,
VALIDATOR
validator
)
{
void
validate
(
const
block_schedule
&
schedule
,
VALIDATOR
validator
)
{
validator
(
schedule
);
}
template
<
typename
VALIDATOR
,
typename
...
VALIDATORS
>
void
validate
(
block_schedule
const
&
schedule
,
VALIDATOR
validator
,
VALIDATORS
...
others
)
{
void
validate
(
const
block_schedule
&
schedule
,
VALIDATOR
validator
,
VALIDATORS
...
others
)
{
validate
(
schedule
,
validator
);
validate
(
schedule
,
others
...);
}
...
...
@@ -95,7 +144,7 @@ private:
PROPERTIES_POLICY
properties_policy
;
};
static
void
null_global_property_object_constructor
(
global_property_object
const
&
)
static
void
null_global_property_object_constructor
(
const
global_property_object
&
)
{}
static
chainbase
::
allocator
<
global_property_object
>
null_global_property_object_allocator
(
nullptr
);
...
...
@@ -126,10 +175,10 @@ typedef compose_fixture<default_properties> default_fixture;
/*
* Evaluators for expect
*/
static
uint
transaction_count
(
block_schedule
const
&
schedule
)
{
static
uint
transaction_count
(
const
block_schedule
&
schedule
)
{
uint
result
=
0
;
for
(
auto
const
&
c
:
schedule
.
cycles
)
{
for
(
auto
const
&
t
:
c
)
{
for
(
const
auto
&
c
:
schedule
.
cycles
)
{
for
(
const
auto
&
t
:
c
)
{
result
+=
t
.
transactions
.
size
();
}
}
...
...
@@ -137,21 +186,21 @@ static uint transaction_count(block_schedule const &schedule) {
return
result
;
}
static
uint
cycle_count
(
block_schedule
const
&
schedule
)
{
static
uint
cycle_count
(
const
block_schedule
&
schedule
)
{
return
schedule
.
cycles
.
size
();
}
static
bool
schedule_is_valid
(
block_schedule
const
&
schedule
)
{
for
(
auto
const
&
c
:
schedule
.
cycles
)
{
static
bool
schedule_is_valid
(
const
block_schedule
&
schedule
)
{
for
(
const
auto
&
c
:
schedule
.
cycles
)
{
std
::
vector
<
bool
>
scope_in_use
;
for
(
auto
const
&
t
:
c
)
{
for
(
const
auto
&
t
:
c
)
{
std
::
set
<
size_t
>
thread_bits
;
size_t
max_bit
=
0
;
for
(
auto
const
&
pt
:
t
.
transactions
)
{
for
(
const
auto
&
pt
:
t
.
transactions
)
{
auto
scopes
=
pt
.
visit
(
scope_extracting_visitor
());
for
(
auto
const
&
s
:
scopes
)
{
for
(
const
auto
&
s
:
scopes
)
{
size_t
bit
=
boost
::
numeric_cast
<
size_t
>
((
uint64_t
)
s
);
thread_bits
.
emplace
(
bit
);
max_bit
=
std
::
max
(
max_bit
,
bit
);
...
...
@@ -267,7 +316,7 @@ BOOST_FIXTURE_TEST_CASE(no_conflicts_shuffled, default_fixture) {
// does not affect the ability to schedule them in a single cycle
for
(
int
i
=
0
;
i
<
3000
;
i
++
)
{
schedule_and_validate
(
block_schedule
::
shuffled
(
block_schedule
::
by_threading_conflicts
),
shuffled
(
block_schedule
::
by_threading_conflicts
),
{
{
0x1ULL
,
0x2ULL
},
{
0x3ULL
,
0x4ULL
},
...
...
@@ -303,7 +352,7 @@ BOOST_FIXTURE_TEST_CASE(some_conflicts_shuffled, default_fixture) {
// does not affect the ability to schedule them in multiple cycles
for
(
int
i
=
0
;
i
<
3000
;
i
++
)
{
schedule_and_validate
(
block_schedule
::
shuffled
(
block_schedule
::
by_threading_conflicts
),
shuffled
(
block_schedule
::
by_threading_conflicts
),
{
{
0x1ULL
,
0x2ULL
},
{
0x3ULL
,
0x2ULL
},
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录