Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
89a9e5a9
Commit
89a9e5a9
authored
May 09, 2017
by
Guy Benoish
Browse files
Merge branch 'unstable' of
https://github.com/antirez/redis
into unstable
parents
71a8df6a
a4c7f34d
Changes
178
Hide whitespace changes
Inline
Side-by-side
deps/jemalloc/test/unit/rb.c
View file @
89a9e5a9
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
#define rbtn_black_height(a_type, a_field, a_rbt, r_height) do { \
#define rbtn_black_height(a_type, a_field, a_rbt, r_height) do { \
a_type *rbp_bh_t; \
a_type *rbp_bh_t; \
for (rbp_bh_t = (a_rbt)->rbt_root, (r_height) = 0; \
for (rbp_bh_t = (a_rbt)->rbt_root, (r_height) = 0; \
rbp_bh_t !=
NULL;
\
rbp_bh_t !=
&(a_rbt)->rbt_nil;
\
rbp_bh_t = rbtn_left_get(a_type, a_field, rbp_bh_t)) { \
rbp_bh_t = rbtn_left_get(a_type, a_field, rbp_bh_t)) { \
if (!rbtn_red_get(a_type, a_field, rbp_bh_t)) { \
if (!rbtn_red_get(a_type, a_field, rbp_bh_t)) { \
(r_height)++; \
(r_height)++; \
...
@@ -21,7 +21,7 @@ struct node_s {
...
@@ -21,7 +21,7 @@ struct node_s {
};
};
static
int
static
int
node_cmp
(
const
node_t
*
a
,
const
node_t
*
b
)
{
node_cmp
(
node_t
*
a
,
node_t
*
b
)
{
int
ret
;
int
ret
;
assert_u32_eq
(
a
->
magic
,
NODE_MAGIC
,
"Bad magic"
);
assert_u32_eq
(
a
->
magic
,
NODE_MAGIC
,
"Bad magic"
);
...
@@ -68,43 +68,38 @@ TEST_BEGIN(test_rb_empty)
...
@@ -68,43 +68,38 @@ TEST_BEGIN(test_rb_empty)
TEST_END
TEST_END
static
unsigned
static
unsigned
tree_recurse
(
node_t
*
node
,
unsigned
black_height
,
unsigned
black_depth
)
tree_recurse
(
node_t
*
node
,
unsigned
black_height
,
unsigned
black_depth
,
node_t
*
nil
)
{
{
unsigned
ret
=
0
;
unsigned
ret
=
0
;
node_t
*
left_node
;
node_t
*
left_node
=
rbtn_left_get
(
node_t
,
link
,
node
);
node_t
*
right_node
;
node_t
*
right_node
=
rbtn_right_get
(
node_t
,
link
,
node
);
if
(
node
==
NULL
)
return
(
ret
);
left_node
=
rbtn_left_get
(
node_t
,
link
,
node
);
right_node
=
rbtn_right_get
(
node_t
,
link
,
node
);
if
(
!
rbtn_red_get
(
node_t
,
link
,
node
))
if
(
!
rbtn_red_get
(
node_t
,
link
,
node
))
black_depth
++
;
black_depth
++
;
/* Red nodes must be interleaved with black nodes. */
/* Red nodes must be interleaved with black nodes. */
if
(
rbtn_red_get
(
node_t
,
link
,
node
))
{
if
(
rbtn_red_get
(
node_t
,
link
,
node
))
{
if
(
left_node
!=
NULL
)
assert_false
(
rbtn_red_get
(
node_t
,
link
,
left_node
),
assert_false
(
rbtn_red_get
(
node_t
,
link
,
left_node
),
"Node should be black"
);
"Node should be black"
);
assert_false
(
rbtn_red_get
(
node_t
,
link
,
right_node
),
if
(
right_node
!=
NULL
)
"Node should be black"
);
assert_false
(
rbtn_red_get
(
node_t
,
link
,
right_node
),
"Node should be black"
);
}
}
if
(
node
==
nil
)
return
(
ret
);
/* Self. */
/* Self. */
assert_u32_eq
(
node
->
magic
,
NODE_MAGIC
,
"Bad magic"
);
assert_u32_eq
(
node
->
magic
,
NODE_MAGIC
,
"Bad magic"
);
/* Left subtree. */
/* Left subtree. */
if
(
left_node
!=
NULL
)
if
(
left_node
!=
nil
)
ret
+=
tree_recurse
(
left_node
,
black_height
,
black_depth
);
ret
+=
tree_recurse
(
left_node
,
black_height
,
black_depth
,
nil
);
else
else
ret
+=
(
black_depth
!=
black_height
);
ret
+=
(
black_depth
!=
black_height
);
/* Right subtree. */
/* Right subtree. */
if
(
right_node
!=
NULL
)
if
(
right_node
!=
nil
)
ret
+=
tree_recurse
(
right_node
,
black_height
,
black_depth
);
ret
+=
tree_recurse
(
right_node
,
black_height
,
black_depth
,
nil
);
else
else
ret
+=
(
black_depth
!=
black_height
);
ret
+=
(
black_depth
!=
black_height
);
...
@@ -186,7 +181,8 @@ node_remove(tree_t *tree, node_t *node, unsigned nnodes)
...
@@ -186,7 +181,8 @@ node_remove(tree_t *tree, node_t *node, unsigned nnodes)
node
->
magic
=
0
;
node
->
magic
=
0
;
rbtn_black_height
(
node_t
,
link
,
tree
,
black_height
);
rbtn_black_height
(
node_t
,
link
,
tree
,
black_height
);
imbalances
=
tree_recurse
(
tree
->
rbt_root
,
black_height
,
0
);
imbalances
=
tree_recurse
(
tree
->
rbt_root
,
black_height
,
0
,
&
(
tree
->
rbt_nil
));
assert_u_eq
(
imbalances
,
0
,
"Tree is unbalanced"
);
assert_u_eq
(
imbalances
,
0
,
"Tree is unbalanced"
);
assert_u_eq
(
tree_iterate
(
tree
),
nnodes
-
1
,
assert_u_eq
(
tree_iterate
(
tree
),
nnodes
-
1
,
"Unexpected node iteration count"
);
"Unexpected node iteration count"
);
...
@@ -216,15 +212,6 @@ remove_reverse_iterate_cb(tree_t *tree, node_t *node, void *data)
...
@@ -216,15 +212,6 @@ remove_reverse_iterate_cb(tree_t *tree, node_t *node, void *data)
return
(
ret
);
return
(
ret
);
}
}
static
void
destroy_cb
(
node_t
*
node
,
void
*
data
)
{
unsigned
*
nnodes
=
(
unsigned
*
)
data
;
assert_u_gt
(
*
nnodes
,
0
,
"Destruction removed too many nodes"
);
(
*
nnodes
)
--
;
}
TEST_BEGIN
(
test_rb_random
)
TEST_BEGIN
(
test_rb_random
)
{
{
#define NNODES 25
#define NNODES 25
...
@@ -257,6 +244,7 @@ TEST_BEGIN(test_rb_random)
...
@@ -257,6 +244,7 @@ TEST_BEGIN(test_rb_random)
for
(
j
=
1
;
j
<=
NNODES
;
j
++
)
{
for
(
j
=
1
;
j
<=
NNODES
;
j
++
)
{
/* Initialize tree and nodes. */
/* Initialize tree and nodes. */
tree_new
(
&
tree
);
tree_new
(
&
tree
);
tree
.
rbt_nil
.
magic
=
0
;
for
(
k
=
0
;
k
<
j
;
k
++
)
{
for
(
k
=
0
;
k
<
j
;
k
++
)
{
nodes
[
k
].
magic
=
NODE_MAGIC
;
nodes
[
k
].
magic
=
NODE_MAGIC
;
nodes
[
k
].
key
=
bag
[
k
];
nodes
[
k
].
key
=
bag
[
k
];
...
@@ -269,7 +257,7 @@ TEST_BEGIN(test_rb_random)
...
@@ -269,7 +257,7 @@ TEST_BEGIN(test_rb_random)
rbtn_black_height
(
node_t
,
link
,
&
tree
,
rbtn_black_height
(
node_t
,
link
,
&
tree
,
black_height
);
black_height
);
imbalances
=
tree_recurse
(
tree
.
rbt_root
,
imbalances
=
tree_recurse
(
tree
.
rbt_root
,
black_height
,
0
);
black_height
,
0
,
&
(
tree
.
rbt_nil
)
);
assert_u_eq
(
imbalances
,
0
,
assert_u_eq
(
imbalances
,
0
,
"Tree is unbalanced"
);
"Tree is unbalanced"
);
...
@@ -290,7 +278,7 @@ TEST_BEGIN(test_rb_random)
...
@@ -290,7 +278,7 @@ TEST_BEGIN(test_rb_random)
}
}
/* Remove nodes. */
/* Remove nodes. */
switch
(
i
%
5
)
{
switch
(
i
%
4
)
{
case
0
:
case
0
:
for
(
k
=
0
;
k
<
j
;
k
++
)
for
(
k
=
0
;
k
<
j
;
k
++
)
node_remove
(
&
tree
,
&
nodes
[
k
],
j
-
k
);
node_remove
(
&
tree
,
&
nodes
[
k
],
j
-
k
);
...
@@ -326,12 +314,6 @@ TEST_BEGIN(test_rb_random)
...
@@ -326,12 +314,6 @@ TEST_BEGIN(test_rb_random)
assert_u_eq
(
nnodes
,
0
,
assert_u_eq
(
nnodes
,
0
,
"Removal terminated early"
);
"Removal terminated early"
);
break
;
break
;
}
case
4
:
{
unsigned
nnodes
=
j
;
tree_destroy
(
&
tree
,
destroy_cb
,
&
nnodes
);
assert_u_eq
(
nnodes
,
0
,
"Destruction terminated early"
);
break
;
}
default
:
}
default
:
not_reached
();
not_reached
();
}
}
...
...
deps/jemalloc/test/unit/run_quantize.c
deleted
100644 → 0
View file @
71a8df6a
#include "test/jemalloc_test.h"
TEST_BEGIN
(
test_small_run_size
)
{
unsigned
nbins
,
i
;
size_t
sz
,
run_size
;
size_t
mib
[
4
];
size_t
miblen
=
sizeof
(
mib
)
/
sizeof
(
size_t
);
/*
* Iterate over all small size classes, get their run sizes, and verify
* that the quantized size is the same as the run size.
*/
sz
=
sizeof
(
unsigned
);
assert_d_eq
(
mallctl
(
"arenas.nbins"
,
(
void
*
)
&
nbins
,
&
sz
,
NULL
,
0
),
0
,
"Unexpected mallctl failure"
);
assert_d_eq
(
mallctlnametomib
(
"arenas.bin.0.run_size"
,
mib
,
&
miblen
),
0
,
"Unexpected mallctlnametomib failure"
);
for
(
i
=
0
;
i
<
nbins
;
i
++
)
{
mib
[
2
]
=
i
;
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctlbymib
(
mib
,
miblen
,
(
void
*
)
&
run_size
,
&
sz
,
NULL
,
0
),
0
,
"Unexpected mallctlbymib failure"
);
assert_zu_eq
(
run_size
,
run_quantize_floor
(
run_size
),
"Small run quantization should be a no-op (run_size=%zu)"
,
run_size
);
assert_zu_eq
(
run_size
,
run_quantize_ceil
(
run_size
),
"Small run quantization should be a no-op (run_size=%zu)"
,
run_size
);
}
}
TEST_END
TEST_BEGIN
(
test_large_run_size
)
{
bool
cache_oblivious
;
unsigned
nlruns
,
i
;
size_t
sz
,
run_size_prev
,
ceil_prev
;
size_t
mib
[
4
];
size_t
miblen
=
sizeof
(
mib
)
/
sizeof
(
size_t
);
/*
* Iterate over all large size classes, get their run sizes, and verify
* that the quantized size is the same as the run size.
*/
sz
=
sizeof
(
bool
);
assert_d_eq
(
mallctl
(
"config.cache_oblivious"
,
(
void
*
)
&
cache_oblivious
,
&
sz
,
NULL
,
0
),
0
,
"Unexpected mallctl failure"
);
sz
=
sizeof
(
unsigned
);
assert_d_eq
(
mallctl
(
"arenas.nlruns"
,
(
void
*
)
&
nlruns
,
&
sz
,
NULL
,
0
),
0
,
"Unexpected mallctl failure"
);
assert_d_eq
(
mallctlnametomib
(
"arenas.lrun.0.size"
,
mib
,
&
miblen
),
0
,
"Unexpected mallctlnametomib failure"
);
for
(
i
=
0
;
i
<
nlruns
;
i
++
)
{
size_t
lrun_size
,
run_size
,
floor
,
ceil
;
mib
[
2
]
=
i
;
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctlbymib
(
mib
,
miblen
,
(
void
*
)
&
lrun_size
,
&
sz
,
NULL
,
0
),
0
,
"Unexpected mallctlbymib failure"
);
run_size
=
cache_oblivious
?
lrun_size
+
PAGE
:
lrun_size
;
floor
=
run_quantize_floor
(
run_size
);
ceil
=
run_quantize_ceil
(
run_size
);
assert_zu_eq
(
run_size
,
floor
,
"Large run quantization should be a no-op for precise "
"size (lrun_size=%zu, run_size=%zu)"
,
lrun_size
,
run_size
);
assert_zu_eq
(
run_size
,
ceil
,
"Large run quantization should be a no-op for precise "
"size (lrun_size=%zu, run_size=%zu)"
,
lrun_size
,
run_size
);
if
(
i
>
0
)
{
assert_zu_eq
(
run_size_prev
,
run_quantize_floor
(
run_size
-
PAGE
),
"Floor should be a precise size"
);
if
(
run_size_prev
<
ceil_prev
)
{
assert_zu_eq
(
ceil_prev
,
run_size
,
"Ceiling should be a precise size "
"(run_size_prev=%zu, ceil_prev=%zu, "
"run_size=%zu)"
,
run_size_prev
,
ceil_prev
,
run_size
);
}
}
run_size_prev
=
floor
;
ceil_prev
=
run_quantize_ceil
(
run_size
+
PAGE
);
}
}
TEST_END
TEST_BEGIN
(
test_monotonic
)
{
unsigned
nbins
,
nlruns
,
i
;
size_t
sz
,
floor_prev
,
ceil_prev
;
/*
* Iterate over all run sizes and verify that
* run_quantize_{floor,ceil}() are monotonic.
*/
sz
=
sizeof
(
unsigned
);
assert_d_eq
(
mallctl
(
"arenas.nbins"
,
(
void
*
)
&
nbins
,
&
sz
,
NULL
,
0
),
0
,
"Unexpected mallctl failure"
);
sz
=
sizeof
(
unsigned
);
assert_d_eq
(
mallctl
(
"arenas.nlruns"
,
(
void
*
)
&
nlruns
,
&
sz
,
NULL
,
0
),
0
,
"Unexpected mallctl failure"
);
floor_prev
=
0
;
ceil_prev
=
0
;
for
(
i
=
1
;
i
<=
chunksize
>>
LG_PAGE
;
i
++
)
{
size_t
run_size
,
floor
,
ceil
;
run_size
=
i
<<
LG_PAGE
;
floor
=
run_quantize_floor
(
run_size
);
ceil
=
run_quantize_ceil
(
run_size
);
assert_zu_le
(
floor
,
run_size
,
"Floor should be <= (floor=%zu, run_size=%zu, ceil=%zu)"
,
floor
,
run_size
,
ceil
);
assert_zu_ge
(
ceil
,
run_size
,
"Ceiling should be >= (floor=%zu, run_size=%zu, ceil=%zu)"
,
floor
,
run_size
,
ceil
);
assert_zu_le
(
floor_prev
,
floor
,
"Floor should be monotonic "
"(floor_prev=%zu, floor=%zu, run_size=%zu, ceil=%zu)"
,
floor_prev
,
floor
,
run_size
,
ceil
);
assert_zu_le
(
ceil_prev
,
ceil
,
"Ceiling should be monotonic "
"(floor=%zu, run_size=%zu, ceil_prev=%zu, ceil=%zu)"
,
floor
,
run_size
,
ceil_prev
,
ceil
);
floor_prev
=
floor
;
ceil_prev
=
ceil
;
}
}
TEST_END
int
main
(
void
)
{
return
(
test
(
test_small_run_size
,
test_large_run_size
,
test_monotonic
));
}
deps/jemalloc/test/unit/size_classes.c
100755 → 100644
View file @
89a9e5a9
...
@@ -8,8 +8,8 @@ get_max_size_class(void)
...
@@ -8,8 +8,8 @@ get_max_size_class(void)
size_t
sz
,
miblen
,
max_size_class
;
size_t
sz
,
miblen
,
max_size_class
;
sz
=
sizeof
(
unsigned
);
sz
=
sizeof
(
unsigned
);
assert_d_eq
(
mallctl
(
"arenas.nhchunks"
,
(
void
*
)
&
nhchunks
,
&
sz
,
NULL
,
0
),
assert_d_eq
(
mallctl
(
"arenas.nhchunks"
,
&
nhchunks
,
&
sz
,
NULL
,
0
),
0
,
0
,
"Unexpected mallctl() error"
);
"Unexpected mallctl() error"
);
miblen
=
sizeof
(
mib
)
/
sizeof
(
size_t
);
miblen
=
sizeof
(
mib
)
/
sizeof
(
size_t
);
assert_d_eq
(
mallctlnametomib
(
"arenas.hchunk.0.size"
,
mib
,
&
miblen
),
0
,
assert_d_eq
(
mallctlnametomib
(
"arenas.hchunk.0.size"
,
mib
,
&
miblen
),
0
,
...
@@ -17,8 +17,8 @@ get_max_size_class(void)
...
@@ -17,8 +17,8 @@ get_max_size_class(void)
mib
[
2
]
=
nhchunks
-
1
;
mib
[
2
]
=
nhchunks
-
1
;
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctlbymib
(
mib
,
miblen
,
(
void
*
)
&
max_size_class
,
&
sz
,
assert_d_eq
(
mallctlbymib
(
mib
,
miblen
,
&
max_size_class
,
&
sz
,
NULL
,
0
),
0
,
NULL
,
0
),
0
,
"Unexpected mallctlbymib() error"
);
"Unexpected mallctlbymib() error"
);
return
(
max_size_class
);
return
(
max_size_class
);
}
}
...
@@ -80,105 +80,10 @@ TEST_BEGIN(test_size_classes)
...
@@ -80,105 +80,10 @@ TEST_BEGIN(test_size_classes)
}
}
TEST_END
TEST_END
TEST_BEGIN
(
test_psize_classes
)
{
size_t
size_class
,
max_size_class
;
pszind_t
pind
,
max_pind
;
max_size_class
=
get_max_size_class
();
max_pind
=
psz2ind
(
max_size_class
);
for
(
pind
=
0
,
size_class
=
pind2sz
(
pind
);
pind
<
max_pind
||
size_class
<
max_size_class
;
pind
++
,
size_class
=
pind2sz
(
pind
))
{
assert_true
(
pind
<
max_pind
,
"Loop conditionals should be equivalent; pind=%u, "
"size_class=%zu (%#zx)"
,
pind
,
size_class
,
size_class
);
assert_true
(
size_class
<
max_size_class
,
"Loop conditionals should be equivalent; pind=%u, "
"size_class=%zu (%#zx)"
,
pind
,
size_class
,
size_class
);
assert_u_eq
(
pind
,
psz2ind
(
size_class
),
"psz2ind() does not reverse pind2sz(): pind=%u -->"
" size_class=%zu --> pind=%u --> size_class=%zu"
,
pind
,
size_class
,
psz2ind
(
size_class
),
pind2sz
(
psz2ind
(
size_class
)));
assert_zu_eq
(
size_class
,
pind2sz
(
psz2ind
(
size_class
)),
"pind2sz() does not reverse psz2ind(): pind=%u -->"
" size_class=%zu --> pind=%u --> size_class=%zu"
,
pind
,
size_class
,
psz2ind
(
size_class
),
pind2sz
(
psz2ind
(
size_class
)));
assert_u_eq
(
pind
+
1
,
psz2ind
(
size_class
+
1
),
"Next size_class does not round up properly"
);
assert_zu_eq
(
size_class
,
(
pind
>
0
)
?
psz2u
(
pind2sz
(
pind
-
1
)
+
1
)
:
psz2u
(
1
),
"psz2u() does not round up to size class"
);
assert_zu_eq
(
size_class
,
psz2u
(
size_class
-
1
),
"psz2u() does not round up to size class"
);
assert_zu_eq
(
size_class
,
psz2u
(
size_class
),
"psz2u() does not compute same size class"
);
assert_zu_eq
(
psz2u
(
size_class
+
1
),
pind2sz
(
pind
+
1
),
"psz2u() does not round up to next size class"
);
}
assert_u_eq
(
pind
,
psz2ind
(
pind2sz
(
pind
)),
"psz2ind() does not reverse pind2sz()"
);
assert_zu_eq
(
max_size_class
,
pind2sz
(
psz2ind
(
max_size_class
)),
"pind2sz() does not reverse psz2ind()"
);
assert_zu_eq
(
size_class
,
psz2u
(
pind2sz
(
pind
-
1
)
+
1
),
"psz2u() does not round up to size class"
);
assert_zu_eq
(
size_class
,
psz2u
(
size_class
-
1
),
"psz2u() does not round up to size class"
);
assert_zu_eq
(
size_class
,
psz2u
(
size_class
),
"psz2u() does not compute same size class"
);
}
TEST_END
TEST_BEGIN
(
test_overflow
)
{
size_t
max_size_class
;
max_size_class
=
get_max_size_class
();
assert_u_eq
(
size2index
(
max_size_class
+
1
),
NSIZES
,
"size2index() should return NSIZES on overflow"
);
assert_u_eq
(
size2index
(
ZU
(
PTRDIFF_MAX
)
+
1
),
NSIZES
,
"size2index() should return NSIZES on overflow"
);
assert_u_eq
(
size2index
(
SIZE_T_MAX
),
NSIZES
,
"size2index() should return NSIZES on overflow"
);
assert_zu_eq
(
s2u
(
max_size_class
+
1
),
0
,
"s2u() should return 0 for unsupported size"
);
assert_zu_eq
(
s2u
(
ZU
(
PTRDIFF_MAX
)
+
1
),
0
,
"s2u() should return 0 for unsupported size"
);
assert_zu_eq
(
s2u
(
SIZE_T_MAX
),
0
,
"s2u() should return 0 on overflow"
);
assert_u_eq
(
psz2ind
(
max_size_class
+
1
),
NPSIZES
,
"psz2ind() should return NPSIZES on overflow"
);
assert_u_eq
(
psz2ind
(
ZU
(
PTRDIFF_MAX
)
+
1
),
NPSIZES
,
"psz2ind() should return NPSIZES on overflow"
);
assert_u_eq
(
psz2ind
(
SIZE_T_MAX
),
NPSIZES
,
"psz2ind() should return NPSIZES on overflow"
);
assert_zu_eq
(
psz2u
(
max_size_class
+
1
),
0
,
"psz2u() should return 0 for unsupported size"
);
assert_zu_eq
(
psz2u
(
ZU
(
PTRDIFF_MAX
)
+
1
),
0
,
"psz2u() should return 0 for unsupported size"
);
assert_zu_eq
(
psz2u
(
SIZE_T_MAX
),
0
,
"psz2u() should return 0 on overflow"
);
}
TEST_END
int
int
main
(
void
)
main
(
void
)
{
{
return
(
test
(
return
(
test
(
test_size_classes
,
test_size_classes
));
test_psize_classes
,
test_overflow
));
}
}
deps/jemalloc/test/unit/smoothstep.c
deleted
100644 → 0
View file @
71a8df6a
#include "test/jemalloc_test.h"
static
const
uint64_t
smoothstep_tab
[]
=
{
#define STEP(step, h, x, y) \
h,
SMOOTHSTEP
#undef STEP
};
TEST_BEGIN
(
test_smoothstep_integral
)
{
uint64_t
sum
,
min
,
max
;
unsigned
i
;
/*
* The integral of smoothstep in the [0..1] range equals 1/2. Verify
* that the fixed point representation's integral is no more than
* rounding error distant from 1/2. Regarding rounding, each table
* element is rounded down to the nearest fixed point value, so the
* integral may be off by as much as SMOOTHSTEP_NSTEPS ulps.
*/
sum
=
0
;
for
(
i
=
0
;
i
<
SMOOTHSTEP_NSTEPS
;
i
++
)
sum
+=
smoothstep_tab
[
i
];
max
=
(
KQU
(
1
)
<<
(
SMOOTHSTEP_BFP
-
1
))
*
(
SMOOTHSTEP_NSTEPS
+
1
);
min
=
max
-
SMOOTHSTEP_NSTEPS
;
assert_u64_ge
(
sum
,
min
,
"Integral too small, even accounting for truncation"
);
assert_u64_le
(
sum
,
max
,
"Integral exceeds 1/2"
);
if
(
false
)
{
malloc_printf
(
"%"
FMTu64
" ulps under 1/2 (limit %d)
\n
"
,
max
-
sum
,
SMOOTHSTEP_NSTEPS
);
}
}
TEST_END
TEST_BEGIN
(
test_smoothstep_monotonic
)
{
uint64_t
prev_h
;
unsigned
i
;
/*
* The smoothstep function is monotonic in [0..1], i.e. its slope is
* non-negative. In practice we want to parametrize table generation
* such that piecewise slope is greater than zero, but do not require
* that here.
*/
prev_h
=
0
;
for
(
i
=
0
;
i
<
SMOOTHSTEP_NSTEPS
;
i
++
)
{
uint64_t
h
=
smoothstep_tab
[
i
];
assert_u64_ge
(
h
,
prev_h
,
"Piecewise non-monotonic, i=%u"
,
i
);
prev_h
=
h
;
}
assert_u64_eq
(
smoothstep_tab
[
SMOOTHSTEP_NSTEPS
-
1
],
(
KQU
(
1
)
<<
SMOOTHSTEP_BFP
),
"Last step must equal 1"
);
}
TEST_END
TEST_BEGIN
(
test_smoothstep_slope
)
{
uint64_t
prev_h
,
prev_delta
;
unsigned
i
;
/*
* The smoothstep slope strictly increases until x=0.5, and then
* strictly decreases until x=1.0. Verify the slightly weaker
* requirement of monotonicity, so that inadequate table precision does
* not cause false test failures.
*/
prev_h
=
0
;
prev_delta
=
0
;
for
(
i
=
0
;
i
<
SMOOTHSTEP_NSTEPS
/
2
+
SMOOTHSTEP_NSTEPS
%
2
;
i
++
)
{
uint64_t
h
=
smoothstep_tab
[
i
];
uint64_t
delta
=
h
-
prev_h
;
assert_u64_ge
(
delta
,
prev_delta
,
"Slope must monotonically increase in 0.0 <= x <= 0.5, "
"i=%u"
,
i
);
prev_h
=
h
;
prev_delta
=
delta
;
}
prev_h
=
KQU
(
1
)
<<
SMOOTHSTEP_BFP
;
prev_delta
=
0
;
for
(
i
=
SMOOTHSTEP_NSTEPS
-
1
;
i
>=
SMOOTHSTEP_NSTEPS
/
2
;
i
--
)
{
uint64_t
h
=
smoothstep_tab
[
i
];
uint64_t
delta
=
prev_h
-
h
;
assert_u64_ge
(
delta
,
prev_delta
,
"Slope must monotonically decrease in 0.5 <= x <= 1.0, "
"i=%u"
,
i
);
prev_h
=
h
;
prev_delta
=
delta
;
}
}
TEST_END
int
main
(
void
)
{
return
(
test
(
test_smoothstep_integral
,
test_smoothstep_monotonic
,
test_smoothstep_slope
));
}
deps/jemalloc/test/unit/stats.c
100755 → 100644
View file @
89a9e5a9
...
@@ -7,18 +7,18 @@ TEST_BEGIN(test_stats_summary)
...
@@ -7,18 +7,18 @@ TEST_BEGIN(test_stats_summary)
int
expected
=
config_stats
?
0
:
ENOENT
;
int
expected
=
config_stats
?
0
:
ENOENT
;
sz
=
sizeof
(
cactive
);
sz
=
sizeof
(
cactive
);
assert_d_eq
(
mallctl
(
"stats.cactive"
,
(
void
*
)
&
cactive
,
&
sz
,
NULL
,
0
),
assert_d_eq
(
mallctl
(
"stats.cactive"
,
&
cactive
,
&
sz
,
NULL
,
0
),
expected
,
expected
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctl
(
"stats.allocated"
,
(
void
*
)
&
allocated
,
&
sz
,
NULL
,
assert_d_eq
(
mallctl
(
"stats.allocated"
,
&
allocated
,
&
sz
,
NULL
,
0
),
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.active"
,
(
void
*
)
&
active
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.resident"
,
(
void
*
)
&
resident
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.mapped"
,
(
void
*
)
&
mapped
,
&
sz
,
NULL
,
0
),
assert_d_eq
(
mallctl
(
"stats.active"
,
&
active
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.resident"
,
&
resident
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.mapped"
,
&
mapped
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
if
(
config_stats
)
{
if
(
config_stats
)
{
assert_zu_le
(
active
,
*
cactive
,
assert_zu_le
(
active
,
*
cactive
,
...
@@ -45,19 +45,19 @@ TEST_BEGIN(test_stats_huge)
...
@@ -45,19 +45,19 @@ TEST_BEGIN(test_stats_huge)
p
=
mallocx
(
large_maxclass
+
1
,
0
);
p
=
mallocx
(
large_maxclass
+
1
,
0
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
(
void
*
)
&
epoch
,
sizeof
(
epoch
)),
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
&
epoch
,
sizeof
(
epoch
)),
0
,
0
,
"Unexpected mallctl() failure"
);
"Unexpected mallctl() failure"
);
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.allocated"
,
(
void
*
)
&
allocated
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.allocated"
,
&
allocated
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
sz
=
sizeof
(
uint64_t
);
sz
=
sizeof
(
uint64_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.nmalloc"
,
(
void
*
)
&
nmalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.nmalloc"
,
&
nmalloc
,
&
sz
,
NULL
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.ndalloc"
,
(
void
*
)
&
ndalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.ndalloc"
,
&
ndalloc
,
&
sz
,
NULL
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.nrequests"
,
(
void
*
)
&
nrequests
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.nrequests"
,
&
nrequests
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
if
(
config_stats
)
{
if
(
config_stats
)
{
assert_zu_gt
(
allocated
,
0
,
assert_zu_gt
(
allocated
,
0
,
...
@@ -83,8 +83,8 @@ TEST_BEGIN(test_stats_arenas_summary)
...
@@ -83,8 +83,8 @@ TEST_BEGIN(test_stats_arenas_summary)
uint64_t
npurge
,
nmadvise
,
purged
;
uint64_t
npurge
,
nmadvise
,
purged
;
arena
=
0
;
arena
=
0
;
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
(
void
*
)
&
arena
,
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
&
arena
,
sizeof
(
arena
))
,
sizeof
(
arena
)),
0
,
"Unexpected mallctl() failure"
);
0
,
"Unexpected mallctl() failure"
);
little
=
mallocx
(
SMALL_MAXCLASS
,
0
);
little
=
mallocx
(
SMALL_MAXCLASS
,
0
);
assert_ptr_not_null
(
little
,
"Unexpected mallocx() failure"
);
assert_ptr_not_null
(
little
,
"Unexpected mallocx() failure"
);
...
@@ -93,26 +93,22 @@ TEST_BEGIN(test_stats_arenas_summary)
...
@@ -93,26 +93,22 @@ TEST_BEGIN(test_stats_arenas_summary)
huge
=
mallocx
(
chunksize
,
0
);
huge
=
mallocx
(
chunksize
,
0
);
assert_ptr_not_null
(
huge
,
"Unexpected mallocx() failure"
);
assert_ptr_not_null
(
huge
,
"Unexpected mallocx() failure"
);
dallocx
(
little
,
0
);
dallocx
(
large
,
0
);
dallocx
(
huge
,
0
);
assert_d_eq
(
mallctl
(
"arena.0.purge"
,
NULL
,
NULL
,
NULL
,
0
),
0
,
assert_d_eq
(
mallctl
(
"arena.0.purge"
,
NULL
,
NULL
,
NULL
,
0
),
0
,
"Unexpected mallctl() failure"
);
"Unexpected mallctl() failure"
);
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
(
void
*
)
&
epoch
,
sizeof
(
epoch
)),
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
&
epoch
,
sizeof
(
epoch
)),
0
,
0
,
"Unexpected mallctl() failure"
);
"Unexpected mallctl() failure"
);
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.mapped"
,
(
void
*
)
&
mapped
,
&
sz
,
NULL
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.mapped"
,
&
mapped
,
&
sz
,
NULL
,
0
),
0
),
expected
,
"Unexepected mallctl() result"
);
expected
,
"Unexepected mallctl() result"
);
sz
=
sizeof
(
uint64_t
);
sz
=
sizeof
(
uint64_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.npurge"
,
(
void
*
)
&
npurge
,
&
sz
,
NULL
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.npurge"
,
&
npurge
,
&
sz
,
NULL
,
0
),
0
),
expected
,
"Unexepected mallctl() result"
);
expected
,
"Unexepected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.nmadvise"
,
(
void
*
)
&
nmadvise
,
&
sz
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.nmadvise"
,
&
nmadvise
,
&
sz
,
NULL
,
0
),
NULL
,
0
),
expected
,
"Unexepected mallctl() result"
);
expected
,
"Unexepected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.purged"
,
(
void
*
)
&
purged
,
&
sz
,
NULL
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.purged"
,
&
purged
,
&
sz
,
NULL
,
0
),
0
),
expected
,
"Unexepected mallctl() result"
);
expected
,
"Unexepected mallctl() result"
);
if
(
config_stats
)
{
if
(
config_stats
)
{
assert_u64_gt
(
npurge
,
0
,
assert_u64_gt
(
npurge
,
0
,
...
@@ -120,6 +116,10 @@ TEST_BEGIN(test_stats_arenas_summary)
...
@@ -120,6 +116,10 @@ TEST_BEGIN(test_stats_arenas_summary)
assert_u64_le
(
nmadvise
,
purged
,
assert_u64_le
(
nmadvise
,
purged
,
"nmadvise should be no greater than purged"
);
"nmadvise should be no greater than purged"
);
}
}
dallocx
(
little
,
0
);
dallocx
(
large
,
0
);
dallocx
(
huge
,
0
);
}
}
TEST_END
TEST_END
...
@@ -150,8 +150,8 @@ TEST_BEGIN(test_stats_arenas_small)
...
@@ -150,8 +150,8 @@ TEST_BEGIN(test_stats_arenas_small)
no_lazy_lock
();
/* Lazy locking would dodge tcache testing. */
no_lazy_lock
();
/* Lazy locking would dodge tcache testing. */
arena
=
0
;
arena
=
0
;
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
(
void
*
)
&
arena
,
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
&
arena
,
sizeof
(
arena
))
,
sizeof
(
arena
)),
0
,
"Unexpected mallctl() failure"
);
0
,
"Unexpected mallctl() failure"
);
p
=
mallocx
(
SMALL_MAXCLASS
,
0
);
p
=
mallocx
(
SMALL_MAXCLASS
,
0
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
...
@@ -159,21 +159,19 @@ TEST_BEGIN(test_stats_arenas_small)
...
@@ -159,21 +159,19 @@ TEST_BEGIN(test_stats_arenas_small)
assert_d_eq
(
mallctl
(
"thread.tcache.flush"
,
NULL
,
NULL
,
NULL
,
0
),
assert_d_eq
(
mallctl
(
"thread.tcache.flush"
,
NULL
,
NULL
,
NULL
,
0
),
config_tcache
?
0
:
ENOENT
,
"Unexpected mallctl() result"
);
config_tcache
?
0
:
ENOENT
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
(
void
*
)
&
epoch
,
sizeof
(
epoch
)),
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
&
epoch
,
sizeof
(
epoch
)),
0
,
0
,
"Unexpected mallctl() failure"
);
"Unexpected mallctl() failure"
);
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.small.allocated"
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.small.allocated"
,
&
allocated
,
&
sz
,
(
void
*
)
&
allocated
,
&
sz
,
NULL
,
0
),
expected
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
sz
=
sizeof
(
uint64_t
);
sz
=
sizeof
(
uint64_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.small.nmalloc"
,
(
void
*
)
&
nmalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.small.nmalloc"
,
&
nmalloc
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.small.ndalloc"
,
(
void
*
)
&
ndalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.small.ndalloc"
,
&
ndalloc
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.small.nrequests"
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.small.nrequests"
,
&
nrequests
,
&
sz
,
(
void
*
)
&
nrequests
,
&
sz
,
NULL
,
0
),
expected
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
if
(
config_stats
)
{
if
(
config_stats
)
{
assert_zu_gt
(
allocated
,
0
,
assert_zu_gt
(
allocated
,
0
,
...
@@ -199,36 +197,34 @@ TEST_BEGIN(test_stats_arenas_large)
...
@@ -199,36 +197,34 @@ TEST_BEGIN(test_stats_arenas_large)
int
expected
=
config_stats
?
0
:
ENOENT
;
int
expected
=
config_stats
?
0
:
ENOENT
;
arena
=
0
;
arena
=
0
;
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
(
void
*
)
&
arena
,
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
&
arena
,
sizeof
(
arena
))
,
sizeof
(
arena
)),
0
,
"Unexpected mallctl() failure"
);
0
,
"Unexpected mallctl() failure"
);
p
=
mallocx
(
large_maxclass
,
0
);
p
=
mallocx
(
large_maxclass
,
0
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
(
void
*
)
&
epoch
,
sizeof
(
epoch
)),
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
&
epoch
,
sizeof
(
epoch
)),
0
,
0
,
"Unexpected mallctl() failure"
);
"Unexpected mallctl() failure"
);
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.large.allocated"
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.large.allocated"
,
&
allocated
,
&
sz
,
(
void
*
)
&
allocated
,
&
sz
,
NULL
,
0
),
expected
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
sz
=
sizeof
(
uint64_t
);
sz
=
sizeof
(
uint64_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.large.nmalloc"
,
(
void
*
)
&
nmalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.large.nmalloc"
,
&
nmalloc
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.large.ndalloc"
,
(
void
*
)
&
ndalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.large.ndalloc"
,
&
ndalloc
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.large.nrequests"
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.large.nrequests"
,
&
nrequests
,
&
sz
,
(
void
*
)
&
nrequests
,
&
sz
,
NULL
,
0
),
expected
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
if
(
config_stats
)
{
if
(
config_stats
)
{
assert_zu_gt
(
allocated
,
0
,
assert_zu_gt
(
allocated
,
0
,
"allocated should be greater than zero"
);
"allocated should be greater than zero"
);
assert_u
64
_gt
(
nmalloc
,
0
,
assert_
z
u_gt
(
nmalloc
,
0
,
"nmalloc should be greater than zero"
);
"nmalloc should be greater than zero"
);
assert_u
64
_ge
(
nmalloc
,
ndalloc
,
assert_
z
u_ge
(
nmalloc
,
ndalloc
,
"nmalloc should be at least as large as ndalloc"
);
"nmalloc should be at least as large as ndalloc"
);
assert_u
64
_gt
(
nrequests
,
0
,
assert_
z
u_gt
(
nrequests
,
0
,
"nrequests should be greater than zero"
);
"nrequests should be greater than zero"
);
}
}
...
@@ -245,30 +241,30 @@ TEST_BEGIN(test_stats_arenas_huge)
...
@@ -245,30 +241,30 @@ TEST_BEGIN(test_stats_arenas_huge)
int
expected
=
config_stats
?
0
:
ENOENT
;
int
expected
=
config_stats
?
0
:
ENOENT
;
arena
=
0
;
arena
=
0
;
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
(
void
*
)
&
arena
,
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
&
arena
,
sizeof
(
arena
))
,
sizeof
(
arena
)),
0
,
"Unexpected mallctl() failure"
);
0
,
"Unexpected mallctl() failure"
);
p
=
mallocx
(
chunksize
,
0
);
p
=
mallocx
(
chunksize
,
0
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
(
void
*
)
&
epoch
,
sizeof
(
epoch
)),
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
&
epoch
,
sizeof
(
epoch
)),
0
,
0
,
"Unexpected mallctl() failure"
);
"Unexpected mallctl() failure"
);
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.allocated"
,
(
void
*
)
&
allocated
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.allocated"
,
&
allocated
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
sz
=
sizeof
(
uint64_t
);
sz
=
sizeof
(
uint64_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.nmalloc"
,
(
void
*
)
&
nmalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.nmalloc"
,
&
nmalloc
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.ndalloc"
,
(
void
*
)
&
ndalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.huge.ndalloc"
,
&
ndalloc
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
if
(
config_stats
)
{
if
(
config_stats
)
{
assert_zu_gt
(
allocated
,
0
,
assert_zu_gt
(
allocated
,
0
,
"allocated should be greater than zero"
);
"allocated should be greater than zero"
);
assert_u
64
_gt
(
nmalloc
,
0
,
assert_
z
u_gt
(
nmalloc
,
0
,
"nmalloc should be greater than zero"
);
"nmalloc should be greater than zero"
);
assert_u
64
_ge
(
nmalloc
,
ndalloc
,
assert_
z
u_ge
(
nmalloc
,
ndalloc
,
"nmalloc should be at least as large as ndalloc"
);
"nmalloc should be at least as large as ndalloc"
);
}
}
...
@@ -286,8 +282,8 @@ TEST_BEGIN(test_stats_arenas_bins)
...
@@ -286,8 +282,8 @@ TEST_BEGIN(test_stats_arenas_bins)
int
expected
=
config_stats
?
0
:
ENOENT
;
int
expected
=
config_stats
?
0
:
ENOENT
;
arena
=
0
;
arena
=
0
;
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
(
void
*
)
&
arena
,
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
&
arena
,
sizeof
(
arena
))
,
sizeof
(
arena
)),
0
,
"Unexpected mallctl() failure"
);
0
,
"Unexpected mallctl() failure"
);
p
=
mallocx
(
arena_bin_info
[
0
].
reg_size
,
0
);
p
=
mallocx
(
arena_bin_info
[
0
].
reg_size
,
0
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
...
@@ -295,36 +291,35 @@ TEST_BEGIN(test_stats_arenas_bins)
...
@@ -295,36 +291,35 @@ TEST_BEGIN(test_stats_arenas_bins)
assert_d_eq
(
mallctl
(
"thread.tcache.flush"
,
NULL
,
NULL
,
NULL
,
0
),
assert_d_eq
(
mallctl
(
"thread.tcache.flush"
,
NULL
,
NULL
,
NULL
,
0
),
config_tcache
?
0
:
ENOENT
,
"Unexpected mallctl() result"
);
config_tcache
?
0
:
ENOENT
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
(
void
*
)
&
epoch
,
sizeof
(
epoch
)),
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
&
epoch
,
sizeof
(
epoch
)),
0
,
0
,
"Unexpected mallctl() failure"
);
"Unexpected mallctl() failure"
);
sz
=
sizeof
(
uint64_t
);
sz
=
sizeof
(
uint64_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nmalloc"
,
(
void
*
)
&
nmalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nmalloc"
,
&
nmalloc
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.ndalloc"
,
(
void
*
)
&
ndalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.ndalloc"
,
&
ndalloc
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nrequests"
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nrequests"
,
&
nrequests
,
&
sz
,
(
void
*
)
&
nrequests
,
&
sz
,
NULL
,
0
),
expected
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.curregs"
,
(
void
*
)
&
curregs
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.curregs"
,
&
curregs
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
sz
=
sizeof
(
uint64_t
);
sz
=
sizeof
(
uint64_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nfills"
,
(
void
*
)
&
nfills
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nfills"
,
&
nfills
,
&
sz
,
&
sz
,
NULL
,
0
),
config_tcache
?
expected
:
ENOENT
,
NULL
,
0
),
config_tcache
?
expected
:
ENOENT
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nflushes"
,
(
void
*
)
&
nflushes
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nflushes"
,
&
nflushes
,
&
sz
,
&
sz
,
NULL
,
0
),
config_tcache
?
expected
:
ENOENT
,
NULL
,
0
),
config_tcache
?
expected
:
ENOENT
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nruns"
,
(
void
*
)
&
nruns
,
&
sz
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nruns"
,
&
nruns
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nreruns"
,
&
nreruns
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.nreruns"
,
(
void
*
)
&
nreruns
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.curruns"
,
(
void
*
)
&
curruns
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.bins.0.curruns"
,
&
curruns
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
if
(
config_stats
)
{
if
(
config_stats
)
{
assert_u64_gt
(
nmalloc
,
0
,
assert_u64_gt
(
nmalloc
,
0
,
...
@@ -360,26 +355,25 @@ TEST_BEGIN(test_stats_arenas_lruns)
...
@@ -360,26 +355,25 @@ TEST_BEGIN(test_stats_arenas_lruns)
int
expected
=
config_stats
?
0
:
ENOENT
;
int
expected
=
config_stats
?
0
:
ENOENT
;
arena
=
0
;
arena
=
0
;
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
(
void
*
)
&
arena
,
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
&
arena
,
sizeof
(
arena
))
,
sizeof
(
arena
)),
0
,
"Unexpected mallctl() failure"
);
0
,
"Unexpected mallctl() failure"
);
p
=
mallocx
(
LARGE_MINCLASS
,
0
);
p
=
mallocx
(
LARGE_MINCLASS
,
0
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
(
void
*
)
&
epoch
,
sizeof
(
epoch
)),
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
&
epoch
,
sizeof
(
epoch
)),
0
,
0
,
"Unexpected mallctl() failure"
);
"Unexpected mallctl() failure"
);
sz
=
sizeof
(
uint64_t
);
sz
=
sizeof
(
uint64_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.lruns.0.nmalloc"
,
(
void
*
)
&
nmalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.lruns.0.nmalloc"
,
&
nmalloc
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.lruns.0.ndalloc"
,
(
void
*
)
&
ndalloc
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.lruns.0.ndalloc"
,
&
ndalloc
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.lruns.0.nrequests"
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.lruns.0.nrequests"
,
&
nrequests
,
&
sz
,
(
void
*
)
&
nrequests
,
&
sz
,
NULL
,
0
),
expected
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.lruns.0.curruns"
,
(
void
*
)
&
curruns
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.lruns.0.curruns"
,
&
curruns
,
&
sz
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
if
(
config_stats
)
{
if
(
config_stats
)
{
assert_u64_gt
(
nmalloc
,
0
,
assert_u64_gt
(
nmalloc
,
0
,
...
@@ -405,26 +399,23 @@ TEST_BEGIN(test_stats_arenas_hchunks)
...
@@ -405,26 +399,23 @@ TEST_BEGIN(test_stats_arenas_hchunks)
int
expected
=
config_stats
?
0
:
ENOENT
;
int
expected
=
config_stats
?
0
:
ENOENT
;
arena
=
0
;
arena
=
0
;
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
(
void
*
)
&
arena
,
assert_d_eq
(
mallctl
(
"thread.arena"
,
NULL
,
NULL
,
&
arena
,
sizeof
(
arena
))
,
sizeof
(
arena
)),
0
,
"Unexpected mallctl() failure"
);
0
,
"Unexpected mallctl() failure"
);
p
=
mallocx
(
chunksize
,
0
);
p
=
mallocx
(
chunksize
,
0
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_ptr_not_null
(
p
,
"Unexpected mallocx() failure"
);
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
(
void
*
)
&
epoch
,
sizeof
(
epoch
)),
assert_d_eq
(
mallctl
(
"epoch"
,
NULL
,
NULL
,
&
epoch
,
sizeof
(
epoch
)),
0
,
0
,
"Unexpected mallctl() failure"
);
"Unexpected mallctl() failure"
);
sz
=
sizeof
(
uint64_t
);
sz
=
sizeof
(
uint64_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.hchunks.0.nmalloc"
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.hchunks.0.nmalloc"
,
&
nmalloc
,
&
sz
,
(
void
*
)
&
nmalloc
,
&
sz
,
NULL
,
0
),
expected
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.hchunks.0.ndalloc"
,
&
ndalloc
,
&
sz
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.hchunks.0.ndalloc"
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
(
void
*
)
&
ndalloc
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
sz
=
sizeof
(
size_t
);
sz
=
sizeof
(
size_t
);
assert_d_eq
(
mallctl
(
"stats.arenas.0.hchunks.0.curhchunks"
,
assert_d_eq
(
mallctl
(
"stats.arenas.0.hchunks.0.curhchunks"
,
&
curhchunks
,
(
void
*
)
&
curhchunks
,
&
sz
,
NULL
,
0
),
expected
,
&
sz
,
NULL
,
0
),
expected
,
"Unexpected mallctl() result"
);
"Unexpected mallctl() result"
);
if
(
config_stats
)
{
if
(
config_stats
)
{
assert_u64_gt
(
nmalloc
,
0
,
assert_u64_gt
(
nmalloc
,
0
,
...
...
deps/jemalloc/test/unit/ticker.c
deleted
100644 → 0
View file @
71a8df6a
#include "test/jemalloc_test.h"
TEST_BEGIN
(
test_ticker_tick
)
{
#define NREPS 2
#define NTICKS 3
ticker_t
ticker
;
int32_t
i
,
j
;
ticker_init
(
&
ticker
,
NTICKS
);
for
(
i
=
0
;
i
<
NREPS
;
i
++
)
{
for
(
j
=
0
;
j
<
NTICKS
;
j
++
)
{
assert_u_eq
(
ticker_read
(
&
ticker
),
NTICKS
-
j
,
"Unexpected ticker value (i=%d, j=%d)"
,
i
,
j
);
assert_false
(
ticker_tick
(
&
ticker
),
"Unexpected ticker fire (i=%d, j=%d)"
,
i
,
j
);
}
assert_u32_eq
(
ticker_read
(
&
ticker
),
0
,
"Expected ticker depletion"
);
assert_true
(
ticker_tick
(
&
ticker
),
"Expected ticker fire (i=%d)"
,
i
);
assert_u32_eq
(
ticker_read
(
&
ticker
),
NTICKS
,
"Expected ticker reset"
);
}
#undef NTICKS
}
TEST_END
TEST_BEGIN
(
test_ticker_ticks
)
{
#define NTICKS 3
ticker_t
ticker
;
ticker_init
(
&
ticker
,
NTICKS
);
assert_u_eq
(
ticker_read
(
&
ticker
),
NTICKS
,
"Unexpected ticker value"
);
assert_false
(
ticker_ticks
(
&
ticker
,
NTICKS
),
"Unexpected ticker fire"
);
assert_u_eq
(
ticker_read
(
&
ticker
),
0
,
"Unexpected ticker value"
);
assert_true
(
ticker_ticks
(
&
ticker
,
NTICKS
),
"Expected ticker fire"
);
assert_u_eq
(
ticker_read
(
&
ticker
),
NTICKS
,
"Unexpected ticker value"
);
assert_true
(
ticker_ticks
(
&
ticker
,
NTICKS
+
1
),
"Expected ticker fire"
);
assert_u_eq
(
ticker_read
(
&
ticker
),
NTICKS
,
"Unexpected ticker value"
);
#undef NTICKS
}
TEST_END
TEST_BEGIN
(
test_ticker_copy
)
{
#define NTICKS 3
ticker_t
ta
,
tb
;
ticker_init
(
&
ta
,
NTICKS
);
ticker_copy
(
&
tb
,
&
ta
);
assert_u_eq
(
ticker_read
(
&
tb
),
NTICKS
,
"Unexpected ticker value"
);
assert_true
(
ticker_ticks
(
&
tb
,
NTICKS
+
1
),
"Expected ticker fire"
);
assert_u_eq
(
ticker_read
(
&
tb
),
NTICKS
,
"Unexpected ticker value"
);
ticker_tick
(
&
ta
);
ticker_copy
(
&
tb
,
&
ta
);
assert_u_eq
(
ticker_read
(
&
tb
),
NTICKS
-
1
,
"Unexpected ticker value"
);
assert_true
(
ticker_ticks
(
&
tb
,
NTICKS
),
"Expected ticker fire"
);
assert_u_eq
(
ticker_read
(
&
tb
),
NTICKS
,
"Unexpected ticker value"
);
#undef NTICKS
}
TEST_END
int
main
(
void
)
{
return
(
test
(
test_ticker_tick
,
test_ticker_ticks
,
test_ticker_copy
));
}
deps/jemalloc/test/unit/tsd.c
View file @
89a9e5a9
...
@@ -58,18 +58,18 @@ thd_start(void *arg)
...
@@ -58,18 +58,18 @@ thd_start(void *arg)
data_t
d
=
(
data_t
)(
uintptr_t
)
arg
;
data_t
d
=
(
data_t
)(
uintptr_t
)
arg
;
void
*
p
;
void
*
p
;
assert_x_eq
(
*
data_tsd_get
(
true
),
DATA_INIT
,
assert_x_eq
(
*
data_tsd_get
(),
DATA_INIT
,
"Initial tsd get should return initialization value"
);
"Initial tsd get should return initialization value"
);
p
=
malloc
(
1
);
p
=
malloc
(
1
);
assert_ptr_not_null
(
p
,
"Unexpected malloc() failure"
);
assert_ptr_not_null
(
p
,
"Unexpected malloc() failure"
);
data_tsd_set
(
&
d
);
data_tsd_set
(
&
d
);
assert_x_eq
(
*
data_tsd_get
(
true
),
d
,
assert_x_eq
(
*
data_tsd_get
(),
d
,
"After tsd set, tsd get should return value that was set"
);
"After tsd set, tsd get should return value that was set"
);
d
=
0
;
d
=
0
;
assert_x_eq
(
*
data_tsd_get
(
true
),
(
data_t
)(
uintptr_t
)
arg
,
assert_x_eq
(
*
data_tsd_get
(),
(
data_t
)(
uintptr_t
)
arg
,
"Resetting local data should have no effect on tsd"
);
"Resetting local data should have no effect on tsd"
);
free
(
p
);
free
(
p
);
...
@@ -79,7 +79,7 @@ thd_start(void *arg)
...
@@ -79,7 +79,7 @@ thd_start(void *arg)
TEST_BEGIN
(
test_tsd_main_thread
)
TEST_BEGIN
(
test_tsd_main_thread
)
{
{
thd_start
((
void
*
)
(
uintptr_t
)
0xa5f3e329
);
thd_start
((
void
*
)
0xa5f3e329
);
}
}
TEST_END
TEST_END
...
@@ -99,11 +99,6 @@ int
...
@@ -99,11 +99,6 @@ int
main
(
void
)
main
(
void
)
{
{
/* Core tsd bootstrapping must happen prior to data_tsd_boot(). */
if
(
nallocx
(
1
,
0
)
==
0
)
{
malloc_printf
(
"Initialization error"
);
return
(
test_status_fail
);
}
data_tsd_boot
();
data_tsd_boot
();
return
(
test
(
return
(
test
(
...
...
deps/jemalloc/test/unit/util.c
View file @
89a9e5a9
#include "test/jemalloc_test.h"
#include "test/jemalloc_test.h"
#define TEST_POW2_CEIL(t, suf, pri) do { \
TEST_BEGIN
(
test_pow2_ceil
)
unsigned i, pow2; \
t x; \
\
assert_##suf##_eq(pow2_ceil_##suf(0), 0, "Unexpected result"); \
\
for (i = 0; i < sizeof(t) * 8; i++) { \
assert_##suf##_eq(pow2_ceil_##suf(((t)1) << i), ((t)1) \
<< i, "Unexpected result"); \
} \
\
for (i = 2; i < sizeof(t) * 8; i++) { \
assert_##suf##_eq(pow2_ceil_##suf((((t)1) << i) - 1), \
((t)1) << i, "Unexpected result"); \
} \
\
for (i = 0; i < sizeof(t) * 8 - 1; i++) { \
assert_##suf##_eq(pow2_ceil_##suf((((t)1) << i) + 1), \
((t)1) << (i+1), "Unexpected result"); \
} \
\
for (pow2 = 1; pow2 < 25; pow2++) { \
for (x = (((t)1) << (pow2-1)) + 1; x <= ((t)1) << pow2; \
x++) { \
assert_##suf##_eq(pow2_ceil_##suf(x), \
((t)1) << pow2, \
"Unexpected result, x=%"pri, x); \
} \
} \
} while (0)
TEST_BEGIN
(
test_pow2_ceil_u64
)
{
{
unsigned
i
,
pow2
;
size_t
x
;
TEST_POW2_CEIL
(
uint64_t
,
u64
,
FMTu64
);
assert_zu_eq
(
pow2_ceil
(
0
),
0
,
"Unexpected result"
);
}
TEST_END
TEST_BEGIN
(
test_pow2_ceil_u32
)
for
(
i
=
0
;
i
<
sizeof
(
size_t
)
*
8
;
i
++
)
{
{
assert_zu_eq
(
pow2_ceil
(
ZU
(
1
)
<<
i
),
ZU
(
1
)
<<
i
,
"Unexpected result"
);
}
TEST_POW2_CEIL
(
uint32_t
,
u32
,
FMTu32
);
for
(
i
=
2
;
i
<
sizeof
(
size_t
)
*
8
;
i
++
)
{
}
assert_zu_eq
(
pow2_ceil
((
ZU
(
1
)
<<
i
)
-
1
),
ZU
(
1
)
<<
i
,
TEST_END
"Unexpected result"
);
}
TEST_BEGIN
(
test_pow2_ceil_zu
)
for
(
i
=
0
;
i
<
sizeof
(
size_t
)
*
8
-
1
;
i
++
)
{
{
assert_zu_eq
(
pow2_ceil
((
ZU
(
1
)
<<
i
)
+
1
),
ZU
(
1
)
<<
(
i
+
1
),
"Unexpected result"
);
}
TEST_POW2_CEIL
(
size_t
,
zu
,
"zu"
);
for
(
pow2
=
1
;
pow2
<
25
;
pow2
++
)
{
for
(
x
=
(
ZU
(
1
)
<<
(
pow2
-
1
))
+
1
;
x
<=
ZU
(
1
)
<<
pow2
;
x
++
)
{
assert_zu_eq
(
pow2_ceil
(
x
),
ZU
(
1
)
<<
pow2
,
"Unexpected result, x=%zu"
,
x
);
}
}
}
}
TEST_END
TEST_END
...
@@ -75,7 +54,6 @@ TEST_BEGIN(test_malloc_strtoumax)
...
@@ -75,7 +54,6 @@ TEST_BEGIN(test_malloc_strtoumax)
};
};
#define ERR(e) e, #e
#define ERR(e) e, #e
#define KUMAX(x) ((uintmax_t)x##ULL)
#define KUMAX(x) ((uintmax_t)x##ULL)
#define KSMAX(x) ((uintmax_t)(intmax_t)x##LL)
struct
test_s
tests
[]
=
{
struct
test_s
tests
[]
=
{
{
"0"
,
"0"
,
-
1
,
ERR
(
EINVAL
),
UINTMAX_MAX
},
{
"0"
,
"0"
,
-
1
,
ERR
(
EINVAL
),
UINTMAX_MAX
},
{
"0"
,
"0"
,
1
,
ERR
(
EINVAL
),
UINTMAX_MAX
},
{
"0"
,
"0"
,
1
,
ERR
(
EINVAL
),
UINTMAX_MAX
},
...
@@ -88,13 +66,13 @@ TEST_BEGIN(test_malloc_strtoumax)
...
@@ -88,13 +66,13 @@ TEST_BEGIN(test_malloc_strtoumax)
{
"42"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
42
)},
{
"42"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
42
)},
{
"+42"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
42
)},
{
"+42"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
42
)},
{
"-42"
,
""
,
0
,
ERR
(
0
),
K
S
MAX
(
-
42
)},
{
"-42"
,
""
,
0
,
ERR
(
0
),
K
U
MAX
(
-
42
)},
{
"042"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
042
)},
{
"042"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
042
)},
{
"+042"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
042
)},
{
"+042"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
042
)},
{
"-042"
,
""
,
0
,
ERR
(
0
),
K
S
MAX
(
-
042
)},
{
"-042"
,
""
,
0
,
ERR
(
0
),
K
U
MAX
(
-
042
)},
{
"0x42"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
0x42
)},
{
"0x42"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
0x42
)},
{
"+0x42"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
0x42
)},
{
"+0x42"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
0x42
)},
{
"-0x42"
,
""
,
0
,
ERR
(
0
),
K
S
MAX
(
-
0x42
)},
{
"-0x42"
,
""
,
0
,
ERR
(
0
),
K
U
MAX
(
-
0x42
)},
{
"0"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
0
)},
{
"0"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
0
)},
{
"1"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
1
)},
{
"1"
,
""
,
0
,
ERR
(
0
),
KUMAX
(
1
)},
...
@@ -131,7 +109,6 @@ TEST_BEGIN(test_malloc_strtoumax)
...
@@ -131,7 +109,6 @@ TEST_BEGIN(test_malloc_strtoumax)
};
};
#undef ERR
#undef ERR
#undef KUMAX
#undef KUMAX
#undef KSMAX
unsigned
i
;
unsigned
i
;
for
(
i
=
0
;
i
<
sizeof
(
tests
)
/
sizeof
(
struct
test_s
);
i
++
)
{
for
(
i
=
0
;
i
<
sizeof
(
tests
)
/
sizeof
(
struct
test_s
);
i
++
)
{
...
@@ -162,14 +139,14 @@ TEST_BEGIN(test_malloc_snprintf_truncated)
...
@@ -162,14 +139,14 @@ TEST_BEGIN(test_malloc_snprintf_truncated)
{
{
#define BUFLEN 15
#define BUFLEN 15
char
buf
[
BUFLEN
];
char
buf
[
BUFLEN
];
size_
t
result
;
in
t
result
;
size_t
len
;
size_t
len
;
#define
TEST(expected_str_untruncated, ...) do { \
#define
TEST(expected_str_untruncated, ...) do { \
result = malloc_snprintf(buf, len, __VA_ARGS__); \
result = malloc_snprintf(buf, len, __VA_ARGS__); \
assert_d_eq(strncmp(buf, expected_str_untruncated, len-1), 0, \
assert_d_eq(strncmp(buf, expected_str_untruncated, len-1), 0, \
"Unexpected string inequality (\"%s\" vs \"%s\")", \
"Unexpected string inequality (\"%s\" vs \"%s\")", \
buf, expected_str_untruncated);
\
buf, expected_str_untruncated); \
assert_
zu
_eq(result, strlen(expected_str_untruncated), \
assert_
d
_eq(result, strlen(expected_str_untruncated), \
"Unexpected result"); \
"Unexpected result"); \
} while (0)
} while (0)
...
@@ -195,11 +172,11 @@ TEST_BEGIN(test_malloc_snprintf)
...
@@ -195,11 +172,11 @@ TEST_BEGIN(test_malloc_snprintf)
{
{
#define BUFLEN 128
#define BUFLEN 128
char
buf
[
BUFLEN
];
char
buf
[
BUFLEN
];
size_
t
result
;
in
t
result
;
#define TEST(expected_str, ...) do { \
#define TEST(expected_str, ...) do { \
result = malloc_snprintf(buf, sizeof(buf), __VA_ARGS__); \
result = malloc_snprintf(buf, sizeof(buf), __VA_ARGS__); \
assert_str_eq(buf, expected_str, "Unexpected output"); \
assert_str_eq(buf, expected_str, "Unexpected output"); \
assert_
zu
_eq(result, strlen(expected_str), "Unexpected result");\
assert_
d
_eq(result, strlen(expected_str), "Unexpected result");
\
} while (0)
} while (0)
TEST
(
"hello"
,
"hello"
);
TEST
(
"hello"
,
"hello"
);
...
@@ -309,9 +286,7 @@ main(void)
...
@@ -309,9 +286,7 @@ main(void)
{
{
return
(
test
(
return
(
test
(
test_pow2_ceil_u64
,
test_pow2_ceil
,
test_pow2_ceil_u32
,
test_pow2_ceil_zu
,
test_malloc_strtoumax_no_endptr
,
test_malloc_strtoumax_no_endptr
,
test_malloc_strtoumax
,
test_malloc_strtoumax
,
test_malloc_snprintf_truncated
,
test_malloc_snprintf_truncated
,
...
...
deps/jemalloc/test/unit/witness.c
deleted
100644 → 0
View file @
71a8df6a
#include "test/jemalloc_test.h"
static
witness_lock_error_t
*
witness_lock_error_orig
;
static
witness_owner_error_t
*
witness_owner_error_orig
;
static
witness_not_owner_error_t
*
witness_not_owner_error_orig
;
static
witness_lockless_error_t
*
witness_lockless_error_orig
;
static
bool
saw_lock_error
;
static
bool
saw_owner_error
;
static
bool
saw_not_owner_error
;
static
bool
saw_lockless_error
;
static
void
witness_lock_error_intercept
(
const
witness_list_t
*
witnesses
,
const
witness_t
*
witness
)
{
saw_lock_error
=
true
;
}
static
void
witness_owner_error_intercept
(
const
witness_t
*
witness
)
{
saw_owner_error
=
true
;
}
static
void
witness_not_owner_error_intercept
(
const
witness_t
*
witness
)
{
saw_not_owner_error
=
true
;
}
static
void
witness_lockless_error_intercept
(
const
witness_list_t
*
witnesses
)
{
saw_lockless_error
=
true
;
}
static
int
witness_comp
(
const
witness_t
*
a
,
const
witness_t
*
b
)
{
assert_u_eq
(
a
->
rank
,
b
->
rank
,
"Witnesses should have equal rank"
);
return
(
strcmp
(
a
->
name
,
b
->
name
));
}
static
int
witness_comp_reverse
(
const
witness_t
*
a
,
const
witness_t
*
b
)
{
assert_u_eq
(
a
->
rank
,
b
->
rank
,
"Witnesses should have equal rank"
);
return
(
-
strcmp
(
a
->
name
,
b
->
name
));
}
TEST_BEGIN
(
test_witness
)
{
witness_t
a
,
b
;
tsdn_t
*
tsdn
;
test_skip_if
(
!
config_debug
);
tsdn
=
tsdn_fetch
();
witness_assert_lockless
(
tsdn
);
witness_init
(
&
a
,
"a"
,
1
,
NULL
);
witness_assert_not_owner
(
tsdn
,
&
a
);
witness_lock
(
tsdn
,
&
a
);
witness_assert_owner
(
tsdn
,
&
a
);
witness_init
(
&
b
,
"b"
,
2
,
NULL
);
witness_assert_not_owner
(
tsdn
,
&
b
);
witness_lock
(
tsdn
,
&
b
);
witness_assert_owner
(
tsdn
,
&
b
);
witness_unlock
(
tsdn
,
&
a
);
witness_unlock
(
tsdn
,
&
b
);
witness_assert_lockless
(
tsdn
);
}
TEST_END
TEST_BEGIN
(
test_witness_comp
)
{
witness_t
a
,
b
,
c
,
d
;
tsdn_t
*
tsdn
;
test_skip_if
(
!
config_debug
);
tsdn
=
tsdn_fetch
();
witness_assert_lockless
(
tsdn
);
witness_init
(
&
a
,
"a"
,
1
,
witness_comp
);
witness_assert_not_owner
(
tsdn
,
&
a
);
witness_lock
(
tsdn
,
&
a
);
witness_assert_owner
(
tsdn
,
&
a
);
witness_init
(
&
b
,
"b"
,
1
,
witness_comp
);
witness_assert_not_owner
(
tsdn
,
&
b
);
witness_lock
(
tsdn
,
&
b
);
witness_assert_owner
(
tsdn
,
&
b
);
witness_unlock
(
tsdn
,
&
b
);
witness_lock_error_orig
=
witness_lock_error
;
witness_lock_error
=
witness_lock_error_intercept
;
saw_lock_error
=
false
;
witness_init
(
&
c
,
"c"
,
1
,
witness_comp_reverse
);
witness_assert_not_owner
(
tsdn
,
&
c
);
assert_false
(
saw_lock_error
,
"Unexpected witness lock error"
);
witness_lock
(
tsdn
,
&
c
);
assert_true
(
saw_lock_error
,
"Expected witness lock error"
);
witness_unlock
(
tsdn
,
&
c
);
saw_lock_error
=
false
;
witness_init
(
&
d
,
"d"
,
1
,
NULL
);
witness_assert_not_owner
(
tsdn
,
&
d
);
assert_false
(
saw_lock_error
,
"Unexpected witness lock error"
);
witness_lock
(
tsdn
,
&
d
);
assert_true
(
saw_lock_error
,
"Expected witness lock error"
);
witness_unlock
(
tsdn
,
&
d
);
witness_unlock
(
tsdn
,
&
a
);
witness_assert_lockless
(
tsdn
);
witness_lock_error
=
witness_lock_error_orig
;
}
TEST_END
TEST_BEGIN
(
test_witness_reversal
)
{
witness_t
a
,
b
;
tsdn_t
*
tsdn
;
test_skip_if
(
!
config_debug
);
witness_lock_error_orig
=
witness_lock_error
;
witness_lock_error
=
witness_lock_error_intercept
;
saw_lock_error
=
false
;
tsdn
=
tsdn_fetch
();
witness_assert_lockless
(
tsdn
);
witness_init
(
&
a
,
"a"
,
1
,
NULL
);
witness_init
(
&
b
,
"b"
,
2
,
NULL
);
witness_lock
(
tsdn
,
&
b
);
assert_false
(
saw_lock_error
,
"Unexpected witness lock error"
);
witness_lock
(
tsdn
,
&
a
);
assert_true
(
saw_lock_error
,
"Expected witness lock error"
);
witness_unlock
(
tsdn
,
&
a
);
witness_unlock
(
tsdn
,
&
b
);
witness_assert_lockless
(
tsdn
);
witness_lock_error
=
witness_lock_error_orig
;
}
TEST_END
TEST_BEGIN
(
test_witness_recursive
)
{
witness_t
a
;
tsdn_t
*
tsdn
;
test_skip_if
(
!
config_debug
);
witness_not_owner_error_orig
=
witness_not_owner_error
;
witness_not_owner_error
=
witness_not_owner_error_intercept
;
saw_not_owner_error
=
false
;
witness_lock_error_orig
=
witness_lock_error
;
witness_lock_error
=
witness_lock_error_intercept
;
saw_lock_error
=
false
;
tsdn
=
tsdn_fetch
();
witness_assert_lockless
(
tsdn
);
witness_init
(
&
a
,
"a"
,
1
,
NULL
);
witness_lock
(
tsdn
,
&
a
);
assert_false
(
saw_lock_error
,
"Unexpected witness lock error"
);
assert_false
(
saw_not_owner_error
,
"Unexpected witness not owner error"
);
witness_lock
(
tsdn
,
&
a
);
assert_true
(
saw_lock_error
,
"Expected witness lock error"
);
assert_true
(
saw_not_owner_error
,
"Expected witness not owner error"
);
witness_unlock
(
tsdn
,
&
a
);
witness_assert_lockless
(
tsdn
);
witness_owner_error
=
witness_owner_error_orig
;
witness_lock_error
=
witness_lock_error_orig
;
}
TEST_END
TEST_BEGIN
(
test_witness_unlock_not_owned
)
{
witness_t
a
;
tsdn_t
*
tsdn
;
test_skip_if
(
!
config_debug
);
witness_owner_error_orig
=
witness_owner_error
;
witness_owner_error
=
witness_owner_error_intercept
;
saw_owner_error
=
false
;
tsdn
=
tsdn_fetch
();
witness_assert_lockless
(
tsdn
);
witness_init
(
&
a
,
"a"
,
1
,
NULL
);
assert_false
(
saw_owner_error
,
"Unexpected owner error"
);
witness_unlock
(
tsdn
,
&
a
);
assert_true
(
saw_owner_error
,
"Expected owner error"
);
witness_assert_lockless
(
tsdn
);
witness_owner_error
=
witness_owner_error_orig
;
}
TEST_END
TEST_BEGIN
(
test_witness_lockful
)
{
witness_t
a
;
tsdn_t
*
tsdn
;
test_skip_if
(
!
config_debug
);
witness_lockless_error_orig
=
witness_lockless_error
;
witness_lockless_error
=
witness_lockless_error_intercept
;
saw_lockless_error
=
false
;
tsdn
=
tsdn_fetch
();
witness_assert_lockless
(
tsdn
);
witness_init
(
&
a
,
"a"
,
1
,
NULL
);
assert_false
(
saw_lockless_error
,
"Unexpected lockless error"
);
witness_assert_lockless
(
tsdn
);
witness_lock
(
tsdn
,
&
a
);
witness_assert_lockless
(
tsdn
);
assert_true
(
saw_lockless_error
,
"Expected lockless error"
);
witness_unlock
(
tsdn
,
&
a
);
witness_assert_lockless
(
tsdn
);
witness_lockless_error
=
witness_lockless_error_orig
;
}
TEST_END
int
main
(
void
)
{
return
(
test
(
test_witness
,
test_witness_comp
,
test_witness_reversal
,
test_witness_recursive
,
test_witness_unlock_not_owned
,
test_witness_lockful
));
}
deps/jemalloc/test/unit/zero.c
View file @
89a9e5a9
...
@@ -8,41 +8,39 @@ const char *malloc_conf =
...
@@ -8,41 +8,39 @@ const char *malloc_conf =
static
void
static
void
test_zero
(
size_t
sz_min
,
size_t
sz_max
)
test_zero
(
size_t
sz_min
,
size_t
sz_max
)
{
{
uint8_t
*
s
;
char
*
s
;
size_t
sz_prev
,
sz
,
i
;
size_t
sz_prev
,
sz
,
i
;
#define MAGIC ((uint8_t)0x61)
sz_prev
=
0
;
sz_prev
=
0
;
s
=
(
uint8_t
*
)
mallocx
(
sz_min
,
0
);
s
=
(
char
*
)
mallocx
(
sz_min
,
0
);
assert_ptr_not_null
((
void
*
)
s
,
"Unexpected mallocx() failure"
);
assert_ptr_not_null
((
void
*
)
s
,
"Unexpected mallocx() failure"
);
for
(
sz
=
sallocx
(
s
,
0
);
sz
<=
sz_max
;
for
(
sz
=
sallocx
(
s
,
0
);
sz
<=
sz_max
;
sz_prev
=
sz
,
sz
=
sallocx
(
s
,
0
))
{
sz_prev
=
sz
,
sz
=
sallocx
(
s
,
0
))
{
if
(
sz_prev
>
0
)
{
if
(
sz_prev
>
0
)
{
assert_
u
_eq
(
s
[
0
],
MAGIC
,
assert_
c
_eq
(
s
[
0
],
'a'
,
"Previously allocated byte %zu/%zu is corrupted"
,
"Previously allocated byte %zu/%zu is corrupted"
,
ZU
(
0
),
sz_prev
);
ZU
(
0
),
sz_prev
);
assert_
u
_eq
(
s
[
sz_prev
-
1
],
MAGIC
,
assert_
c
_eq
(
s
[
sz_prev
-
1
],
'a'
,
"Previously allocated byte %zu/%zu is corrupted"
,
"Previously allocated byte %zu/%zu is corrupted"
,
sz_prev
-
1
,
sz_prev
);
sz_prev
-
1
,
sz_prev
);
}
}
for
(
i
=
sz_prev
;
i
<
sz
;
i
++
)
{
for
(
i
=
sz_prev
;
i
<
sz
;
i
++
)
{
assert_
u
_eq
(
s
[
i
],
0x0
,
assert_
c
_eq
(
s
[
i
],
0x0
,
"Newly allocated byte %zu/%zu isn't zero-filled"
,
"Newly allocated byte %zu/%zu isn't zero-filled"
,
i
,
sz
);
i
,
sz
);
s
[
i
]
=
MAGIC
;
s
[
i
]
=
'a'
;
}
}
if
(
xallocx
(
s
,
sz
+
1
,
0
,
0
)
==
sz
)
{
if
(
xallocx
(
s
,
sz
+
1
,
0
,
0
)
==
sz
)
{
s
=
(
uint8_t
*
)
rallocx
(
s
,
sz
+
1
,
0
);
s
=
(
char
*
)
rallocx
(
s
,
sz
+
1
,
0
);
assert_ptr_not_null
((
void
*
)
s
,
assert_ptr_not_null
((
void
*
)
s
,
"Unexpected rallocx() failure"
);
"Unexpected rallocx() failure"
);
}
}
}
}
dallocx
(
s
,
0
);
dallocx
(
s
,
0
);
#undef MAGIC
}
}
TEST_BEGIN
(
test_zero_small
)
TEST_BEGIN
(
test_zero_small
)
...
...
src/Makefile
View file @
89a9e5a9
...
@@ -139,7 +139,7 @@ endif
...
@@ -139,7 +139,7 @@ endif
REDIS_SERVER_NAME
=
redis-server
REDIS_SERVER_NAME
=
redis-server
REDIS_SENTINEL_NAME
=
redis-sentinel
REDIS_SENTINEL_NAME
=
redis-sentinel
REDIS_SERVER_OBJ
=
adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o
REDIS_SERVER_OBJ
=
adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o
rax.o
REDIS_CLI_NAME
=
redis-cli
REDIS_CLI_NAME
=
redis-cli
REDIS_CLI_OBJ
=
anet.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o
REDIS_CLI_OBJ
=
anet.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o
REDIS_BENCHMARK_NAME
=
redis-benchmark
REDIS_BENCHMARK_NAME
=
redis-benchmark
...
@@ -214,8 +214,8 @@ $(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ)
...
@@ -214,8 +214,8 @@ $(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ)
$(REDIS_CHECK_AOF_NAME)
:
$(REDIS_CHECK_AOF_OBJ)
$(REDIS_CHECK_AOF_NAME)
:
$(REDIS_CHECK_AOF_OBJ)
$(REDIS_LD)
-o
$@
$^
$(FINAL_LIBS)
$(REDIS_LD)
-o
$@
$^
$(FINAL_LIBS)
dict-benchmark
:
dict.c zmalloc.c sds.c
dict-benchmark
:
dict.c zmalloc.c sds.c
siphash.c
$(REDIS_CC)
$(FINAL_CFLAGS)
dict.c zmalloc.c sds.c siphash.c
-D
DICT_BENCHMARK_MAIN
-o
dict-benchmark
$(REDIS_CC)
$(FINAL_CFLAGS)
$^
-D
DICT_BENCHMARK_MAIN
-o
$@
$(FINAL_LIBS)
# Because the jemalloc.h header is generated as a part of the jemalloc build,
# Because the jemalloc.h header is generated as a part of the jemalloc build,
# building it should complete before building any other object. Instead of
# building it should complete before building any other object. Instead of
...
...
src/adlist.c
View file @
89a9e5a9
...
@@ -52,10 +52,8 @@ list *listCreate(void)
...
@@ -52,10 +52,8 @@ list *listCreate(void)
return
list
;
return
list
;
}
}
/* Free the whole list.
/* Remove all the elements from the list without destroying the list itself. */
*
void
listEmpty
(
list
*
list
)
* This function can't fail. */
void
listRelease
(
list
*
list
)
{
{
unsigned
long
len
;
unsigned
long
len
;
listNode
*
current
,
*
next
;
listNode
*
current
,
*
next
;
...
@@ -68,6 +66,16 @@ void listRelease(list *list)
...
@@ -68,6 +66,16 @@ void listRelease(list *list)
zfree
(
current
);
zfree
(
current
);
current
=
next
;
current
=
next
;
}
}
list
->
head
=
list
->
tail
=
NULL
;
list
->
len
=
0
;
}
/* Free the whole list.
*
* This function can't fail. */
void
listRelease
(
list
*
list
)
{
listEmpty
(
list
);
zfree
(
list
);
zfree
(
list
);
}
}
...
...
src/adlist.h
View file @
89a9e5a9
...
@@ -72,6 +72,7 @@ typedef struct list {
...
@@ -72,6 +72,7 @@ typedef struct list {
/* Prototypes */
/* Prototypes */
list
*
listCreate
(
void
);
list
*
listCreate
(
void
);
void
listRelease
(
list
*
list
);
void
listRelease
(
list
*
list
);
void
listEmpty
(
list
*
list
);
list
*
listAddNodeHead
(
list
*
list
,
void
*
value
);
list
*
listAddNodeHead
(
list
*
list
,
void
*
value
);
list
*
listAddNodeTail
(
list
*
list
,
void
*
value
);
list
*
listAddNodeTail
(
list
*
list
,
void
*
value
);
list
*
listInsertNode
(
list
*
list
,
listNode
*
old_node
,
void
*
value
,
int
after
);
list
*
listInsertNode
(
list
*
list
,
listNode
*
old_node
,
void
*
value
,
int
after
);
...
...
src/anet.c
View file @
89a9e5a9
...
@@ -380,8 +380,10 @@ int anetUnixGenericConnect(char *err, char *path, int flags)
...
@@ -380,8 +380,10 @@ int anetUnixGenericConnect(char *err, char *path, int flags)
sa
.
sun_family
=
AF_LOCAL
;
sa
.
sun_family
=
AF_LOCAL
;
strncpy
(
sa
.
sun_path
,
path
,
sizeof
(
sa
.
sun_path
)
-
1
);
strncpy
(
sa
.
sun_path
,
path
,
sizeof
(
sa
.
sun_path
)
-
1
);
if
(
flags
&
ANET_CONNECT_NONBLOCK
)
{
if
(
flags
&
ANET_CONNECT_NONBLOCK
)
{
if
(
anetNonBlock
(
err
,
s
)
!=
ANET_OK
)
if
(
anetNonBlock
(
err
,
s
)
!=
ANET_OK
)
{
close
(
s
);
return
ANET_ERR
;
return
ANET_ERR
;
}
}
}
if
(
connect
(
s
,(
struct
sockaddr
*
)
&
sa
,
sizeof
(
sa
))
==
-
1
)
{
if
(
connect
(
s
,(
struct
sockaddr
*
)
&
sa
,
sizeof
(
sa
))
==
-
1
)
{
if
(
errno
==
EINPROGRESS
&&
if
(
errno
==
EINPROGRESS
&&
...
@@ -462,7 +464,7 @@ static int anetV6Only(char *err, int s) {
...
@@ -462,7 +464,7 @@ static int anetV6Only(char *err, int s) {
static
int
_anetTcpServer
(
char
*
err
,
int
port
,
char
*
bindaddr
,
int
af
,
int
backlog
)
static
int
_anetTcpServer
(
char
*
err
,
int
port
,
char
*
bindaddr
,
int
af
,
int
backlog
)
{
{
int
s
,
rv
;
int
s
=
-
1
,
rv
;
char
_port
[
6
];
/* strlen("65535") */
char
_port
[
6
];
/* strlen("65535") */
struct
addrinfo
hints
,
*
servinfo
,
*
p
;
struct
addrinfo
hints
,
*
servinfo
,
*
p
;
...
@@ -491,6 +493,7 @@ static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backl
...
@@ -491,6 +493,7 @@ static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backl
}
}
error:
error:
if
(
s
!=
-
1
)
close
(
s
);
s
=
ANET_ERR
;
s
=
ANET_ERR
;
end:
end:
freeaddrinfo
(
servinfo
);
freeaddrinfo
(
servinfo
);
...
...
src/aof.c
View file @
89a9e5a9
...
@@ -115,6 +115,7 @@ void aofChildWriteDiffData(aeEventLoop *el, int fd, void *privdata, int mask) {
...
@@ -115,6 +115,7 @@ void aofChildWriteDiffData(aeEventLoop *el, int fd, void *privdata, int mask) {
if
(
nwritten
<=
0
)
return
;
if
(
nwritten
<=
0
)
return
;
memmove
(
block
->
buf
,
block
->
buf
+
nwritten
,
block
->
used
-
nwritten
);
memmove
(
block
->
buf
,
block
->
buf
+
nwritten
,
block
->
used
-
nwritten
);
block
->
used
-=
nwritten
;
block
->
used
-=
nwritten
;
block
->
free
+=
nwritten
;
}
}
if
(
block
->
used
==
0
)
listDelNode
(
server
.
aof_rewrite_buf_blocks
,
ln
);
if
(
block
->
used
==
0
)
listDelNode
(
server
.
aof_rewrite_buf_blocks
,
ln
);
}
}
...
...
src/cluster.c
View file @
89a9e5a9
...
@@ -423,8 +423,11 @@ void clusterInit(void) {
...
@@ -423,8 +423,11 @@ void clusterInit(void) {
server
.
cluster
->
failover_auth_epoch
=
0
;
server
.
cluster
->
failover_auth_epoch
=
0
;
server
.
cluster
->
cant_failover_reason
=
CLUSTER_CANT_FAILOVER_NONE
;
server
.
cluster
->
cant_failover_reason
=
CLUSTER_CANT_FAILOVER_NONE
;
server
.
cluster
->
lastVoteEpoch
=
0
;
server
.
cluster
->
lastVoteEpoch
=
0
;
server
.
cluster
->
stats_bus_messages_sent
=
0
;
for
(
int
i
=
0
;
i
<
CLUSTERMSG_TYPE_COUNT
;
i
++
)
{
server
.
cluster
->
stats_bus_messages_received
=
0
;
server
.
cluster
->
stats_bus_messages_sent
[
i
]
=
0
;
server
.
cluster
->
stats_bus_messages_received
[
i
]
=
0
;
}
server
.
cluster
->
stats_pfail_nodes
=
0
;
memset
(
server
.
cluster
->
slots
,
0
,
sizeof
(
server
.
cluster
->
slots
));
memset
(
server
.
cluster
->
slots
,
0
,
sizeof
(
server
.
cluster
->
slots
));
clusterCloseAllSlots
();
clusterCloseAllSlots
();
...
@@ -476,8 +479,10 @@ void clusterInit(void) {
...
@@ -476,8 +479,10 @@ void clusterInit(void) {
}
}
}
}
/* The slots -> keys map is a sorted set. Init it. */
/* The slots -> keys map is a radix tree. Initialize it here. */
server
.
cluster
->
slots_to_keys
=
zslCreate
();
server
.
cluster
->
slots_to_keys
=
raxNew
();
memset
(
server
.
cluster
->
slots_keys_count
,
0
,
sizeof
(
server
.
cluster
->
slots_keys_count
));
/* Set myself->port / cport to my listening ports, we'll just need to
/* Set myself->port / cport to my listening ports, we'll just need to
* discover the IP address via MEET messages. */
* discover the IP address via MEET messages. */
...
@@ -1350,6 +1355,28 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) {
...
@@ -1350,6 +1355,28 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) {
}
}
}
}
/* If from our POV the node is up (no failure flags are set),
* we have no pending ping for the node, nor we have failure
* reports for this node, update the last pong time with the
* one we see from the other nodes. */
if
(
!
(
flags
&
(
CLUSTER_NODE_FAIL
|
CLUSTER_NODE_PFAIL
))
&&
node
->
ping_sent
==
0
&&
clusterNodeFailureReportsCount
(
node
)
==
0
)
{
mstime_t
pongtime
=
ntohl
(
g
->
pong_received
);
pongtime
*=
1000
;
/* Convert back to milliseconds. */
/* Replace the pong time with the received one only if
* it's greater than our view but is not in the future
* (with 500 milliseconds tolerance) from the POV of our
* clock. */
if
(
pongtime
<=
(
server
.
mstime
+
500
)
&&
pongtime
>
node
->
pong_received
)
{
node
->
pong_received
=
pongtime
;
}
}
/* If we already know this node, but it is not reachable, and
/* If we already know this node, but it is not reachable, and
* we see a different address in the gossip section of a node that
* we see a different address in the gossip section of a node that
* can talk with this other node, update the address, disconnect
* can talk with this other node, update the address, disconnect
...
@@ -1581,7 +1608,8 @@ int clusterProcessPacket(clusterLink *link) {
...
@@ -1581,7 +1608,8 @@ int clusterProcessPacket(clusterLink *link) {
uint32_t
totlen
=
ntohl
(
hdr
->
totlen
);
uint32_t
totlen
=
ntohl
(
hdr
->
totlen
);
uint16_t
type
=
ntohs
(
hdr
->
type
);
uint16_t
type
=
ntohs
(
hdr
->
type
);
server
.
cluster
->
stats_bus_messages_received
++
;
if
(
type
<
CLUSTERMSG_TYPE_COUNT
)
server
.
cluster
->
stats_bus_messages_received
[
type
]
++
;
serverLog
(
LL_DEBUG
,
"--- Processing packet of type %d, %lu bytes"
,
serverLog
(
LL_DEBUG
,
"--- Processing packet of type %d, %lu bytes"
,
type
,
(
unsigned
long
)
totlen
);
type
,
(
unsigned
long
)
totlen
);
...
@@ -2128,7 +2156,12 @@ void clusterSendMessage(clusterLink *link, unsigned char *msg, size_t msglen) {
...
@@ -2128,7 +2156,12 @@ void clusterSendMessage(clusterLink *link, unsigned char *msg, size_t msglen) {
clusterWriteHandler
,
link
);
clusterWriteHandler
,
link
);
link
->
sndbuf
=
sdscatlen
(
link
->
sndbuf
,
msg
,
msglen
);
link
->
sndbuf
=
sdscatlen
(
link
->
sndbuf
,
msg
,
msglen
);
server
.
cluster
->
stats_bus_messages_sent
++
;
/* Populate sent messages stats. */
clusterMsg
*
hdr
=
(
clusterMsg
*
)
msg
;
uint16_t
type
=
ntohs
(
hdr
->
type
);
if
(
type
<
CLUSTERMSG_TYPE_COUNT
)
server
.
cluster
->
stats_bus_messages_sent
[
type
]
++
;
}
}
/* Send a message to all the nodes that are part of the cluster having
/* Send a message to all the nodes that are part of the cluster having
...
@@ -2229,6 +2262,33 @@ void clusterBuildMessageHdr(clusterMsg *hdr, int type) {
...
@@ -2229,6 +2262,33 @@ void clusterBuildMessageHdr(clusterMsg *hdr, int type) {
/* For PING, PONG, and MEET, fixing the totlen field is up to the caller. */
/* For PING, PONG, and MEET, fixing the totlen field is up to the caller. */
}
}
/* Return non zero if the node is already present in the gossip section of the
* message pointed by 'hdr' and having 'count' gossip entries. Otherwise
* zero is returned. Helper for clusterSendPing(). */
int
clusterNodeIsInGossipSection
(
clusterMsg
*
hdr
,
int
count
,
clusterNode
*
n
)
{
int
j
;
for
(
j
=
0
;
j
<
count
;
j
++
)
{
if
(
memcmp
(
hdr
->
data
.
ping
.
gossip
[
j
].
nodename
,
n
->
name
,
CLUSTER_NAMELEN
)
==
0
)
break
;
}
return
j
!=
count
;
}
/* Set the i-th entry of the gossip section in the message pointed by 'hdr'
* to the info of the specified node 'n'. */
void
clusterSetGossipEntry
(
clusterMsg
*
hdr
,
int
i
,
clusterNode
*
n
)
{
clusterMsgDataGossip
*
gossip
;
gossip
=
&
(
hdr
->
data
.
ping
.
gossip
[
i
]);
memcpy
(
gossip
->
nodename
,
n
->
name
,
CLUSTER_NAMELEN
);
gossip
->
ping_sent
=
htonl
(
n
->
ping_sent
/
1000
);
gossip
->
pong_received
=
htonl
(
n
->
pong_received
/
1000
);
memcpy
(
gossip
->
ip
,
n
->
ip
,
sizeof
(
n
->
ip
));
gossip
->
port
=
htons
(
n
->
port
);
gossip
->
cport
=
htons
(
n
->
cport
);
gossip
->
flags
=
htons
(
n
->
flags
);
gossip
->
notused1
=
0
;
}
/* Send a PING or PONG packet to the specified node, making sure to add enough
/* Send a PING or PONG packet to the specified node, making sure to add enough
* gossip informations. */
* gossip informations. */
void
clusterSendPing
(
clusterLink
*
link
,
int
type
)
{
void
clusterSendPing
(
clusterLink
*
link
,
int
type
)
{
...
@@ -2273,11 +2333,15 @@ void clusterSendPing(clusterLink *link, int type) {
...
@@ -2273,11 +2333,15 @@ void clusterSendPing(clusterLink *link, int type) {
if
(
wanted
<
3
)
wanted
=
3
;
if
(
wanted
<
3
)
wanted
=
3
;
if
(
wanted
>
freshnodes
)
wanted
=
freshnodes
;
if
(
wanted
>
freshnodes
)
wanted
=
freshnodes
;
/* Include all the nodes in PFAIL state, so that failure reports are
* faster to propagate to go from PFAIL to FAIL state. */
int
pfail_wanted
=
server
.
cluster
->
stats_pfail_nodes
;
/* Compute the maxium totlen to allocate our buffer. We'll fix the totlen
/* Compute the maxium totlen to allocate our buffer. We'll fix the totlen
* later according to the number of gossip sections we really were able
* later according to the number of gossip sections we really were able
* to put inside the packet. */
* to put inside the packet. */
totlen
=
sizeof
(
clusterMsg
)
-
sizeof
(
union
clusterMsgData
);
totlen
=
sizeof
(
clusterMsg
)
-
sizeof
(
union
clusterMsgData
);
totlen
+=
(
sizeof
(
clusterMsgDataGossip
)
*
wanted
);
totlen
+=
(
sizeof
(
clusterMsgDataGossip
)
*
(
wanted
+
pfail_wanted
)
);
/* Note: clusterBuildMessageHdr() expects the buffer to be always at least
/* Note: clusterBuildMessageHdr() expects the buffer to be always at least
* sizeof(clusterMsg) or more. */
* sizeof(clusterMsg) or more. */
if
(
totlen
<
(
int
)
sizeof
(
clusterMsg
))
totlen
=
sizeof
(
clusterMsg
);
if
(
totlen
<
(
int
)
sizeof
(
clusterMsg
))
totlen
=
sizeof
(
clusterMsg
);
...
@@ -2294,17 +2358,13 @@ void clusterSendPing(clusterLink *link, int type) {
...
@@ -2294,17 +2358,13 @@ void clusterSendPing(clusterLink *link, int type) {
while
(
freshnodes
>
0
&&
gossipcount
<
wanted
&&
maxiterations
--
)
{
while
(
freshnodes
>
0
&&
gossipcount
<
wanted
&&
maxiterations
--
)
{
dictEntry
*
de
=
dictGetRandomKey
(
server
.
cluster
->
nodes
);
dictEntry
*
de
=
dictGetRandomKey
(
server
.
cluster
->
nodes
);
clusterNode
*
this
=
dictGetVal
(
de
);
clusterNode
*
this
=
dictGetVal
(
de
);
clusterMsgDataGossip
*
gossip
;
int
j
;
/* Don't include this node: the whole packet header is about us
/* Don't include this node: the whole packet header is about us
* already, so we just gossip about other nodes. */
* already, so we just gossip about other nodes. */
if
(
this
==
myself
)
continue
;
if
(
this
==
myself
)
continue
;
/* Give a bias to FAIL/PFAIL nodes. */
/* PFAIL nodes will be added later. */
if
(
maxiterations
>
wanted
*
2
&&
if
(
this
->
flags
&
CLUSTER_NODE_PFAIL
)
continue
;
!
(
this
->
flags
&
(
CLUSTER_NODE_PFAIL
|
CLUSTER_NODE_FAIL
)))
continue
;
/* In the gossip section don't include:
/* In the gossip section don't include:
* 1) Nodes in HANDSHAKE state.
* 1) Nodes in HANDSHAKE state.
...
@@ -2318,27 +2378,37 @@ void clusterSendPing(clusterLink *link, int type) {
...
@@ -2318,27 +2378,37 @@ void clusterSendPing(clusterLink *link, int type) {
continue
;
continue
;
}
}
/* Check if we already added this node */
/* Do not add a node we already have. */
for
(
j
=
0
;
j
<
gossipcount
;
j
++
)
{
if
(
clusterNodeIsInGossipSection
(
hdr
,
gossipcount
,
this
))
continue
;
if
(
memcmp
(
hdr
->
data
.
ping
.
gossip
[
j
].
nodename
,
this
->
name
,
CLUSTER_NAMELEN
)
==
0
)
break
;
}
if
(
j
!=
gossipcount
)
continue
;
/* Add it */
/* Add it */
clusterSetGossipEntry
(
hdr
,
gossipcount
,
this
);
freshnodes
--
;
freshnodes
--
;
gossip
=
&
(
hdr
->
data
.
ping
.
gossip
[
gossipcount
]);
memcpy
(
gossip
->
nodename
,
this
->
name
,
CLUSTER_NAMELEN
);
gossip
->
ping_sent
=
htonl
(
this
->
ping_sent
);
gossip
->
pong_received
=
htonl
(
this
->
pong_received
);
memcpy
(
gossip
->
ip
,
this
->
ip
,
sizeof
(
this
->
ip
));
gossip
->
port
=
htons
(
this
->
port
);
gossip
->
cport
=
htons
(
this
->
cport
);
gossip
->
flags
=
htons
(
this
->
flags
);
gossip
->
notused1
=
0
;
gossipcount
++
;
gossipcount
++
;
}
}
/* If there are PFAIL nodes, add them at the end. */
if
(
pfail_wanted
)
{
dictIterator
*
di
;
dictEntry
*
de
;
di
=
dictGetSafeIterator
(
server
.
cluster
->
nodes
);
while
((
de
=
dictNext
(
di
))
!=
NULL
&&
pfail_wanted
>
0
)
{
clusterNode
*
node
=
dictGetVal
(
de
);
if
(
node
->
flags
&
CLUSTER_NODE_HANDSHAKE
)
continue
;
if
(
node
->
flags
&
CLUSTER_NODE_NOADDR
)
continue
;
if
(
!
(
node
->
flags
&
CLUSTER_NODE_PFAIL
))
continue
;
clusterSetGossipEntry
(
hdr
,
gossipcount
,
node
);
freshnodes
--
;
gossipcount
++
;
/* We take the count of the slots we allocated, since the
* PFAIL stats may not match perfectly with the current number
* of PFAIL nodes. */
pfail_wanted
--
;
}
dictReleaseIterator
(
di
);
}
/* Ready to send... fix the totlen fiend and queue the message in the
/* Ready to send... fix the totlen fiend and queue the message in the
* output buffer. */
* output buffer. */
totlen
=
sizeof
(
clusterMsg
)
-
sizeof
(
union
clusterMsgData
);
totlen
=
sizeof
(
clusterMsg
)
-
sizeof
(
union
clusterMsgData
);
...
@@ -3164,13 +3234,21 @@ void clusterCron(void) {
...
@@ -3164,13 +3234,21 @@ void clusterCron(void) {
handshake_timeout
=
server
.
cluster_node_timeout
;
handshake_timeout
=
server
.
cluster_node_timeout
;
if
(
handshake_timeout
<
1000
)
handshake_timeout
=
1000
;
if
(
handshake_timeout
<
1000
)
handshake_timeout
=
1000
;
/* Check if we have disconnected nodes and re-establish the connection. */
/* Check if we have disconnected nodes and re-establish the connection.
* Also update a few stats while we are here, that can be used to make
* better decisions in other part of the code. */
di
=
dictGetSafeIterator
(
server
.
cluster
->
nodes
);
di
=
dictGetSafeIterator
(
server
.
cluster
->
nodes
);
server
.
cluster
->
stats_pfail_nodes
=
0
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
clusterNode
*
node
=
dictGetVal
(
de
);
clusterNode
*
node
=
dictGetVal
(
de
);
/* Not interested in reconnecting the link with myself or nodes
* for which we have no address. */
if
(
node
->
flags
&
(
CLUSTER_NODE_MYSELF
|
CLUSTER_NODE_NOADDR
))
continue
;
if
(
node
->
flags
&
(
CLUSTER_NODE_MYSELF
|
CLUSTER_NODE_NOADDR
))
continue
;
if
(
node
->
flags
&
CLUSTER_NODE_PFAIL
)
server
.
cluster
->
stats_pfail_nodes
++
;
/* A Node in HANDSHAKE state has a limited lifespan equal to the
/* A Node in HANDSHAKE state has a limited lifespan equal to the
* configured node timeout. */
* configured node timeout. */
if
(
nodeInHandshake
(
node
)
&&
now
-
node
->
ctime
>
handshake_timeout
)
{
if
(
nodeInHandshake
(
node
)
&&
now
-
node
->
ctime
>
handshake_timeout
)
{
...
@@ -3875,6 +3953,21 @@ sds clusterGenNodesDescription(int filter) {
...
@@ -3875,6 +3953,21 @@ sds clusterGenNodesDescription(int filter) {
* CLUSTER command
* CLUSTER command
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
const
char
*
clusterGetMessageTypeString
(
int
type
)
{
switch
(
type
)
{
case
CLUSTERMSG_TYPE_PING
:
return
"ping"
;
case
CLUSTERMSG_TYPE_PONG
:
return
"pong"
;
case
CLUSTERMSG_TYPE_MEET
:
return
"meet"
;
case
CLUSTERMSG_TYPE_FAIL
:
return
"fail"
;
case
CLUSTERMSG_TYPE_PUBLISH
:
return
"publish"
;
case
CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST
:
return
"auth-req"
;
case
CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK
:
return
"auth-ack"
;
case
CLUSTERMSG_TYPE_UPDATE
:
return
"update"
;
case
CLUSTERMSG_TYPE_MFSTART
:
return
"mfstart"
;
}
return
"unknown"
;
}
int
getSlotOrReply
(
client
*
c
,
robj
*
o
)
{
int
getSlotOrReply
(
client
*
c
,
robj
*
o
)
{
long
long
slot
;
long
long
slot
;
...
@@ -4206,8 +4299,6 @@ void clusterCommand(client *c) {
...
@@ -4206,8 +4299,6 @@ void clusterCommand(client *c) {
"cluster_size:%d
\r\n
"
"cluster_size:%d
\r\n
"
"cluster_current_epoch:%llu
\r\n
"
"cluster_current_epoch:%llu
\r\n
"
"cluster_my_epoch:%llu
\r\n
"
"cluster_my_epoch:%llu
\r\n
"
"cluster_stats_messages_sent:%lld
\r\n
"
"cluster_stats_messages_received:%lld
\r\n
"
,
statestr
[
server
.
cluster
->
state
],
,
statestr
[
server
.
cluster
->
state
],
slots_assigned
,
slots_assigned
,
slots_ok
,
slots_ok
,
...
@@ -4216,10 +4307,36 @@ void clusterCommand(client *c) {
...
@@ -4216,10 +4307,36 @@ void clusterCommand(client *c) {
dictSize
(
server
.
cluster
->
nodes
),
dictSize
(
server
.
cluster
->
nodes
),
server
.
cluster
->
size
,
server
.
cluster
->
size
,
(
unsigned
long
long
)
server
.
cluster
->
currentEpoch
,
(
unsigned
long
long
)
server
.
cluster
->
currentEpoch
,
(
unsigned
long
long
)
myepoch
,
(
unsigned
long
long
)
myepoch
server
.
cluster
->
stats_bus_messages_sent
,
server
.
cluster
->
stats_bus_messages_received
);
);
/* Show stats about messages sent and received. */
long
long
tot_msg_sent
=
0
;
long
long
tot_msg_received
=
0
;
for
(
int
i
=
0
;
i
<
CLUSTERMSG_TYPE_COUNT
;
i
++
)
{
if
(
server
.
cluster
->
stats_bus_messages_sent
[
i
]
==
0
)
continue
;
tot_msg_sent
+=
server
.
cluster
->
stats_bus_messages_sent
[
i
];
info
=
sdscatprintf
(
info
,
"cluster_stats_messages_%s_sent:%lld
\r\n
"
,
clusterGetMessageTypeString
(
i
),
server
.
cluster
->
stats_bus_messages_sent
[
i
]);
}
info
=
sdscatprintf
(
info
,
"cluster_stats_messages_sent:%lld
\r\n
"
,
tot_msg_sent
);
for
(
int
i
=
0
;
i
<
CLUSTERMSG_TYPE_COUNT
;
i
++
)
{
if
(
server
.
cluster
->
stats_bus_messages_received
[
i
]
==
0
)
continue
;
tot_msg_received
+=
server
.
cluster
->
stats_bus_messages_received
[
i
];
info
=
sdscatprintf
(
info
,
"cluster_stats_messages_%s_received:%lld
\r\n
"
,
clusterGetMessageTypeString
(
i
),
server
.
cluster
->
stats_bus_messages_received
[
i
]);
}
info
=
sdscatprintf
(
info
,
"cluster_stats_messages_received:%lld
\r\n
"
,
tot_msg_received
);
/* Produce the reply protocol. */
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
"$%lu
\r\n
"
,
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
"$%lu
\r\n
"
,
(
unsigned
long
)
sdslen
(
info
)));
(
unsigned
long
)
sdslen
(
info
)));
addReplySds
(
c
,
info
);
addReplySds
(
c
,
info
);
...
...
src/cluster.h
View file @
89a9e5a9
...
@@ -73,6 +73,29 @@ typedef struct clusterLink {
...
@@ -73,6 +73,29 @@ typedef struct clusterLink {
#define CLUSTER_CANT_FAILOVER_WAITING_VOTES 4
#define CLUSTER_CANT_FAILOVER_WAITING_VOTES 4
#define CLUSTER_CANT_FAILOVER_RELOG_PERIOD (60*5)
/* seconds. */
#define CLUSTER_CANT_FAILOVER_RELOG_PERIOD (60*5)
/* seconds. */
/* clusterState todo_before_sleep flags. */
#define CLUSTER_TODO_HANDLE_FAILOVER (1<<0)
#define CLUSTER_TODO_UPDATE_STATE (1<<1)
#define CLUSTER_TODO_SAVE_CONFIG (1<<2)
#define CLUSTER_TODO_FSYNC_CONFIG (1<<3)
/* Message types.
*
* Note that the PING, PONG and MEET messages are actually the same exact
* kind of packet. PONG is the reply to ping, in the exact format as a PING,
* while MEET is a special PING that forces the receiver to add the sender
* as a node (if it is not already in the list). */
#define CLUSTERMSG_TYPE_PING 0
/* Ping */
#define CLUSTERMSG_TYPE_PONG 1
/* Pong (reply to Ping) */
#define CLUSTERMSG_TYPE_MEET 2
/* Meet "let's join" message */
#define CLUSTERMSG_TYPE_FAIL 3
/* Mark node xxx as failing */
#define CLUSTERMSG_TYPE_PUBLISH 4
/* Pub/Sub Publish propagation */
#define CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 5
/* May I failover? */
#define CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 6
/* Yes, you have my vote */
#define CLUSTERMSG_TYPE_UPDATE 7
/* Another node slots configuration */
#define CLUSTERMSG_TYPE_MFSTART 8
/* Pause clients for manual failover */
#define CLUSTERMSG_TYPE_COUNT 9
/* Total number of message types. */
/* This structure represent elements of node->fail_reports. */
/* This structure represent elements of node->fail_reports. */
typedef
struct
clusterNodeFailReport
{
typedef
struct
clusterNodeFailReport
{
struct
clusterNode
*
node
;
/* Node reporting the failure condition. */
struct
clusterNode
*
node
;
/* Node reporting the failure condition. */
...
@@ -116,7 +139,8 @@ typedef struct clusterState {
...
@@ -116,7 +139,8 @@ typedef struct clusterState {
clusterNode
*
migrating_slots_to
[
CLUSTER_SLOTS
];
clusterNode
*
migrating_slots_to
[
CLUSTER_SLOTS
];
clusterNode
*
importing_slots_from
[
CLUSTER_SLOTS
];
clusterNode
*
importing_slots_from
[
CLUSTER_SLOTS
];
clusterNode
*
slots
[
CLUSTER_SLOTS
];
clusterNode
*
slots
[
CLUSTER_SLOTS
];
zskiplist
*
slots_to_keys
;
uint64_t
slots_keys_count
[
CLUSTER_SLOTS
];
rax
*
slots_to_keys
;
/* The following fields are used to take the slave state on elections. */
/* The following fields are used to take the slave state on elections. */
mstime_t
failover_auth_time
;
/* Time of previous or next election. */
mstime_t
failover_auth_time
;
/* Time of previous or next election. */
int
failover_auth_count
;
/* Number of votes received so far. */
int
failover_auth_count
;
/* Number of votes received so far. */
...
@@ -138,32 +162,15 @@ typedef struct clusterState {
...
@@ -138,32 +162,15 @@ typedef struct clusterState {
/* The followign fields are used by masters to take state on elections. */
/* The followign fields are used by masters to take state on elections. */
uint64_t
lastVoteEpoch
;
/* Epoch of the last vote granted. */
uint64_t
lastVoteEpoch
;
/* Epoch of the last vote granted. */
int
todo_before_sleep
;
/* Things to do in clusterBeforeSleep(). */
int
todo_before_sleep
;
/* Things to do in clusterBeforeSleep(). */
long
long
stats_bus_messages_sent
;
/* Num of msg sent via cluster bus. */
/* Messages received and sent by type. */
long
long
stats_bus_messages_received
;
/* Num of msg rcvd via cluster bus.*/
long
long
stats_bus_messages_sent
[
CLUSTERMSG_TYPE_COUNT
];
long
long
stats_bus_messages_received
[
CLUSTERMSG_TYPE_COUNT
];
long
long
stats_pfail_nodes
;
/* Number of nodes in PFAIL status,
excluding nodes without address. */
}
clusterState
;
}
clusterState
;
/* clusterState todo_before_sleep flags. */
#define CLUSTER_TODO_HANDLE_FAILOVER (1<<0)
#define CLUSTER_TODO_UPDATE_STATE (1<<1)
#define CLUSTER_TODO_SAVE_CONFIG (1<<2)
#define CLUSTER_TODO_FSYNC_CONFIG (1<<3)
/* Redis cluster messages header */
/* Redis cluster messages header */
/* Note that the PING, PONG and MEET messages are actually the same exact
* kind of packet. PONG is the reply to ping, in the exact format as a PING,
* while MEET is a special PING that forces the receiver to add the sender
* as a node (if it is not already in the list). */
#define CLUSTERMSG_TYPE_PING 0
/* Ping */
#define CLUSTERMSG_TYPE_PONG 1
/* Pong (reply to Ping) */
#define CLUSTERMSG_TYPE_MEET 2
/* Meet "let's join" message */
#define CLUSTERMSG_TYPE_FAIL 3
/* Mark node xxx as failing */
#define CLUSTERMSG_TYPE_PUBLISH 4
/* Pub/Sub Publish propagation */
#define CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 5
/* May I failover? */
#define CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 6
/* Yes, you have my vote */
#define CLUSTERMSG_TYPE_UPDATE 7
/* Another node slots configuration */
#define CLUSTERMSG_TYPE_MFSTART 8
/* Pause clients for manual failover */
/* Initially we don't know our "name", but we'll find it once we connect
/* Initially we don't know our "name", but we'll find it once we connect
* to the first node, using the getsockname() function. Then we'll use this
* to the first node, using the getsockname() function. Then we'll use this
* address for all the next messages. */
* address for all the next messages. */
...
...
src/db.c
View file @
89a9e5a9
...
@@ -1133,11 +1133,24 @@ int *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, in
...
@@ -1133,11 +1133,24 @@ int *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, in
*
numkeys
=
0
;
*
numkeys
=
0
;
return
NULL
;
return
NULL
;
}
}
last
=
cmd
->
lastkey
;
last
=
cmd
->
lastkey
;
if
(
last
<
0
)
last
=
argc
+
last
;
if
(
last
<
0
)
last
=
argc
+
last
;
keys
=
zmalloc
(
sizeof
(
int
)
*
((
last
-
cmd
->
firstkey
)
+
1
));
keys
=
zmalloc
(
sizeof
(
int
)
*
((
last
-
cmd
->
firstkey
)
+
1
));
for
(
j
=
cmd
->
firstkey
;
j
<=
last
;
j
+=
cmd
->
keystep
)
{
for
(
j
=
cmd
->
firstkey
;
j
<=
last
;
j
+=
cmd
->
keystep
)
{
serverAssert
(
j
<
argc
);
if
(
j
>=
argc
)
{
/* Modules command do not have dispatch time arity checks, so
* we need to handle the case where the user passed an invalid
* number of arguments here. In this case we return no keys
* and expect the module command to report an arity error. */
if
(
cmd
->
flags
&
CMD_MODULE
)
{
zfree
(
keys
);
*
numkeys
=
0
;
return
NULL
;
}
else
{
serverPanic
(
"Redis built-in command declared keys positions not matching the arity requirements."
);
}
}
keys
[
i
++
]
=
j
;
keys
[
i
++
]
=
j
;
}
}
*
numkeys
=
i
;
*
numkeys
=
i
;
...
@@ -1301,90 +1314,85 @@ int *migrateGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkey
...
@@ -1301,90 +1314,85 @@ int *migrateGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkey
/* Slot to Key API. This is used by Redis Cluster in order to obtain in
/* Slot to Key API. This is used by Redis Cluster in order to obtain in
* a fast way a key that belongs to a specified hash slot. This is useful
* a fast way a key that belongs to a specified hash slot. This is useful
* while rehashing the cluster. */
* while rehashing the cluster and in other conditions when we need to
void
slotToKeyAdd
(
robj
*
key
)
{
* understand if we have keys for a given hash slot. */
void
slotToKeyUpdateKey
(
robj
*
key
,
int
add
)
{
unsigned
int
hashslot
=
keyHashSlot
(
key
->
ptr
,
sdslen
(
key
->
ptr
));
unsigned
int
hashslot
=
keyHashSlot
(
key
->
ptr
,
sdslen
(
key
->
ptr
));
unsigned
char
buf
[
64
];
unsigned
char
*
indexed
=
buf
;
size_t
keylen
=
sdslen
(
key
->
ptr
);
server
.
cluster
->
slots_keys_count
[
hashslot
]
+=
add
?
1
:
-
1
;
if
(
keylen
+
2
>
64
)
indexed
=
zmalloc
(
keylen
+
2
);
indexed
[
0
]
=
(
hashslot
>>
8
)
&
0xff
;
indexed
[
1
]
=
hashslot
&
0xff
;
memcpy
(
indexed
+
2
,
key
->
ptr
,
keylen
);
if
(
add
)
{
raxInsert
(
server
.
cluster
->
slots_to_keys
,
indexed
,
keylen
+
2
,
NULL
,
NULL
);
}
else
{
raxRemove
(
server
.
cluster
->
slots_to_keys
,
indexed
,
keylen
+
2
,
NULL
);
}
if
(
indexed
!=
buf
)
zfree
(
indexed
);
}
sds
sdskey
=
sdsdup
(
key
->
ptr
);
void
slotToKeyAdd
(
robj
*
key
)
{
zslInsert
(
server
.
cluster
->
slots_to_keys
,
hashslot
,
sds
key
);
slotToKeyUpdateKey
(
key
,
1
);
}
}
void
slotToKeyDel
(
robj
*
key
)
{
void
slotToKeyDel
(
robj
*
key
)
{
unsigned
int
hashslot
=
keyHashSlot
(
key
->
ptr
,
sdslen
(
key
->
ptr
));
slotToKeyUpdateKey
(
key
,
0
);
zslDelete
(
server
.
cluster
->
slots_to_keys
,
hashslot
,
key
->
ptr
,
NULL
);
}
}
void
slotToKeyFlush
(
void
)
{
void
slotToKeyFlush
(
void
)
{
zslFree
(
server
.
cluster
->
slots_to_keys
);
raxFree
(
server
.
cluster
->
slots_to_keys
);
server
.
cluster
->
slots_to_keys
=
zslCreate
();
server
.
cluster
->
slots_to_keys
=
raxNew
();
memset
(
server
.
cluster
->
slots_keys_count
,
0
,
sizeof
(
server
.
cluster
->
slots_keys_count
));
}
}
/* Pupulate the specified array of objects with keys in the specified slot.
/* Pupulate the specified array of objects with keys in the specified slot.
* New objects are returned to represent keys, it's up to the caller to
* New objects are returned to represent keys, it's up to the caller to
* decrement the reference count to release the keys names. */
* decrement the reference count to release the keys names. */
unsigned
int
getKeysInSlot
(
unsigned
int
hashslot
,
robj
**
keys
,
unsigned
int
count
)
{
unsigned
int
getKeysInSlot
(
unsigned
int
hashslot
,
robj
**
keys
,
unsigned
int
count
)
{
zskiplistNode
*
n
;
raxIterator
iter
;
zrangespec
range
;
int
j
=
0
;
int
j
=
0
;
unsigned
char
indexed
[
2
];
range
.
min
=
range
.
max
=
hashslot
;
range
.
minex
=
range
.
maxex
=
0
;
indexed
[
0
]
=
(
hashslot
>>
8
)
&
0xff
;
indexed
[
1
]
=
hashslot
&
0xff
;
n
=
zslFirstInRange
(
server
.
cluster
->
slots_to_keys
,
&
range
);
raxStart
(
&
iter
,
server
.
cluster
->
slots_to_keys
);
while
(
n
&&
n
->
score
==
hashslot
&&
count
--
)
{
raxSeek
(
&
iter
,
">="
,
indexed
,
2
);
keys
[
j
++
]
=
createStringObject
(
n
->
ele
,
sdslen
(
n
->
ele
));
while
(
count
--
&&
raxNext
(
&
iter
))
{
n
=
n
->
level
[
0
].
forward
;
if
(
iter
.
key
[
0
]
!=
indexed
[
0
]
||
iter
.
key
[
1
]
!=
indexed
[
1
])
break
;
keys
[
j
++
]
=
createStringObject
((
char
*
)
iter
.
key
+
2
,
iter
.
key_len
-
2
);
}
}
raxStop
(
&
iter
);
return
j
;
return
j
;
}
}
/* Remove all the keys in the specified hash slot.
/* Remove all the keys in the specified hash slot.
* The number of removed items is returned. */
* The number of removed items is returned. */
unsigned
int
delKeysInSlot
(
unsigned
int
hashslot
)
{
unsigned
int
delKeysInSlot
(
unsigned
int
hashslot
)
{
zskiplistNode
*
n
;
raxIterator
iter
;
zrangespec
range
;
int
j
=
0
;
int
j
=
0
;
unsigned
char
indexed
[
2
];
range
.
min
=
range
.
max
=
hashslot
;
indexed
[
0
]
=
(
hashslot
>>
8
)
&
0xff
;
range
.
minex
=
range
.
maxex
=
0
;
indexed
[
1
]
=
hashslot
&
0xff
;
raxStart
(
&
iter
,
server
.
cluster
->
slots_to_keys
);
while
(
server
.
cluster
->
slots_keys_count
[
hashslot
])
{
raxSeek
(
&
iter
,
">="
,
indexed
,
2
);
raxNext
(
&
iter
);
n
=
zslFirstInRange
(
server
.
cluster
->
slots_to_keys
,
&
range
);
robj
*
key
=
createStringObject
((
char
*
)
iter
.
key
+
2
,
iter
.
key_len
-
2
);
while
(
n
&&
n
->
score
==
hashslot
)
{
sds
sdskey
=
n
->
ele
;
robj
*
key
=
createStringObject
(
sdskey
,
sdslen
(
sdskey
));
n
=
n
->
level
[
0
].
forward
;
/* Go to the next item before freeing it. */
dbDelete
(
&
server
.
db
[
0
],
key
);
dbDelete
(
&
server
.
db
[
0
],
key
);
decrRefCount
(
key
);
decrRefCount
(
key
);
j
++
;
j
++
;
}
}
raxStop
(
&
iter
);
return
j
;
return
j
;
}
}
unsigned
int
countKeysInSlot
(
unsigned
int
hashslot
)
{
unsigned
int
countKeysInSlot
(
unsigned
int
hashslot
)
{
zskiplist
*
zsl
=
server
.
cluster
->
slots_to_keys
;
return
server
.
cluster
->
slots_keys_count
[
hashslot
];
zskiplistNode
*
zn
;
zrangespec
range
;
int
rank
,
count
=
0
;
range
.
min
=
range
.
max
=
hashslot
;
range
.
minex
=
range
.
maxex
=
0
;
/* Find first element in range */
zn
=
zslFirstInRange
(
zsl
,
&
range
);
/* Use rank of first element, if any, to determine preliminary count */
if
(
zn
!=
NULL
)
{
rank
=
zslGetRank
(
zsl
,
zn
->
score
,
zn
->
ele
);
count
=
(
zsl
->
length
-
(
rank
-
1
));
/* Find last element in range */
zn
=
zslLastInRange
(
zsl
,
&
range
);
/* Use rank of last element, if any, to determine the actual count */
if
(
zn
!=
NULL
)
{
rank
=
zslGetRank
(
zsl
,
zn
->
score
,
zn
->
ele
);
count
-=
(
zsl
->
length
-
rank
);
}
}
return
count
;
}
}
src/expire.c
View file @
89a9e5a9
...
@@ -92,7 +92,7 @@ int activeExpireCycleTryExpire(redisDb *db, dictEntry *de, long long now) {
...
@@ -92,7 +92,7 @@ int activeExpireCycleTryExpire(redisDb *db, dictEntry *de, long long now) {
*
*
* If type is ACTIVE_EXPIRE_CYCLE_SLOW, that normal expire cycle is
* If type is ACTIVE_EXPIRE_CYCLE_SLOW, that normal expire cycle is
* executed, where the time limit is a percentage of the REDIS_HZ period
* executed, where the time limit is a percentage of the REDIS_HZ period
* as specified by the
REDIS
_EXPIRE
LOOKUPS
_TIME_PERC define. */
* as specified by the
ACTIVE
_EXPIRE
_CYCLE_SLOW
_TIME_PERC define. */
void
activeExpireCycle
(
int
type
)
{
void
activeExpireCycle
(
int
type
)
{
/* This function has some global state in order to continue the work
/* This function has some global state in order to continue the work
...
...
src/lazyfree.c
View file @
89a9e5a9
...
@@ -97,11 +97,14 @@ void emptyDbAsync(redisDb *db) {
...
@@ -97,11 +97,14 @@ void emptyDbAsync(redisDb *db) {
/* Empty the slots-keys map of Redis CLuster by creating a new empty one
/* Empty the slots-keys map of Redis CLuster by creating a new empty one
* and scheduiling the old for lazy freeing. */
* and scheduiling the old for lazy freeing. */
void
slotToKeyFlushAsync
(
void
)
{
void
slotToKeyFlushAsync
(
void
)
{
zskiplist
*
oldsl
=
server
.
cluster
->
slots_to_keys
;
rax
*
old
=
server
.
cluster
->
slots_to_keys
;
server
.
cluster
->
slots_to_keys
=
zslCreate
();
atomicIncr
(
lazyfree_objects
,
oldsl
->
length
,
server
.
cluster
->
slots_to_keys
=
raxNew
();
memset
(
server
.
cluster
->
slots_keys_count
,
0
,
sizeof
(
server
.
cluster
->
slots_keys_count
));
atomicIncr
(
lazyfree_objects
,
old
->
numele
,
lazyfree_objects_mutex
);
lazyfree_objects_mutex
);
bioCreateBackgroundJob
(
BIO_LAZY_FREE
,
NULL
,
NULL
,
old
sl
);
bioCreateBackgroundJob
(
BIO_LAZY_FREE
,
NULL
,
NULL
,
old
);
}
}
/* Release objects from the lazyfree thread. It's just decrRefCount()
/* Release objects from the lazyfree thread. It's just decrRefCount()
...
@@ -125,8 +128,8 @@ void lazyfreeFreeDatabaseFromBioThread(dict *ht1, dict *ht2) {
...
@@ -125,8 +128,8 @@ void lazyfreeFreeDatabaseFromBioThread(dict *ht1, dict *ht2) {
/* Release the skiplist mapping Redis Cluster keys to slots in the
/* Release the skiplist mapping Redis Cluster keys to slots in the
* lazyfree thread. */
* lazyfree thread. */
void
lazyfreeFreeSlotsMapFromBioThread
(
zskiplist
*
sl
)
{
void
lazyfreeFreeSlotsMapFromBioThread
(
rax
*
rt
)
{
size_t
len
=
sl
->
length
;
size_t
len
=
rt
->
numele
;
zsl
Free
(
sl
);
rax
Free
(
rt
);
atomicDecr
(
lazyfree_objects
,
len
,
lazyfree_objects_mutex
);
atomicDecr
(
lazyfree_objects
,
len
,
lazyfree_objects_mutex
);
}
}
Prev
1
…
4
5
6
7
8
9
Next
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