Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
489e3eab
Commit
489e3eab
authored
Mar 01, 2014
by
John Esmet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Got rid if some stuff, tokufractaltree compiling
parent
10a4b766
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
59 additions
and
93 deletions
+59
-93
ft/cachetable.cc
ft/cachetable.cc
+0
-2
ft/ft-cachetable-wrappers.cc
ft/ft-cachetable-wrappers.cc
+3
-18
ft/ft-cachetable-wrappers.h
ft/ft-cachetable-wrappers.h
+1
-38
ft/ft-flusher.cc
ft/ft-flusher.cc
+4
-4
ft/ft-hot-flusher.cc
ft/ft-hot-flusher.cc
+2
-1
ft/ft-ops.cc
ft/ft-ops.cc
+22
-16
ft/ft-test-helpers.cc
ft/ft-test-helpers.cc
+2
-1
ft/ft-verify.cc
ft/ft-verify.cc
+1
-1
ft/tests/test-checkpoint-during-merge.cc
ft/tests/test-checkpoint-during-merge.cc
+12
-6
ft/tests/test-checkpoint-during-rebalance.cc
ft/tests/test-checkpoint-during-rebalance.cc
+4
-2
ft/tests/test-dirty-flushes-on-cleaner.cc
ft/tests/test-dirty-flushes-on-cleaner.cc
+8
-4
No files found.
ft/cachetable.cc
View file @
489e3eab
...
...
@@ -1302,8 +1302,6 @@ void toku_cachetable_pf_pinned_pair(
pair_unlock
(
p
);
}
// NOW A TEST ONLY FUNCTION!!!
int
toku_cachetable_get_and_pin
(
CACHEFILE
cachefile
,
CACHEKEY
key
,
...
...
ft/ft-cachetable-wrappers.cc
View file @
489e3eab
...
...
@@ -324,22 +324,7 @@ toku_pin_ftnode_off_client_thread(
FTNODE_FETCH_EXTRA
bfe
,
pair_lock_type
lock_type
,
uint32_t
num_dependent_nodes
,
FTNODE
*
dependent_nodes
,
FTNODE
*
node_p
)
{
toku_pin_ftnode_off_client_thread_and_maybe_move_messages
(
h
,
blocknum
,
fullhash
,
bfe
,
lock_type
,
num_dependent_nodes
,
dependent_nodes
,
node_p
,
true
);
}
void
toku_pin_ftnode_off_client_thread_and_maybe_move_messages
(
FT
h
,
BLOCKNUM
blocknum
,
uint32_t
fullhash
,
FTNODE_FETCH_EXTRA
bfe
,
pair_lock_type
lock_type
,
uint32_t
num_dependent_nodes
,
FTNODE
*
dependent_nodes
,
FTNODE
*
dependent_nodes
,
FTNODE
*
node_p
,
bool
move_messages
)
{
...
...
@@ -367,9 +352,9 @@ toku_pin_ftnode_off_client_thread_and_maybe_move_messages(
dependent_pairs
,
dependent_dirty_bits
);
assert
(
r
==
0
);
invariant_zero
(
r
);
FTNODE
node
=
(
FTNODE
)
node_v
;
if
(
(
lock_type
!=
PL_READ
)
&&
node
->
height
>
0
&&
move_messages
)
{
if
(
lock_type
!=
PL_READ
&&
node
->
height
>
0
&&
move_messages
)
{
toku_move_ftnode_messages_to_stale
(
h
,
node
);
}
*
node_p
=
node
;
...
...
ft/ft-cachetable-wrappers.h
View file @
489e3eab
...
...
@@ -167,19 +167,7 @@ toku_pin_ftnode_off_client_thread(
FTNODE_FETCH_EXTRA
bfe
,
pair_lock_type
lock_type
,
uint32_t
num_dependent_nodes
,
FTNODE
*
dependent_nodes
,
FTNODE
*
node_p
);
void
toku_pin_ftnode_off_client_thread_and_maybe_move_messages
(
FT
h
,
BLOCKNUM
blocknum
,
uint32_t
fullhash
,
FTNODE_FETCH_EXTRA
bfe
,
pair_lock_type
lock_type
,
uint32_t
num_dependent_nodes
,
FTNODE
*
dependent_nodes
,
FTNODE
*
dependent_nodes
,
FTNODE
*
node_p
,
bool
move_messages
);
...
...
@@ -190,31 +178,6 @@ toku_pin_ftnode_off_client_thread_and_maybe_move_messages(
*/
int
toku_maybe_pin_ftnode_clean
(
FT
ft
,
BLOCKNUM
blocknum
,
uint32_t
fullhash
,
pair_lock_type
lock_type
,
FTNODE
*
nodep
);
void
toku_pin_ftnode_off_client_thread_and_maybe_move_messages
(
FT
h
,
BLOCKNUM
blocknum
,
uint32_t
fullhash
,
FTNODE_FETCH_EXTRA
bfe
,
pair_lock_type
lock_type
,
uint32_t
num_dependent_nodes
,
FTNODE
*
dependent_nodes
,
FTNODE
*
node_p
,
bool
move_messages
);
void
toku_pin_ftnode_off_client_thread
(
FT
h
,
BLOCKNUM
blocknum
,
uint32_t
fullhash
,
FTNODE_FETCH_EXTRA
bfe
,
pair_lock_type
lock_type
,
uint32_t
num_dependent_nodes
,
FTNODE
*
dependent_nodes
,
FTNODE
*
node_p
);
/**
* Effect: Unpin a brt node. Used for
* nodes that were pinned off client thread.
...
...
ft/ft-flusher.cc
View file @
489e3eab
...
...
@@ -496,7 +496,7 @@ ct_maybe_merge_child(struct flusher_advice *fa,
toku_calculate_root_offset_pointer
(
h
,
&
root
,
&
fullhash
);
struct
ftnode_fetch_extra
bfe
;
fill_bfe_for_full_read
(
&
bfe
,
h
);
toku_pin_ftnode_off_client_thread
(
h
,
root
,
fullhash
,
&
bfe
,
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
root_node
);
toku_pin_ftnode_off_client_thread
(
h
,
root
,
fullhash
,
&
bfe
,
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
root_node
,
true
);
toku_assert_entire_node_in_memory
(
root_node
);
}
...
...
@@ -1426,7 +1426,7 @@ ft_merge_child(
uint32_t
childfullhash
=
compute_child_fullhash
(
h
->
cf
,
node
,
childnuma
);
struct
ftnode_fetch_extra
bfe
;
fill_bfe_for_full_read
(
&
bfe
,
h
);
toku_pin_ftnode_off_client_thread
(
h
,
BP_BLOCKNUM
(
node
,
childnuma
),
childfullhash
,
&
bfe
,
PL_WRITE_EXPENSIVE
,
1
,
&
node
,
&
childa
);
toku_pin_ftnode_off_client_thread
(
h
,
BP_BLOCKNUM
(
node
,
childnuma
),
childfullhash
,
&
bfe
,
PL_WRITE_EXPENSIVE
,
1
,
&
node
,
&
childa
,
true
);
}
// for test
call_flusher_thread_callback
(
flt_flush_before_pin_second_node_for_merge
);
...
...
@@ -1437,7 +1437,7 @@ ft_merge_child(
uint32_t
childfullhash
=
compute_child_fullhash
(
h
->
cf
,
node
,
childnumb
);
struct
ftnode_fetch_extra
bfe
;
fill_bfe_for_full_read
(
&
bfe
,
h
);
toku_pin_ftnode_off_client_thread
(
h
,
BP_BLOCKNUM
(
node
,
childnumb
),
childfullhash
,
&
bfe
,
PL_WRITE_EXPENSIVE
,
2
,
dep_nodes
,
&
childb
);
toku_pin_ftnode_off_client_thread
(
h
,
BP_BLOCKNUM
(
node
,
childnumb
),
childfullhash
,
&
bfe
,
PL_WRITE_EXPENSIVE
,
2
,
dep_nodes
,
&
childb
,
true
);
}
if
(
toku_bnc_n_entries
(
BNC
(
node
,
childnuma
))
>
0
)
{
...
...
@@ -1575,7 +1575,7 @@ void toku_ft_flush_some_child(FT ft, FTNODE parent, struct flusher_advice *fa)
// Note that we don't read the entire node into memory yet.
// The idea is let's try to do the minimum work before releasing the parent lock
fill_bfe_for_min_read
(
&
bfe
,
ft
);
toku_pin_ftnode_off_client_thread
(
ft
,
targetchild
,
childfullhash
,
&
bfe
,
PL_WRITE_EXPENSIVE
,
1
,
&
parent
,
&
child
);
toku_pin_ftnode_off_client_thread
(
ft
,
targetchild
,
childfullhash
,
&
bfe
,
PL_WRITE_EXPENSIVE
,
1
,
&
parent
,
&
child
,
true
);
// for test
call_flusher_thread_callback
(
ft_flush_aflter_child_pin
);
...
...
ft/ft-hot-flusher.cc
View file @
489e3eab
...
...
@@ -339,7 +339,8 @@ toku_ft_hot_optimize(FT_HANDLE brt, DBT* left, DBT* right,
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
root
);
&
root
,
true
);
toku_assert_entire_node_in_memory
(
root
);
}
...
...
ft/ft-ops.cc
View file @
489e3eab
...
...
@@ -1682,7 +1682,8 @@ ft_init_new_root(FT ft, FTNODE oldroot, FTNODE *newrootp)
PL_WRITE_EXPENSIVE
,
// may_modify_node
0
,
NULL
,
newrootp
newrootp
,
true
);
}
...
...
@@ -2792,7 +2793,7 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
struct
ftnode_fetch_extra
bfe
;
fill_bfe_for_full_read
(
&
bfe
,
ft
);
FTNODE
newparent
,
newchild
;
toku_pin_ftnode_off_client_thread
(
ft
,
parent_blocknum
,
parent_fullhash
,
&
bfe
,
PL_WRITE_CHEAP
,
0
,
nullptr
,
&
newparent
);
toku_pin_ftnode_off_client_thread
(
ft
,
parent_blocknum
,
parent_fullhash
,
&
bfe
,
PL_WRITE_CHEAP
,
0
,
nullptr
,
&
newparent
,
true
);
if
(
newparent
->
height
!=
parent_height
||
newparent
->
n_children
!=
parent_n_children
||
childnum
>=
newparent
->
n_children
||
toku_bnc_n_entries
(
BNC
(
newparent
,
childnum
)))
{
// If the height changed or childnum is now off the end, something clearly got split or merged out from under us.
...
...
@@ -2806,7 +2807,7 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
// and split it.
child_blocknum
=
BP_BLOCKNUM
(
newparent
,
childnum
);
child_fullhash
=
compute_child_fullhash
(
ft
->
cf
,
newparent
,
childnum
);
toku_pin_ftnode_off_client_thread
(
ft
,
child_blocknum
,
child_fullhash
,
&
bfe
,
PL_WRITE_CHEAP
,
1
,
&
newparent
,
&
newchild
);
toku_pin_ftnode_off_client_thread
(
ft
,
child_blocknum
,
child_fullhash
,
&
bfe
,
PL_WRITE_CHEAP
,
1
,
&
newparent
,
&
newchild
,
true
);
newre
=
get_node_reactivity
(
ft
,
newchild
);
if
(
newre
==
RE_FISSIBLE
)
{
enum
split_mode
split_mode
;
...
...
@@ -2844,7 +2845,7 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
struct
ftnode_fetch_extra
bfe
;
fill_bfe_for_full_read
(
&
bfe
,
ft
);
FTNODE
newparent
,
newchild
;
toku_pin_ftnode_off_client_thread
(
ft
,
parent_blocknum
,
parent_fullhash
,
&
bfe
,
PL_WRITE_CHEAP
,
0
,
nullptr
,
&
newparent
);
toku_pin_ftnode_off_client_thread
(
ft
,
parent_blocknum
,
parent_fullhash
,
&
bfe
,
PL_WRITE_CHEAP
,
0
,
nullptr
,
&
newparent
,
true
);
if
(
newparent
->
height
!=
parent_height
||
childnum
>=
newparent
->
n_children
)
{
// looks like this is the root and it got merged, let's just start over (like in the split case above)
toku_unpin_ftnode_read_only
(
ft
,
newparent
);
...
...
@@ -2852,7 +2853,7 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
}
child_blocknum
=
BP_BLOCKNUM
(
newparent
,
childnum
);
child_fullhash
=
compute_child_fullhash
(
ft
->
cf
,
newparent
,
childnum
);
toku_pin_ftnode_off_client_thread
(
ft
,
child_blocknum
,
child_fullhash
,
&
bfe
,
PL_READ
,
1
,
&
newparent
,
&
newchild
);
toku_pin_ftnode_off_client_thread
(
ft
,
child_blocknum
,
child_fullhash
,
&
bfe
,
PL_READ
,
1
,
&
newparent
,
&
newchild
,
true
);
newre
=
get_node_reactivity
(
ft
,
newchild
);
if
(
newre
==
RE_FUSIBLE
&&
newparent
->
n_children
>=
2
)
{
toku_unpin_ftnode_read_only
(
ft
,
newchild
);
...
...
@@ -2885,7 +2886,7 @@ static void inject_message_at_this_blocknum(FT ft, CACHEKEY cachekey, uint32_t f
FTNODE
node
;
struct
ftnode_fetch_extra
bfe
;
fill_bfe_for_full_read
(
&
bfe
,
ft
);
toku_pin_ftnode_off_client_thread
(
ft
,
cachekey
,
fullhash
,
&
bfe
,
PL_WRITE_CHEAP
,
0
,
NULL
,
&
node
);
toku_pin_ftnode_off_client_thread
(
ft
,
cachekey
,
fullhash
,
&
bfe
,
PL_WRITE_CHEAP
,
0
,
NULL
,
&
node
,
true
);
toku_assert_entire_node_in_memory
(
node
);
paranoid_invariant
(
node
->
fullhash
==
fullhash
);
ft_verify_flags
(
ft
,
node
);
...
...
@@ -3008,11 +3009,11 @@ static void push_something_in_subtree(
if
(
lock_type
==
PL_WRITE_CHEAP
)
{
// We intend to take the write lock for message injection
toku
::
context
inject_ctx
(
CTX_MESSAGE_INJECTION
);
toku_pin_ftnode_off_client_thread
(
ft
,
child_blocknum
,
child_fullhash
,
&
bfe
,
lock_type
,
0
,
nullptr
,
&
child
);
toku_pin_ftnode_off_client_thread
(
ft
,
child_blocknum
,
child_fullhash
,
&
bfe
,
lock_type
,
0
,
nullptr
,
&
child
,
true
);
}
else
{
// We're going to keep promoting
toku
::
context
promo_ctx
(
CTX_PROMO
);
toku_pin_ftnode_off_client_thread
(
ft
,
child_blocknum
,
child_fullhash
,
&
bfe
,
lock_type
,
0
,
nullptr
,
&
child
);
toku_pin_ftnode_off_client_thread
(
ft
,
child_blocknum
,
child_fullhash
,
&
bfe
,
lock_type
,
0
,
nullptr
,
&
child
,
true
);
}
}
else
{
r
=
toku_maybe_pin_ftnode_clean
(
ft
,
child_blocknum
,
child_fullhash
,
lock_type
,
&
child
);
...
...
@@ -3045,7 +3046,7 @@ static void push_something_in_subtree(
FTNODE
newparent
;
struct
ftnode_fetch_extra
bfe
;
fill_bfe_for_full_read
(
&
bfe
,
ft
);
// should be fully in memory, we just split it
toku_pin_ftnode_off_client_thread
(
ft
,
subtree_root_blocknum
,
subtree_root_fullhash
,
&
bfe
,
PL_READ
,
0
,
nullptr
,
&
newparent
);
toku_pin_ftnode_off_client_thread
(
ft
,
subtree_root_blocknum
,
subtree_root_fullhash
,
&
bfe
,
PL_READ
,
0
,
nullptr
,
&
newparent
,
true
);
push_something_in_subtree
(
ft
,
newparent
,
-
1
,
msg
,
flow_deltas
,
gc_info
,
depth
,
loc
,
true
);
return
;
}
...
...
@@ -3142,7 +3143,7 @@ void toku_ft_root_put_msg(
// and jump back to here.
change_lock_type:
// get the root node
toku_pin_ftnode_off_client_thread
(
ft
,
root_key
,
fullhash
,
&
bfe
,
lock_type
,
0
,
NULL
,
&
node
);
toku_pin_ftnode_off_client_thread
(
ft
,
root_key
,
fullhash
,
&
bfe
,
lock_type
,
0
,
NULL
,
&
node
,
true
);
toku_assert_entire_node_in_memory
(
node
);
paranoid_invariant
(
node
->
fullhash
==
fullhash
);
ft_verify_flags
(
ft
,
node
);
...
...
@@ -5473,7 +5474,8 @@ try_again:
PL_READ
,
// may_modify_node set to false, because root cannot change during search
0
,
NULL
,
&
node
&
node
,
true
);
}
...
...
@@ -6095,7 +6097,8 @@ try_again:
PL_READ
,
// may_modify_node, cannot change root during keyrange
0
,
NULL
,
&
node
&
node
,
true
);
}
...
...
@@ -6305,7 +6308,7 @@ int toku_ft_get_key_after_bytes(FT_HANDLE ft_h, const DBT *start_key, uint64_t s
uint32_t
fullhash
;
CACHEKEY
root_key
;
toku_calculate_root_offset_pointer
(
ft
,
&
root_key
,
&
fullhash
);
toku_pin_ftnode_off_client_thread
(
ft
,
root_key
,
fullhash
,
&
bfe
,
PL_READ
,
0
,
nullptr
,
&
root
);
toku_pin_ftnode_off_client_thread
(
ft
,
root_key
,
fullhash
,
&
bfe
,
PL_READ
,
0
,
nullptr
,
&
root
,
true
);
}
struct
unlock_ftnode_extra
unlock_extra
=
{
ft_h
,
root
,
false
};
struct
unlockers
unlockers
=
{
true
,
unlock_ftnode_fun
,
(
void
*
)
&
unlock_extra
,
(
UNLOCKERS
)
nullptr
};
...
...
@@ -6371,7 +6374,8 @@ toku_dump_ftnode (FILE *file, FT_HANDLE brt, BLOCKNUM blocknum, int depth, const
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
fullhash
==
fullhash
);
fprintf
(
file
,
"%*sNode=%p
\n
"
,
depth
,
""
,
node
);
...
...
@@ -6571,7 +6575,8 @@ static bool is_empty_fast_iter (FT_HANDLE brt, FTNODE node) {
PL_READ
,
// may_modify_node set to false, as nodes not modified
0
,
NULL
,
&
childnode
&
childnode
,
true
);
}
int
child_is_empty
=
is_empty_fast_iter
(
brt
,
childnode
);
...
...
@@ -6609,7 +6614,8 @@ bool toku_ft_is_empty_fast (FT_HANDLE brt)
PL_READ
,
// may_modify_node set to false, node does not change
0
,
NULL
,
&
node
&
node
,
true
);
}
bool
r
=
is_empty_fast_iter
(
brt
,
node
);
...
...
ft/ft-test-helpers.cc
View file @
489e3eab
...
...
@@ -262,7 +262,8 @@ toku_pin_node_with_min_bfe(FTNODE* node, BLOCKNUM b, FT_HANDLE t)
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
node
node
,
true
);
}
...
...
ft/ft-verify.cc
View file @
489e3eab
...
...
@@ -297,7 +297,7 @@ toku_get_node_for_verify(
uint32_t
fullhash
=
toku_cachetable_hash
(
brt
->
ft
->
cf
,
blocknum
);
struct
ftnode_fetch_extra
bfe
;
fill_bfe_for_full_read
(
&
bfe
,
brt
->
ft
);
toku_pin_ftnode_off_client_thread
_and_maybe_move_messages
(
toku_pin_ftnode_off_client_thread
(
brt
->
ft
,
blocknum
,
fullhash
,
...
...
ft/tests/test-checkpoint-during-merge.cc
View file @
489e3eab
...
...
@@ -256,7 +256,8 @@ doit (int state) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
height
==
1
);
assert
(
node
->
n_children
==
2
);
...
...
@@ -274,7 +275,8 @@ doit (int state) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
height
==
1
);
assert
(
node
->
n_children
==
1
);
...
...
@@ -313,7 +315,8 @@ doit (int state) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
height
==
1
);
assert
(
!
node
->
dirty
);
...
...
@@ -343,7 +346,8 @@ doit (int state) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
height
==
0
);
assert
(
!
node
->
dirty
);
...
...
@@ -359,7 +363,8 @@ doit (int state) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
height
==
0
);
assert
(
!
node
->
dirty
);
...
...
@@ -376,7 +381,8 @@ doit (int state) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
height
==
0
);
assert
(
!
node
->
dirty
);
...
...
ft/tests/test-checkpoint-during-rebalance.cc
View file @
489e3eab
...
...
@@ -276,7 +276,8 @@ doit (int state) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
height
==
1
);
assert
(
node
->
n_children
==
2
);
...
...
@@ -294,7 +295,8 @@ doit (int state) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
height
==
1
);
assert
(
node
->
n_children
==
2
);
...
...
ft/tests/test-dirty-flushes-on-cleaner.cc
View file @
489e3eab
...
...
@@ -248,7 +248,8 @@ doit (void) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
dirty
);
assert
(
node
->
n_children
==
2
);
...
...
@@ -277,7 +278,8 @@ doit (void) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
dirty
);
assert
(
node
->
n_children
==
2
);
...
...
@@ -297,7 +299,8 @@ doit (void) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
assert
(
node
->
dirty
);
...
...
@@ -321,7 +324,8 @@ doit (void) {
PL_WRITE_EXPENSIVE
,
0
,
NULL
,
&
node
&
node
,
true
);
// check that buffers are empty
assert
(
toku_bnc_nbytesinbuf
(
BNC
(
node
,
0
))
==
0
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment