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
0701cad3
Commit
0701cad3
authored
Mar 29, 2018
by
antirez
Browse files
Modules Cluster API: message bus implementation.
parent
8ac7af1c
Changes
4
Show whitespace changes
Inline
Side-by-side
src/cluster.c
View file @
0701cad3
...
...
@@ -75,6 +75,7 @@ void clusterDelNode(clusterNode *delnode);
sds representClusterNodeFlags(sds ci, uint16_t flags);
uint64_t clusterGetMaxEpoch(void);
int clusterBumpConfigEpochWithoutConsensus(void);
void moduleCallClusterReceivers(char *sender_id, uint64_t module_id, uint8_t type, const unsigned char *payload, uint32_t len);
/* -----------------------------------------------------------------------------
* Initialization
...
...
@@ -1682,6 +1683,12 @@ int clusterProcessPacket(clusterLink *link) {
explen += sizeof(clusterMsgDataUpdate);
if (totlen != explen) return 1;
} else if (type == CLUSTERMSG_TYPE_MODULE) {
uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);
explen += sizeof(clusterMsgDataPublish) -
3 + ntohl(hdr->data.module.msg.len);
if (totlen != explen) return 1;
}
/* Check if the sender is a known node. */
...
...
@@ -2076,6 +2083,15 @@ int clusterProcessPacket(clusterLink *link) {
* config accordingly. */
clusterUpdateSlotsConfigWith(n,reportedConfigEpoch,
hdr->data.update.nodecfg.slots);
} else if (type == CLUSTERMSG_TYPE_MODULE) {
if (!sender) return 1; /* Protect the module from unknown nodes. */
/* We need to route this message back to the right module subscribed
* for the right message type. */
uint64_t module_id = hdr->data.module.msg.module_id; /* Endian-safe ID */
uint32_t len = ntohl(hdr->data.module.msg.len);
uint8_t type = hdr->data.module.msg.type;
unsigned char *payload = hdr->data.module.msg.bulk_data;
moduleCallClusterReceivers(sender->name,module_id,type,payload,len);
} else {
serverLog(LL_WARNING,"Received unknown packet type: %d", type);
}
...
...
@@ -2563,6 +2579,61 @@ void clusterSendUpdate(clusterLink *link, clusterNode *node) {
clusterSendMessage(link,buf,ntohl(hdr->totlen));
}
/* Send a MODULE message.
*
* If link is NULL, then the message is broadcasted to the whole cluster. */
void clusterSendModule(clusterLink *link, uint64_t module_id, uint8_t type,
unsigned char *payload, uint32_t len) {
unsigned char buf[sizeof(clusterMsg)], *heapbuf;
clusterMsg *hdr = (clusterMsg*) buf;
uint32_t totlen;
clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_MODULE);
totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);
totlen += sizeof(clusterMsgModule) - 3 + len;
hdr->data.module.msg.module_id = module_id; /* Already endian adjusted. */
hdr->data.module.msg.type = type;
hdr->data.module.msg.len = htonl(len);
hdr->totlen = htonl(totlen);
/* Try to use the local buffer if possible */
if (totlen < sizeof(buf)) {
heapbuf = buf;
} else {
heapbuf = zmalloc(totlen);
memcpy(heapbuf,hdr,sizeof(*hdr));
hdr = (clusterMsg*) heapbuf;
}
memcpy(hdr->data.module.msg.bulk_data,payload,len);
if (link)
clusterSendMessage(link,heapbuf,totlen);
else
clusterBroadcastMessage(heapbuf,totlen);
if (heapbuf != buf) zfree(heapbuf);
}
/* This function gets a cluster node ID string as target, the same way the nodes
* addresses are represented in the modules side, resolves the node, and sends
* the message. If the target is NULL the message is broadcasted.
*
* The function returns C_OK if the target is valid, otherwise C_ERR is
* returned. */
int clusterSendModuleMessageToTarget(char *target, uint64_t module_id, uint8_t type, unsigned char *payload, uint32_t len) {
clusterNode *node = NULL;
if (target != NULL) {
node = clusterLookupNode(target);
if (node == NULL || node->link == NULL) return C_ERR;
}
clusterSendModule(target ? node->link : NULL,
module_id, type, payload, len);
return C_OK;
}
/* -----------------------------------------------------------------------------
* CLUSTER Pub/Sub support
*
...
...
@@ -4008,6 +4079,7 @@ const char *clusterGetMessageTypeString(int type) {
case CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK: return "auth-ack";
case CLUSTERMSG_TYPE_UPDATE: return "update";
case CLUSTERMSG_TYPE_MFSTART: return "mfstart";
case CLUSTERMSG_TYPE_MODULE: return "module";
}
return "unknown";
}
...
...
src/cluster.h
View file @
0701cad3
...
...
@@ -97,7 +97,8 @@ typedef struct clusterLink {
#define CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 6
/* Yes, you have my vote */
#define CLUSTERMSG_TYPE_UPDATE 7
/* Another node slots configuration */
#define CLUSTERMSG_TYPE_MFSTART 8
/* Pause clients for manual failover */
#define CLUSTERMSG_TYPE_COUNT 9
/* Total number of message types. */
#define CLUSTERMSG_TYPE_MODULE 9
/* Module cluster API message. */
#define CLUSTERMSG_TYPE_COUNT 10
/* Total number of message types. */
/* This structure represent elements of node->fail_reports. */
typedef
struct
clusterNodeFailReport
{
...
...
@@ -195,10 +196,7 @@ typedef struct {
typedef
struct
{
uint32_t
channel_len
;
uint32_t
message_len
;
/* We can't reclare bulk_data as bulk_data[] since this structure is
* nested. The 8 bytes are removed from the count during the message
* length computation. */
unsigned
char
bulk_data
[
8
];
unsigned
char
bulk_data
[
8
];
/* 8 bytes just as placeholder. */
}
clusterMsgDataPublish
;
typedef
struct
{
...
...
@@ -207,6 +205,13 @@ typedef struct {
unsigned
char
slots
[
CLUSTER_SLOTS
/
8
];
/* Slots bitmap. */
}
clusterMsgDataUpdate
;
typedef
struct
{
uint64_t
module_id
;
/* ID of the sender module. */
uint32_t
len
;
/* ID of the sender module. */
uint8_t
type
;
/* Type from 0 to 255. */
unsigned
char
bulk_data
[
3
];
/* 3 bytes just as placeholder. */
}
clusterMsgModule
;
union
clusterMsgData
{
/* PING, MEET and PONG */
struct
{
...
...
@@ -228,6 +233,11 @@ union clusterMsgData {
struct
{
clusterMsgDataUpdate
nodecfg
;
}
update
;
/* MODULE */
struct
{
clusterMsgModule
msg
;
}
module
;
};
#define CLUSTER_PROTO_VER 1
/* Cluster bus protocol version. */
...
...
src/module.c
View file @
0701cad3
...
...
@@ -3808,6 +3808,29 @@ void moduleUnsubscribeNotifications(RedisModule *module) {
}
}
/* --------------------------------------------------------------------------
* Modules Cluster API
* -------------------------------------------------------------------------- */
typedef void (*RedisModuleClusterMessageReceiver)(RedisModuleCtx *ctx, char *sender_id, uint8_t type, const unsigned char *payload, uint32_t len);
/* This structure identifies a registered caller: it must match a given module
* ID, for a given message type. The callback function is just the function
* that was registered as receiver. */
struct moduleClusterReceiver {
uint64_t module_id;
uint8_t msg_type;
RedisModuleClusterMessageReceiver callback;
struct moduleClusterReceiver *next;
};
/* We have an array of message types: each bucket is a linked list of
* configured receivers. */
static struct moduleClusterReceiver *clusterReceivers[UINT8_MAX];
void moduleCallClusterReceivers(char *sender_id, uint64_t module_id, uint8_t type, const unsigned char *payload, uint32_t len) {
}
/* --------------------------------------------------------------------------
* Modules API internals
* -------------------------------------------------------------------------- */
...
...
src/server.h
View file @
0701cad3
...
...
@@ -1808,6 +1808,7 @@ void clusterCron(void);
void
clusterPropagatePublish
(
robj
*
channel
,
robj
*
message
);
void
migrateCloseTimedoutSockets
(
void
);
void
clusterBeforeSleep
(
void
);
int
clusterSendModuleMessageToTarget
(
char
*
target
,
uint64_t
module_id
,
uint8_t
type
,
unsigned
char
*
payload
,
uint32_t
len
);
/* Sentinel */
void
initSentinelConfig
(
void
);
...
...
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