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
Nov 26, 2019
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
)
{
...
...
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
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
;
...
...
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
{
...
...
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"
)
...
...
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