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
ba07e1f5
Commit
ba07e1f5
authored
May 07, 2011
by
antirez
Browse files
Merge branch '2.4' of github.com:antirez/redis into 2.4
parents
8ec9d6ef
deff2338
Changes
26
Hide whitespace changes
Inline
Side-by-side
src/redis.h
View file @
ba07e1f5
...
...
@@ -29,6 +29,7 @@
#include "ziplist.h"
/* Compact list data structure */
#include "intset.h"
/* Compact integer set structure */
#include "version.h"
#include "util.h"
/* Error codes */
#define REDIS_OK 0
...
...
@@ -719,6 +720,7 @@ void freeHashObject(robj *o);
robj
*
createObject
(
int
type
,
void
*
ptr
);
robj
*
createStringObject
(
char
*
ptr
,
size_t
len
);
robj
*
dupStringObject
(
robj
*
o
);
int
isObjectRepresentableAsLongLong
(
robj
*
o
,
long
long
*
llongval
);
robj
*
tryObjectEncoding
(
robj
*
o
);
robj
*
getDecodedObject
(
robj
*
o
);
size_t
stringObjectLen
(
robj
*
o
);
...
...
@@ -872,18 +874,6 @@ int pubsubUnsubscribeAllPatterns(redisClient *c, int notify);
void
freePubsubPattern
(
void
*
p
);
int
listMatchPubsubPattern
(
void
*
a
,
void
*
b
);
/* Utility functions */
int
stringmatchlen
(
const
char
*
pattern
,
int
patternLen
,
const
char
*
string
,
int
stringLen
,
int
nocase
);
int
stringmatch
(
const
char
*
pattern
,
const
char
*
string
,
int
nocase
);
long
long
memtoll
(
const
char
*
p
,
int
*
err
);
int
ll2string
(
char
*
s
,
size_t
len
,
long
long
value
);
int
string2ll
(
char
*
s
,
size_t
len
,
long
long
*
value
);
int
d2string
(
char
*
s
,
size_t
len
,
double
value
);
int
isStringRepresentableAsLong
(
sds
s
,
long
*
longval
);
int
isStringRepresentableAsLongLong
(
sds
s
,
long
long
*
longval
);
int
isObjectRepresentableAsLongLong
(
robj
*
o
,
long
long
*
llongval
);
/* Configuration */
void
loadServerConfig
(
char
*
filename
);
void
appendServerSaveParams
(
time_t
seconds
,
int
changes
);
...
...
src/sds.c
View file @
ba07e1f5
...
...
@@ -36,11 +36,11 @@
#define SDS_ABORT_ON_OOM
#include "sds.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "sds.h"
#include "zmalloc.h"
static
void
sdsOomAbort
(
void
)
{
...
...
@@ -76,11 +76,6 @@ sds sdsnew(const char *init) {
return
sdsnewlen
(
init
,
initlen
);
}
size_t
sdslen
(
const
sds
s
)
{
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
return
sh
->
len
;
}
sds
sdsdup
(
const
sds
s
)
{
return
sdsnewlen
(
s
,
sdslen
(
s
));
}
...
...
@@ -90,11 +85,6 @@ void sdsfree(sds s) {
zfree
(
s
-
sizeof
(
struct
sdshdr
));
}
size_t
sdsavail
(
sds
s
)
{
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
return
sh
->
free
;
}
void
sdsupdatelen
(
sds
s
)
{
struct
sdshdr
*
sh
=
(
void
*
)
(
s
-
(
sizeof
(
struct
sdshdr
)));
int
reallen
=
strlen
(
s
);
...
...
@@ -306,12 +296,17 @@ int sdscmp(sds s1, sds s2) {
*/
sds
*
sdssplitlen
(
char
*
s
,
int
len
,
char
*
sep
,
int
seplen
,
int
*
count
)
{
int
elements
=
0
,
slots
=
5
,
start
=
0
,
j
;
sds
*
tokens
;
if
(
seplen
<
1
||
len
<
0
)
return
NULL
;
sds
*
tokens
=
zmalloc
(
sizeof
(
sds
)
*
slots
);
tokens
=
zmalloc
(
sizeof
(
sds
)
*
slots
);
#ifdef SDS_ABORT_ON_OOM
if
(
tokens
==
NULL
)
sdsOomAbort
();
#else
if
(
tokens
==
NULL
)
return
NULL
;
#endif
if
(
seplen
<
1
||
len
<
0
||
tokens
==
NULL
)
return
NULL
;
if
(
len
==
0
)
{
*
count
=
0
;
return
tokens
;
...
...
@@ -401,11 +396,11 @@ sds sdscatrepr(sds s, char *p, size_t len) {
case
'"'
:
s
=
sdscatprintf
(
s
,
"
\\
%c"
,
*
p
);
break
;
case
'\n'
:
s
=
sdscatlen
(
s
,
"
\\
n"
,
1
);
break
;
case
'\r'
:
s
=
sdscatlen
(
s
,
"
\\
r"
,
1
);
break
;
case
'\t'
:
s
=
sdscatlen
(
s
,
"
\\
t"
,
1
);
break
;
case
'\a'
:
s
=
sdscatlen
(
s
,
"
\\
a"
,
1
);
break
;
case
'\b'
:
s
=
sdscatlen
(
s
,
"
\\
b"
,
1
);
break
;
case
'\n'
:
s
=
sdscatlen
(
s
,
"
\\
n"
,
2
);
break
;
case
'\r'
:
s
=
sdscatlen
(
s
,
"
\\
r"
,
2
);
break
;
case
'\t'
:
s
=
sdscatlen
(
s
,
"
\\
t"
,
2
);
break
;
case
'\a'
:
s
=
sdscatlen
(
s
,
"
\\
a"
,
2
);
break
;
case
'\b'
:
s
=
sdscatlen
(
s
,
"
\\
b"
,
2
);
break
;
default:
if
(
isprint
(
*
p
))
s
=
sdscatprintf
(
s
,
"%c"
,
*
p
);
...
...
src/sds.h
View file @
ba07e1f5
...
...
@@ -42,6 +42,16 @@ struct sdshdr {
char
buf
[];
};
static
inline
size_t
sdslen
(
const
sds
s
)
{
struct
sdshdr
*
sh
=
(
void
*
)(
s
-
(
sizeof
(
struct
sdshdr
)));
return
sh
->
len
;
}
static
inline
size_t
sdsavail
(
const
sds
s
)
{
struct
sdshdr
*
sh
=
(
void
*
)(
s
-
(
sizeof
(
struct
sdshdr
)));
return
sh
->
free
;
}
sds
sdsnewlen
(
const
void
*
init
,
size_t
initlen
);
sds
sdsnew
(
const
char
*
init
);
sds
sdsempty
();
...
...
src/util.c
View file @
ba07e1f5
#include "redis.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include "util.h"
/* Glob-style pattern matching. */
int
stringmatchlen
(
const
char
*
pattern
,
int
patternLen
,
...
...
@@ -213,6 +216,12 @@ int string2ll(char *s, size_t slen, long long *value) {
if
(
plen
==
slen
)
return
0
;
/* Special case: first and only digit is 0. */
if
(
slen
==
1
&&
p
[
0
]
==
'0'
)
{
if
(
value
!=
NULL
)
*
value
=
0
;
return
1
;
}
if
(
p
[
0
]
==
'-'
)
{
negative
=
1
;
p
++
;
plen
++
;
...
...
@@ -250,7 +259,7 @@ int string2ll(char *s, size_t slen, long long *value) {
return
0
;
if
(
negative
)
{
if
(
v
>
(
-
(
unsigned
long
long
)
LLONG_MIN
))
/* Overflow. */
if
(
v
>
((
unsigned
long
long
)
(
-
(
LLONG_MIN
+
1
))
+
1
))
/* Overflow. */
return
0
;
if
(
value
!=
NULL
)
*
value
=
-
v
;
}
else
{
...
...
@@ -261,6 +270,22 @@ int string2ll(char *s, size_t slen, long long *value) {
return
1
;
}
/* Convert a string into a long. Returns 1 if the string could be parsed into a
* (non-overflowing) long, 0 otherwise. The value will be set to the parsed
* value when appropriate. */
int
string2l
(
char
*
s
,
size_t
slen
,
long
*
lval
)
{
long
long
llval
;
if
(
!
string2ll
(
s
,
slen
,
&
llval
))
return
0
;
if
(
llval
<
LONG_MIN
||
llval
>
LONG_MAX
)
return
0
;
*
lval
=
(
long
)
llval
;
return
1
;
}
/* Convert a double to a string representation. Returns the number of bytes
* required. The representation should always be parsable by stdtod(3). */
int
d2string
(
char
*
buf
,
size_t
len
,
double
value
)
{
...
...
@@ -300,44 +325,116 @@ int d2string(char *buf, size_t len, double value) {
return
len
;
}
/* Check if the sds string 's' can be represented by a long long
* (that is, is a number that fits into long without any other space or
* character before or after the digits, so that converting this number
* back to a string will result in the same bytes as the original string).
*
* If so, the function returns REDIS_OK and *llongval is set to the value
* of the number. Otherwise REDIS_ERR is returned */
int
isStringRepresentableAsLongLong
(
sds
s
,
long
long
*
llongval
)
{
char
buf
[
32
],
*
endptr
;
long
long
value
;
int
slen
;
value
=
strtoll
(
s
,
&
endptr
,
10
);
if
(
endptr
[
0
]
!=
'\0'
)
return
REDIS_ERR
;
slen
=
ll2string
(
buf
,
32
,
value
);
/* If the number converted back into a string is not identical
* then it's not possible to encode the string as integer */
if
(
sdslen
(
s
)
!=
(
unsigned
)
slen
||
memcmp
(
buf
,
s
,
slen
))
return
REDIS_ERR
;
if
(
llongval
)
*
llongval
=
value
;
return
REDIS_OK
;
#ifdef UTIL_TEST_MAIN
#include <assert.h>
void
test_string2ll
(
void
)
{
char
buf
[
32
];
long
long
v
;
/* May not start with +. */
strcpy
(
buf
,
"+1"
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
0
);
/* Leading space. */
strcpy
(
buf
,
" 1"
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
0
);
/* Trailing space. */
strcpy
(
buf
,
"1 "
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
0
);
/* May not start with 0. */
strcpy
(
buf
,
"01"
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
0
);
strcpy
(
buf
,
"-1"
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
-
1
);
strcpy
(
buf
,
"0"
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
0
);
strcpy
(
buf
,
"1"
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
1
);
strcpy
(
buf
,
"99"
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
99
);
strcpy
(
buf
,
"-99"
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
-
99
);
strcpy
(
buf
,
"-9223372036854775808"
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
LLONG_MIN
);
strcpy
(
buf
,
"-9223372036854775809"
);
/* overflow */
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
0
);
strcpy
(
buf
,
"9223372036854775807"
);
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
LLONG_MAX
);
strcpy
(
buf
,
"9223372036854775808"
);
/* overflow */
assert
(
string2ll
(
buf
,
strlen
(
buf
),
&
v
)
==
0
);
}
int
isStringRepresentableAsLong
(
sds
s
,
long
*
longval
)
{
long
long
ll
;
void
test_string2l
(
void
)
{
char
buf
[
32
];
long
v
;
/* May not start with +. */
strcpy
(
buf
,
"+1"
);
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
0
);
/* May not start with 0. */
strcpy
(
buf
,
"01"
);
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
0
);
strcpy
(
buf
,
"-1"
);
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
-
1
);
strcpy
(
buf
,
"0"
);
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
0
);
strcpy
(
buf
,
"1"
);
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
1
);
if
(
isStringRepresentableAsLongLong
(
s
,
&
ll
)
==
REDIS_ERR
)
return
REDIS_ERR
;
if
(
ll
<
LONG_MIN
||
ll
>
LONG_MAX
)
return
REDIS_ERR
;
*
longval
=
(
long
)
ll
;
return
REDIS_OK
;
strcpy
(
buf
,
"99"
);
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
99
);
strcpy
(
buf
,
"-99"
);
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
-
99
);
#if LONG_MAX != LLONG_MAX
strcpy
(
buf
,
"-2147483648"
);
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
LONG_MIN
);
strcpy
(
buf
,
"-2147483649"
);
/* overflow */
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
0
);
strcpy
(
buf
,
"2147483647"
);
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
1
);
assert
(
v
==
LONG_MAX
);
strcpy
(
buf
,
"2147483648"
);
/* overflow */
assert
(
string2l
(
buf
,
strlen
(
buf
),
&
v
)
==
0
);
#endif
}
int
isObjectRepresentableAsLongLong
(
robj
*
o
,
long
long
*
llongval
)
{
redisAssert
(
o
->
type
==
REDIS_STRING
);
if
(
o
->
encoding
==
REDIS_ENCODING_INT
)
{
if
(
llongval
)
*
llongval
=
(
long
)
o
->
ptr
;
return
REDIS_OK
;
}
else
{
return
isStringRepresentableAsLongLong
(
o
->
ptr
,
llongval
);
}
int
main
(
int
argc
,
char
**
argv
)
{
test_string2ll
();
test_string2l
();
return
0
;
}
#endif
src/util.h
0 → 100644
View file @
ba07e1f5
#ifndef __REDIS_UTIL_H
#define __REDIS_UTIL_H
int
stringmatchlen
(
const
char
*
p
,
int
plen
,
const
char
*
s
,
int
slen
,
int
nocase
);
int
stringmatch
(
const
char
*
p
,
const
char
*
s
,
int
nocase
);
long
long
memtoll
(
const
char
*
p
,
int
*
err
);
int
ll2string
(
char
*
s
,
size_t
len
,
long
long
value
);
int
string2ll
(
char
*
s
,
size_t
slen
,
long
long
*
value
);
int
string2l
(
char
*
s
,
size_t
slen
,
long
*
value
);
int
d2string
(
char
*
buf
,
size_t
len
,
double
value
);
#endif
src/ziplist.c
View file @
ba07e1f5
...
...
@@ -67,10 +67,9 @@
#include <assert.h>
#include <limits.h>
#include "zmalloc.h"
#include "util.h"
#include "ziplist.h"
int
ll2string
(
char
*
s
,
size_t
len
,
long
long
value
);
#define ZIP_END 255
#define ZIP_BIGLEN 254
...
...
@@ -248,22 +247,9 @@ static int zipPrevLenByteDiff(unsigned char *p, unsigned int len) {
* Stores the integer value in 'v' and its encoding in 'encoding'. */
static
int
zipTryEncoding
(
unsigned
char
*
entry
,
unsigned
int
entrylen
,
long
long
*
v
,
unsigned
char
*
encoding
)
{
long
long
value
;
char
*
eptr
;
char
buf
[
32
];
if
(
entrylen
>=
32
||
entrylen
==
0
)
return
0
;
if
(
entry
[
0
]
==
'-'
||
(
entry
[
0
]
>=
'0'
&&
entry
[
0
]
<=
'9'
))
{
int
slen
;
/* Perform a back-and-forth conversion to make sure that
* the string turned into an integer is not losing any info. */
memcpy
(
buf
,
entry
,
entrylen
);
buf
[
entrylen
]
=
'\0'
;
value
=
strtoll
(
buf
,
&
eptr
,
10
);
if
(
eptr
[
0
]
!=
'\0'
)
return
0
;
slen
=
ll2string
(
buf
,
32
,
value
);
if
(
entrylen
!=
(
unsigned
)
slen
||
memcmp
(
buf
,
entry
,
slen
))
return
0
;
if
(
string2ll
((
char
*
)
entry
,
entrylen
,
&
value
))
{
/* Great, the string can be encoded. Check what's the smallest
* of our encoding types that can hold this value. */
if
(
value
>=
INT16_MIN
&&
value
<=
INT16_MAX
)
{
...
...
@@ -398,12 +384,17 @@ static unsigned char *__ziplistCascadeUpdate(unsigned char *zl, unsigned char *p
offset
=
p
-
zl
;
extra
=
rawlensize
-
next
.
prevrawlensize
;
zl
=
ziplistResize
(
zl
,
curlen
+
extra
);
ZIPLIST_TAIL_OFFSET
(
zl
)
+=
extra
;
p
=
zl
+
offset
;
/*
Move the tail to the back
. */
/*
Current pointer and offset for next element
. */
np
=
p
+
rawlen
;
noffset
=
np
-
zl
;
/* Update tail offset when next element is not the tail element. */
if
((
zl
+
ZIPLIST_TAIL_OFFSET
(
zl
))
!=
np
)
ZIPLIST_TAIL_OFFSET
(
zl
)
+=
extra
;
/* Move the tail to the back. */
memmove
(
np
+
rawlensize
,
np
+
next
.
prevrawlensize
,
curlen
-
noffset
-
next
.
prevrawlensize
-
1
);
...
...
@@ -879,7 +870,7 @@ void pop(unsigned char *zl, int where) {
}
}
void
randstring
(
char
*
target
,
unsigned
int
min
,
unsigned
int
max
)
{
int
randstring
(
char
*
target
,
unsigned
int
min
,
unsigned
int
max
)
{
int
p
,
len
=
min
+
rand
()
%
(
max
-
min
+
1
);
int
minval
,
maxval
;
switch
(
rand
()
%
3
)
{
...
...
@@ -901,10 +892,9 @@ void randstring(char *target, unsigned int min, unsigned int max) {
while
(
p
<
len
)
target
[
p
++
]
=
minval
+
rand
()
%
(
maxval
-
minval
+
1
);
return
;
return
len
;
}
int
main
(
int
argc
,
char
**
argv
)
{
unsigned
char
*
zl
,
*
p
;
unsigned
char
*
entry
;
...
...
@@ -1237,6 +1227,7 @@ int main(int argc, char **argv) {
int
i
,
j
,
len
,
where
;
unsigned
char
*
p
;
char
buf
[
1024
];
int
buflen
;
list
*
ref
;
listNode
*
refnode
;
...
...
@@ -1245,10 +1236,6 @@ int main(int argc, char **argv) {
unsigned
int
slen
;
long
long
sval
;
/* In the regression for the cascade bug, it was triggered
* with a random seed of 2. */
srand
(
2
);
for
(
i
=
0
;
i
<
20000
;
i
++
)
{
zl
=
ziplistNew
();
ref
=
listCreate
();
...
...
@@ -1258,31 +1245,32 @@ int main(int argc, char **argv) {
/* Create lists */
for
(
j
=
0
;
j
<
len
;
j
++
)
{
where
=
(
rand
()
&
1
)
?
ZIPLIST_HEAD
:
ZIPLIST_TAIL
;
switch
(
rand
()
%
4
)
{
case
0
:
sprintf
(
buf
,
"%lld"
,(
0LL
+
rand
())
>>
20
);
break
;
case
1
:
sprintf
(
buf
,
"%lld"
,(
0LL
+
rand
()));
break
;
case
2
:
sprintf
(
buf
,
"%lld"
,(
0LL
+
rand
())
<<
20
);
break
;
case
3
:
randstring
(
buf
,
0
,
256
);
break
;
default:
assert
(
NULL
);
if
(
rand
()
%
2
)
{
buflen
=
randstring
(
buf
,
1
,
sizeof
(
buf
)
-
1
);
}
else
{
switch
(
rand
()
%
3
)
{
case
0
:
buflen
=
sprintf
(
buf
,
"%lld"
,(
0LL
+
rand
())
>>
20
);
break
;
case
1
:
buflen
=
sprintf
(
buf
,
"%lld"
,(
0LL
+
rand
()));
break
;
case
2
:
buflen
=
sprintf
(
buf
,
"%lld"
,(
0LL
+
rand
())
<<
20
);
break
;
default:
assert
(
NULL
);
}
}
/* Add to ziplist */
zl
=
ziplistPush
(
zl
,
(
unsigned
char
*
)
buf
,
strlen
(
buf
)
,
where
);
zl
=
ziplistPush
(
zl
,
(
unsigned
char
*
)
buf
,
buflen
,
where
);
/* Add to reference list */
if
(
where
==
ZIPLIST_HEAD
)
{
listAddNodeHead
(
ref
,
sdsnew
(
buf
));
listAddNodeHead
(
ref
,
sdsnew
len
(
buf
,
buflen
));
}
else
if
(
where
==
ZIPLIST_TAIL
)
{
listAddNodeTail
(
ref
,
sdsnew
(
buf
));
listAddNodeTail
(
ref
,
sdsnew
len
(
buf
,
buflen
));
}
else
{
assert
(
NULL
);
}
...
...
@@ -1297,12 +1285,13 @@ int main(int argc, char **argv) {
assert
(
ziplistGet
(
p
,
&
sstr
,
&
slen
,
&
sval
));
if
(
sstr
==
NULL
)
{
sprintf
(
buf
,
"%lld"
,
sval
);
buflen
=
sprintf
(
buf
,
"%lld"
,
sval
);
}
else
{
memcpy
(
buf
,
sstr
,
slen
);
buf
[
slen
]
=
'\0'
;
buflen
=
slen
;
memcpy
(
buf
,
sstr
,
buflen
);
buf
[
buflen
]
=
'\0'
;
}
assert
(
str
cmp
(
buf
,
listNodeValue
(
refnode
))
==
0
);
assert
(
mem
cmp
(
buf
,
listNodeValue
(
refnode
)
,
buflen
)
==
0
);
}
zfree
(
zl
);
listRelease
(
ref
);
...
...
Prev
1
2
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