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
2e4b0e77
Commit
2e4b0e77
authored
May 13, 2011
by
Pieter Noordhuis
Browse files
Abstract file/buffer I/O to support in-memory serialization
parent
70bc5f77
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/Makefile
View file @
2e4b0e77
...
@@ -47,7 +47,7 @@ BINCOLOR="\033[37;1m"
...
@@ -47,7 +47,7 @@ BINCOLOR="\033[37;1m"
MAKECOLOR
=
"
\0
33[32;1m"
MAKECOLOR
=
"
\0
33[32;1m"
ENDCOLOR
=
"
\0
33[0m"
ENDCOLOR
=
"
\0
33[0m"
OBJ
=
adlist.o ae.o anet.o dict.o redis.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 dscache.o pubsub.o multi.o debug.o sort.o intset.o syncio.o diskstore.o cluster.o crc16.o endian.o
OBJ
=
adlist.o ae.o anet.o dict.o redis.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 dscache.o pubsub.o multi.o debug.o sort.o intset.o syncio.o diskstore.o cluster.o crc16.o endian.o
rio.o
BENCHOBJ
=
ae.o anet.o redis-benchmark.o sds.o adlist.o zmalloc.o
BENCHOBJ
=
ae.o anet.o redis-benchmark.o sds.o adlist.o zmalloc.o
CLIOBJ
=
anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o
CLIOBJ
=
anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o
CHECKDUMPOBJ
=
redis-check-dump.o lzf_c.o lzf_d.o
CHECKDUMPOBJ
=
redis-check-dump.o lzf_c.o lzf_d.o
...
@@ -109,6 +109,7 @@ redis.o: redis.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
...
@@ -109,6 +109,7 @@ redis.o: redis.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
release.o
:
release.c release.h
release.o
:
release.c release.h
replication.o
:
replication.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
replication.o
:
replication.c redis.h fmacros.h config.h ae.h sds.h dict.h
\
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
rio.o
:
rio.c sds.h
sds.o
:
sds.c sds.h zmalloc.h
sds.o
:
sds.c sds.h zmalloc.h
sha1.o
:
sha1.c sha1.h
sha1.o
:
sha1.c sha1.h
sort.o
:
sort.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
sort.o
:
sort.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h
\
...
...
src/cluster.c
View file @
2e4b0e77
...
@@ -1383,11 +1383,10 @@ void clusterCommand(redisClient *c) {
...
@@ -1383,11 +1383,10 @@ void clusterCommand(redisClient *c) {
/* RESTORE key ttl serialized-value */
/* RESTORE key ttl serialized-value */
void
restoreCommand
(
redisClient
*
c
)
{
void
restoreCommand
(
redisClient
*
c
)
{
FILE
*
fp
;
char
buf
[
64
];
robj
*
o
;
robj
*
o
;
unsigned
char
*
data
;
long
ttl
;
long
ttl
;
rio
payload
;
unsigned
char
*
data
;
/* Make sure this key does not already exist here... */
/* Make sure this key does not already exist here... */
if
(
dbExists
(
c
->
db
,
c
->
argv
[
1
]))
{
if
(
dbExists
(
c
->
db
,
c
->
argv
[
1
]))
{
...
@@ -1403,41 +1402,20 @@ void restoreCommand(redisClient *c) {
...
@@ -1403,41 +1402,20 @@ void restoreCommand(redisClient *c) {
return
;
return
;
}
}
/* rdbLoadObject() only works against file descriptors so we need to
/* Temporary hack to get RDB-aligned payload. */
* dump the serialized object into a file and reload. */
payload
=
rioInitWithBuffer
(
sdsnewlen
(
c
->
argv
[
3
]
->
ptr
+
1
,
sdslen
(
c
->
argv
[
3
]
->
ptr
)
-
1
));
snprintf
(
buf
,
sizeof
(
buf
),
"redis-restore-%d.tmp"
,
getpid
());
data
=
c
->
argv
[
3
]
->
ptr
;
fp
=
fopen
(
buf
,
"w+"
);
if
(
!
fp
)
{
redisLog
(
REDIS_WARNING
,
"Can't open tmp file for RESTORE: %s"
,
strerror
(
errno
));
addReplyErrorFormat
(
c
,
"RESTORE failed, tmp file creation error: %s"
,
strerror
(
errno
));
return
;
}
unlink
(
buf
);
/* Write the actual data and rewind the file */
/* Create the object from the serialized dump. */
data
=
(
unsigned
char
*
)
c
->
argv
[
3
]
->
ptr
;
if
(
fwrite
(
data
+
1
,
sdslen
((
sds
)
data
)
-
1
,
1
,
fp
)
!=
1
)
{
redisLog
(
REDIS_WARNING
,
"Can't write against tmp file for RESTORE: %s"
,
strerror
(
errno
));
addReplyError
(
c
,
"RESTORE failed, tmp file I/O error."
);
fclose
(
fp
);
return
;
}
rewind
(
fp
);
/* Finally create the object from the serialized dump and
* store it at the specified key. */
if
((
data
[
0
]
>
4
&&
data
[
0
]
<
9
)
||
if
((
data
[
0
]
>
4
&&
data
[
0
]
<
9
)
||
data
[
0
]
>
11
||
data
[
0
]
>
11
||
(
o
=
rdbLoadObject
(
data
[
0
],
fp
))
==
NULL
)
(
o
=
rdbLoadObject
(
data
[
0
],
&
payload
))
==
NULL
)
{
{
addReplyError
(
c
,
"Bad data format."
);
addReplyError
(
c
,
"Bad data format."
);
fclose
(
fp
);
sdsfree
(
payload
.
io
.
buffer
.
ptr
);
return
;
return
;
}
}
fclose
(
fp
);
sdsfree
(
payload
.
io
.
buffer
.
ptr
);
/* Create the key and set the TTL if any */
/* Create the key and set the TTL if any */
dbAdd
(
c
->
db
,
c
->
argv
[
1
],
o
);
dbAdd
(
c
->
db
,
c
->
argv
[
1
],
o
);
...
@@ -1450,12 +1428,10 @@ void migrateCommand(redisClient *c) {
...
@@ -1450,12 +1428,10 @@ void migrateCommand(redisClient *c) {
int
fd
;
int
fd
;
long
timeout
;
long
timeout
;
long
dbid
;
long
dbid
;
char
buf
[
64
];
FILE
*
fp
;
time_t
ttl
;
time_t
ttl
;
robj
*
o
;
robj
*
o
;
unsigned
char
type
;
unsigned
char
type
;
off_t
payload
_len
;
rio
cmd
,
payload
;
/* Sanity check */
/* Sanity check */
if
(
getLongFromObjectOrReply
(
c
,
c
->
argv
[
5
],
&
timeout
,
NULL
)
!=
REDIS_OK
)
if
(
getLongFromObjectOrReply
(
c
,
c
->
argv
[
5
],
&
timeout
,
NULL
)
!=
REDIS_OK
)
...
@@ -1485,54 +1461,51 @@ void migrateCommand(redisClient *c) {
...
@@ -1485,54 +1461,51 @@ void migrateCommand(redisClient *c) {
return
;
return
;
}
}
/* Create temp file */
cmd
=
rioInitWithBuffer
(
sdsempty
());
snprintf
(
buf
,
sizeof
(
buf
),
"redis-migrate-%d.tmp"
,
getpid
());
redisAssert
(
rioWriteBulkCount
(
&
cmd
,
'*'
,
2
));
fp
=
fopen
(
buf
,
"w+"
);
redisAssert
(
rioWriteBulkString
(
&
cmd
,
"SELECT"
,
6
));
if
(
!
fp
)
{
redisAssert
(
rioWriteBulkLongLong
(
&
cmd
,
dbid
));
redisLog
(
REDIS_WARNING
,
"Can't open tmp file for MIGRATE: %s"
,
strerror
(
errno
));
addReplyErrorFormat
(
c
,
"MIGRATE failed, tmp file creation error: %s."
,
strerror
(
errno
));
return
;
}
unlink
(
buf
);
/* Build the SELECT + RESTORE query writing it in our temp file. */
if
(
fwriteBulkCount
(
fp
,
'*'
,
2
)
==
0
)
goto
file_wr_err
;
if
(
fwriteBulkString
(
fp
,
"SELECT"
,
6
)
==
0
)
goto
file_wr_err
;
if
(
fwriteBulkLongLong
(
fp
,
dbid
)
==
0
)
goto
file_wr_err
;
ttl
=
getExpire
(
c
->
db
,
c
->
argv
[
3
]);
ttl
=
getExpire
(
c
->
db
,
c
->
argv
[
3
]);
type
=
o
->
type
;
type
=
o
->
type
;
if
(
fwriteBulkCount
(
fp
,
'*'
,
4
)
==
0
)
goto
file_wr_err
;
if
(
type
==
REDIS_LIST
&&
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
if
(
fwriteBulkString
(
fp
,
"RESTORE"
,
7
)
==
0
)
goto
file_wr_err
;
type
=
REDIS_LIST_ZIPLIST
;
if
(
fwriteBulkObject
(
fp
,
c
->
argv
[
3
])
==
0
)
goto
file_wr_err
;
else
if
(
type
==
REDIS_HASH
&&
o
->
encoding
==
REDIS_ENCODING_ZIPMAP
)
if
(
fwriteBulkLongLong
(
fp
,
(
ttl
==
-
1
)
?
0
:
ttl
)
==
0
)
goto
file_wr_err
;
type
=
REDIS_HASH_ZIPMAP
;
else
if
(
type
==
REDIS_SET
&&
o
->
encoding
==
REDIS_ENCODING_INTSET
)
type
=
REDIS_SET_INTSET
;
else
type
=
o
->
type
;
redisAssert
(
rioWriteBulkCount
(
&
cmd
,
'*'
,
4
));
redisAssert
(
rioWriteBulkString
(
&
cmd
,
"RESTORE"
,
7
));
redisAssert
(
c
->
argv
[
3
]
->
encoding
==
REDIS_ENCODING_RAW
);
redisAssert
(
rioWriteBulkString
(
&
cmd
,
c
->
argv
[
3
]
->
ptr
,
sdslen
(
c
->
argv
[
3
]
->
ptr
)));
redisAssert
(
rioWriteBulkLongLong
(
&
cmd
,(
ttl
==
-
1
)
?
0
:
ttl
));
/* Finally the last argument that is the serailized object payload
/* Finally the last argument that is the serailized object payload
* in the form: <type><rdb-serailized-object>. */
* in the form: <type><rdb-serialized-object>. */
payload_len
=
rdbSavedObjectLen
(
o
);
payload
=
rioInitWithBuffer
(
sdsempty
());
if
(
fwriteBulkCount
(
fp
,
'$'
,
payload_len
+
1
)
==
0
)
goto
file_wr_err
;
redisAssert
(
rioWrite
(
&
payload
,
&
type
,
1
));
if
(
fwrite
(
&
type
,
1
,
1
,
fp
)
==
0
)
goto
file_wr_err
;
redisAssert
(
rdbSaveObject
(
&
payload
,
o
)
!=
-
1
);
if
(
rdbSaveObject
(
fp
,
o
)
==
-
1
)
goto
file_wr_err
;
redisAssert
(
rioWriteBulkString
(
&
cmd
,
payload
.
io
.
buffer
.
ptr
,
sdslen
(
payload
.
io
.
buffer
.
ptr
)));
if
(
fwrite
(
"
\r\n
"
,
2
,
1
,
fp
)
==
0
)
goto
file_wr_err
;
sdsfree
(
payload
.
io
.
buffer
.
ptr
);
/* Tranfer the query to the other node */
/* Tranfer the query to the other node in 64K chunks. */
rewind
(
fp
);
{
{
char
buf
[
4096
];
sds
buf
=
cmd
.
io
.
buffer
.
ptr
;
size_t
nread
;
size_t
pos
=
0
,
towrite
;
int
nwritten
=
0
;
while
((
nread
=
fread
(
buf
,
1
,
sizeof
(
buf
),
fp
))
!=
0
)
{
int
nwritten
;
while
((
towrite
=
sdslen
(
buf
)
-
pos
)
>
0
)
{
towrite
=
(
towrite
>
(
64
*
1024
)
?
(
64
*
1024
)
:
towrite
);
nwritten
=
syncWrite
(
fd
,
buf
,
nread
,
timeout
);
nwritten
=
syncWrite
(
fd
,
buf
+
nwritten
,
towrite
,
timeout
);
if
(
nwritten
!=
(
signed
)
nread
)
goto
socket_wr_err
;
if
(
nwritten
!=
(
signed
)
towrite
)
goto
socket_wr_err
;
pos
+=
nwritten
;
}
}
if
(
ferror
(
fp
))
goto
file_rd_err
;
}
}
/* Read back the reply */
/* Read back the reply
.
*/
{
{
char
buf1
[
1024
];
char
buf1
[
1024
];
char
buf2
[
1024
];
char
buf2
[
1024
];
...
@@ -1541,7 +1514,7 @@ void migrateCommand(redisClient *c) {
...
@@ -1541,7 +1514,7 @@ void migrateCommand(redisClient *c) {
if
(
syncReadLine
(
fd
,
buf1
,
sizeof
(
buf1
),
timeout
)
<=
0
)
if
(
syncReadLine
(
fd
,
buf1
,
sizeof
(
buf1
),
timeout
)
<=
0
)
goto
socket_rd_err
;
goto
socket_rd_err
;
if
(
syncReadLine
(
fd
,
buf2
,
sizeof
(
buf2
),
timeout
)
<=
0
)
if
(
syncReadLine
(
fd
,
buf2
,
sizeof
(
buf2
),
timeout
)
<=
0
)
goto
socket_rd_err
;
goto
socket_rd_err
;
if
(
buf1
[
0
]
==
'-'
||
buf2
[
0
]
==
'-'
)
{
if
(
buf1
[
0
]
==
'-'
||
buf2
[
0
]
==
'-'
)
{
addReplyErrorFormat
(
c
,
"Target instance replied with error: %s"
,
addReplyErrorFormat
(
c
,
"Target instance replied with error: %s"
,
(
buf1
[
0
]
==
'-'
)
?
buf1
+
1
:
buf2
+
1
);
(
buf1
[
0
]
==
'-'
)
?
buf1
+
1
:
buf2
+
1
);
...
@@ -1550,25 +1523,8 @@ void migrateCommand(redisClient *c) {
...
@@ -1550,25 +1523,8 @@ void migrateCommand(redisClient *c) {
addReply
(
c
,
shared
.
ok
);
addReply
(
c
,
shared
.
ok
);
}
}
}
}
fclose
(
fp
);
close
(
fd
);
return
;
file_wr_err:
sdsfree
(
cmd
.
io
.
buffer
.
ptr
);
redisLog
(
REDIS_WARNING
,
"Can't write on tmp file for MIGRATE: %s"
,
strerror
(
errno
));
addReplyErrorFormat
(
c
,
"MIGRATE failed, tmp file write error: %s."
,
strerror
(
errno
));
fclose
(
fp
);
close
(
fd
);
return
;
file_rd_err:
redisLog
(
REDIS_WARNING
,
"Can't read from tmp file for MIGRATE: %s"
,
strerror
(
errno
));
addReplyErrorFormat
(
c
,
"MIGRATE failed, tmp file read error: %s."
,
strerror
(
errno
));
fclose
(
fp
);
close
(
fd
);
close
(
fd
);
return
;
return
;
...
@@ -1577,7 +1533,7 @@ socket_wr_err:
...
@@ -1577,7 +1533,7 @@ socket_wr_err:
strerror
(
errno
));
strerror
(
errno
));
addReplyErrorFormat
(
c
,
"MIGRATE failed, writing to target node: %s."
,
addReplyErrorFormat
(
c
,
"MIGRATE failed, writing to target node: %s."
,
strerror
(
errno
));
strerror
(
errno
));
fclose
(
fp
);
sdsfree
(
cmd
.
io
.
buffer
.
ptr
);
close
(
fd
);
close
(
fd
);
return
;
return
;
...
@@ -1586,7 +1542,7 @@ socket_rd_err:
...
@@ -1586,7 +1542,7 @@ socket_rd_err:
strerror
(
errno
));
strerror
(
errno
));
addReplyErrorFormat
(
c
,
"MIGRATE failed, reading from target node: %s."
,
addReplyErrorFormat
(
c
,
"MIGRATE failed, reading from target node: %s."
,
strerror
(
errno
));
strerror
(
errno
));
fclose
(
fp
);
sdsfree
(
cmd
.
io
.
buffer
.
ptr
);
close
(
fd
);
close
(
fd
);
return
;
return
;
}
}
...
@@ -1595,11 +1551,9 @@ socket_rd_err:
...
@@ -1595,11 +1551,9 @@ socket_rd_err:
* DUMP is actually not used by Redis Cluster but it is the obvious
* DUMP is actually not used by Redis Cluster but it is the obvious
* complement of RESTORE and can be useful for different applications. */
* complement of RESTORE and can be useful for different applications. */
void
dumpCommand
(
redisClient
*
c
)
{
void
dumpCommand
(
redisClient
*
c
)
{
char
buf
[
64
];
FILE
*
fp
;
robj
*
o
,
*
dumpobj
;
robj
*
o
,
*
dumpobj
;
sds
dump
=
NULL
;
sds
dump
=
NULL
;
off_t
payload
_len
;
rio
payload
;
unsigned
int
type
;
unsigned
int
type
;
/* Check if the key is here. */
/* Check if the key is here. */
...
@@ -1608,27 +1562,15 @@ void dumpCommand(redisClient *c) {
...
@@ -1608,27 +1562,15 @@ void dumpCommand(redisClient *c) {
return
;
return
;
}
}
/* Create temp file */
/* Dump the serailized object and read it back in memory. We prefix it
snprintf
(
buf
,
sizeof
(
buf
),
"redis-dump-%d.tmp"
,
getpid
());
* with a one byte containing the type ID. This is the serialization
fp
=
fopen
(
buf
,
"w+"
);
* format understood by RESTORE. */
if
(
!
fp
)
{
payload
=
rioInitWithBuffer
(
sdsempty
());
redisLog
(
REDIS_WARNING
,
"Can't open tmp file for MIGRATE: %s"
,
redisAssert
(
rdbSaveObject
(
&
payload
,
o
));
/* always write >= 1 bytes. */
strerror
(
errno
));
dump
=
sdsnewlen
(
NULL
,
sdslen
(
payload
.
io
.
buffer
.
ptr
)
+
1
);
addReplyErrorFormat
(
c
,
"DUMP failed, tmp file creation error: %s."
,
memcpy
(
dump
+
1
,
payload
.
io
.
buffer
.
ptr
,
sdslen
(
payload
.
io
.
buffer
.
ptr
));
strerror
(
errno
));
sdsfree
(
payload
.
io
.
buffer
.
ptr
);
return
;
}
unlink
(
buf
);
/* Dump the serailized object and read it back in memory.
* We prefix it with a one byte containing the type ID.
* This is the serialization format understood by RESTORE. */
if
(
rdbSaveObject
(
fp
,
o
)
==
-
1
)
goto
file_wr_err
;
payload_len
=
ftello
(
fp
);
if
(
fseeko
(
fp
,
0
,
SEEK_SET
)
==
-
1
)
goto
file_rd_err
;
dump
=
sdsnewlen
(
NULL
,
payload_len
+
1
);
if
(
payload_len
&&
fread
(
dump
+
1
,
payload_len
,
1
,
fp
)
!=
1
)
goto
file_rd_err
;
fclose
(
fp
);
type
=
o
->
type
;
type
=
o
->
type
;
if
(
type
==
REDIS_LIST
&&
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
if
(
type
==
REDIS_LIST
&&
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
type
=
REDIS_LIST_ZIPLIST
;
type
=
REDIS_LIST_ZIPLIST
;
...
@@ -1645,24 +1587,6 @@ void dumpCommand(redisClient *c) {
...
@@ -1645,24 +1587,6 @@ void dumpCommand(redisClient *c) {
addReplyBulk
(
c
,
dumpobj
);
addReplyBulk
(
c
,
dumpobj
);
decrRefCount
(
dumpobj
);
decrRefCount
(
dumpobj
);
return
;
return
;
file_wr_err:
redisLog
(
REDIS_WARNING
,
"Can't write on tmp file for DUMP: %s"
,
strerror
(
errno
));
addReplyErrorFormat
(
c
,
"DUMP failed, tmp file write error: %s."
,
strerror
(
errno
));
sdsfree
(
dump
);
fclose
(
fp
);
return
;
file_rd_err:
redisLog
(
REDIS_WARNING
,
"Can't read from tmp file for DUMP: %s"
,
strerror
(
errno
));
addReplyErrorFormat
(
c
,
"DUMP failed, tmp file read error: %s."
,
strerror
(
errno
));
sdsfree
(
dump
);
fclose
(
fp
);
return
;
}
}
/* -----------------------------------------------------------------------------
/* -----------------------------------------------------------------------------
...
...
src/diskstore.c
View file @
2e4b0e77
...
@@ -185,8 +185,9 @@ int dsKeyToPath(redisDb *db, char *buf, robj *key) {
...
@@ -185,8 +185,9 @@ int dsKeyToPath(redisDb *db, char *buf, robj *key) {
int
dsSet
(
redisDb
*
db
,
robj
*
key
,
robj
*
val
,
time_t
expire
)
{
int
dsSet
(
redisDb
*
db
,
robj
*
key
,
robj
*
val
,
time_t
expire
)
{
char
buf
[
1024
],
buf2
[
1024
];
char
buf
[
1024
],
buf2
[
1024
];
FILE
*
fp
;
int
retval
,
len
;
int
retval
,
len
;
FILE
*
fp
;
rio
rdb
;
len
=
dsKeyToPath
(
db
,
buf
,
key
);
len
=
dsKeyToPath
(
db
,
buf
,
key
);
memcpy
(
buf2
,
buf
,
len
);
memcpy
(
buf2
,
buf
,
len
);
...
@@ -201,7 +202,9 @@ int dsSet(redisDb *db, robj *key, robj *val, time_t expire) {
...
@@ -201,7 +202,9 @@ int dsSet(redisDb *db, robj *key, robj *val, time_t expire) {
redisPanic
(
"Unrecoverable diskstore error. Exiting."
);
redisPanic
(
"Unrecoverable diskstore error. Exiting."
);
}
}
}
}
if
((
retval
=
rdbSaveKeyValuePair
(
fp
,
key
,
val
,
expire
,
time
(
NULL
)))
==
-
1
)
rdb
=
rioInitWithFile
(
fp
);
if
((
retval
=
rdbSaveKeyValuePair
(
&
rdb
,
key
,
val
,
expire
,
time
(
NULL
)))
==
-
1
)
return
REDIS_ERR
;
return
REDIS_ERR
;
fclose
(
fp
);
fclose
(
fp
);
if
(
retval
==
0
)
{
if
(
retval
==
0
)
{
...
@@ -226,6 +229,7 @@ robj *dsGet(redisDb *db, robj *key, time_t *expire) {
...
@@ -226,6 +229,7 @@ robj *dsGet(redisDb *db, robj *key, time_t *expire) {
robj
*
dskey
;
/* Key as loaded from disk. */
robj
*
dskey
;
/* Key as loaded from disk. */
robj
*
val
;
robj
*
val
;
FILE
*
fp
;
FILE
*
fp
;
rio
rdb
;
dsKeyToPath
(
db
,
buf
,
key
);
dsKeyToPath
(
db
,
buf
,
key
);
fp
=
fopen
(
buf
,
"r"
);
fp
=
fopen
(
buf
,
"r"
);
...
@@ -236,16 +240,17 @@ robj *dsGet(redisDb *db, robj *key, time_t *expire) {
...
@@ -236,16 +240,17 @@ robj *dsGet(redisDb *db, robj *key, time_t *expire) {
goto
readerr
;
goto
readerr
;
}
}
if
((
type
=
rdbLoadType
(
fp
))
==
-
1
)
goto
readerr
;
rdb
=
rioInitWithFile
(
fp
);
if
((
type
=
rdbLoadType
(
&
rdb
))
==
-
1
)
goto
readerr
;
if
(
type
==
REDIS_EXPIRETIME
)
{
if
(
type
==
REDIS_EXPIRETIME
)
{
if
((
expiretime
=
rdbLoadTime
(
fp
))
==
-
1
)
goto
readerr
;
if
((
expiretime
=
rdbLoadTime
(
&
rdb
))
==
-
1
)
goto
readerr
;
/* We read the time so we need to read the object type again */
/* We read the time so we need to read the object type again */
if
((
type
=
rdbLoadType
(
fp
))
==
-
1
)
goto
readerr
;
if
((
type
=
rdbLoadType
(
&
rdb
))
==
-
1
)
goto
readerr
;
}
}
/* Read key */
/* Read key */
if
((
dskey
=
rdbLoadStringObject
(
fp
))
==
NULL
)
goto
readerr
;
if
((
dskey
=
rdbLoadStringObject
(
&
rdb
))
==
NULL
)
goto
readerr
;
/* Read value */
/* Read value */
if
((
val
=
rdbLoadObject
(
type
,
fp
))
==
NULL
)
goto
readerr
;
if
((
val
=
rdbLoadObject
(
type
,
&
rdb
))
==
NULL
)
goto
readerr
;
fclose
(
fp
);
fclose
(
fp
);
/* The key we asked, and the key returned, must be the same */
/* The key we asked, and the key returned, must be the same */
...
@@ -362,6 +367,7 @@ void *dsRdbSave_thread(void *arg) {
...
@@ -362,6 +367,7 @@ void *dsRdbSave_thread(void *arg) {
struct
dirent
*
dp
,
de
;
struct
dirent
*
dp
,
de
;
int
j
,
i
,
last_dbid
=
-
1
;
int
j
,
i
,
last_dbid
=
-
1
;
FILE
*
fp
;
FILE
*
fp
;
rio
rdb
;
/* Change state to ACTIVE, to signal there is a saving thead working. */
/* Change state to ACTIVE, to signal there is a saving thead working. */
redisLog
(
REDIS_NOTICE
,
"Diskstore BGSAVE thread started"
);
redisLog
(
REDIS_NOTICE
,
"Diskstore BGSAVE thread started"
);
...
@@ -375,7 +381,9 @@ void *dsRdbSave_thread(void *arg) {
...
@@ -375,7 +381,9 @@ void *dsRdbSave_thread(void *arg) {
dsRdbSaveSetState
(
REDIS_BGSAVE_THREAD_DONE_ERR
);
dsRdbSaveSetState
(
REDIS_BGSAVE_THREAD_DONE_ERR
);
return
NULL
;
return
NULL
;
}
}
if
(
fwrite
(
"REDIS0001"
,
9
,
1
,
fp
)
==
0
)
goto
werr
;
rdb
=
rioInitWithFile
(
fp
);
if
(
rioWrite
(
&
rdb
,
"REDIS0001"
,
9
)
==
0
)
goto
werr
;
sleep
(
5
);
sleep
(
5
);
...
@@ -408,8 +416,8 @@ void *dsRdbSave_thread(void *arg) {
...
@@ -408,8 +416,8 @@ void *dsRdbSave_thread(void *arg) {
dbid
=
dsGetDbidFromFilename
(
dp
->
d_name
);
dbid
=
dsGetDbidFromFilename
(
dp
->
d_name
);
if
(
dbid
!=
last_dbid
)
{
if
(
dbid
!=
last_dbid
)
{
last_dbid
=
dbid
;
last_dbid
=
dbid
;
if
(
rdbSaveType
(
fp
,
REDIS_SELECTDB
)
==
-
1
)
goto
werr
;
if
(
rdbSaveType
(
&
rdb
,
REDIS_SELECTDB
)
==
-
1
)
goto
werr
;
if
(
rdbSaveLen
(
fp
,
dbid
)
==
-
1
)
goto
werr
;
if
(
rdbSaveLen
(
&
rdb
,
dbid
)
==
-
1
)
goto
werr
;
}
}
/* Let's copy this file into the target .rdb */
/* Let's copy this file into the target .rdb */
...
@@ -422,7 +430,7 @@ void *dsRdbSave_thread(void *arg) {
...
@@ -422,7 +430,7 @@ void *dsRdbSave_thread(void *arg) {
goto
werr
;
goto
werr
;
}
}
while
(
1
)
{
while
(
1
)
{
in
t
nread
=
fread
(
buf
,
1
,
sizeof
(
buf
),
entryfp
);
size_
t
nread
=
fread
(
buf
,
1
,
sizeof
(
buf
),
entryfp
);
if
(
nread
==
0
)
{
if
(
nread
==
0
)
{
if
(
ferror
(
entryfp
))
{
if
(
ferror
(
entryfp
))
{
...
@@ -433,7 +441,7 @@ void *dsRdbSave_thread(void *arg) {
...
@@ -433,7 +441,7 @@ void *dsRdbSave_thread(void *arg) {
break
;
break
;
}
}
}
}
if
(
fw
rite
(
buf
,
1
,
nread
,
fp
)
!
=
(
unsigned
)
nread
)
{
if
(
rioW
rite
(
&
rdb
,
buf
,
nread
)
=
=
0
)
{
closedir
(
dir
);
closedir
(
dir
);
goto
werr
;
goto
werr
;
}
}
...
@@ -445,7 +453,7 @@ void *dsRdbSave_thread(void *arg) {
...
@@ -445,7 +453,7 @@ void *dsRdbSave_thread(void *arg) {
}
}
/* Output the end of file opcode */
/* Output the end of file opcode */
if
(
rdbSaveType
(
fp
,
REDIS_EOF
)
==
-
1
)
goto
werr
;
if
(
rdbSaveType
(
&
rdb
,
REDIS_EOF
)
==
-
1
)
goto
werr
;
/* Make sure data will not remain on the OS's output buffers */
/* Make sure data will not remain on the OS's output buffers */
fflush
(
fp
);
fflush
(
fp
);
...
...
src/rdb.c
View file @
2e4b0e77
#include "redis.h"
#include "lzf.h"
/* LZF compression library */
#include <math.h>
#include <math.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/time.h>
...
@@ -8,47 +5,46 @@
...
@@ -8,47 +5,46 @@
#include <sys/wait.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include "rdb.h"
#include "lzf.h"
/* LZF compression library */
/* Convenience wrapper around fwrite, that returns the number of bytes written
static
int
rdbWriteRaw
(
rio
*
rdb
,
void
*
p
,
size_t
len
)
{
* to the file instead of the number of objects (see fwrite(3)) and -1 in the
if
(
rioWrite
(
rdb
,
p
,
len
)
==
0
)
* case of an error. It also supports a NULL *fp to skip writing altogether
return
-
1
;
* instead of writing to /dev/null. */
return
1
;
static
int
rdbWriteRaw
(
FILE
*
fp
,
void
*
p
,
size_t
len
)
{
if
(
fp
!=
NULL
&&
fwrite
(
p
,
len
,
1
,
fp
)
==
0
)
return
-
1
;
return
len
;
}
}
int
rdbSaveType
(
FILE
*
fp
,
unsigned
char
type
)
{
int
rdbSaveType
(
rio
*
rdb
,
unsigned
char
type
)
{
return
rdbWriteRaw
(
fp
,
&
type
,
1
);
return
rdbWriteRaw
(
rdb
,
&
type
,
1
);
}
}
int
rdbSaveTime
(
FILE
*
fp
,
time_t
t
)
{
int
rdbSaveTime
(
rio
*
rdb
,
time_t
t
)
{
int32_t
t32
=
(
int32_t
)
t
;
int32_t
t32
=
(
int32_t
)
t
;
return
rdbWriteRaw
(
fp
,
&
t32
,
4
);
return
rdbWriteRaw
(
rdb
,
&
t32
,
4
);
}
}
/* check rdbLoadLen() comments for more info */
/* check rdbLoadLen() comments for more info */
int
rdbSaveLen
(
FILE
*
fp
,
uint32_t
len
)
{
int
rdbSaveLen
(
rio
*
rdb
,
uint32_t
len
)
{
unsigned
char
buf
[
2
];
unsigned
char
buf
[
2
];
in
t
nwritten
;
size_
t
nwritten
;
if
(
len
<
(
1
<<
6
))
{
if
(
len
<
(
1
<<
6
))
{
/* Save a 6 bit len */
/* Save a 6 bit len */
buf
[
0
]
=
(
len
&
0xFF
)
|
(
REDIS_RDB_6BITLEN
<<
6
);
buf
[
0
]
=
(
len
&
0xFF
)
|
(
REDIS_RDB_6BITLEN
<<
6
);
if
(
rdbWriteRaw
(
fp
,
buf
,
1
)
==
-
1
)
return
-
1
;
if
(
rdbWriteRaw
(
rdb
,
buf
,
1
)
==
-
1
)
return
-
1
;
nwritten
=
1
;
nwritten
=
1
;
}
else
if
(
len
<
(
1
<<
14
))
{
}
else
if
(
len
<
(
1
<<
14
))
{
/* Save a 14 bit len */
/* Save a 14 bit len */
buf
[
0
]
=
((
len
>>
8
)
&
0xFF
)
|
(
REDIS_RDB_14BITLEN
<<
6
);
buf
[
0
]
=
((
len
>>
8
)
&
0xFF
)
|
(
REDIS_RDB_14BITLEN
<<
6
);
buf
[
1
]
=
len
&
0xFF
;
buf
[
1
]
=
len
&
0xFF
;
if
(
rdbWriteRaw
(
fp
,
buf
,
2
)
==
-
1
)
return
-
1
;
if
(
rdbWriteRaw
(
rdb
,
buf
,
2
)
==
-
1
)
return
-
1
;
nwritten
=
2
;
nwritten
=
2
;
}
else
{
}
else
{
/* Save a 32 bit len */
/* Save a 32 bit len */
buf
[
0
]
=
(
REDIS_RDB_32BITLEN
<<
6
);
buf
[
0
]
=
(
REDIS_RDB_32BITLEN
<<
6
);
if
(
rdbWriteRaw
(
fp
,
buf
,
1
)
==
-
1
)
return
-
1
;
if
(
rdbWriteRaw
(
rdb
,
buf
,
1
)
==
-
1
)
return
-
1
;
len
=
htonl
(
len
);
len
=
htonl
(
len
);
if
(
rdbWriteRaw
(
fp
,
&
len
,
4
)
==
-
1
)
return
-
1
;
if
(
rdbWriteRaw
(
rdb
,
&
len
,
4
)
==
-
4
)
return
-
1
;
nwritten
=
1
+
4
;
nwritten
=
1
+
4
;
}
}
return
nwritten
;
return
nwritten
;
...
@@ -101,7 +97,7 @@ int rdbTryIntegerEncoding(char *s, size_t len, unsigned char *enc) {
...
@@ -101,7 +97,7 @@ int rdbTryIntegerEncoding(char *s, size_t len, unsigned char *enc) {
return
rdbEncodeInteger
(
value
,
enc
);
return
rdbEncodeInteger
(
value
,
enc
);
}
}
int
rdbSaveLzfStringObject
(
FILE
*
fp
,
unsigned
char
*
s
,
size_t
len
)
{
int
rdbSaveLzfStringObject
(
rio
*
rdb
,
unsigned
char
*
s
,
size_t
len
)
{
size_t
comprlen
,
outlen
;
size_t
comprlen
,
outlen
;
unsigned
char
byte
;
unsigned
char
byte
;
int
n
,
nwritten
=
0
;
int
n
,
nwritten
=
0
;
...
@@ -118,16 +114,16 @@ int rdbSaveLzfStringObject(FILE *fp, unsigned char *s, size_t len) {
...
@@ -118,16 +114,16 @@ int rdbSaveLzfStringObject(FILE *fp, unsigned char *s, size_t len) {
}
}
/* Data compressed! Let's save it on disk */
/* Data compressed! Let's save it on disk */
byte
=
(
REDIS_RDB_ENCVAL
<<
6
)
|
REDIS_RDB_ENC_LZF
;
byte
=
(
REDIS_RDB_ENCVAL
<<
6
)
|
REDIS_RDB_ENC_LZF
;
if
((
n
=
rdbWriteRaw
(
fp
,
&
byte
,
1
))
==
-
1
)
goto
writeerr
;
if
((
n
=
rdbWriteRaw
(
rdb
,
&
byte
,
1
))
==
-
1
)
goto
writeerr
;
nwritten
+=
n
;
nwritten
+=
n
;
if
((
n
=
rdbSaveLen
(
fp
,
comprlen
))
==
-
1
)
goto
writeerr
;
if
((
n
=
rdbSaveLen
(
rdb
,
comprlen
))
==
-
1
)
goto
writeerr
;
nwritten
+=
n
;
nwritten
+=
n
;
if
((
n
=
rdbSaveLen
(
fp
,
len
))
==
-
1
)
goto
writeerr
;
if
((
n
=
rdbSaveLen
(
rdb
,
len
))
==
-
1
)
goto
writeerr
;
nwritten
+=
n
;
nwritten
+=
n
;
if
((
n
=
rdbWriteRaw
(
fp
,
out
,
comprlen
))
==
-
1
)
goto
writeerr
;
if
((
n
=
rdbWriteRaw
(
rdb
,
out
,
comprlen
))
==
-
1
)
goto
writeerr
;
nwritten
+=
n
;
nwritten
+=
n
;
zfree
(
out
);
zfree
(
out
);
...
@@ -140,7 +136,7 @@ writeerr:
...
@@ -140,7 +136,7 @@ writeerr:
/* Save a string objet as [len][data] on disk. If the object is a string
/* Save a string objet as [len][data] on disk. If the object is a string
* representation of an integer value we try to save it in a special form */
* representation of an integer value we try to save it in a special form */
int
rdbSaveRawString
(
FILE
*
fp
,
unsigned
char
*
s
,
size_t
len
)
{
int
rdbSaveRawString
(
rio
*
rdb
,
unsigned
char
*
s
,
size_t
len
)
{
int
enclen
;
int
enclen
;
int
n
,
nwritten
=
0
;
int
n
,
nwritten
=
0
;
...
@@ -148,7 +144,7 @@ int rdbSaveRawString(FILE *fp, unsigned char *s, size_t len) {
...
@@ -148,7 +144,7 @@ int rdbSaveRawString(FILE *fp, unsigned char *s, size_t len) {
if
(
len
<=
11
)
{
if
(
len
<=
11
)
{
unsigned
char
buf
[
5
];
unsigned
char
buf
[
5
];
if
((
enclen
=
rdbTryIntegerEncoding
((
char
*
)
s
,
len
,
buf
))
>
0
)
{
if
((
enclen
=
rdbTryIntegerEncoding
((
char
*
)
s
,
len
,
buf
))
>
0
)
{
if
(
rdbWriteRaw
(
fp
,
buf
,
enclen
)
==
-
1
)
return
-
1
;
if
(
rdbWriteRaw
(
rdb
,
buf
,
enclen
)
==
-
1
)
return
-
1
;
return
enclen
;
return
enclen
;
}
}
}
}
...
@@ -156,50 +152,50 @@ int rdbSaveRawString(FILE *fp, unsigned char *s, size_t len) {
...
@@ -156,50 +152,50 @@ int rdbSaveRawString(FILE *fp, unsigned char *s, size_t len) {
/* Try LZF compression - under 20 bytes it's unable to compress even
/* Try LZF compression - under 20 bytes it's unable to compress even
* aaaaaaaaaaaaaaaaaa so skip it */
* aaaaaaaaaaaaaaaaaa so skip it */
if
(
server
.
rdbcompression
&&
len
>
20
)
{
if
(
server
.
rdbcompression
&&
len
>
20
)
{
n
=
rdbSaveLzfStringObject
(
fp
,
s
,
len
);
n
=
rdbSaveLzfStringObject
(
rdb
,
s
,
len
);
if
(
n
==
-
1
)
return
-
1
;
if
(
n
==
-
1
)
return
-
1
;
if
(
n
>
0
)
return
n
;
if
(
n
>
0
)
return
n
;
/* Return value of 0 means data can't be compressed, save the old way */
/* Return value of 0 means data can't be compressed, save the old way */
}
}
/* Store verbatim */
/* Store verbatim */
if
((
n
=
rdbSaveLen
(
fp
,
len
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveLen
(
rdb
,
len
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
if
(
len
>
0
)
{
if
(
len
>
0
)
{
if
(
rdbWriteRaw
(
fp
,
s
,
len
)
==
-
1
)
return
-
1
;
if
(
rdbWriteRaw
(
rdb
,
s
,
len
)
==
-
1
)
return
-
1
;
nwritten
+=
len
;
nwritten
+=
len
;
}
}
return
nwritten
;
return
nwritten
;
}
}
/* Save a long long value as either an encoded string or a string. */
/* Save a long long value as either an encoded string or a string. */
int
rdbSaveLongLongAsStringObject
(
FILE
*
fp
,
long
long
value
)
{
int
rdbSaveLongLongAsStringObject
(
rio
*
rdb
,
long
long
value
)
{
unsigned
char
buf
[
32
];
unsigned
char
buf
[
32
];
int
n
,
nwritten
=
0
;
int
n
,
nwritten
=
0
;
int
enclen
=
rdbEncodeInteger
(
value
,
buf
);
int
enclen
=
rdbEncodeInteger
(
value
,
buf
);
if
(
enclen
>
0
)
{
if
(
enclen
>
0
)
{
return
rdbWriteRaw
(
fp
,
buf
,
enclen
);
return
rdbWriteRaw
(
rdb
,
buf
,
enclen
);
}
else
{
}
else
{
/* Encode as string */
/* Encode as string */
enclen
=
ll2string
((
char
*
)
buf
,
32
,
value
);
enclen
=
ll2string
((
char
*
)
buf
,
32
,
value
);
redisAssert
(
enclen
<
32
);
redisAssert
(
enclen
<
32
);
if
((
n
=
rdbSaveLen
(
fp
,
enclen
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveLen
(
rdb
,
enclen
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
if
((
n
=
rdbWriteRaw
(
fp
,
buf
,
enclen
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbWriteRaw
(
rdb
,
buf
,
enclen
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
}
}
return
nwritten
;
return
nwritten
;
}
}
/* Like rdbSaveStringObjectRaw() but handle encoded objects */
/* Like rdbSaveStringObjectRaw() but handle encoded objects */
int
rdbSaveStringObject
(
FILE
*
fp
,
robj
*
obj
)
{
int
rdbSaveStringObject
(
rio
*
rdb
,
robj
*
obj
)
{
/* Avoid to decode the object, then encode it again, if the
/* Avoid to decode the object, then encode it again, if the
* object is alrady integer encoded. */
* object is alrady integer encoded. */
if
(
obj
->
encoding
==
REDIS_ENCODING_INT
)
{
if
(
obj
->
encoding
==
REDIS_ENCODING_INT
)
{
return
rdbSaveLongLongAsStringObject
(
fp
,(
long
)
obj
->
ptr
);
return
rdbSaveLongLongAsStringObject
(
rdb
,(
long
)
obj
->
ptr
);
}
else
{
}
else
{
redisAssert
(
obj
->
encoding
==
REDIS_ENCODING_RAW
);
redisAssert
(
obj
->
encoding
==
REDIS_ENCODING_RAW
);
return
rdbSaveRawString
(
fp
,
obj
->
ptr
,
sdslen
(
obj
->
ptr
));
return
rdbSaveRawString
(
rdb
,
obj
->
ptr
,
sdslen
(
obj
->
ptr
));
}
}
}
}
...
@@ -211,7 +207,7 @@ int rdbSaveStringObject(FILE *fp, robj *obj) {
...
@@ -211,7 +207,7 @@ int rdbSaveStringObject(FILE *fp, robj *obj) {
* 254: + inf
* 254: + inf
* 255: - inf
* 255: - inf
*/
*/
int
rdbSaveDoubleValue
(
FILE
*
fp
,
double
val
)
{
int
rdbSaveDoubleValue
(
rio
*
rdb
,
double
val
)
{
unsigned
char
buf
[
128
];
unsigned
char
buf
[
128
];
int
len
;
int
len
;
...
@@ -242,36 +238,36 @@ int rdbSaveDoubleValue(FILE *fp, double val) {
...
@@ -242,36 +238,36 @@ int rdbSaveDoubleValue(FILE *fp, double val) {
buf
[
0
]
=
strlen
((
char
*
)
buf
+
1
);
buf
[
0
]
=
strlen
((
char
*
)
buf
+
1
);
len
=
buf
[
0
]
+
1
;
len
=
buf
[
0
]
+
1
;
}
}
return
rdbWriteRaw
(
fp
,
buf
,
len
);
return
rdbWriteRaw
(
rdb
,
buf
,
len
);
}
}
/* Save a Redis object. Returns -1 on error, 0 on success. */
/* Save a Redis object. Returns -1 on error, 0 on success. */
int
rdbSaveObject
(
FILE
*
fp
,
robj
*
o
)
{
int
rdbSaveObject
(
rio
*
rdb
,
robj
*
o
)
{
int
n
,
nwritten
=
0
;
int
n
,
nwritten
=
0
;
if
(
o
->
type
==
REDIS_STRING
)
{
if
(
o
->
type
==
REDIS_STRING
)
{
/* Save a string value */
/* Save a string value */
if
((
n
=
rdbSaveStringObject
(
fp
,
o
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveStringObject
(
rdb
,
o
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
}
else
if
(
o
->
type
==
REDIS_LIST
)
{
}
else
if
(
o
->
type
==
REDIS_LIST
)
{
/* Save a list value */
/* Save a list value */
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
size_t
l
=
ziplistBlobLen
((
unsigned
char
*
)
o
->
ptr
);
size_t
l
=
ziplistBlobLen
((
unsigned
char
*
)
o
->
ptr
);
if
((
n
=
rdbSaveRawString
(
fp
,
o
->
ptr
,
l
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveRawString
(
rdb
,
o
->
ptr
,
l
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
}
else
if
(
o
->
encoding
==
REDIS_ENCODING_LINKEDLIST
)
{
}
else
if
(
o
->
encoding
==
REDIS_ENCODING_LINKEDLIST
)
{
list
*
list
=
o
->
ptr
;
list
*
list
=
o
->
ptr
;
listIter
li
;
listIter
li
;
listNode
*
ln
;
listNode
*
ln
;
if
((
n
=
rdbSaveLen
(
fp
,
listLength
(
list
)))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveLen
(
rdb
,
listLength
(
list
)))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
listRewind
(
list
,
&
li
);
listRewind
(
list
,
&
li
);
while
((
ln
=
listNext
(
&
li
)))
{
while
((
ln
=
listNext
(
&
li
)))
{
robj
*
eleobj
=
listNodeValue
(
ln
);
robj
*
eleobj
=
listNodeValue
(
ln
);
if
((
n
=
rdbSaveStringObject
(
fp
,
eleobj
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveStringObject
(
rdb
,
eleobj
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
}
}
}
else
{
}
else
{
...
@@ -284,19 +280,19 @@ int rdbSaveObject(FILE *fp, robj *o) {
...
@@ -284,19 +280,19 @@ int rdbSaveObject(FILE *fp, robj *o) {
dictIterator
*
di
=
dictGetIterator
(
set
);
dictIterator
*
di
=
dictGetIterator
(
set
);
dictEntry
*
de
;
dictEntry
*
de
;
if
((
n
=
rdbSaveLen
(
fp
,
dictSize
(
set
)))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveLen
(
rdb
,
dictSize
(
set
)))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
robj
*
eleobj
=
dictGetEntryKey
(
de
);
robj
*
eleobj
=
dictGetEntryKey
(
de
);
if
((
n
=
rdbSaveStringObject
(
fp
,
eleobj
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveStringObject
(
rdb
,
eleobj
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
}
}
dictReleaseIterator
(
di
);
dictReleaseIterator
(
di
);
}
else
if
(
o
->
encoding
==
REDIS_ENCODING_INTSET
)
{
}
else
if
(
o
->
encoding
==
REDIS_ENCODING_INTSET
)
{
size_t
l
=
intsetBlobLen
((
intset
*
)
o
->
ptr
);
size_t
l
=
intsetBlobLen
((
intset
*
)
o
->
ptr
);
if
((
n
=
rdbSaveRawString
(
fp
,
o
->
ptr
,
l
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveRawString
(
rdb
,
o
->
ptr
,
l
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
}
else
{
}
else
{
redisPanic
(
"Unknown set encoding"
);
redisPanic
(
"Unknown set encoding"
);
...
@@ -306,23 +302,23 @@ int rdbSaveObject(FILE *fp, robj *o) {
...
@@ -306,23 +302,23 @@ int rdbSaveObject(FILE *fp, robj *o) {
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
size_t
l
=
ziplistBlobLen
((
unsigned
char
*
)
o
->
ptr
);
size_t
l
=
ziplistBlobLen
((
unsigned
char
*
)
o
->
ptr
);
if
((
n
=
rdbSaveRawString
(
fp
,
o
->
ptr
,
l
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveRawString
(
rdb
,
o
->
ptr
,
l
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
}
else
if
(
o
->
encoding
==
REDIS_ENCODING_SKIPLIST
)
{
}
else
if
(
o
->
encoding
==
REDIS_ENCODING_SKIPLIST
)
{
zset
*
zs
=
o
->
ptr
;
zset
*
zs
=
o
->
ptr
;
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
dictIterator
*
di
=
dictGetIterator
(
zs
->
dict
);
dictEntry
*
de
;
dictEntry
*
de
;
if
((
n
=
rdbSaveLen
(
fp
,
dictSize
(
zs
->
dict
)))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveLen
(
rdb
,
dictSize
(
zs
->
dict
)))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
robj
*
eleobj
=
dictGetEntryKey
(
de
);
robj
*
eleobj
=
dictGetEntryKey
(
de
);
double
*
score
=
dictGetEntryVal
(
de
);
double
*
score
=
dictGetEntryVal
(
de
);
if
((
n
=
rdbSaveStringObject
(
fp
,
eleobj
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveStringObject
(
rdb
,
eleobj
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
if
((
n
=
rdbSaveDoubleValue
(
fp
,
*
score
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveDoubleValue
(
rdb
,
*
score
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
}
}
dictReleaseIterator
(
di
);
dictReleaseIterator
(
di
);
...
@@ -334,22 +330,22 @@ int rdbSaveObject(FILE *fp, robj *o) {
...
@@ -334,22 +330,22 @@ int rdbSaveObject(FILE *fp, robj *o) {
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPMAP
)
{
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPMAP
)
{
size_t
l
=
zipmapBlobLen
((
unsigned
char
*
)
o
->
ptr
);
size_t
l
=
zipmapBlobLen
((
unsigned
char
*
)
o
->
ptr
);
if
((
n
=
rdbSaveRawString
(
fp
,
o
->
ptr
,
l
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveRawString
(
rdb
,
o
->
ptr
,
l
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
}
else
{
}
else
{
dictIterator
*
di
=
dictGetIterator
(
o
->
ptr
);
dictIterator
*
di
=
dictGetIterator
(
o
->
ptr
);
dictEntry
*
de
;
dictEntry
*
de
;
if
((
n
=
rdbSaveLen
(
fp
,
dictSize
((
dict
*
)
o
->
ptr
)))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveLen
(
rdb
,
dictSize
((
dict
*
)
o
->
ptr
)))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
robj
*
key
=
dictGetEntryKey
(
de
);
robj
*
key
=
dictGetEntryKey
(
de
);
robj
*
val
=
dictGetEntryVal
(
de
);
robj
*
val
=
dictGetEntryVal
(
de
);
if
((
n
=
rdbSaveStringObject
(
fp
,
key
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveStringObject
(
rdb
,
key
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
if
((
n
=
rdbSaveStringObject
(
fp
,
val
))
==
-
1
)
return
-
1
;
if
((
n
=
rdbSaveStringObject
(
rdb
,
val
))
==
-
1
)
return
-
1
;
nwritten
+=
n
;
nwritten
+=
n
;
}
}
dictReleaseIterator
(
di
);
dictReleaseIterator
(
di
);
...
@@ -374,7 +370,7 @@ off_t rdbSavedObjectLen(robj *o) {
...
@@ -374,7 +370,7 @@ off_t rdbSavedObjectLen(robj *o) {
* On error -1 is returned.
* On error -1 is returned.
* On success if the key was actaully saved 1 is returned, otherwise 0
* On success if the key was actaully saved 1 is returned, otherwise 0
* is returned (the key was already expired). */
* is returned (the key was already expired). */
int
rdbSaveKeyValuePair
(
FILE
*
fp
,
robj
*
key
,
robj
*
val
,
int
rdbSaveKeyValuePair
(
rio
*
rdb
,
robj
*
key
,
robj
*
val
,
time_t
expiretime
,
time_t
now
)
time_t
expiretime
,
time_t
now
)
{
{
int
vtype
;
int
vtype
;
...
@@ -383,8 +379,8 @@ int rdbSaveKeyValuePair(FILE *fp, robj *key, robj *val,
...
@@ -383,8 +379,8 @@ int rdbSaveKeyValuePair(FILE *fp, robj *key, robj *val,
if
(
expiretime
!=
-
1
)
{
if
(
expiretime
!=
-
1
)
{
/* If this key is already expired skip it */
/* If this key is already expired skip it */
if
(
expiretime
<
now
)
return
0
;
if
(
expiretime
<
now
)
return
0
;
if
(
rdbSaveType
(
fp
,
REDIS_EXPIRETIME
)
==
-
1
)
return
-
1
;
if
(
rdbSaveType
(
rdb
,
REDIS_EXPIRETIME
)
==
-
1
)
return
-
1
;
if
(
rdbSaveTime
(
fp
,
expiretime
)
==
-
1
)
return
-
1
;
if
(
rdbSaveTime
(
rdb
,
expiretime
)
==
-
1
)
return
-
1
;
}
}
/* Fix the object type if needed, to support saving zipmaps, ziplists,
/* Fix the object type if needed, to support saving zipmaps, ziplists,
* and intsets, directly as blobs of bytes: they are already serialized. */
* and intsets, directly as blobs of bytes: they are already serialized. */
...
@@ -398,9 +394,9 @@ int rdbSaveKeyValuePair(FILE *fp, robj *key, robj *val,
...
@@ -398,9 +394,9 @@ int rdbSaveKeyValuePair(FILE *fp, robj *key, robj *val,
else
if
(
vtype
==
REDIS_ZSET
&&
val
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
else
if
(
vtype
==
REDIS_ZSET
&&
val
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
vtype
=
REDIS_ZSET_ZIPLIST
;
vtype
=
REDIS_ZSET_ZIPLIST
;
/* Save type, key, value */
/* Save type, key, value */
if
(
rdbSaveType
(
fp
,
vtype
)
==
-
1
)
return
-
1
;
if
(
rdbSaveType
(
rdb
,
vtype
)
==
-
1
)
return
-
1
;
if
(
rdbSaveStringObject
(
fp
,
key
)
==
-
1
)
return
-
1
;
if
(
rdbSaveStringObject
(
rdb
,
key
)
==
-
1
)
return
-
1
;
if
(
rdbSaveObject
(
fp
,
val
)
==
-
1
)
return
-
1
;
if
(
rdbSaveObject
(
rdb
,
val
)
==
-
1
)
return
-
1
;
return
1
;
return
1
;
}
}
...
@@ -408,10 +404,11 @@ int rdbSaveKeyValuePair(FILE *fp, robj *key, robj *val,
...
@@ -408,10 +404,11 @@ int rdbSaveKeyValuePair(FILE *fp, robj *key, robj *val,
int
rdbSave
(
char
*
filename
)
{
int
rdbSave
(
char
*
filename
)
{
dictIterator
*
di
=
NULL
;
dictIterator
*
di
=
NULL
;
dictEntry
*
de
;
dictEntry
*
de
;
FILE
*
fp
;
char
tmpfile
[
256
];
char
tmpfile
[
256
];
int
j
;
int
j
;
time_t
now
=
time
(
NULL
);
time_t
now
=
time
(
NULL
);
FILE
*
fp
;
rio
rdb
;
if
(
server
.
ds_enabled
)
{
if
(
server
.
ds_enabled
)
{
cacheForcePointInTime
();
cacheForcePointInTime
();
...
@@ -425,7 +422,10 @@ int rdbSave(char *filename) {
...
@@ -425,7 +422,10 @@ int rdbSave(char *filename) {
strerror
(
errno
));
strerror
(
errno
));
return
REDIS_ERR
;
return
REDIS_ERR
;
}
}
if
(
fwrite
(
"REDIS0002"
,
9
,
1
,
fp
)
==
0
)
goto
werr
;
rdb
=
rioInitWithFile
(
fp
);
if
(
rdbWriteRaw
(
&
rdb
,
"REDIS0002"
,
9
)
==
-
1
)
goto
werr
;
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
redisDb
*
db
=
server
.
db
+
j
;
redisDb
*
db
=
server
.
db
+
j
;
dict
*
d
=
db
->
dict
;
dict
*
d
=
db
->
dict
;
...
@@ -437,8 +437,8 @@ int rdbSave(char *filename) {
...
@@ -437,8 +437,8 @@ int rdbSave(char *filename) {
}
}
/* Write the SELECT DB opcode */
/* Write the SELECT DB opcode */
if
(
rdbSaveType
(
fp
,
REDIS_SELECTDB
)
==
-
1
)
goto
werr
;
if
(
rdbSaveType
(
&
rdb
,
REDIS_SELECTDB
)
==
-
1
)
goto
werr
;
if
(
rdbSaveLen
(
fp
,
j
)
==
-
1
)
goto
werr
;
if
(
rdbSaveLen
(
&
rdb
,
j
)
==
-
1
)
goto
werr
;
/* Iterate this DB writing every entry */
/* Iterate this DB writing every entry */
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
...
@@ -448,12 +448,12 @@ int rdbSave(char *filename) {
...
@@ -448,12 +448,12 @@ int rdbSave(char *filename) {
initStaticStringObject
(
key
,
keystr
);
initStaticStringObject
(
key
,
keystr
);
expire
=
getExpire
(
db
,
&
key
);
expire
=
getExpire
(
db
,
&
key
);
if
(
rdbSaveKeyValuePair
(
fp
,
&
key
,
o
,
expire
,
now
)
==
-
1
)
goto
werr
;
if
(
rdbSaveKeyValuePair
(
&
rdb
,
&
key
,
o
,
expire
,
now
)
==
-
1
)
goto
werr
;
}
}
dictReleaseIterator
(
di
);
dictReleaseIterator
(
di
);
}
}
/* EOF opcode */
/* EOF opcode */
if
(
rdbSaveType
(
fp
,
REDIS_EOF
)
==
-
1
)
goto
werr
;
if
(
rdbSaveType
(
&
rdb
,
REDIS_EOF
)
==
-
1
)
goto
werr
;
/* Make sure data will not remain on the OS's output buffers */
/* Make sure data will not remain on the OS's output buffers */
fflush
(
fp
);
fflush
(
fp
);
...
@@ -523,15 +523,15 @@ void rdbRemoveTempFile(pid_t childpid) {
...
@@ -523,15 +523,15 @@ void rdbRemoveTempFile(pid_t childpid) {
unlink
(
tmpfile
);
unlink
(
tmpfile
);
}
}
int
rdbLoadType
(
FILE
*
fp
)
{
int
rdbLoadType
(
rio
*
rdb
)
{
unsigned
char
type
;
unsigned
char
type
;
if
(
fread
(
&
type
,
1
,
1
,
fp
)
==
0
)
return
-
1
;
if
(
rioRead
(
rdb
,
&
type
,
1
)
==
0
)
return
-
1
;
return
type
;
return
type
;
}
}
time_t
rdbLoadTime
(
FILE
*
fp
)
{
time_t
rdbLoadTime
(
rio
*
rdb
)
{
int32_t
t32
;
int32_t
t32
;
if
(
fread
(
&
t32
,
4
,
1
,
fp
)
==
0
)
return
-
1
;
if
(
rioRead
(
rdb
,
&
t32
,
4
)
==
0
)
return
-
1
;
return
(
time_t
)
t32
;
return
(
time_t
)
t32
;
}
}
...
@@ -540,13 +540,13 @@ time_t rdbLoadTime(FILE *fp) {
...
@@ -540,13 +540,13 @@ time_t rdbLoadTime(FILE *fp) {
*
*
* isencoded is set to 1 if the readed length is not actually a length but
* isencoded is set to 1 if the readed length is not actually a length but
* an "encoding type", check the above comments for more info */
* an "encoding type", check the above comments for more info */
uint32_t
rdbLoadLen
(
FILE
*
fp
,
int
*
isencoded
)
{
uint32_t
rdbLoadLen
(
rio
*
rdb
,
int
*
isencoded
)
{
unsigned
char
buf
[
2
];
unsigned
char
buf
[
2
];
uint32_t
len
;
uint32_t
len
;
int
type
;
int
type
;
if
(
isencoded
)
*
isencoded
=
0
;
if
(
isencoded
)
*
isencoded
=
0
;
if
(
fread
(
buf
,
1
,
1
,
fp
)
==
0
)
return
REDIS_RDB_LENERR
;
if
(
rioRead
(
rdb
,
buf
,
1
)
==
0
)
return
REDIS_RDB_LENERR
;
type
=
(
buf
[
0
]
&
0xC0
)
>>
6
;
type
=
(
buf
[
0
]
&
0xC0
)
>>
6
;
if
(
type
==
REDIS_RDB_6BITLEN
)
{
if
(
type
==
REDIS_RDB_6BITLEN
)
{
/* Read a 6 bit len */
/* Read a 6 bit len */
...
@@ -557,11 +557,11 @@ uint32_t rdbLoadLen(FILE *fp, int *isencoded) {
...
@@ -557,11 +557,11 @@ uint32_t rdbLoadLen(FILE *fp, int *isencoded) {
return
buf
[
0
]
&
0x3F
;
return
buf
[
0
]
&
0x3F
;
}
else
if
(
type
==
REDIS_RDB_14BITLEN
)
{
}
else
if
(
type
==
REDIS_RDB_14BITLEN
)
{
/* Read a 14 bit len */
/* Read a 14 bit len */
if
(
fread
(
buf
+
1
,
1
,
1
,
fp
)
==
0
)
return
REDIS_RDB_LENERR
;
if
(
rioRead
(
rdb
,
buf
+
1
,
1
)
==
0
)
return
REDIS_RDB_LENERR
;
return
((
buf
[
0
]
&
0x3F
)
<<
8
)
|
buf
[
1
];
return
((
buf
[
0
]
&
0x3F
)
<<
8
)
|
buf
[
1
];
}
else
{
}
else
{
/* Read a 32 bit len */
/* Read a 32 bit len */
if
(
fread
(
&
len
,
4
,
1
,
fp
)
==
0
)
return
REDIS_RDB_LENERR
;
if
(
rioRead
(
rdb
,
&
len
,
4
)
==
0
)
return
REDIS_RDB_LENERR
;
return
ntohl
(
len
);
return
ntohl
(
len
);
}
}
}
}
...
@@ -570,21 +570,21 @@ uint32_t rdbLoadLen(FILE *fp, int *isencoded) {
...
@@ -570,21 +570,21 @@ uint32_t rdbLoadLen(FILE *fp, int *isencoded) {
* encoding type 'enctype'. If encode is true the function may return
* encoding type 'enctype'. If encode is true the function may return
* an integer-encoded object as reply, otherwise the returned object
* an integer-encoded object as reply, otherwise the returned object
* will always be encoded as a raw string. */
* will always be encoded as a raw string. */
robj
*
rdbLoadIntegerObject
(
FILE
*
fp
,
int
enctype
,
int
encode
)
{
robj
*
rdbLoadIntegerObject
(
rio
*
rdb
,
int
enctype
,
int
encode
)
{
unsigned
char
enc
[
4
];
unsigned
char
enc
[
4
];
long
long
val
;
long
long
val
;
if
(
enctype
==
REDIS_RDB_ENC_INT8
)
{
if
(
enctype
==
REDIS_RDB_ENC_INT8
)
{
if
(
fread
(
enc
,
1
,
1
,
fp
)
==
0
)
return
NULL
;
if
(
rioRead
(
rdb
,
enc
,
1
)
==
0
)
return
NULL
;
val
=
(
signed
char
)
enc
[
0
];
val
=
(
signed
char
)
enc
[
0
];
}
else
if
(
enctype
==
REDIS_RDB_ENC_INT16
)
{
}
else
if
(
enctype
==
REDIS_RDB_ENC_INT16
)
{
uint16_t
v
;
uint16_t
v
;
if
(
fread
(
enc
,
2
,
1
,
fp
)
==
0
)
return
NULL
;
if
(
rioRead
(
rdb
,
enc
,
2
)
==
0
)
return
NULL
;
v
=
enc
[
0
]
|
(
enc
[
1
]
<<
8
);
v
=
enc
[
0
]
|
(
enc
[
1
]
<<
8
);
val
=
(
int16_t
)
v
;
val
=
(
int16_t
)
v
;
}
else
if
(
enctype
==
REDIS_RDB_ENC_INT32
)
{
}
else
if
(
enctype
==
REDIS_RDB_ENC_INT32
)
{
uint32_t
v
;
uint32_t
v
;
if
(
fread
(
enc
,
4
,
1
,
fp
)
==
0
)
return
NULL
;
if
(
rioRead
(
rdb
,
enc
,
4
)
==
0
)
return
NULL
;
v
=
enc
[
0
]
|
(
enc
[
1
]
<<
8
)
|
(
enc
[
2
]
<<
16
)
|
(
enc
[
3
]
<<
24
);
v
=
enc
[
0
]
|
(
enc
[
1
]
<<
8
)
|
(
enc
[
2
]
<<
16
)
|
(
enc
[
3
]
<<
24
);
val
=
(
int32_t
)
v
;
val
=
(
int32_t
)
v
;
}
else
{
}
else
{
...
@@ -597,16 +597,16 @@ robj *rdbLoadIntegerObject(FILE *fp, int enctype, int encode) {
...
@@ -597,16 +597,16 @@ robj *rdbLoadIntegerObject(FILE *fp, int enctype, int encode) {
return
createObject
(
REDIS_STRING
,
sdsfromlonglong
(
val
));
return
createObject
(
REDIS_STRING
,
sdsfromlonglong
(
val
));
}
}
robj
*
rdbLoadLzfStringObject
(
FILE
*
fp
)
{
robj
*
rdbLoadLzfStringObject
(
rio
*
rdb
)
{
unsigned
int
len
,
clen
;
unsigned
int
len
,
clen
;
unsigned
char
*
c
=
NULL
;
unsigned
char
*
c
=
NULL
;
sds
val
=
NULL
;
sds
val
=
NULL
;
if
((
clen
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
if
((
clen
=
rdbLoadLen
(
rdb
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
if
((
len
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
if
((
len
=
rdbLoadLen
(
rdb
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
if
((
c
=
zmalloc
(
clen
))
==
NULL
)
goto
err
;
if
((
c
=
zmalloc
(
clen
))
==
NULL
)
goto
err
;
if
((
val
=
sdsnewlen
(
NULL
,
len
))
==
NULL
)
goto
err
;
if
((
val
=
sdsnewlen
(
NULL
,
len
))
==
NULL
)
goto
err
;
if
(
fread
(
c
,
clen
,
1
,
fp
)
==
0
)
goto
err
;
if
(
rioRead
(
rdb
,
c
,
clen
)
==
0
)
goto
err
;
if
(
lzf_decompress
(
c
,
clen
,
val
,
len
)
==
0
)
goto
err
;
if
(
lzf_decompress
(
c
,
clen
,
val
,
len
)
==
0
)
goto
err
;
zfree
(
c
);
zfree
(
c
);
return
createObject
(
REDIS_STRING
,
val
);
return
createObject
(
REDIS_STRING
,
val
);
...
@@ -616,20 +616,20 @@ err:
...
@@ -616,20 +616,20 @@ err:
return
NULL
;
return
NULL
;
}
}
robj
*
rdbGenericLoadStringObject
(
FILE
*
fp
,
int
encode
)
{
robj
*
rdbGenericLoadStringObject
(
rio
*
rdb
,
int
encode
)
{
int
isencoded
;
int
isencoded
;
uint32_t
len
;
uint32_t
len
;
sds
val
;
sds
val
;
len
=
rdbLoadLen
(
fp
,
&
isencoded
);
len
=
rdbLoadLen
(
rdb
,
&
isencoded
);
if
(
isencoded
)
{
if
(
isencoded
)
{
switch
(
len
)
{
switch
(
len
)
{
case
REDIS_RDB_ENC_INT8
:
case
REDIS_RDB_ENC_INT8
:
case
REDIS_RDB_ENC_INT16
:
case
REDIS_RDB_ENC_INT16
:
case
REDIS_RDB_ENC_INT32
:
case
REDIS_RDB_ENC_INT32
:
return
rdbLoadIntegerObject
(
fp
,
len
,
encode
);
return
rdbLoadIntegerObject
(
rdb
,
len
,
encode
);
case
REDIS_RDB_ENC_LZF
:
case
REDIS_RDB_ENC_LZF
:
return
rdbLoadLzfStringObject
(
fp
);
return
rdbLoadLzfStringObject
(
rdb
);
default:
default:
redisPanic
(
"Unknown RDB encoding type"
);
redisPanic
(
"Unknown RDB encoding type"
);
}
}
...
@@ -637,33 +637,33 @@ robj *rdbGenericLoadStringObject(FILE*fp, int encode) {
...
@@ -637,33 +637,33 @@ robj *rdbGenericLoadStringObject(FILE*fp, int encode) {
if
(
len
==
REDIS_RDB_LENERR
)
return
NULL
;
if
(
len
==
REDIS_RDB_LENERR
)
return
NULL
;
val
=
sdsnewlen
(
NULL
,
len
);
val
=
sdsnewlen
(
NULL
,
len
);
if
(
len
&&
fread
(
val
,
len
,
1
,
fp
)
==
0
)
{
if
(
len
&&
rioRead
(
rdb
,
val
,
len
)
==
0
)
{
sdsfree
(
val
);
sdsfree
(
val
);
return
NULL
;
return
NULL
;
}
}
return
createObject
(
REDIS_STRING
,
val
);
return
createObject
(
REDIS_STRING
,
val
);
}
}
robj
*
rdbLoadStringObject
(
FILE
*
fp
)
{
robj
*
rdbLoadStringObject
(
rio
*
rdb
)
{
return
rdbGenericLoadStringObject
(
fp
,
0
);
return
rdbGenericLoadStringObject
(
rdb
,
0
);
}
}
robj
*
rdbLoadEncodedStringObject
(
FILE
*
fp
)
{
robj
*
rdbLoadEncodedStringObject
(
rio
*
rdb
)
{
return
rdbGenericLoadStringObject
(
fp
,
1
);
return
rdbGenericLoadStringObject
(
rdb
,
1
);
}
}
/* For information about double serialization check rdbSaveDoubleValue() */
/* For information about double serialization check rdbSaveDoubleValue() */
int
rdbLoadDoubleValue
(
FILE
*
fp
,
double
*
val
)
{
int
rdbLoadDoubleValue
(
rio
*
rdb
,
double
*
val
)
{
char
buf
[
128
];
char
buf
[
128
];
unsigned
char
len
;
unsigned
char
len
;
if
(
fread
(
&
len
,
1
,
1
,
fp
)
==
0
)
return
-
1
;
if
(
rioRead
(
rdb
,
&
len
,
1
)
==
0
)
return
-
1
;
switch
(
len
)
{
switch
(
len
)
{
case
255
:
*
val
=
R_NegInf
;
return
0
;
case
255
:
*
val
=
R_NegInf
;
return
0
;
case
254
:
*
val
=
R_PosInf
;
return
0
;
case
254
:
*
val
=
R_PosInf
;
return
0
;
case
253
:
*
val
=
R_Nan
;
return
0
;
case
253
:
*
val
=
R_Nan
;
return
0
;
default:
default:
if
(
fread
(
buf
,
len
,
1
,
fp
)
==
0
)
return
-
1
;
if
(
rioRead
(
rdb
,
buf
,
len
)
==
0
)
return
-
1
;
buf
[
len
]
=
'\0'
;
buf
[
len
]
=
'\0'
;
sscanf
(
buf
,
"%lg"
,
val
);
sscanf
(
buf
,
"%lg"
,
val
);
return
0
;
return
0
;
...
@@ -672,19 +672,19 @@ int rdbLoadDoubleValue(FILE *fp, double *val) {
...
@@ -672,19 +672,19 @@ int rdbLoadDoubleValue(FILE *fp, double *val) {
/* Load a Redis object of the specified type from the specified file.
/* Load a Redis object of the specified type from the specified file.
* On success a newly allocated object is returned, otherwise NULL. */
* On success a newly allocated object is returned, otherwise NULL. */
robj
*
rdbLoadObject
(
int
type
,
FILE
*
fp
)
{
robj
*
rdbLoadObject
(
int
type
,
rio
*
rdb
)
{
robj
*
o
,
*
ele
,
*
dec
;
robj
*
o
,
*
ele
,
*
dec
;
size_t
len
;
size_t
len
;
unsigned
int
i
;
unsigned
int
i
;
redisLog
(
REDIS_DEBUG
,
"LOADING OBJECT %d (at %d)
\n
"
,
type
,
f
tell
(
fp
));
redisLog
(
REDIS_DEBUG
,
"LOADING OBJECT %d (at %d)
\n
"
,
type
,
rdb
->
tell
(
rdb
));
if
(
type
==
REDIS_STRING
)
{
if
(
type
==
REDIS_STRING
)
{
/* Read string value */
/* Read string value */
if
((
o
=
rdbLoadEncodedStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
o
=
rdbLoadEncodedStringObject
(
rdb
))
==
NULL
)
return
NULL
;
o
=
tryObjectEncoding
(
o
);
o
=
tryObjectEncoding
(
o
);
}
else
if
(
type
==
REDIS_LIST
)
{
}
else
if
(
type
==
REDIS_LIST
)
{
/* Read list value */
/* Read list value */
if
((
len
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
if
((
len
=
rdbLoadLen
(
rdb
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
/* Use a real list when there are too many entries */
/* Use a real list when there are too many entries */
if
(
len
>
server
.
list_max_ziplist_entries
)
{
if
(
len
>
server
.
list_max_ziplist_entries
)
{
...
@@ -695,7 +695,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -695,7 +695,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
/* Load every single element of the list */
/* Load every single element of the list */
while
(
len
--
)
{
while
(
len
--
)
{
if
((
ele
=
rdbLoadEncodedStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
ele
=
rdbLoadEncodedStringObject
(
rdb
))
==
NULL
)
return
NULL
;
/* If we are using a ziplist and the value is too big, convert
/* If we are using a ziplist and the value is too big, convert
* the object to a real list. */
* the object to a real list. */
...
@@ -716,7 +716,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -716,7 +716,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
}
}
}
else
if
(
type
==
REDIS_SET
)
{
}
else
if
(
type
==
REDIS_SET
)
{
/* Read list/set value */
/* Read list/set value */
if
((
len
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
if
((
len
=
rdbLoadLen
(
rdb
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
/* Use a regular set when there are too many entries. */
/* Use a regular set when there are too many entries. */
if
(
len
>
server
.
set_max_intset_entries
)
{
if
(
len
>
server
.
set_max_intset_entries
)
{
...
@@ -732,7 +732,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -732,7 +732,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
/* Load every single element of the list/set */
/* Load every single element of the list/set */
for
(
i
=
0
;
i
<
len
;
i
++
)
{
for
(
i
=
0
;
i
<
len
;
i
++
)
{
long
long
llval
;
long
long
llval
;
if
((
ele
=
rdbLoadEncodedStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
ele
=
rdbLoadEncodedStringObject
(
rdb
))
==
NULL
)
return
NULL
;
ele
=
tryObjectEncoding
(
ele
);
ele
=
tryObjectEncoding
(
ele
);
if
(
o
->
encoding
==
REDIS_ENCODING_INTSET
)
{
if
(
o
->
encoding
==
REDIS_ENCODING_INTSET
)
{
...
@@ -759,7 +759,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -759,7 +759,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
size_t
maxelelen
=
0
;
size_t
maxelelen
=
0
;
zset
*
zs
;
zset
*
zs
;
if
((
zsetlen
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
if
((
zsetlen
=
rdbLoadLen
(
rdb
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
o
=
createZsetObject
();
o
=
createZsetObject
();
zs
=
o
->
ptr
;
zs
=
o
->
ptr
;
...
@@ -769,9 +769,9 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -769,9 +769,9 @@ robj *rdbLoadObject(int type, FILE *fp) {
double
score
;
double
score
;
zskiplistNode
*
znode
;
zskiplistNode
*
znode
;
if
((
ele
=
rdbLoadEncodedStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
ele
=
rdbLoadEncodedStringObject
(
rdb
))
==
NULL
)
return
NULL
;
ele
=
tryObjectEncoding
(
ele
);
ele
=
tryObjectEncoding
(
ele
);
if
(
rdbLoadDoubleValue
(
fp
,
&
score
)
==
-
1
)
return
NULL
;
if
(
rdbLoadDoubleValue
(
rdb
,
&
score
)
==
-
1
)
return
NULL
;
/* Don't care about integer-encoded strings. */
/* Don't care about integer-encoded strings. */
if
(
ele
->
encoding
==
REDIS_ENCODING_RAW
&&
if
(
ele
->
encoding
==
REDIS_ENCODING_RAW
&&
...
@@ -790,7 +790,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -790,7 +790,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
}
else
if
(
type
==
REDIS_HASH
)
{
}
else
if
(
type
==
REDIS_HASH
)
{
size_t
hashlen
;
size_t
hashlen
;
if
((
hashlen
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
if
((
hashlen
=
rdbLoadLen
(
rdb
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
o
=
createHashObject
();
o
=
createHashObject
();
/* Too many entries? Use an hash table. */
/* Too many entries? Use an hash table. */
if
(
hashlen
>
server
.
hash_max_zipmap_entries
)
if
(
hashlen
>
server
.
hash_max_zipmap_entries
)
...
@@ -800,8 +800,8 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -800,8 +800,8 @@ robj *rdbLoadObject(int type, FILE *fp) {
while
(
hashlen
--
)
{
while
(
hashlen
--
)
{
robj
*
key
,
*
val
;
robj
*
key
,
*
val
;
if
((
key
=
rdbLoadEncodedStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
key
=
rdbLoadEncodedStringObject
(
rdb
))
==
NULL
)
return
NULL
;
if
((
val
=
rdbLoadEncodedStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
val
=
rdbLoadEncodedStringObject
(
rdb
))
==
NULL
)
return
NULL
;
/* If we are using a zipmap and there are too big values
/* If we are using a zipmap and there are too big values
* the object is converted to real hash table encoding. */
* the object is converted to real hash table encoding. */
if
(
o
->
encoding
!=
REDIS_ENCODING_HT
&&
if
(
o
->
encoding
!=
REDIS_ENCODING_HT
&&
...
@@ -838,7 +838,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -838,7 +838,7 @@ robj *rdbLoadObject(int type, FILE *fp) {
type
==
REDIS_SET_INTSET
||
type
==
REDIS_SET_INTSET
||
type
==
REDIS_ZSET_ZIPLIST
)
type
==
REDIS_ZSET_ZIPLIST
)
{
{
robj
*
aux
=
rdbLoadStringObject
(
fp
);
robj
*
aux
=
rdbLoadStringObject
(
rdb
);
if
(
aux
==
NULL
)
return
NULL
;
if
(
aux
==
NULL
)
return
NULL
;
o
=
createObject
(
REDIS_STRING
,
NULL
);
/* string is just placeholder */
o
=
createObject
(
REDIS_STRING
,
NULL
);
/* string is just placeholder */
...
@@ -913,13 +913,14 @@ void stopLoading(void) {
...
@@ -913,13 +913,14 @@ void stopLoading(void) {
}
}
int
rdbLoad
(
char
*
filename
)
{
int
rdbLoad
(
char
*
filename
)
{
FILE
*
fp
;
uint32_t
dbid
;
uint32_t
dbid
;
int
type
,
retval
,
rdbver
;
int
type
,
retval
,
rdbver
;
redisDb
*
db
=
server
.
db
+
0
;
redisDb
*
db
=
server
.
db
+
0
;
char
buf
[
1024
];
char
buf
[
1024
];
time_t
expiretime
,
now
=
time
(
NULL
);
time_t
expiretime
,
now
=
time
(
NULL
);
long
loops
=
0
;
long
loops
=
0
;
FILE
*
fp
;
rio
rdb
;
fp
=
fopen
(
filename
,
"r"
);
fp
=
fopen
(
filename
,
"r"
);
if
(
!
fp
)
return
REDIS_ERR
;
if
(
!
fp
)
return
REDIS_ERR
;
...
@@ -938,27 +939,28 @@ int rdbLoad(char *filename) {
...
@@ -938,27 +939,28 @@ int rdbLoad(char *filename) {
}
}
startLoading
(
fp
);
startLoading
(
fp
);
rdb
=
rioInitWithFile
(
fp
);
while
(
1
)
{
while
(
1
)
{
robj
*
key
,
*
val
;
robj
*
key
,
*
val
;
expiretime
=
-
1
;
expiretime
=
-
1
;
/* Serve the clients from time to time */
/* Serve the clients from time to time */
if
(
!
(
loops
++
%
1000
))
{
if
(
!
(
loops
++
%
1000
))
{
loadingProgress
(
ftello
(
fp
));
loadingProgress
(
rdb
.
tell
(
&
rdb
));
aeProcessEvents
(
server
.
el
,
AE_FILE_EVENTS
|
AE_DONT_WAIT
);
aeProcessEvents
(
server
.
el
,
AE_FILE_EVENTS
|
AE_DONT_WAIT
);
}
}
/* Read type. */
/* Read type. */
if
((
type
=
rdbLoadType
(
fp
))
==
-
1
)
goto
eoferr
;
if
((
type
=
rdbLoadType
(
&
rdb
))
==
-
1
)
goto
eoferr
;
if
(
type
==
REDIS_EXPIRETIME
)
{
if
(
type
==
REDIS_EXPIRETIME
)
{
if
((
expiretime
=
rdbLoadTime
(
fp
))
==
-
1
)
goto
eoferr
;
if
((
expiretime
=
rdbLoadTime
(
&
rdb
))
==
-
1
)
goto
eoferr
;
/* We read the time so we need to read the object type again */
/* We read the time so we need to read the object type again */
if
((
type
=
rdbLoadType
(
fp
))
==
-
1
)
goto
eoferr
;
if
((
type
=
rdbLoadType
(
&
rdb
))
==
-
1
)
goto
eoferr
;
}
}
if
(
type
==
REDIS_EOF
)
break
;
if
(
type
==
REDIS_EOF
)
break
;
/* Handle SELECT DB opcode as a special case */
/* Handle SELECT DB opcode as a special case */
if
(
type
==
REDIS_SELECTDB
)
{
if
(
type
==
REDIS_SELECTDB
)
{
if
((
dbid
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
if
((
dbid
=
rdbLoadLen
(
&
rdb
,
NULL
))
==
REDIS_RDB_LENERR
)
goto
eoferr
;
goto
eoferr
;
if
(
dbid
>=
(
unsigned
)
server
.
dbnum
)
{
if
(
dbid
>=
(
unsigned
)
server
.
dbnum
)
{
redisLog
(
REDIS_WARNING
,
"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting
\n
"
,
server
.
dbnum
);
redisLog
(
REDIS_WARNING
,
"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting
\n
"
,
server
.
dbnum
);
...
@@ -968,9 +970,9 @@ int rdbLoad(char *filename) {
...
@@ -968,9 +970,9 @@ int rdbLoad(char *filename) {
continue
;
continue
;
}
}
/* Read key */
/* Read key */
if
((
key
=
rdbLoadStringObject
(
fp
))
==
NULL
)
goto
eoferr
;
if
((
key
=
rdbLoadStringObject
(
&
rdb
))
==
NULL
)
goto
eoferr
;
/* Read value */
/* Read value */
if
((
val
=
rdbLoadObject
(
type
,
fp
))
==
NULL
)
goto
eoferr
;
if
((
val
=
rdbLoadObject
(
type
,
&
rdb
))
==
NULL
)
goto
eoferr
;
/* Check if the key already expired */
/* Check if the key already expired */
if
(
expiretime
!=
-
1
&&
expiretime
<
now
)
{
if
(
expiretime
!=
-
1
&&
expiretime
<
now
)
{
decrRefCount
(
key
);
decrRefCount
(
key
);
...
...
src/rdb.h
0 → 100644
View file @
2e4b0e77
#ifndef __REDIS_RDB_H
#define __REDIS_RDB_H
#include <stdio.h>
#include "rio.h"
/* TBD: include only necessary headers. */
#include "redis.h"
int
rdbLoad
(
char
*
filename
);
int
rdbSaveBackground
(
char
*
filename
);
void
rdbRemoveTempFile
(
pid_t
childpid
);
int
rdbSave
(
char
*
filename
);
int
rdbSaveObject
(
rio
*
rdb
,
robj
*
o
);
off_t
rdbSavedObjectLen
(
robj
*
o
);
off_t
rdbSavedObjectPages
(
robj
*
o
);
robj
*
rdbLoadObject
(
int
type
,
rio
*
rdb
);
void
backgroundSaveDoneHandler
(
int
exitcode
,
int
bysignal
);
int
rdbSaveKeyValuePair
(
rio
*
rdb
,
robj
*
key
,
robj
*
val
,
time_t
expireitme
,
time_t
now
);
int
rdbLoadType
(
rio
*
rdb
);
time_t
rdbLoadTime
(
rio
*
rdb
);
robj
*
rdbLoadStringObject
(
rio
*
rdb
);
int
rdbSaveType
(
rio
*
rdb
,
unsigned
char
type
);
int
rdbSaveLen
(
rio
*
rdb
,
uint32_t
len
);
#endif
src/redis.h
View file @
2e4b0e77
...
@@ -898,21 +898,7 @@ void loadingProgress(off_t pos);
...
@@ -898,21 +898,7 @@ void loadingProgress(off_t pos);
void
stopLoading
(
void
);
void
stopLoading
(
void
);
/* RDB persistence */
/* RDB persistence */
int
rdbLoad
(
char
*
filename
);
#include "rdb.h"
int
rdbSaveBackground
(
char
*
filename
);
void
rdbRemoveTempFile
(
pid_t
childpid
);
int
rdbSave
(
char
*
filename
);
int
rdbSaveObject
(
FILE
*
fp
,
robj
*
o
);
off_t
rdbSavedObjectLen
(
robj
*
o
);
off_t
rdbSavedObjectPages
(
robj
*
o
);
robj
*
rdbLoadObject
(
int
type
,
FILE
*
fp
);
void
backgroundSaveDoneHandler
(
int
exitcode
,
int
bysignal
);
int
rdbSaveKeyValuePair
(
FILE
*
fp
,
robj
*
key
,
robj
*
val
,
time_t
expireitme
,
time_t
now
);
int
rdbLoadType
(
FILE
*
fp
);
time_t
rdbLoadTime
(
FILE
*
fp
);
robj
*
rdbLoadStringObject
(
FILE
*
fp
);
int
rdbSaveType
(
FILE
*
fp
,
unsigned
char
type
);
int
rdbSaveLen
(
FILE
*
fp
,
uint32_t
len
);
/* AOF persistence */
/* AOF persistence */
void
flushAppendOnlyFile
(
void
);
void
flushAppendOnlyFile
(
void
);
...
...
src/rio.c
0 → 100644
View file @
2e4b0e77
#include <string.h>
#include "rio.h"
#include "util.h"
/* Returns 1 or 0 for success/failure. */
static
size_t
rioBufferWrite
(
rio
*
r
,
const
void
*
buf
,
size_t
len
)
{
r
->
io
.
buffer
.
ptr
=
sdscatlen
(
r
->
io
.
buffer
.
ptr
,(
char
*
)
buf
,
len
);
r
->
io
.
buffer
.
pos
+=
len
;
return
len
;
}
/* Returns 1 or 0 for success/failure. */
static
size_t
rioBufferRead
(
rio
*
r
,
void
*
buf
,
size_t
len
)
{
if
(
sdslen
(
r
->
io
.
buffer
.
ptr
)
-
r
->
io
.
buffer
.
pos
<
len
)
return
0
;
memcpy
(
buf
,
r
->
io
.
buffer
.
ptr
+
r
->
io
.
buffer
.
pos
,
len
);
r
->
io
.
buffer
.
pos
+=
len
;
return
1
;
}
/* Returns read/write position in buffer. */
static
off_t
rioBufferTell
(
rio
*
r
)
{
return
r
->
io
.
buffer
.
pos
;
}
/* Returns 1 or 0 for success/failure. */
static
size_t
rioFileWrite
(
rio
*
r
,
const
void
*
buf
,
size_t
len
)
{
return
fwrite
(
buf
,
len
,
1
,
r
->
io
.
file
.
fp
);
}
/* Returns 1 or 0 for success/failure. */
static
size_t
rioFileRead
(
rio
*
r
,
void
*
buf
,
size_t
len
)
{
return
fread
(
buf
,
len
,
1
,
r
->
io
.
file
.
fp
);
}
/* Returns read/write position in file. */
static
off_t
rioFileTell
(
rio
*
r
)
{
return
ftello
(
r
->
io
.
file
.
fp
);
}
static
const
rio
rioBufferIO
=
{
rioBufferRead
,
rioBufferWrite
,
rioBufferTell
,
{
{
NULL
,
0
}
}
/* union for io-specific vars */
};
static
const
rio
rioFileIO
=
{
rioFileRead
,
rioFileWrite
,
rioFileTell
,
{
{
NULL
,
0
}
}
/* union for io-specific vars */
};
rio
rioInitWithFile
(
FILE
*
fp
)
{
rio
r
=
rioFileIO
;
r
.
io
.
file
.
fp
=
fp
;
return
r
;
}
rio
rioInitWithBuffer
(
sds
s
)
{
rio
r
=
rioBufferIO
;
r
.
io
.
buffer
.
ptr
=
s
;
r
.
io
.
buffer
.
pos
=
0
;
return
r
;
}
/* Write multi bulk count in the format: "*<count>\r\n". */
size_t
rioWriteBulkCount
(
rio
*
r
,
char
prefix
,
int
count
)
{
char
cbuf
[
128
];
int
clen
;
cbuf
[
0
]
=
prefix
;
clen
=
1
+
ll2string
(
cbuf
+
1
,
sizeof
(
cbuf
)
-
1
,
count
);
cbuf
[
clen
++
]
=
'\r'
;
cbuf
[
clen
++
]
=
'\n'
;
if
(
rioWrite
(
r
,
cbuf
,
clen
)
==
0
)
return
0
;
return
clen
;
}
/* Write binary-safe string in the format: "$<count>\r\n<payload>\r\n". */
size_t
rioWriteBulkString
(
rio
*
r
,
const
char
*
buf
,
size_t
len
)
{
size_t
nwritten
;
if
((
nwritten
=
rioWriteBulkCount
(
r
,
'$'
,
len
))
==
0
)
return
0
;
if
(
len
>
0
&&
rioWrite
(
r
,
buf
,
len
)
==
0
)
return
0
;
if
(
rioWrite
(
r
,
"
\r\n
"
,
2
)
==
0
)
return
0
;
return
nwritten
+
len
+
2
;
}
/* Write a long long value in format: "$<count>\r\n<payload>\r\n". */
size_t
rioWriteBulkLongLong
(
rio
*
r
,
long
long
l
)
{
char
lbuf
[
32
];
unsigned
int
llen
;
llen
=
ll2string
(
lbuf
,
sizeof
(
lbuf
),
l
);
return
rioWriteBulkString
(
r
,
lbuf
,
llen
);
}
/* Write a double value in the format: "$<count>\r\n<payload>\r\n" */
size_t
rioWriteBulkDouble
(
rio
*
r
,
double
d
)
{
char
dbuf
[
128
];
unsigned
int
dlen
;
dlen
=
snprintf
(
dbuf
,
sizeof
(
dbuf
),
"%.17g"
,
d
);
return
rioWriteBulkString
(
r
,
dbuf
,
dlen
);
}
src/rio.h
0 → 100644
View file @
2e4b0e77
#ifndef __REDIS_RIO_H
#define __REDIS_RIO_H
#include <stdio.h>
#include "sds.h"
struct
_rio
{
/* Backend functions. Both read and write should return 0 for short reads
* or writes, identical to the return values of fread/fwrite. */
size_t
(
*
read
)(
struct
_rio
*
,
void
*
buf
,
size_t
len
);
size_t
(
*
write
)(
struct
_rio
*
,
const
void
*
buf
,
size_t
len
);
off_t
(
*
tell
)(
struct
_rio
*
);
/* Backend-specific vars. */
union
{
struct
{
sds
ptr
;
off_t
pos
;
}
buffer
;
struct
{
FILE
*
fp
;
}
file
;
}
io
;
};
typedef
struct
_rio
rio
;
#define rioWrite(rio,buf,len) ((rio)->write((rio),(buf),(len)))
#define rioRead(rio,buf,len) ((rio)->read((rio),(buf),(len)))
rio
rioInitWithFile
(
FILE
*
fp
);
rio
rioInitWithBuffer
(
sds
s
);
size_t
rioWriteBulkCount
(
rio
*
r
,
char
prefix
,
int
count
);
size_t
rioWriteBulkString
(
rio
*
r
,
const
char
*
buf
,
size_t
len
);
size_t
rioWriteBulkLongLong
(
rio
*
r
,
long
long
l
);
size_t
rioWriteBulkDouble
(
rio
*
r
,
double
d
);
#endif
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