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
hiredis
Commits
e621f313
Commit
e621f313
authored
Sep 20, 2010
by
Pieter Noordhuis
Browse files
Expose API for streaming bytes to a reply
parent
4ec97f59
Changes
2
Hide whitespace changes
Inline
Side-by-side
hiredis.c
View file @
e621f313
...
...
@@ -38,14 +38,12 @@
#include "sds.h"
typedef
struct
redisReader
{
char
*
buf
;
/* read buffer */
int
len
;
/* buffer length */
int
avail
;
/* available bytes for consumption */
int
pos
;
/* buffer cursor */
sds
buf
;
/* read buffer */
unsigned
int
pos
;
/* buffer cursor */
redisReply
**
rlist
;
/* list of items to process */
int
rlen
;
/* list length */
int
rpos
;
/* list cursor */
unsigned
int
rlen
;
/* list length */
unsigned
int
rpos
;
/* list cursor */
}
redisReader
;
static
redisReply
*
redisReadReply
(
int
fd
);
...
...
@@ -105,9 +103,9 @@ static redisReply *redisIOError(void) {
return
createReplyObject
(
REDIS_REPLY_ERROR
,
sdsnew
(
"I/O error"
));
}
static
char
*
readBytes
(
redisReader
*
r
,
int
bytes
)
{
static
char
*
readBytes
(
redisReader
*
r
,
unsigned
int
bytes
)
{
char
*
p
;
if
(
r
->
len
-
r
->
pos
>=
bytes
)
{
if
(
sdslen
(
r
->
buf
)
-
r
->
pos
>=
bytes
)
{
p
=
r
->
buf
+
r
->
pos
;
r
->
pos
+=
bytes
;
return
p
;
...
...
@@ -274,56 +272,96 @@ static int processItem(redisReader *r) {
#define READ_BUFFER_SIZE 2048
static
redisReply
*
redisReadReply
(
int
fd
)
{
void
*
reader
=
redisCreateReplyReader
();
redisReply
*
reply
;
redisReader
r
;
int
bytes
;
/* setup read buffer */
r
.
buf
=
malloc
(
READ_BUFFER_SIZE
+
1
);
r
.
len
=
READ_BUFFER_SIZE
;
r
.
avail
=
0
;
r
.
pos
=
0
;
/* setup list of items to process */
r
.
rlist
=
malloc
(
sizeof
(
redisReply
*
));
r
.
rlist
[
0
]
=
createReplyObject
(
-
1
,
NULL
);
r
.
rlen
=
1
;
r
.
rpos
=
0
;
while
(
r
.
rpos
<
r
.
rlen
)
{
/* discard the buffer upto pos */
if
(
r
.
pos
>
0
)
{
memmove
(
r
.
buf
,
r
.
buf
+
r
.
pos
,
r
.
len
-
r
.
pos
);
r
.
avail
-=
r
.
pos
;
r
.
pos
=
0
;
char
buf
[
1024
];
int
nread
;
do
{
if
((
nread
=
read
(
fd
,
buf
,
sizeof
(
buf
)))
<=
0
)
{
reply
=
redisIOError
();
break
;
}
else
{
reply
=
redisFeedReplyReader
(
reader
,
buf
,
nread
);
}
}
while
(
reply
==
NULL
);
redisFreeReplyReader
(
reader
);
return
reply
;
}
void
*
redisCreateReplyReader
()
{
redisReader
*
r
=
calloc
(
sizeof
(
redisReader
),
1
);
r
->
buf
=
sdsempty
();
return
r
;
}
void
redisFreeReplyReader
(
void
*
reader
)
{
redisReader
*
r
=
reader
;
if
(
r
->
buf
!=
NULL
)
{
sdsfree
(
r
->
buf
);
}
if
(
r
->
rlen
>
0
)
{
freeReplyObject
(
r
->
rlist
[
0
]);
free
(
r
->
rlist
);
}
free
(
r
);
}
void
*
redisFeedReplyReader
(
void
*
reader
,
char
*
buf
,
int
len
)
{
redisReader
*
r
=
reader
;
/* Check if we are able to do *something*. */
if
(
sdslen
(
r
->
buf
)
==
0
&&
(
buf
==
NULL
||
len
<=
0
))
return
NULL
;
/* Copy the provided buffer. */
if
(
buf
!=
NULL
&&
len
>=
1
)
r
->
buf
=
sdscatlen
(
r
->
buf
,
buf
,
len
);
/* Create first item to process when the item list is empty. */
if
(
r
->
rlen
==
0
)
{
r
->
rlist
=
malloc
(
sizeof
(
redisReply
*
));
r
->
rlist
[
0
]
=
createReplyObject
(
-
1
,
NULL
);
r
->
rlen
=
1
;
r
->
rpos
=
0
;
}
/* make sure there is room for at least BUFFER_SIZE */
if
(
r
.
len
-
r
.
avail
<
READ_BUFFER_SIZE
)
{
r
.
buf
=
realloc
(
r
.
buf
,
r
.
avail
+
READ_BUFFER_SIZE
+
1
);
r
.
len
=
r
.
avail
+
READ_BUFFER_SIZE
;
/* Process items in reply. */
while
(
r
->
rpos
<
r
->
rlen
)
if
(
processItem
(
r
)
<
0
)
break
;
/* Discard the consumed part of the buffer. */
if
(
r
->
pos
>
0
)
{
if
(
r
->
pos
==
sdslen
(
r
->
buf
))
{
/* sdsrange has a quirck on this edge case. */
sdsfree
(
r
->
buf
);
r
->
buf
=
sdsempty
();
}
else
{
r
->
buf
=
sdsrange
(
r
->
buf
,
r
->
pos
,
sdslen
(
r
->
buf
));
}
r
->
pos
=
0
;
}
/* Emit a reply when there is one. */
if
(
r
->
rpos
==
r
->
rlen
)
{
redisReply
*
reply
=
r
->
rlist
[
0
];
/* read from socket into buffer */
if
((
bytes
=
read
(
fd
,
r
.
buf
+
r
.
avail
,
READ_BUFFER_SIZE
))
<=
0
)
{
/* rlist[0] is the "root" reply object */
freeReplyObject
(
r
.
rlist
[
0
]);
free
(
r
.
buf
);
free
(
r
.
rlist
);
return
redisIOError
();
/* Destroy the buffer when it is empty and is quite large. */
if
(
sdslen
(
r
->
buf
)
==
0
&&
sdsavail
(
r
->
buf
)
>
16
*
1024
)
{
sdsfree
(
r
->
buf
);
r
->
buf
=
sdsempty
();
r
->
pos
=
0
;
}
r
.
avail
+=
bytes
;
r
.
buf
[
r
.
avail
]
=
'\0'
;
/* process items in reply */
while
(
r
.
rpos
<
r
.
rlen
)
if
(
processItem
(
&
r
)
<
0
)
break
;
/* Free list of items to process. */
free
(
r
->
rlist
);
r
->
rlen
=
r
->
rpos
=
0
;
return
reply
;
}
else
{
return
NULL
;
}
reply
=
r
.
rlist
[
0
];
free
(
r
.
buf
);
free
(
r
.
rlist
);
return
reply
;
}
/* Helper function for redisCommand(). It's used to append the next argument
...
...
hiredis.h
View file @
e621f313
...
...
@@ -51,5 +51,8 @@ typedef struct redisReply {
redisReply
*
redisConnect
(
int
*
fd
,
const
char
*
ip
,
int
port
);
void
freeReplyObject
(
redisReply
*
r
);
redisReply
*
redisCommand
(
int
fd
,
const
char
*
format
,
...);
void
*
redisCreateReplyReader
();
void
redisFreeReplyReader
(
void
*
ptr
);
void
*
redisFeedReplyReader
(
void
*
reader
,
char
*
buf
,
int
len
);
#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