Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
2bbc8919
Commit
2bbc8919
authored
Nov 21, 2022
by
Viktor Söderqvist
Browse files
Move stat_active_defrag_hits increment to activeDefragAlloc
instead of passing it around to every defrag function
parent
b60d33c9
Changes
3
Show whitespace changes
Inline
Side-by-side
src/defrag.c
View file @
2bbc8919
...
@@ -64,6 +64,7 @@ void* activeDefragAlloc(void *ptr) {
...
@@ -64,6 +64,7 @@ void* activeDefragAlloc(void *ptr) {
newptr
=
zmalloc_no_tcache
(
size
);
newptr
=
zmalloc_no_tcache
(
size
);
memcpy
(
newptr
,
ptr
,
size
);
memcpy
(
newptr
,
ptr
,
size
);
zfree_no_tcache
(
ptr
);
zfree_no_tcache
(
ptr
);
server
.
stat_active_defrag_hits
++
;
return
newptr
;
return
newptr
;
}
}
...
@@ -88,7 +89,7 @@ sds activeDefragSds(sds sdsptr) {
...
@@ -88,7 +89,7 @@ sds activeDefragSds(sds sdsptr) {
* returns NULL in case the allocation wasn't moved.
* returns NULL in case the allocation wasn't moved.
* when it returns a non-null value, the old pointer was already released
* when it returns a non-null value, the old pointer was already released
* and should NOT be accessed. */
* and should NOT be accessed. */
robj
*
activeDefragStringOb
(
robj
*
ob
,
long
*
defragged
)
{
robj
*
activeDefragStringOb
(
robj
*
ob
)
{
robj
*
ret
=
NULL
;
robj
*
ret
=
NULL
;
if
(
ob
->
refcount
!=
1
)
if
(
ob
->
refcount
!=
1
)
return
NULL
;
return
NULL
;
...
@@ -97,7 +98,6 @@ robj *activeDefragStringOb(robj* ob, long *defragged) {
...
@@ -97,7 +98,6 @@ robj *activeDefragStringOb(robj* ob, long *defragged) {
if
(
ob
->
type
!=
OBJ_STRING
||
ob
->
encoding
!=
OBJ_ENCODING_EMBSTR
)
{
if
(
ob
->
type
!=
OBJ_STRING
||
ob
->
encoding
!=
OBJ_ENCODING_EMBSTR
)
{
if
((
ret
=
activeDefragAlloc
(
ob
)))
{
if
((
ret
=
activeDefragAlloc
(
ob
)))
{
ob
=
ret
;
ob
=
ret
;
(
*
defragged
)
++
;
}
}
}
}
...
@@ -107,7 +107,6 @@ robj *activeDefragStringOb(robj* ob, long *defragged) {
...
@@ -107,7 +107,6 @@ robj *activeDefragStringOb(robj* ob, long *defragged) {
sds
newsds
=
activeDefragSds
((
sds
)
ob
->
ptr
);
sds
newsds
=
activeDefragSds
((
sds
)
ob
->
ptr
);
if
(
newsds
)
{
if
(
newsds
)
{
ob
->
ptr
=
newsds
;
ob
->
ptr
=
newsds
;
(
*
defragged
)
++
;
}
}
}
else
if
(
ob
->
encoding
==
OBJ_ENCODING_EMBSTR
)
{
}
else
if
(
ob
->
encoding
==
OBJ_ENCODING_EMBSTR
)
{
/* The sds is embedded in the object allocation, calculate the
/* The sds is embedded in the object allocation, calculate the
...
@@ -115,7 +114,6 @@ robj *activeDefragStringOb(robj* ob, long *defragged) {
...
@@ -115,7 +114,6 @@ robj *activeDefragStringOb(robj* ob, long *defragged) {
long
ofs
=
(
intptr_t
)
ob
->
ptr
-
(
intptr_t
)
ob
;
long
ofs
=
(
intptr_t
)
ob
->
ptr
-
(
intptr_t
)
ob
;
if
((
ret
=
activeDefragAlloc
(
ob
)))
{
if
((
ret
=
activeDefragAlloc
(
ob
)))
{
ret
->
ptr
=
(
void
*
)((
intptr_t
)
ret
+
ofs
);
ret
->
ptr
=
(
void
*
)((
intptr_t
)
ret
+
ofs
);
(
*
defragged
)
++
;
}
}
}
else
if
(
ob
->
encoding
!=
OBJ_ENCODING_INT
)
{
}
else
if
(
ob
->
encoding
!=
OBJ_ENCODING_INT
)
{
serverPanic
(
"Unknown string encoding"
);
serverPanic
(
"Unknown string encoding"
);
...
@@ -129,17 +127,16 @@ robj *activeDefragStringOb(robj* ob, long *defragged) {
...
@@ -129,17 +127,16 @@ robj *activeDefragStringOb(robj* ob, long *defragged) {
* returns NULL in case the allocation wasn't moved.
* returns NULL in case the allocation wasn't moved.
* when it returns a non-null value, the old pointer was already released
* when it returns a non-null value, the old pointer was already released
* and should NOT be accessed. */
* and should NOT be accessed. */
luaScript
*
activeDefragLuaScript
(
luaScript
*
script
,
long
*
defragged
)
{
luaScript
*
activeDefragLuaScript
(
luaScript
*
script
)
{
luaScript
*
ret
=
NULL
;
luaScript
*
ret
=
NULL
;
/* try to defrag script struct */
/* try to defrag script struct */
if
((
ret
=
activeDefragAlloc
(
script
)))
{
if
((
ret
=
activeDefragAlloc
(
script
)))
{
script
=
ret
;
script
=
ret
;
(
*
defragged
)
++
;
}
}
/* try to defrag actual script object */
/* try to defrag actual script object */
robj
*
ob
=
activeDefragStringOb
(
script
->
body
,
defragged
);
robj
*
ob
=
activeDefragStringOb
(
script
->
body
);
if
(
ob
)
script
->
body
=
ob
;
if
(
ob
)
script
->
body
=
ob
;
return
ret
;
return
ret
;
...
@@ -148,20 +145,18 @@ luaScript *activeDefragLuaScript(luaScript *script, long *defragged) {
...
@@ -148,20 +145,18 @@ luaScript *activeDefragLuaScript(luaScript *script, long *defragged) {
/* Defrag helper for dict main allocations (dict struct, and hash tables).
/* Defrag helper for dict main allocations (dict struct, and hash tables).
* receives a pointer to the dict* and implicitly updates it when the dict
* receives a pointer to the dict* and implicitly updates it when the dict
* struct itself was moved. Returns a stat of how many pointers were moved. */
* struct itself was moved. Returns a stat of how many pointers were moved. */
long
dictDefragTables
(
dict
*
d
)
{
void
dictDefragTables
(
dict
*
d
)
{
dictEntry
**
newtable
;
dictEntry
**
newtable
;
long
defragged
=
0
;
/* handle the first hash table */
/* handle the first hash table */
newtable
=
activeDefragAlloc
(
d
->
ht_table
[
0
]);
newtable
=
activeDefragAlloc
(
d
->
ht_table
[
0
]);
if
(
newtable
)
if
(
newtable
)
defragged
++
,
d
->
ht_table
[
0
]
=
newtable
;
d
->
ht_table
[
0
]
=
newtable
;
/* handle the second hash table */
/* handle the second hash table */
if
(
d
->
ht_table
[
1
])
{
if
(
d
->
ht_table
[
1
])
{
newtable
=
activeDefragAlloc
(
d
->
ht_table
[
1
]);
newtable
=
activeDefragAlloc
(
d
->
ht_table
[
1
]);
if
(
newtable
)
if
(
newtable
)
defragged
++
,
d
->
ht_table
[
1
]
=
newtable
;
d
->
ht_table
[
1
]
=
newtable
;
}
}
return
defragged
;
}
}
/* Internal function used by zslDefrag */
/* Internal function used by zslDefrag */
...
@@ -225,19 +220,16 @@ double *zslDefrag(zskiplist *zsl, double score, sds oldele, sds newele) {
...
@@ -225,19 +220,16 @@ double *zslDefrag(zskiplist *zsl, double score, sds oldele, sds newele) {
/* Defrag helper for sorted set.
/* Defrag helper for sorted set.
* Defrag a single dict entry key name, and corresponding skiplist struct */
* Defrag a single dict entry key name, and corresponding skiplist struct */
long
activeDefragZsetEntry
(
zset
*
zs
,
dictEntry
*
de
)
{
void
activeDefragZsetEntry
(
zset
*
zs
,
dictEntry
*
de
)
{
sds
newsds
;
sds
newsds
;
double
*
newscore
;
double
*
newscore
;
long
defragged
=
0
;
sds
sdsele
=
dictGetKey
(
de
);
sds
sdsele
=
dictGetKey
(
de
);
if
((
newsds
=
activeDefragSds
(
sdsele
)))
if
((
newsds
=
activeDefragSds
(
sdsele
)))
defragged
++
,
dictSetKey
(
zs
->
dict
,
de
,
newsds
);
dictSetKey
(
zs
->
dict
,
de
,
newsds
);
newscore
=
zslDefrag
(
zs
->
zsl
,
*
(
double
*
)
dictGetVal
(
de
),
sdsele
,
newsds
);
newscore
=
zslDefrag
(
zs
->
zsl
,
*
(
double
*
)
dictGetVal
(
de
),
sdsele
,
newsds
);
if
(
newscore
)
{
if
(
newscore
)
{
dictSetVal
(
zs
->
dict
,
de
,
newscore
);
dictSetVal
(
zs
->
dict
,
de
,
newscore
);
defragged
++
;
}
}
return
defragged
;
}
}
#define DEFRAG_SDS_DICT_NO_VAL 0
#define DEFRAG_SDS_DICT_NO_VAL 0
...
@@ -249,7 +241,6 @@ long activeDefragZsetEntry(zset *zs, dictEntry *de) {
...
@@ -249,7 +241,6 @@ long activeDefragZsetEntry(zset *zs, dictEntry *de) {
typedef
struct
{
typedef
struct
{
dict
*
dict
;
dict
*
dict
;
int
val_type
;
int
val_type
;
long
defragged
;
}
activeDefragSdsDictData
;
}
activeDefragSdsDictData
;
void
activeDefragSdsDictCallback
(
void
*
privdata
,
const
dictEntry
*
_de
)
{
void
activeDefragSdsDictCallback
(
void
*
privdata
,
const
dictEntry
*
_de
)
{
...
@@ -259,41 +250,39 @@ void activeDefragSdsDictCallback(void *privdata, const dictEntry *_de) {
...
@@ -259,41 +250,39 @@ void activeDefragSdsDictCallback(void *privdata, const dictEntry *_de) {
int
val_type
=
data
->
val_type
;
int
val_type
=
data
->
val_type
;
sds
sdsele
=
dictGetKey
(
de
),
newsds
;
sds
sdsele
=
dictGetKey
(
de
),
newsds
;
if
((
newsds
=
activeDefragSds
(
sdsele
)))
if
((
newsds
=
activeDefragSds
(
sdsele
)))
dictSetKey
(
d
,
de
,
newsds
)
,
data
->
defragged
++
;
dictSetKey
(
d
,
de
,
newsds
);
/* defrag the value */
/* defrag the value */
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_IS_SDS
)
{
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_IS_SDS
)
{
sdsele
=
dictGetVal
(
de
);
sdsele
=
dictGetVal
(
de
);
if
((
newsds
=
activeDefragSds
(
sdsele
)))
if
((
newsds
=
activeDefragSds
(
sdsele
)))
dictSetVal
(
d
,
de
,
newsds
)
,
data
->
defragged
++
;
dictSetVal
(
d
,
de
,
newsds
);
}
else
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_IS_STROB
)
{
}
else
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_IS_STROB
)
{
robj
*
newele
,
*
ele
=
dictGetVal
(
de
);
robj
*
newele
,
*
ele
=
dictGetVal
(
de
);
if
((
newele
=
activeDefragStringOb
(
ele
,
&
data
->
defragged
)))
if
((
newele
=
activeDefragStringOb
(
ele
)))
dictSetVal
(
d
,
de
,
newele
);
dictSetVal
(
d
,
de
,
newele
);
}
else
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_VOID_PTR
)
{
}
else
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_VOID_PTR
)
{
void
*
newptr
,
*
ptr
=
dictGetVal
(
de
);
void
*
newptr
,
*
ptr
=
dictGetVal
(
de
);
if
((
newptr
=
activeDefragAlloc
(
ptr
)))
if
((
newptr
=
activeDefragAlloc
(
ptr
)))
dictSetVal
(
d
,
de
,
newptr
)
,
data
->
defragged
++
;
dictSetVal
(
d
,
de
,
newptr
);
}
else
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_LUA_SCRIPT
)
{
}
else
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_LUA_SCRIPT
)
{
void
*
newptr
,
*
ptr
=
dictGetVal
(
de
);
void
*
newptr
,
*
ptr
=
dictGetVal
(
de
);
if
((
newptr
=
activeDefragLuaScript
(
ptr
,
&
data
->
defragged
)))
if
((
newptr
=
activeDefragLuaScript
(
ptr
)))
dictSetVal
(
d
,
de
,
newptr
);
dictSetVal
(
d
,
de
,
newptr
);
}
}
}
}
/* Defrag a dict with sds key and optional value (either ptr, sds or robj string) */
/* Defrag a dict with sds key and optional value (either ptr, sds or robj string) */
long
activeDefragSdsDict
(
dict
*
d
,
int
val_type
)
{
void
activeDefragSdsDict
(
dict
*
d
,
int
val_type
)
{
activeDefragSdsDictData
data
=
{
d
,
val_type
,
0
};
activeDefragSdsDictData
data
=
{
d
,
val_type
};
unsigned
long
cursor
=
0
;
unsigned
long
cursor
=
0
;
do
{
do
{
cursor
=
dictScanDefrag
(
d
,
cursor
,
activeDefragSdsDictCallback
,
cursor
=
dictScanDefrag
(
d
,
cursor
,
activeDefragSdsDictCallback
,
activeDefragAlloc
,
&
data
);
activeDefragAlloc
,
&
data
);
}
while
(
cursor
!=
0
);
}
while
(
cursor
!=
0
);
return
data
.
defragged
;
}
}
/* Defrag a list of ptr, sds or robj string values */
/* Defrag a list of ptr, sds or robj string values */
long
activeDefragList
(
list
*
l
,
int
val_type
)
{
void
activeDefragList
(
list
*
l
,
int
val_type
)
{
long
defragged
=
0
;
listNode
*
ln
,
*
newln
;
listNode
*
ln
,
*
newln
;
for
(
ln
=
l
->
head
;
ln
;
ln
=
ln
->
next
)
{
for
(
ln
=
l
->
head
;
ln
;
ln
=
ln
->
next
)
{
if
((
newln
=
activeDefragAlloc
(
ln
)))
{
if
((
newln
=
activeDefragAlloc
(
ln
)))
{
...
@@ -306,28 +295,25 @@ long activeDefragList(list *l, int val_type) {
...
@@ -306,28 +295,25 @@ long activeDefragList(list *l, int val_type) {
else
else
l
->
tail
=
newln
;
l
->
tail
=
newln
;
ln
=
newln
;
ln
=
newln
;
defragged
++
;
}
}
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_IS_SDS
)
{
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_IS_SDS
)
{
sds
newsds
,
sdsele
=
ln
->
value
;
sds
newsds
,
sdsele
=
ln
->
value
;
if
((
newsds
=
activeDefragSds
(
sdsele
)))
if
((
newsds
=
activeDefragSds
(
sdsele
)))
ln
->
value
=
newsds
,
defragged
++
;
ln
->
value
=
newsds
;
}
else
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_IS_STROB
)
{
}
else
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_IS_STROB
)
{
robj
*
newele
,
*
ele
=
ln
->
value
;
robj
*
newele
,
*
ele
=
ln
->
value
;
if
((
newele
=
activeDefragStringOb
(
ele
,
&
defragged
)))
if
((
newele
=
activeDefragStringOb
(
ele
)))
ln
->
value
=
newele
;
ln
->
value
=
newele
;
}
else
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_VOID_PTR
)
{
}
else
if
(
val_type
==
DEFRAG_SDS_DICT_VAL_VOID_PTR
)
{
void
*
newptr
,
*
ptr
=
ln
->
value
;
void
*
newptr
,
*
ptr
=
ln
->
value
;
if
((
newptr
=
activeDefragAlloc
(
ptr
)))
if
((
newptr
=
activeDefragAlloc
(
ptr
)))
ln
->
value
=
newptr
,
defragged
++
;
ln
->
value
=
newptr
;
}
}
}
}
return
defragged
;
}
}
long
activeDefragQuickListNode
(
quicklist
*
ql
,
quicklistNode
**
node_ref
)
{
void
activeDefragQuickListNode
(
quicklist
*
ql
,
quicklistNode
**
node_ref
)
{
quicklistNode
*
newnode
,
*
node
=
*
node_ref
;
quicklistNode
*
newnode
,
*
node
=
*
node_ref
;
long
defragged
=
0
;
unsigned
char
*
newzl
;
unsigned
char
*
newzl
;
if
((
newnode
=
activeDefragAlloc
(
node
)))
{
if
((
newnode
=
activeDefragAlloc
(
node
)))
{
if
(
newnode
->
prev
)
if
(
newnode
->
prev
)
...
@@ -339,21 +325,17 @@ long activeDefragQuickListNode(quicklist *ql, quicklistNode **node_ref) {
...
@@ -339,21 +325,17 @@ long activeDefragQuickListNode(quicklist *ql, quicklistNode **node_ref) {
else
else
ql
->
tail
=
newnode
;
ql
->
tail
=
newnode
;
*
node_ref
=
node
=
newnode
;
*
node_ref
=
node
=
newnode
;
defragged
++
;
}
}
if
((
newzl
=
activeDefragAlloc
(
node
->
entry
)))
if
((
newzl
=
activeDefragAlloc
(
node
->
entry
)))
defragged
++
,
node
->
entry
=
newzl
;
node
->
entry
=
newzl
;
return
defragged
;
}
}
long
activeDefragQuickListNodes
(
quicklist
*
ql
)
{
void
activeDefragQuickListNodes
(
quicklist
*
ql
)
{
quicklistNode
*
node
=
ql
->
head
;
quicklistNode
*
node
=
ql
->
head
;
long
defragged
=
0
;
while
(
node
)
{
while
(
node
)
{
defragged
+=
activeDefragQuickListNode
(
ql
,
&
node
);
activeDefragQuickListNode
(
ql
,
&
node
);
node
=
node
->
next
;
node
=
node
->
next
;
}
}
return
defragged
;
}
}
/* when the value has lots of elements, we want to handle it later and not as
/* when the value has lots of elements, we want to handle it later and not as
...
@@ -365,7 +347,7 @@ void defragLater(redisDb *db, dictEntry *kde) {
...
@@ -365,7 +347,7 @@ void defragLater(redisDb *db, dictEntry *kde) {
}
}
/* returns 0 if no more work needs to be been done, and 1 if time is up and more work is needed. */
/* returns 0 if no more work needs to be been done, and 1 if time is up and more work is needed. */
long
scanLaterList
(
robj
*
ob
,
unsigned
long
*
cursor
,
long
long
endtime
,
long
long
*
defragged
)
{
long
scanLaterList
(
robj
*
ob
,
unsigned
long
*
cursor
,
long
long
endtime
)
{
quicklist
*
ql
=
ob
->
ptr
;
quicklist
*
ql
=
ob
->
ptr
;
quicklistNode
*
node
;
quicklistNode
*
node
;
long
iterations
=
0
;
long
iterations
=
0
;
...
@@ -388,7 +370,7 @@ long scanLaterList(robj *ob, unsigned long *cursor, long long endtime, long long
...
@@ -388,7 +370,7 @@ long scanLaterList(robj *ob, unsigned long *cursor, long long endtime, long long
(
*
cursor
)
++
;
(
*
cursor
)
++
;
while
(
node
)
{
while
(
node
)
{
(
*
defragged
)
+=
activeDefragQuickListNode
(
ql
,
&
node
);
activeDefragQuickListNode
(
ql
,
&
node
);
server
.
stat_active_defrag_scanned
++
;
server
.
stat_active_defrag_scanned
++
;
if
(
++
iterations
>
128
&&
!
bookmark_failed
)
{
if
(
++
iterations
>
128
&&
!
bookmark_failed
)
{
if
(
ustime
()
>
endtime
)
{
if
(
ustime
()
>
endtime
)
{
...
@@ -410,29 +392,26 @@ long scanLaterList(robj *ob, unsigned long *cursor, long long endtime, long long
...
@@ -410,29 +392,26 @@ long scanLaterList(robj *ob, unsigned long *cursor, long long endtime, long long
typedef
struct
{
typedef
struct
{
zset
*
zs
;
zset
*
zs
;
long
defragged
;
}
scanLaterZsetData
;
}
scanLaterZsetData
;
void
scanLaterZsetCallback
(
void
*
privdata
,
const
dictEntry
*
_de
)
{
void
scanLaterZsetCallback
(
void
*
privdata
,
const
dictEntry
*
_de
)
{
dictEntry
*
de
=
(
dictEntry
*
)
_de
;
dictEntry
*
de
=
(
dictEntry
*
)
_de
;
scanLaterZsetData
*
data
=
privdata
;
scanLaterZsetData
*
data
=
privdata
;
data
->
defragged
+=
activeDefragZsetEntry
(
data
->
zs
,
de
);
activeDefragZsetEntry
(
data
->
zs
,
de
);
server
.
stat_active_defrag_scanned
++
;
server
.
stat_active_defrag_scanned
++
;
}
}
long
scanLaterZset
(
robj
*
ob
,
unsigned
long
*
cursor
)
{
void
scanLaterZset
(
robj
*
ob
,
unsigned
long
*
cursor
)
{
if
(
ob
->
type
!=
OBJ_ZSET
||
ob
->
encoding
!=
OBJ_ENCODING_SKIPLIST
)
if
(
ob
->
type
!=
OBJ_ZSET
||
ob
->
encoding
!=
OBJ_ENCODING_SKIPLIST
)
return
0
;
return
;
zset
*
zs
=
(
zset
*
)
ob
->
ptr
;
zset
*
zs
=
(
zset
*
)
ob
->
ptr
;
dict
*
d
=
zs
->
dict
;
dict
*
d
=
zs
->
dict
;
scanLaterZsetData
data
=
{
zs
,
0
};
scanLaterZsetData
data
=
{
zs
};
*
cursor
=
dictScanDefrag
(
d
,
*
cursor
,
scanLaterZsetCallback
,
activeDefragAlloc
,
&
data
);
*
cursor
=
dictScanDefrag
(
d
,
*
cursor
,
scanLaterZsetCallback
,
activeDefragAlloc
,
&
data
);
return
data
.
defragged
;
}
}
typedef
struct
{
typedef
struct
{
dict
*
dict
;
dict
*
dict
;
long
defragged
;
}
scanLaterDictData
;
}
scanLaterDictData
;
void
scanLaterSetCallback
(
void
*
privdata
,
const
dictEntry
*
_de
)
{
void
scanLaterSetCallback
(
void
*
privdata
,
const
dictEntry
*
_de
)
{
...
@@ -440,17 +419,16 @@ void scanLaterSetCallback(void *privdata, const dictEntry *_de) {
...
@@ -440,17 +419,16 @@ void scanLaterSetCallback(void *privdata, const dictEntry *_de) {
scanLaterDictData
*
data
=
privdata
;
scanLaterDictData
*
data
=
privdata
;
sds
sdsele
=
dictGetKey
(
de
),
newsds
;
sds
sdsele
=
dictGetKey
(
de
),
newsds
;
if
((
newsds
=
activeDefragSds
(
sdsele
)))
if
((
newsds
=
activeDefragSds
(
sdsele
)))
data
->
defragged
++
,
dictSetKey
(
data
->
dict
,
de
,
newsds
);
dictSetKey
(
data
->
dict
,
de
,
newsds
);
server
.
stat_active_defrag_scanned
++
;
server
.
stat_active_defrag_scanned
++
;
}
}
long
scanLaterSet
(
robj
*
ob
,
unsigned
long
*
cursor
)
{
void
scanLaterSet
(
robj
*
ob
,
unsigned
long
*
cursor
)
{
if
(
ob
->
type
!=
OBJ_SET
||
ob
->
encoding
!=
OBJ_ENCODING_HT
)
if
(
ob
->
type
!=
OBJ_SET
||
ob
->
encoding
!=
OBJ_ENCODING_HT
)
return
0
;
return
;
dict
*
d
=
ob
->
ptr
;
dict
*
d
=
ob
->
ptr
;
scanLaterDictData
data
=
{
d
,
0
};
scanLaterDictData
data
=
{
d
};
*
cursor
=
dictScanDefrag
(
d
,
*
cursor
,
scanLaterSetCallback
,
activeDefragAlloc
,
&
data
);
*
cursor
=
dictScanDefrag
(
d
,
*
cursor
,
scanLaterSetCallback
,
activeDefragAlloc
,
&
data
);
return
data
.
defragged
;
}
}
void
scanLaterHashCallback
(
void
*
privdata
,
const
dictEntry
*
_de
)
{
void
scanLaterHashCallback
(
void
*
privdata
,
const
dictEntry
*
_de
)
{
...
@@ -458,39 +436,35 @@ void scanLaterHashCallback(void *privdata, const dictEntry *_de) {
...
@@ -458,39 +436,35 @@ void scanLaterHashCallback(void *privdata, const dictEntry *_de) {
scanLaterDictData
*
data
=
privdata
;
scanLaterDictData
*
data
=
privdata
;
sds
sdsele
=
dictGetKey
(
de
),
newsds
;
sds
sdsele
=
dictGetKey
(
de
),
newsds
;
if
((
newsds
=
activeDefragSds
(
sdsele
)))
if
((
newsds
=
activeDefragSds
(
sdsele
)))
data
->
defragged
++
,
dictSetKey
(
data
->
dict
,
de
,
newsds
);
dictSetKey
(
data
->
dict
,
de
,
newsds
);
sdsele
=
dictGetVal
(
de
);
sdsele
=
dictGetVal
(
de
);
if
((
newsds
=
activeDefragSds
(
sdsele
)))
if
((
newsds
=
activeDefragSds
(
sdsele
)))
data
->
defragged
++
,
dictSetVal
(
data
->
dict
,
de
,
newsds
);
dictSetVal
(
data
->
dict
,
de
,
newsds
);
server
.
stat_active_defrag_scanned
++
;
server
.
stat_active_defrag_scanned
++
;
}
}
long
scanLaterHash
(
robj
*
ob
,
unsigned
long
*
cursor
)
{
void
scanLaterHash
(
robj
*
ob
,
unsigned
long
*
cursor
)
{
if
(
ob
->
type
!=
OBJ_HASH
||
ob
->
encoding
!=
OBJ_ENCODING_HT
)
if
(
ob
->
type
!=
OBJ_HASH
||
ob
->
encoding
!=
OBJ_ENCODING_HT
)
return
0
;
return
;
dict
*
d
=
ob
->
ptr
;
dict
*
d
=
ob
->
ptr
;
scanLaterDictData
data
=
{
d
,
0
};
scanLaterDictData
data
=
{
d
};
*
cursor
=
dictScanDefrag
(
d
,
*
cursor
,
scanLaterHashCallback
,
activeDefragAlloc
,
&
data
);
*
cursor
=
dictScanDefrag
(
d
,
*
cursor
,
scanLaterHashCallback
,
activeDefragAlloc
,
&
data
);
return
data
.
defragged
;
}
}
long
defragQuicklist
(
redisDb
*
db
,
dictEntry
*
kde
)
{
void
defragQuicklist
(
redisDb
*
db
,
dictEntry
*
kde
)
{
robj
*
ob
=
dictGetVal
(
kde
);
robj
*
ob
=
dictGetVal
(
kde
);
long
defragged
=
0
;
quicklist
*
ql
=
ob
->
ptr
,
*
newql
;
quicklist
*
ql
=
ob
->
ptr
,
*
newql
;
serverAssert
(
ob
->
type
==
OBJ_LIST
&&
ob
->
encoding
==
OBJ_ENCODING_QUICKLIST
);
serverAssert
(
ob
->
type
==
OBJ_LIST
&&
ob
->
encoding
==
OBJ_ENCODING_QUICKLIST
);
if
((
newql
=
activeDefragAlloc
(
ql
)))
if
((
newql
=
activeDefragAlloc
(
ql
)))
defragged
++
,
ob
->
ptr
=
ql
=
newql
;
ob
->
ptr
=
ql
=
newql
;
if
(
ql
->
len
>
server
.
active_defrag_max_scan_fields
)
if
(
ql
->
len
>
server
.
active_defrag_max_scan_fields
)
defragLater
(
db
,
kde
);
defragLater
(
db
,
kde
);
else
else
defragged
+=
activeDefragQuickListNodes
(
ql
);
activeDefragQuickListNodes
(
ql
);
return
defragged
;
}
}
long
defragZsetSkiplist
(
redisDb
*
db
,
dictEntry
*
kde
)
{
void
defragZsetSkiplist
(
redisDb
*
db
,
dictEntry
*
kde
)
{
robj
*
ob
=
dictGetVal
(
kde
);
robj
*
ob
=
dictGetVal
(
kde
);
long
defragged
=
0
;
zset
*
zs
=
(
zset
*
)
ob
->
ptr
;
zset
*
zs
=
(
zset
*
)
ob
->
ptr
;
zset
*
newzs
;
zset
*
newzs
;
zskiplist
*
newzsl
;
zskiplist
*
newzsl
;
...
@@ -499,30 +473,28 @@ long defragZsetSkiplist(redisDb *db, dictEntry *kde) {
...
@@ -499,30 +473,28 @@ long defragZsetSkiplist(redisDb *db, dictEntry *kde) {
struct
zskiplistNode
*
newheader
;
struct
zskiplistNode
*
newheader
;
serverAssert
(
ob
->
type
==
OBJ_ZSET
&&
ob
->
encoding
==
OBJ_ENCODING_SKIPLIST
);
serverAssert
(
ob
->
type
==
OBJ_ZSET
&&
ob
->
encoding
==
OBJ_ENCODING_SKIPLIST
);
if
((
newzs
=
activeDefragAlloc
(
zs
)))
if
((
newzs
=
activeDefragAlloc
(
zs
)))
defragged
++
,
ob
->
ptr
=
zs
=
newzs
;
ob
->
ptr
=
zs
=
newzs
;
if
((
newzsl
=
activeDefragAlloc
(
zs
->
zsl
)))
if
((
newzsl
=
activeDefragAlloc
(
zs
->
zsl
)))
defragged
++
,
zs
->
zsl
=
newzsl
;
zs
->
zsl
=
newzsl
;
if
((
newheader
=
activeDefragAlloc
(
zs
->
zsl
->
header
)))
if
((
newheader
=
activeDefragAlloc
(
zs
->
zsl
->
header
)))
defragged
++
,
zs
->
zsl
->
header
=
newheader
;
zs
->
zsl
->
header
=
newheader
;
if
(
dictSize
(
zs
->
dict
)
>
server
.
active_defrag_max_scan_fields
)
if
(
dictSize
(
zs
->
dict
)
>
server
.
active_defrag_max_scan_fields
)
defragLater
(
db
,
kde
);
defragLater
(
db
,
kde
);
else
{
else
{
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
defragged
+=
activeDefragZsetEntry
(
zs
,
de
);
activeDefragZsetEntry
(
zs
,
de
);
}
}
dictReleaseIterator
(
di
);
dictReleaseIterator
(
di
);
}
}
/* handle the dict struct */
/* handle the dict struct */
if
((
newdict
=
activeDefragAlloc
(
zs
->
dict
)))
if
((
newdict
=
activeDefragAlloc
(
zs
->
dict
)))
defragged
++
,
zs
->
dict
=
newdict
;
zs
->
dict
=
newdict
;
/* defrag the dict tables */
/* defrag the dict tables */
defragged
+=
dictDefragTables
(
zs
->
dict
);
dictDefragTables
(
zs
->
dict
);
return
defragged
;
}
}
long
defragHash
(
redisDb
*
db
,
dictEntry
*
kde
)
{
void
defragHash
(
redisDb
*
db
,
dictEntry
*
kde
)
{
long
defragged
=
0
;
robj
*
ob
=
dictGetVal
(
kde
);
robj
*
ob
=
dictGetVal
(
kde
);
dict
*
d
,
*
newd
;
dict
*
d
,
*
newd
;
serverAssert
(
ob
->
type
==
OBJ_HASH
&&
ob
->
encoding
==
OBJ_ENCODING_HT
);
serverAssert
(
ob
->
type
==
OBJ_HASH
&&
ob
->
encoding
==
OBJ_ENCODING_HT
);
...
@@ -530,17 +502,15 @@ long defragHash(redisDb *db, dictEntry *kde) {
...
@@ -530,17 +502,15 @@ long defragHash(redisDb *db, dictEntry *kde) {
if
(
dictSize
(
d
)
>
server
.
active_defrag_max_scan_fields
)
if
(
dictSize
(
d
)
>
server
.
active_defrag_max_scan_fields
)
defragLater
(
db
,
kde
);
defragLater
(
db
,
kde
);
else
else
defragged
+=
activeDefragSdsDict
(
d
,
DEFRAG_SDS_DICT_VAL_IS_SDS
);
activeDefragSdsDict
(
d
,
DEFRAG_SDS_DICT_VAL_IS_SDS
);
/* handle the dict struct */
/* handle the dict struct */
if
((
newd
=
activeDefragAlloc
(
ob
->
ptr
)))
if
((
newd
=
activeDefragAlloc
(
ob
->
ptr
)))
defragged
++
,
ob
->
ptr
=
newd
;
ob
->
ptr
=
newd
;
/* defrag the dict tables */
/* defrag the dict tables */
defragged
+=
dictDefragTables
(
ob
->
ptr
);
dictDefragTables
(
ob
->
ptr
);
return
defragged
;
}
}
long
defragSet
(
redisDb
*
db
,
dictEntry
*
kde
)
{
void
defragSet
(
redisDb
*
db
,
dictEntry
*
kde
)
{
long
defragged
=
0
;
robj
*
ob
=
dictGetVal
(
kde
);
robj
*
ob
=
dictGetVal
(
kde
);
dict
*
d
,
*
newd
;
dict
*
d
,
*
newd
;
serverAssert
(
ob
->
type
==
OBJ_SET
&&
ob
->
encoding
==
OBJ_ENCODING_HT
);
serverAssert
(
ob
->
type
==
OBJ_SET
&&
ob
->
encoding
==
OBJ_ENCODING_HT
);
...
@@ -548,13 +518,12 @@ long defragSet(redisDb *db, dictEntry *kde) {
...
@@ -548,13 +518,12 @@ long defragSet(redisDb *db, dictEntry *kde) {
if
(
dictSize
(
d
)
>
server
.
active_defrag_max_scan_fields
)
if
(
dictSize
(
d
)
>
server
.
active_defrag_max_scan_fields
)
defragLater
(
db
,
kde
);
defragLater
(
db
,
kde
);
else
else
defragged
+=
activeDefragSdsDict
(
d
,
DEFRAG_SDS_DICT_NO_VAL
);
activeDefragSdsDict
(
d
,
DEFRAG_SDS_DICT_NO_VAL
);
/* handle the dict struct */
/* handle the dict struct */
if
((
newd
=
activeDefragAlloc
(
ob
->
ptr
)))
if
((
newd
=
activeDefragAlloc
(
ob
->
ptr
)))
defragged
++
,
ob
->
ptr
=
newd
;
ob
->
ptr
=
newd
;
/* defrag the dict tables */
/* defrag the dict tables */
defragged
+=
dictDefragTables
(
ob
->
ptr
);
dictDefragTables
(
ob
->
ptr
);
return
defragged
;
}
}
/* Defrag callback for radix tree iterator, called for each node,
/* Defrag callback for radix tree iterator, called for each node,
...
@@ -569,7 +538,7 @@ int defragRaxNode(raxNode **noderef) {
...
@@ -569,7 +538,7 @@ int defragRaxNode(raxNode **noderef) {
}
}
/* returns 0 if no more work needs to be been done, and 1 if time is up and more work is needed. */
/* returns 0 if no more work needs to be been done, and 1 if time is up and more work is needed. */
int
scanLaterStreamListpacks
(
robj
*
ob
,
unsigned
long
*
cursor
,
long
long
endtime
,
long
long
*
defragged
)
{
int
scanLaterStreamListpacks
(
robj
*
ob
,
unsigned
long
*
cursor
,
long
long
endtime
)
{
static
unsigned
char
last
[
sizeof
(
streamID
)];
static
unsigned
char
last
[
sizeof
(
streamID
)];
raxIterator
ri
;
raxIterator
ri
;
long
iterations
=
0
;
long
iterations
=
0
;
...
@@ -603,7 +572,7 @@ int scanLaterStreamListpacks(robj *ob, unsigned long *cursor, long long endtime,
...
@@ -603,7 +572,7 @@ int scanLaterStreamListpacks(robj *ob, unsigned long *cursor, long long endtime,
while
(
raxNext
(
&
ri
))
{
while
(
raxNext
(
&
ri
))
{
void
*
newdata
=
activeDefragAlloc
(
ri
.
data
);
void
*
newdata
=
activeDefragAlloc
(
ri
.
data
);
if
(
newdata
)
if
(
newdata
)
raxSetData
(
ri
.
node
,
ri
.
data
=
newdata
)
,
(
*
defragged
)
++
;
raxSetData
(
ri
.
node
,
ri
.
data
=
newdata
);
server
.
stat_active_defrag_scanned
++
;
server
.
stat_active_defrag_scanned
++
;
if
(
++
iterations
>
128
)
{
if
(
++
iterations
>
128
)
{
if
(
ustime
()
>
endtime
)
{
if
(
ustime
()
>
endtime
)
{
...
@@ -621,19 +590,18 @@ int scanLaterStreamListpacks(robj *ob, unsigned long *cursor, long long endtime,
...
@@ -621,19 +590,18 @@ int scanLaterStreamListpacks(robj *ob, unsigned long *cursor, long long endtime,
}
}
/* optional callback used defrag each rax element (not including the element pointer itself) */
/* optional callback used defrag each rax element (not including the element pointer itself) */
typedef
void
*
(
raxDefragFunction
)(
raxIterator
*
ri
,
void
*
privdata
,
long
*
defragged
);
typedef
void
*
(
raxDefragFunction
)(
raxIterator
*
ri
,
void
*
privdata
);
/* defrag radix tree including:
/* defrag radix tree including:
* 1) rax struct
* 1) rax struct
* 2) rax nodes
* 2) rax nodes
* 3) rax entry data (only if defrag_data is specified)
* 3) rax entry data (only if defrag_data is specified)
* 4) call a callback per element, and allow the callback to return a new pointer for the element */
* 4) call a callback per element, and allow the callback to return a new pointer for the element */
long
defragRadixTree
(
rax
**
raxref
,
int
defrag_data
,
raxDefragFunction
*
element_cb
,
void
*
element_cb_data
)
{
void
defragRadixTree
(
rax
**
raxref
,
int
defrag_data
,
raxDefragFunction
*
element_cb
,
void
*
element_cb_data
)
{
long
defragged
=
0
;
raxIterator
ri
;
raxIterator
ri
;
rax
*
rax
;
rax
*
rax
;
if
((
rax
=
activeDefragAlloc
(
*
raxref
)))
if
((
rax
=
activeDefragAlloc
(
*
raxref
)))
defragged
++
,
*
raxref
=
rax
;
*
raxref
=
rax
;
rax
=
*
raxref
;
rax
=
*
raxref
;
raxStart
(
&
ri
,
rax
);
raxStart
(
&
ri
,
rax
);
ri
.
node_cb
=
defragRaxNode
;
ri
.
node_cb
=
defragRaxNode
;
...
@@ -642,14 +610,13 @@ long defragRadixTree(rax **raxref, int defrag_data, raxDefragFunction *element_c
...
@@ -642,14 +610,13 @@ long defragRadixTree(rax **raxref, int defrag_data, raxDefragFunction *element_c
while
(
raxNext
(
&
ri
))
{
while
(
raxNext
(
&
ri
))
{
void
*
newdata
=
NULL
;
void
*
newdata
=
NULL
;
if
(
element_cb
)
if
(
element_cb
)
newdata
=
element_cb
(
&
ri
,
element_cb_data
,
&
defragged
);
newdata
=
element_cb
(
&
ri
,
element_cb_data
);
if
(
defrag_data
&&
!
newdata
)
if
(
defrag_data
&&
!
newdata
)
newdata
=
activeDefragAlloc
(
ri
.
data
);
newdata
=
activeDefragAlloc
(
ri
.
data
);
if
(
newdata
)
if
(
newdata
)
raxSetData
(
ri
.
node
,
ri
.
data
=
newdata
)
,
defragged
++
;
raxSetData
(
ri
.
node
,
ri
.
data
=
newdata
);
}
}
raxStop
(
&
ri
);
raxStop
(
&
ri
);
return
defragged
;
}
}
typedef
struct
{
typedef
struct
{
...
@@ -657,8 +624,7 @@ typedef struct {
...
@@ -657,8 +624,7 @@ typedef struct {
streamConsumer
*
c
;
streamConsumer
*
c
;
}
PendingEntryContext
;
}
PendingEntryContext
;
void
*
defragStreamConsumerPendingEntry
(
raxIterator
*
ri
,
void
*
privdata
,
long
*
defragged
)
{
void
*
defragStreamConsumerPendingEntry
(
raxIterator
*
ri
,
void
*
privdata
)
{
UNUSED
(
defragged
);
PendingEntryContext
*
ctx
=
privdata
;
PendingEntryContext
*
ctx
=
privdata
;
streamNACK
*
nack
=
ri
->
data
,
*
newnack
;
streamNACK
*
nack
=
ri
->
data
,
*
newnack
;
nack
->
consumer
=
ctx
->
c
;
/* update nack pointer to consumer */
nack
->
consumer
=
ctx
->
c
;
/* update nack pointer to consumer */
...
@@ -668,90 +634,81 @@ void* defragStreamConsumerPendingEntry(raxIterator *ri, void *privdata, long *de
...
@@ -668,90 +634,81 @@ void* defragStreamConsumerPendingEntry(raxIterator *ri, void *privdata, long *de
void
*
prev
;
void
*
prev
;
raxInsert
(
ctx
->
cg
->
pel
,
ri
->
key
,
ri
->
key_len
,
newnack
,
&
prev
);
raxInsert
(
ctx
->
cg
->
pel
,
ri
->
key
,
ri
->
key_len
,
newnack
,
&
prev
);
serverAssert
(
prev
==
nack
);
serverAssert
(
prev
==
nack
);
/* note: we don't increment 'defragged' that's done by the caller */
}
}
return
newnack
;
return
newnack
;
}
}
void
*
defragStreamConsumer
(
raxIterator
*
ri
,
void
*
privdata
,
long
*
defragged
)
{
void
*
defragStreamConsumer
(
raxIterator
*
ri
,
void
*
privdata
)
{
streamConsumer
*
c
=
ri
->
data
;
streamConsumer
*
c
=
ri
->
data
;
streamCG
*
cg
=
privdata
;
streamCG
*
cg
=
privdata
;
void
*
newc
=
activeDefragAlloc
(
c
);
void
*
newc
=
activeDefragAlloc
(
c
);
if
(
newc
)
{
if
(
newc
)
{
/* note: we don't increment 'defragged' that's done by the caller */
c
=
newc
;
c
=
newc
;
}
}
sds
newsds
=
activeDefragSds
(
c
->
name
);
sds
newsds
=
activeDefragSds
(
c
->
name
);
if
(
newsds
)
if
(
newsds
)
(
*
defragged
)
++
,
c
->
name
=
newsds
;
c
->
name
=
newsds
;
if
(
c
->
pel
)
{
if
(
c
->
pel
)
{
PendingEntryContext
pel_ctx
=
{
cg
,
c
};
PendingEntryContext
pel_ctx
=
{
cg
,
c
};
*
defragged
+=
defragRadixTree
(
&
c
->
pel
,
0
,
defragStreamConsumerPendingEntry
,
&
pel_ctx
);
defragRadixTree
(
&
c
->
pel
,
0
,
defragStreamConsumerPendingEntry
,
&
pel_ctx
);
}
}
return
newc
;
/* returns NULL if c was not defragged */
return
newc
;
/* returns NULL if c was not defragged */
}
}
void
*
defragStreamConsumerGroup
(
raxIterator
*
ri
,
void
*
privdata
,
long
*
defragged
)
{
void
*
defragStreamConsumerGroup
(
raxIterator
*
ri
,
void
*
privdata
)
{
streamCG
*
cg
=
ri
->
data
;
streamCG
*
cg
=
ri
->
data
;
UNUSED
(
privdata
);
UNUSED
(
privdata
);
if
(
cg
->
consumers
)
if
(
cg
->
consumers
)
*
defragged
+=
defragRadixTree
(
&
cg
->
consumers
,
0
,
defragStreamConsumer
,
cg
);
defragRadixTree
(
&
cg
->
consumers
,
0
,
defragStreamConsumer
,
cg
);
if
(
cg
->
pel
)
if
(
cg
->
pel
)
*
defragged
+=
defragRadixTree
(
&
cg
->
pel
,
0
,
NULL
,
NULL
);
defragRadixTree
(
&
cg
->
pel
,
0
,
NULL
,
NULL
);
return
NULL
;
return
NULL
;
}
}
long
defragStream
(
redisDb
*
db
,
dictEntry
*
kde
)
{
void
defragStream
(
redisDb
*
db
,
dictEntry
*
kde
)
{
long
defragged
=
0
;
robj
*
ob
=
dictGetVal
(
kde
);
robj
*
ob
=
dictGetVal
(
kde
);
serverAssert
(
ob
->
type
==
OBJ_STREAM
&&
ob
->
encoding
==
OBJ_ENCODING_STREAM
);
serverAssert
(
ob
->
type
==
OBJ_STREAM
&&
ob
->
encoding
==
OBJ_ENCODING_STREAM
);
stream
*
s
=
ob
->
ptr
,
*
news
;
stream
*
s
=
ob
->
ptr
,
*
news
;
/* handle the main struct */
/* handle the main struct */
if
((
news
=
activeDefragAlloc
(
s
)))
if
((
news
=
activeDefragAlloc
(
s
)))
defragged
++
,
ob
->
ptr
=
s
=
news
;
ob
->
ptr
=
s
=
news
;
if
(
raxSize
(
s
->
rax
)
>
server
.
active_defrag_max_scan_fields
)
{
if
(
raxSize
(
s
->
rax
)
>
server
.
active_defrag_max_scan_fields
)
{
rax
*
newrax
=
activeDefragAlloc
(
s
->
rax
);
rax
*
newrax
=
activeDefragAlloc
(
s
->
rax
);
if
(
newrax
)
if
(
newrax
)
defragged
++
,
s
->
rax
=
newrax
;
s
->
rax
=
newrax
;
defragLater
(
db
,
kde
);
defragLater
(
db
,
kde
);
}
else
}
else
defragged
+=
defragRadixTree
(
&
s
->
rax
,
1
,
NULL
,
NULL
);
defragRadixTree
(
&
s
->
rax
,
1
,
NULL
,
NULL
);
if
(
s
->
cgroups
)
if
(
s
->
cgroups
)
defragged
+=
defragRadixTree
(
&
s
->
cgroups
,
1
,
defragStreamConsumerGroup
,
NULL
);
defragRadixTree
(
&
s
->
cgroups
,
1
,
defragStreamConsumerGroup
,
NULL
);
return
defragged
;
}
}
/* Defrag a module key. This is either done immediately or scheduled
/* Defrag a module key. This is either done immediately or scheduled
* for later. Returns then number of pointers defragged.
* for later. Returns then number of pointers defragged.
*/
*/
long
defragModule
(
redisDb
*
db
,
dictEntry
*
kde
)
{
void
defragModule
(
redisDb
*
db
,
dictEntry
*
kde
)
{
robj
*
obj
=
dictGetVal
(
kde
);
robj
*
obj
=
dictGetVal
(
kde
);
serverAssert
(
obj
->
type
==
OBJ_MODULE
);
serverAssert
(
obj
->
type
==
OBJ_MODULE
);
long
defragged
=
0
;
if
(
!
moduleDefragValue
(
dictGetKey
(
kde
),
obj
,
&
defragged
,
db
->
id
))
if
(
!
moduleDefragValue
(
dictGetKey
(
kde
),
obj
,
db
->
id
))
defragLater
(
db
,
kde
);
defragLater
(
db
,
kde
);
return
defragged
;
}
}
/* for each key we scan in the main dict, this function will attempt to defrag
/* for each key we scan in the main dict, this function will attempt to defrag
* all the various pointers it has. Returns a stat of how many pointers were
* all the various pointers it has. Returns a stat of how many pointers were
* moved. */
* moved. */
long
defragKey
(
redisDb
*
db
,
dictEntry
*
de
)
{
void
defragKey
(
redisDb
*
db
,
dictEntry
*
de
)
{
sds
keysds
=
dictGetKey
(
de
);
sds
keysds
=
dictGetKey
(
de
);
robj
*
newob
,
*
ob
;
robj
*
newob
,
*
ob
;
unsigned
char
*
newzl
;
unsigned
char
*
newzl
;
long
defragged
=
0
;
sds
newsds
;
sds
newsds
;
/* Try to defrag the key name. */
/* Try to defrag the key name. */
newsds
=
activeDefragSds
(
keysds
);
newsds
=
activeDefragSds
(
keysds
);
if
(
newsds
)
{
if
(
newsds
)
{
defragged
++
;
dictSetKey
(
db
->
dict
,
de
,
newsds
);
dictSetKey
(
db
->
dict
,
de
,
newsds
);
if
(
dictSize
(
db
->
expires
))
{
if
(
dictSize
(
db
->
expires
))
{
/* We can't search in db->expires for that key after we've released
/* We can't search in db->expires for that key after we've released
...
@@ -765,7 +722,7 @@ long defragKey(redisDb *db, dictEntry *de) {
...
@@ -765,7 +722,7 @@ long defragKey(redisDb *db, dictEntry *de) {
/* Try to defrag robj and / or string value. */
/* Try to defrag robj and / or string value. */
ob
=
dictGetVal
(
de
);
ob
=
dictGetVal
(
de
);
if
((
newob
=
activeDefragStringOb
(
ob
,
&
defragged
)))
{
if
((
newob
=
activeDefragStringOb
(
ob
)))
{
dictSetVal
(
db
->
dict
,
de
,
newob
);
dictSetVal
(
db
->
dict
,
de
,
newob
);
ob
=
newob
;
ob
=
newob
;
}
}
...
@@ -774,58 +731,57 @@ long defragKey(redisDb *db, dictEntry *de) {
...
@@ -774,58 +731,57 @@ long defragKey(redisDb *db, dictEntry *de) {
/* Already handled in activeDefragStringOb. */
/* Already handled in activeDefragStringOb. */
}
else
if
(
ob
->
type
==
OBJ_LIST
)
{
}
else
if
(
ob
->
type
==
OBJ_LIST
)
{
if
(
ob
->
encoding
==
OBJ_ENCODING_QUICKLIST
)
{
if
(
ob
->
encoding
==
OBJ_ENCODING_QUICKLIST
)
{
defragged
+=
defragQuicklist
(
db
,
de
);
defragQuicklist
(
db
,
de
);
}
else
if
(
ob
->
encoding
==
OBJ_ENCODING_LISTPACK
)
{
}
else
if
(
ob
->
encoding
==
OBJ_ENCODING_LISTPACK
)
{
if
((
newzl
=
activeDefragAlloc
(
ob
->
ptr
)))
if
((
newzl
=
activeDefragAlloc
(
ob
->
ptr
)))
defragged
++
,
ob
->
ptr
=
newzl
;
ob
->
ptr
=
newzl
;
}
else
{
}
else
{
serverPanic
(
"Unknown list encoding"
);
serverPanic
(
"Unknown list encoding"
);
}
}
}
else
if
(
ob
->
type
==
OBJ_SET
)
{
}
else
if
(
ob
->
type
==
OBJ_SET
)
{
if
(
ob
->
encoding
==
OBJ_ENCODING_HT
)
{
if
(
ob
->
encoding
==
OBJ_ENCODING_HT
)
{
defragged
+=
defragSet
(
db
,
de
);
defragSet
(
db
,
de
);
}
else
if
(
ob
->
encoding
==
OBJ_ENCODING_INTSET
||
}
else
if
(
ob
->
encoding
==
OBJ_ENCODING_INTSET
||
ob
->
encoding
==
OBJ_ENCODING_LISTPACK
)
ob
->
encoding
==
OBJ_ENCODING_LISTPACK
)
{
{
void
*
newptr
,
*
ptr
=
ob
->
ptr
;
void
*
newptr
,
*
ptr
=
ob
->
ptr
;
if
((
newptr
=
activeDefragAlloc
(
ptr
)))
if
((
newptr
=
activeDefragAlloc
(
ptr
)))
defragged
++
,
ob
->
ptr
=
newptr
;
ob
->
ptr
=
newptr
;
}
else
{
}
else
{
serverPanic
(
"Unknown set encoding"
);
serverPanic
(
"Unknown set encoding"
);
}
}
}
else
if
(
ob
->
type
==
OBJ_ZSET
)
{
}
else
if
(
ob
->
type
==
OBJ_ZSET
)
{
if
(
ob
->
encoding
==
OBJ_ENCODING_LISTPACK
)
{
if
(
ob
->
encoding
==
OBJ_ENCODING_LISTPACK
)
{
if
((
newzl
=
activeDefragAlloc
(
ob
->
ptr
)))
if
((
newzl
=
activeDefragAlloc
(
ob
->
ptr
)))
defragged
++
,
ob
->
ptr
=
newzl
;
ob
->
ptr
=
newzl
;
}
else
if
(
ob
->
encoding
==
OBJ_ENCODING_SKIPLIST
)
{
}
else
if
(
ob
->
encoding
==
OBJ_ENCODING_SKIPLIST
)
{
defragged
+=
defragZsetSkiplist
(
db
,
de
);
defragZsetSkiplist
(
db
,
de
);
}
else
{
}
else
{
serverPanic
(
"Unknown sorted set encoding"
);
serverPanic
(
"Unknown sorted set encoding"
);
}
}
}
else
if
(
ob
->
type
==
OBJ_HASH
)
{
}
else
if
(
ob
->
type
==
OBJ_HASH
)
{
if
(
ob
->
encoding
==
OBJ_ENCODING_LISTPACK
)
{
if
(
ob
->
encoding
==
OBJ_ENCODING_LISTPACK
)
{
if
((
newzl
=
activeDefragAlloc
(
ob
->
ptr
)))
if
((
newzl
=
activeDefragAlloc
(
ob
->
ptr
)))
defragged
++
,
ob
->
ptr
=
newzl
;
ob
->
ptr
=
newzl
;
}
else
if
(
ob
->
encoding
==
OBJ_ENCODING_HT
)
{
}
else
if
(
ob
->
encoding
==
OBJ_ENCODING_HT
)
{
defragged
+=
defragHash
(
db
,
de
);
defragHash
(
db
,
de
);
}
else
{
}
else
{
serverPanic
(
"Unknown hash encoding"
);
serverPanic
(
"Unknown hash encoding"
);
}
}
}
else
if
(
ob
->
type
==
OBJ_STREAM
)
{
}
else
if
(
ob
->
type
==
OBJ_STREAM
)
{
defragged
+=
defragStream
(
db
,
de
);
defragStream
(
db
,
de
);
}
else
if
(
ob
->
type
==
OBJ_MODULE
)
{
}
else
if
(
ob
->
type
==
OBJ_MODULE
)
{
defragged
+=
defragModule
(
db
,
de
);
defragModule
(
db
,
de
);
}
else
{
}
else
{
serverPanic
(
"Unknown object type"
);
serverPanic
(
"Unknown object type"
);
}
}
return
defragged
;
}
}
/* Defrag scan callback for the main db dictionary. */
/* Defrag scan callback for the main db dictionary. */
void
defragScanCallback
(
void
*
privdata
,
const
dictEntry
*
de
)
{
void
defragScanCallback
(
void
*
privdata
,
const
dictEntry
*
de
)
{
long
defragged
=
defragKey
((
redisDb
*
)
privdata
,
(
dictEntry
*
)
de
)
;
long
long
hits_before
=
server
.
stat_active_defrag_hits
;
server
.
stat_active_defrag_hits
+=
defragged
;
defragKey
((
redisDb
*
)
privdata
,
(
dictEntry
*
)
de
)
;
if
(
defragged
)
if
(
server
.
stat_active_defrag_hits
!=
hits_before
)
server
.
stat_active_defrag_key_hits
++
;
server
.
stat_active_defrag_key_hits
++
;
else
else
server
.
stat_active_defrag_key_misses
++
;
server
.
stat_active_defrag_key_misses
++
;
...
@@ -863,15 +819,13 @@ float getAllocatorFragmentation(size_t *out_frag_bytes) {
...
@@ -863,15 +819,13 @@ float getAllocatorFragmentation(size_t *out_frag_bytes) {
/* We may need to defrag other globals, one small allocation can hold a full allocator run.
/* We may need to defrag other globals, one small allocation can hold a full allocator run.
* so although small, it is still important to defrag these */
* so although small, it is still important to defrag these */
long
defragOtherGlobals
()
{
void
defragOtherGlobals
()
{
long
defragged
=
0
;
/* there are many more pointers to defrag (e.g. client argv, output / aof buffers, etc.
/* there are many more pointers to defrag (e.g. client argv, output / aof buffers, etc.
* but we assume most of these are short lived, we only need to defrag allocations
* but we assume most of these are short lived, we only need to defrag allocations
* that remain static for a long time */
* that remain static for a long time */
defragged
+=
activeDefragSdsDict
(
evalScriptsDict
(),
DEFRAG_SDS_DICT_VAL_LUA_SCRIPT
);
activeDefragSdsDict
(
evalScriptsDict
(),
DEFRAG_SDS_DICT_VAL_LUA_SCRIPT
);
defragged
+=
moduleDefragGlobals
();
moduleDefragGlobals
();
return
defragged
;
}
}
/* returns 0 more work may or may not be needed (see non-zero cursor),
/* returns 0 more work may or may not be needed (see non-zero cursor),
...
@@ -880,17 +834,17 @@ int defragLaterItem(dictEntry *de, unsigned long *cursor, long long endtime, int
...
@@ -880,17 +834,17 @@ int defragLaterItem(dictEntry *de, unsigned long *cursor, long long endtime, int
if
(
de
)
{
if
(
de
)
{
robj
*
ob
=
dictGetVal
(
de
);
robj
*
ob
=
dictGetVal
(
de
);
if
(
ob
->
type
==
OBJ_LIST
)
{
if
(
ob
->
type
==
OBJ_LIST
)
{
return
scanLaterList
(
ob
,
cursor
,
endtime
,
&
server
.
stat_active_defrag_hits
);
return
scanLaterList
(
ob
,
cursor
,
endtime
);
}
else
if
(
ob
->
type
==
OBJ_SET
)
{
}
else
if
(
ob
->
type
==
OBJ_SET
)
{
server
.
stat_active_defrag_hits
+=
scanLaterSet
(
ob
,
cursor
);
scanLaterSet
(
ob
,
cursor
);
}
else
if
(
ob
->
type
==
OBJ_ZSET
)
{
}
else
if
(
ob
->
type
==
OBJ_ZSET
)
{
server
.
stat_active_defrag_hits
+=
scanLaterZset
(
ob
,
cursor
);
scanLaterZset
(
ob
,
cursor
);
}
else
if
(
ob
->
type
==
OBJ_HASH
)
{
}
else
if
(
ob
->
type
==
OBJ_HASH
)
{
server
.
stat_active_defrag_hits
+=
scanLaterHash
(
ob
,
cursor
);
scanLaterHash
(
ob
,
cursor
);
}
else
if
(
ob
->
type
==
OBJ_STREAM
)
{
}
else
if
(
ob
->
type
==
OBJ_STREAM
)
{
return
scanLaterStreamListpacks
(
ob
,
cursor
,
endtime
,
&
server
.
stat_active_defrag_hits
);
return
scanLaterStreamListpacks
(
ob
,
cursor
,
endtime
);
}
else
if
(
ob
->
type
==
OBJ_MODULE
)
{
}
else
if
(
ob
->
type
==
OBJ_MODULE
)
{
return
moduleLateDefrag
(
dictGetKey
(
de
),
ob
,
cursor
,
endtime
,
&
server
.
stat_active_defrag_hits
,
dbid
);
return
moduleLateDefrag
(
dictGetKey
(
de
),
ob
,
cursor
,
endtime
,
dbid
);
}
else
{
}
else
{
*
cursor
=
0
;
/* object type may have changed since we schedule it for later */
*
cursor
=
0
;
/* object type may have changed since we schedule it for later */
}
}
...
@@ -1061,7 +1015,7 @@ void activeDefragCycle(void) {
...
@@ -1061,7 +1015,7 @@ void activeDefragCycle(void) {
/* Move on to next database, and stop if we reached the last one. */
/* Move on to next database, and stop if we reached the last one. */
if
(
++
current_db
>=
server
.
dbnum
)
{
if
(
++
current_db
>=
server
.
dbnum
)
{
/* defrag other items not part of the db / keys */
/* defrag other items not part of the db / keys */
server
.
stat_active_defrag_hits
+=
defragOtherGlobals
();
defragOtherGlobals
();
long
long
now
=
ustime
();
long
long
now
=
ustime
();
size_t
frag_bytes
;
size_t
frag_bytes
;
...
@@ -1100,19 +1054,14 @@ void activeDefragCycle(void) {
...
@@ -1100,19 +1054,14 @@ void activeDefragCycle(void) {
/* Scan the keyspace dict unless we're scanning the expire dict. */
/* Scan the keyspace dict unless we're scanning the expire dict. */
if
(
!
expires_cursor
)
if
(
!
expires_cursor
)
cursor
=
dictScanDefrag
(
db
->
dict
,
cursor
=
dictScanDefrag
(
db
->
dict
,
cursor
,
defragScanCallback
,
cursor
,
activeDefragAlloc
,
db
);
defragScanCallback
,
activeDefragAlloc
,
db
);
/* When done scanning the keyspace dict, we scan the expire dict. */
/* When done scanning the keyspace dict, we scan the expire dict. */
if
(
!
cursor
)
if
(
!
cursor
)
expires_cursor
=
dictScanDefrag
(
db
->
expires
,
expires_cursor
=
dictScanDefrag
(
db
->
expires
,
expires_cursor
,
expires_cursor
,
defragExpireScanCallback
,
defragExpireScanCallback
,
activeDefragAlloc
,
activeDefragAlloc
,
NULL
);
NULL
);
/* Once in 16 scan iterations, 512 pointer reallocations. or 64 keys
/* Once in 16 scan iterations, 512 pointer reallocations. or 64 keys
* (if we have a lot of pointers in one hash bucket or rehashing),
* (if we have a lot of pointers in one hash bucket or rehashing),
...
@@ -1159,9 +1108,8 @@ void *activeDefragAlloc(void *ptr) {
...
@@ -1159,9 +1108,8 @@ void *activeDefragAlloc(void *ptr) {
return
NULL
;
return
NULL
;
}
}
robj
*
activeDefragStringOb
(
robj
*
ob
,
long
*
defragged
)
{
robj
*
activeDefragStringOb
(
robj
*
ob
)
{
UNUSED
(
ob
);
UNUSED
(
ob
);
UNUSED
(
defragged
);
return
NULL
;
return
NULL
;
}
}
...
...
src/module.c
View file @
2bbc8919
...
@@ -12562,7 +12562,6 @@ const char *RM_GetCurrentCommandName(RedisModuleCtx *ctx) {
...
@@ -12562,7 +12562,6 @@ const char *RM_GetCurrentCommandName(RedisModuleCtx *ctx) {
* defrag callback.
* defrag callback.
*/
*/
struct RedisModuleDefragCtx {
struct RedisModuleDefragCtx {
long defragged;
long long int endtime;
long long int endtime;
unsigned long *cursor;
unsigned long *cursor;
struct redisObject *key; /* Optional name of key processed, NULL when unknown. */
struct redisObject *key; /* Optional name of key processed, NULL when unknown. */
...
@@ -12651,11 +12650,8 @@ int RM_DefragCursorGet(RedisModuleDefragCtx *ctx, unsigned long *cursor) {
...
@@ -12651,11 +12650,8 @@ int RM_DefragCursorGet(RedisModuleDefragCtx *ctx, unsigned long *cursor) {
* be used again.
* be used again.
*/
*/
void *RM_DefragAlloc(RedisModuleDefragCtx *ctx, void *ptr) {
void *RM_DefragAlloc(RedisModuleDefragCtx *ctx, void *ptr) {
void *newptr = activeDefragAlloc(ptr);
UNUSED(ctx);
if (newptr)
return activeDefragAlloc(ptr);
ctx->defragged++;
return newptr;
}
}
/* Defrag a RedisModuleString previously allocated by RM_Alloc, RM_Calloc, etc.
/* Defrag a RedisModuleString previously allocated by RM_Alloc, RM_Calloc, etc.
...
@@ -12669,7 +12665,8 @@ void *RM_DefragAlloc(RedisModuleDefragCtx *ctx, void *ptr) {
...
@@ -12669,7 +12665,8 @@ void *RM_DefragAlloc(RedisModuleDefragCtx *ctx, void *ptr) {
* on the Redis side is dropped as soon as the command callback returns).
* on the Redis side is dropped as soon as the command callback returns).
*/
*/
RedisModuleString *RM_DefragRedisModuleString(RedisModuleDefragCtx *ctx, RedisModuleString *str) {
RedisModuleString *RM_DefragRedisModuleString(RedisModuleDefragCtx *ctx, RedisModuleString *str) {
return activeDefragStringOb(str, &ctx->defragged);
UNUSED(ctx);
return activeDefragStringOb(str);
}
}
...
@@ -12678,11 +12675,11 @@ RedisModuleString *RM_DefragRedisModuleString(RedisModuleDefragCtx *ctx, RedisMo
...
@@ -12678,11 +12675,11 @@ RedisModuleString *RM_DefragRedisModuleString(RedisModuleDefragCtx *ctx, RedisMo
* Returns a zero value (and initializes the cursor) if no more needs to be done,
* Returns a zero value (and initializes the cursor) if no more needs to be done,
* or a non-zero value otherwise.
* or a non-zero value otherwise.
*/
*/
int moduleLateDefrag(robj *key, robj *value, unsigned long *cursor, long long endtime,
long long *defragged,
int dbid) {
int moduleLateDefrag(robj *key, robj *value, unsigned long *cursor, long long endtime, int dbid) {
moduleValue *mv = value->ptr;
moduleValue *mv = value->ptr;
moduleType *mt = mv->type;
moduleType *mt = mv->type;
RedisModuleDefragCtx defrag_ctx = {
0,
endtime, cursor, key, dbid};
RedisModuleDefragCtx defrag_ctx = { endtime, cursor, key, dbid};
/* Invoke callback. Note that the callback may be missing if the key has been
/* Invoke callback. Note that the callback may be missing if the key has been
* replaced with a different type since our last visit.
* replaced with a different type since our last visit.
...
@@ -12691,7 +12688,6 @@ int moduleLateDefrag(robj *key, robj *value, unsigned long *cursor, long long en
...
@@ -12691,7 +12688,6 @@ int moduleLateDefrag(robj *key, robj *value, unsigned long *cursor, long long en
if (mt->defrag)
if (mt->defrag)
ret = mt->defrag(&defrag_ctx, key, &mv->value);
ret = mt->defrag(&defrag_ctx, key, &mv->value);
*defragged += defrag_ctx.defragged;
if (!ret) {
if (!ret) {
*cursor = 0; /* No more work to do */
*cursor = 0; /* No more work to do */
return 0;
return 0;
...
@@ -12706,7 +12702,7 @@ int moduleLateDefrag(robj *key, robj *value, unsigned long *cursor, long long en
...
@@ -12706,7 +12702,7 @@ int moduleLateDefrag(robj *key, robj *value, unsigned long *cursor, long long en
* Returns 1 if the operation has been completed or 0 if it needs to
* Returns 1 if the operation has been completed or 0 if it needs to
* be scheduled for late defrag.
* be scheduled for late defrag.
*/
*/
int moduleDefragValue(robj *key, robj *value,
long *defragged,
int dbid) {
int moduleDefragValue(robj *key, robj *value, int dbid) {
moduleValue *mv = value->ptr;
moduleValue *mv = value->ptr;
moduleType *mt = mv->type;
moduleType *mt = mv->type;
...
@@ -12715,7 +12711,6 @@ int moduleDefragValue(robj *key, robj *value, long *defragged, int dbid) {
...
@@ -12715,7 +12711,6 @@ int moduleDefragValue(robj *key, robj *value, long *defragged, int dbid) {
*/
*/
moduleValue *newmv = activeDefragAlloc(mv);
moduleValue *newmv = activeDefragAlloc(mv);
if (newmv) {
if (newmv) {
(*defragged)++;
value->ptr = mv = newmv;
value->ptr = mv = newmv;
}
}
...
@@ -12733,29 +12728,24 @@ int moduleDefragValue(robj *key, robj *value, long *defragged, int dbid) {
...
@@ -12733,29 +12728,24 @@ int moduleDefragValue(robj *key, robj *value, long *defragged, int dbid) {
return 0; /* Defrag later */
return 0; /* Defrag later */
}
}
RedisModuleDefragCtx defrag_ctx = { 0,
0,
NULL, key, dbid};
RedisModuleDefragCtx defrag_ctx = { 0, NULL, key, dbid
};
mt->defrag(&defrag_ctx, key, &mv->value);
mt->defrag(&defrag_ctx, key, &mv->value);
(*defragged) += defrag_ctx.defragged;
return 1;
return 1;
}
}
/* Call registered module API defrag functions */
/* Call registered module API defrag functions */
long
moduleDefragGlobals(void) {
void
moduleDefragGlobals(void) {
dictIterator *di = dictGetIterator(modules);
dictIterator *di = dictGetIterator(modules);
dictEntry *de;
dictEntry *de;
long defragged = 0;
while ((de = dictNext(di)) != NULL) {
while ((de = dictNext(di)) != NULL) {
struct RedisModule *module = dictGetVal(de);
struct RedisModule *module = dictGetVal(de);
if (!module->defrag_cb)
if (!module->defrag_cb)
continue;
continue;
RedisModuleDefragCtx defrag_ctx = { 0,
0,
NULL, NULL, -1};
RedisModuleDefragCtx defrag_ctx = { 0, NULL, NULL, -1};
module->defrag_cb(&defrag_ctx);
module->defrag_cb(&defrag_ctx);
defragged += defrag_ctx.defragged;
}
}
dictReleaseIterator(di);
dictReleaseIterator(di);
return defragged;
}
}
/* Returns the name of the key currently being processed.
/* Returns the name of the key currently being processed.
...
...
src/server.h
View file @
2bbc8919
...
@@ -2442,9 +2442,9 @@ void moduleNotifyKeyUnlink(robj *key, robj *val, int dbid, int flags);
...
@@ -2442,9 +2442,9 @@ void moduleNotifyKeyUnlink(robj *key, robj *val, int dbid, int flags);
size_t
moduleGetFreeEffort
(
robj
*
key
,
robj
*
val
,
int
dbid
);
size_t
moduleGetFreeEffort
(
robj
*
key
,
robj
*
val
,
int
dbid
);
size_t
moduleGetMemUsage
(
robj
*
key
,
robj
*
val
,
size_t
sample_size
,
int
dbid
);
size_t
moduleGetMemUsage
(
robj
*
key
,
robj
*
val
,
size_t
sample_size
,
int
dbid
);
robj
*
moduleTypeDupOrReply
(
client
*
c
,
robj
*
fromkey
,
robj
*
tokey
,
int
todb
,
robj
*
value
);
robj
*
moduleTypeDupOrReply
(
client
*
c
,
robj
*
fromkey
,
robj
*
tokey
,
int
todb
,
robj
*
value
);
int
moduleDefragValue
(
robj
*
key
,
robj
*
obj
,
long
*
defragged
,
int
dbid
);
int
moduleDefragValue
(
robj
*
key
,
robj
*
obj
,
int
dbid
);
int
moduleLateDefrag
(
robj
*
key
,
robj
*
value
,
unsigned
long
*
cursor
,
long
long
endtime
,
long
long
*
defragged
,
int
dbid
);
int
moduleLateDefrag
(
robj
*
key
,
robj
*
value
,
unsigned
long
*
cursor
,
long
long
endtime
,
int
dbid
);
long
moduleDefragGlobals
(
void
);
void
moduleDefragGlobals
(
void
);
void
*
moduleGetHandleByName
(
char
*
modulename
);
void
*
moduleGetHandleByName
(
char
*
modulename
);
int
moduleIsModuleCommand
(
void
*
module_handle
,
struct
redisCommand
*
cmd
);
int
moduleIsModuleCommand
(
void
*
module_handle
,
struct
redisCommand
*
cmd
);
...
@@ -2988,7 +2988,7 @@ void checkChildrenDone(void);
...
@@ -2988,7 +2988,7 @@ void checkChildrenDone(void);
int
setOOMScoreAdj
(
int
process_class
);
int
setOOMScoreAdj
(
int
process_class
);
void
rejectCommandFormat
(
client
*
c
,
const
char
*
fmt
,
...);
void
rejectCommandFormat
(
client
*
c
,
const
char
*
fmt
,
...);
void
*
activeDefragAlloc
(
void
*
ptr
);
void
*
activeDefragAlloc
(
void
*
ptr
);
robj
*
activeDefragStringOb
(
robj
*
ob
,
long
*
defragged
);
robj
*
activeDefragStringOb
(
robj
*
ob
);
void
dismissSds
(
sds
s
);
void
dismissSds
(
sds
s
);
void
dismissMemory
(
void
*
ptr
,
size_t
size_hint
);
void
dismissMemory
(
void
*
ptr
,
size_t
size_hint
);
void
dismissMemoryInChild
(
void
);
void
dismissMemoryInChild
(
void
);
...
...
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