Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
B
brpc
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
brpc
Commits
bace6cca
Commit
bace6cca
authored
5 years ago
by
zhujiashun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
redis_server_protocol: add async interface
parent
8c1f531f
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
56 additions
and
37 deletions
+56
-37
redis_protocol.cpp
src/brpc/policy/redis_protocol.cpp
+0
-0
redis.cpp
src/brpc/redis.cpp
+2
-2
redis.h
src/brpc/redis.h
+19
-15
redis_message.cpp
src/brpc/redis_message.cpp
+1
-1
redis_message.h
src/brpc/redis_message.h
+33
-18
CMakeLists.txt
test/CMakeLists.txt
+1
-1
brpc_redis_unittest.cpp
test/brpc_redis_unittest.cpp
+0
-0
No files found.
src/brpc/policy/redis_protocol.cpp
View file @
bace6cca
This diff is collapsed.
Click to expand it.
src/brpc/redis.cpp
View file @
bace6cca
...
...
@@ -325,7 +325,7 @@ void RedisResponse::MergeFrom(const RedisResponse& from) {
RedisMessage
*
new_others
=
(
RedisMessage
*
)
_arena
.
allocate
(
sizeof
(
RedisMessage
)
*
(
new_nreply
-
1
));
for
(
int
i
=
0
;
i
<
new_nreply
-
1
;
++
i
)
{
new
(
new_others
+
i
)
RedisMessage
;
new
(
new_others
+
i
)
RedisMessage
(
NULL
)
;
}
int
new_other_index
=
0
;
for
(
int
i
=
1
;
i
<
_nreply
;
++
i
)
{
...
...
@@ -436,7 +436,7 @@ std::ostream& operator<<(std::ostream& os, const RedisResponse& response) {
return
os
;
}
bool
RedisService
::
AddHandler
(
const
std
::
string
&
name
,
RedisCommandHandler
*
handler
)
{
bool
RedisService
::
Add
Command
Handler
(
const
std
::
string
&
name
,
RedisCommandHandler
*
handler
)
{
std
::
string
lcname
;
lcname
.
reserve
(
name
.
size
());
for
(
auto
c
:
name
)
{
...
...
This diff is collapsed.
Click to expand it.
src/brpc/redis.h
View file @
bace6cca
...
...
@@ -21,12 +21,15 @@
#define BRPC_REDIS_H
#include <google/protobuf/message.h>
#include <unordered_map>
#include <vector>
#include "butil/iobuf.h"
#include "butil/strings/string_piece.h"
#include "butil/arena.h"
#include "brpc/proto_base.pb.h"
#include "brpc/redis_message.h"
#include "brpc/parse_result.h"
#include "brpc/callback.h"
namespace
brpc
{
...
...
@@ -209,39 +212,41 @@ private:
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
RedisRequest
&
);
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
RedisResponse
&
);
enum
RedisCommandResult
{
REDIS_COMMAND_OK
=
0
,
REDIS_COMMAND_CONTINUE
=
1
,
REDIS_COMMAND_ERROR
=
2
,
};
// The handler for a redis command. Run() and New() should be implemented
// by user. For Run(), `args` is the redis command argument. For example,
// "set foo bar" corresponds to args[0] == "set", args[1] == "foo" and
// args[2] == "bar". `output` is the content that sent to client side,
// which should be set by user. Read brpc/src/redis_message.h for more usage.
// `arena` is the memory arena that `output` would use.
// For New(), whenever a tcp connection is established, all handlers would
// be cloned and brpc makes sure that all requests of the same command name
// from one connection would be sent to the same command handler. All requests
// in one connection are executed sequentially, just like what redis-server does.
// For New(), whenever a tcp connection is established, a bunch of new handlers
// would be created using New() of corresponding handler and brpc makes sure that
// all requests of the same command name from one connection would be redirected
// to the same New()-ed command handler. All requests in one connection are
// executed sequentially, just like what redis-server does.
class
RedisCommandHandler
{
public
:
enum
Result
{
OK
=
0
,
CONTINUE
=
1
,
};
~
RedisCommandHandler
()
{}
virtual
RedisCommandResult
Run
(
const
std
::
vector
<
const
char
*>&
args
,
RedisMessage
*
output
,
butil
::
Arena
*
arena
)
=
0
;
virtual
RedisCommandHandler
::
Result
Run
(
const
char
*
args
[],
RedisMessage
*
output
,
google
::
protobuf
::
Closure
*
done
)
=
0
;
virtual
RedisCommandHandler
*
New
()
=
0
;
};
// Implement this class and assign an instance to ServerOption.redis_service
// to enable redis support. To support a particular command, you should implement
// the corresponding handler and call AddHandler to install it.
// the corresponding handler and call Add
Command
Handler to install it.
class
RedisService
{
public
:
typedef
std
::
unordered_map
<
std
::
string
,
std
::
shared_ptr
<
RedisCommandHandler
>>
CommandMap
;
virtual
~
RedisService
()
{}
bool
AddHandler
(
const
std
::
string
&
name
,
RedisCommandHandler
*
handler
);
bool
Add
Command
Handler
(
const
std
::
string
&
name
,
RedisCommandHandler
*
handler
);
void
CloneCommandMap
(
CommandMap
*
map
);
private
:
CommandMap
_command_map
;
...
...
@@ -249,5 +254,4 @@ private:
}
// namespace brpc
#endif // BRPC_REDIS_H
This diff is collapsed.
Click to expand it.
src/brpc/redis_message.cpp
View file @
bace6cca
...
...
@@ -245,7 +245,7 @@ ParseError RedisMessage::ConsumePartialIOBuf(butil::IOBuf& buf, butil::Arena* ar
return
PARSE_ERROR_ABSOLUTELY_WRONG
;
}
for
(
int64_t
i
=
0
;
i
<
count
;
++
i
)
{
new
(
&
subs
[
i
])
RedisMessage
;
new
(
&
subs
[
i
])
RedisMessage
(
NULL
)
;
}
buf
.
pop_front
(
crlf_pos
+
2
/*CRLF*/
);
_type
=
REDIS_MESSAGE_ARRAY
;
...
...
This diff is collapsed.
Click to expand it.
src/brpc/redis_message.h
View file @
bace6cca
...
...
@@ -44,8 +44,9 @@ const char* RedisMessageTypeToString(RedisMessageType);
// A reply from redis-server.
class
RedisMessage
{
public
:
// A default
constructed
reply is a nil.
// A default reply is a nil.
RedisMessage
();
RedisMessage
(
butil
::
Arena
*
arena
);
// Type of the reply.
RedisMessageType
type
()
const
{
return
_type
;
}
...
...
@@ -57,11 +58,11 @@ public:
bool
is_array
()
const
;
// True if the reply is an array.
bool
set_nil_string
();
// "$-1\r\n"
bool
set_array
(
int
size
,
butil
::
Arena
*
arena
);
// size == -1 means nil array("*-1\r\n")
bool
set_status
(
const
std
::
string
&
str
,
butil
::
Arena
*
arena
);
bool
set_error
(
const
std
::
string
&
str
,
butil
::
Arena
*
arena
);
bool
set_array
(
int
size
);
// size == -1 means nil array("*-1\r\n")
bool
set_status
(
const
std
::
string
&
str
);
bool
set_error
(
const
std
::
string
&
str
);
bool
set_integer
(
int64_t
value
);
bool
set_bulk_string
(
const
std
::
string
&
str
,
butil
::
Arena
*
arena
);
bool
set_bulk_string
(
const
std
::
string
&
str
);
// Convert the reply into a signed 64-bit integer(according to
// http://redis.io/topics/protocol). If the reply is not an integer,
...
...
@@ -129,7 +130,7 @@ private:
// by calling CopyFrom[Different|Same]Arena.
DISALLOW_COPY_AND_ASSIGN
(
RedisMessage
);
bool
set_basic_string
(
const
std
::
string
&
str
,
butil
::
Arena
*
arena
,
RedisMessageType
type
);
bool
set_basic_string
(
const
std
::
string
&
str
,
RedisMessageType
type
);
RedisMessageType
_type
;
uint32_t
_length
;
// length of short_str/long_str, count of replies
...
...
@@ -143,6 +144,7 @@ private:
}
array
;
uint64_t
padding
[
2
];
// For swapping, must cover all bytes.
}
_data
;
butil
::
Arena
*
_arena
;
};
// =========== inline impl. ==============
...
...
@@ -152,9 +154,15 @@ inline std::ostream& operator<<(std::ostream& os, const RedisMessage& r) {
return
os
;
}
inline
RedisMessage
::
RedisMessage
(
butil
::
Arena
*
arena
)
:
RedisMessage
()
{
_arena
=
arena
;
}
inline
RedisMessage
::
RedisMessage
()
:
_type
(
REDIS_MESSAGE_NIL
)
,
_length
(
0
)
{
,
_length
(
0
)
,
_arena
(
NULL
)
{
_data
.
array
.
last_index
=
-
1
;
_data
.
array
.
replies
=
NULL
;
}
...
...
@@ -180,12 +188,16 @@ inline int64_t RedisMessage::integer() const {
}
inline
bool
RedisMessage
::
set_nil_string
()
{
if
(
!
_arena
)
return
false
;
_type
=
REDIS_MESSAGE_STRING
;
_length
=
npos
;
return
true
;
}
inline
bool
RedisMessage
::
set_array
(
int
size
,
butil
::
Arena
*
arena
)
{
inline
bool
RedisMessage
::
set_array
(
int
size
)
{
if
(
!
_arena
)
{
return
false
;
}
_type
=
REDIS_MESSAGE_ARRAY
;
if
(
size
<
0
)
{
_length
=
npos
;
...
...
@@ -194,26 +206,29 @@ inline bool RedisMessage::set_array(int size, butil::Arena* arena) {
_length
=
0
;
return
true
;
}
RedisMessage
*
subs
=
(
RedisMessage
*
)
arena
->
allocate
(
sizeof
(
RedisMessage
)
*
size
);
RedisMessage
*
subs
=
(
RedisMessage
*
)
_
arena
->
allocate
(
sizeof
(
RedisMessage
)
*
size
);
if
(
!
subs
)
{
LOG
(
FATAL
)
<<
"Fail to allocate RedisMessage["
<<
size
<<
"]"
;
return
false
;
}
for
(
int
i
=
0
;
i
<
size
;
++
i
)
{
new
(
&
subs
[
i
])
RedisMessage
;
new
(
&
subs
[
i
])
RedisMessage
(
_arena
)
;
}
_length
=
size
;
_data
.
array
.
replies
=
subs
;
return
true
;
}
inline
bool
RedisMessage
::
set_basic_string
(
const
std
::
string
&
str
,
butil
::
Arena
*
arena
,
RedisMessageType
type
)
{
inline
bool
RedisMessage
::
set_basic_string
(
const
std
::
string
&
str
,
RedisMessageType
type
)
{
if
(
!
_arena
)
{
return
false
;
}
size_t
size
=
str
.
size
();
if
(
size
<
sizeof
(
_data
.
short_str
))
{
memcpy
(
_data
.
short_str
,
str
.
c_str
(),
size
);
_data
.
short_str
[
size
]
=
'\0'
;
}
else
{
char
*
d
=
(
char
*
)
arena
->
allocate
((
_length
/
8
+
1
)
*
8
);
char
*
d
=
(
char
*
)
_
arena
->
allocate
((
_length
/
8
+
1
)
*
8
);
if
(
!
d
)
{
LOG
(
FATAL
)
<<
"Fail to allocate string["
<<
size
<<
"]"
;
return
false
;
...
...
@@ -227,12 +242,12 @@ inline bool RedisMessage::set_basic_string(const std::string& str, butil::Arena*
return
true
;
}
inline
bool
RedisMessage
::
set_status
(
const
std
::
string
&
str
,
butil
::
Arena
*
arena
)
{
return
set_basic_string
(
str
,
arena
,
REDIS_MESSAGE_STATUS
);
inline
bool
RedisMessage
::
set_status
(
const
std
::
string
&
str
)
{
return
set_basic_string
(
str
,
REDIS_MESSAGE_STATUS
);
}
inline
bool
RedisMessage
::
set_error
(
const
std
::
string
&
str
,
butil
::
Arena
*
arena
)
{
return
set_basic_string
(
str
,
arena
,
REDIS_MESSAGE_ERROR
);
inline
bool
RedisMessage
::
set_error
(
const
std
::
string
&
str
)
{
return
set_basic_string
(
str
,
REDIS_MESSAGE_ERROR
);
}
inline
bool
RedisMessage
::
set_integer
(
int64_t
value
)
{
...
...
@@ -242,8 +257,8 @@ inline bool RedisMessage::set_integer(int64_t value) {
return
true
;
}
inline
bool
RedisMessage
::
set_bulk_string
(
const
std
::
string
&
str
,
butil
::
Arena
*
arena
)
{
return
set_basic_string
(
str
,
arena
,
REDIS_MESSAGE_STRING
);
inline
bool
RedisMessage
::
set_bulk_string
(
const
std
::
string
&
str
)
{
return
set_basic_string
(
str
,
REDIS_MESSAGE_STRING
);
}
inline
const
char
*
RedisMessage
::
c_str
()
const
{
...
...
This diff is collapsed.
Click to expand it.
test/CMakeLists.txt
View file @
bace6cca
...
...
@@ -53,7 +53,7 @@ endif()
set
(
CMAKE_CPP_FLAGS
"
${
DEFINE_CLOCK_GETTIME
}
-DBRPC_WITH_GLOG=
${
WITH_GLOG_VAL
}
-DGFLAGS_NS=
${
GFLAGS_NS
}
"
)
set
(
CMAKE_CPP_FLAGS
"
${
CMAKE_CPP_FLAGS
}
-DBTHREAD_USE_FAST_PTHREAD_MUTEX -D__const__= -D_GNU_SOURCE -DUSE_SYMBOLIZE -DNO_TCMALLOC -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DUNIT_TEST -Dprivate=public -Dprotected=public -DBVAR_NOT_LINK_DEFAULT_VARIABLES -D__STRICT_ANSI__ -include
${
PROJECT_SOURCE_DIR
}
/test/sstream_workaround.h"
)
set
(
CMAKE_CXX_FLAGS
"
${
CMAKE_CPP_FLAGS
}
-
O2
-pipe -Wall -W -fPIC -fstrict-aliasing -Wno-invalid-offsetof -Wno-unused-parameter -fno-omit-frame-pointer"
)
set
(
CMAKE_CXX_FLAGS
"
${
CMAKE_CPP_FLAGS
}
-
g
-pipe -Wall -W -fPIC -fstrict-aliasing -Wno-invalid-offsetof -Wno-unused-parameter -fno-omit-frame-pointer"
)
use_cxx11
()
if
(
CMAKE_CXX_COMPILER_ID STREQUAL
"GNU"
)
...
...
This diff is collapsed.
Click to expand it.
test/brpc_redis_unittest.cpp
View file @
bace6cca
This diff is collapsed.
Click to expand it.
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