mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-24 20:23:06 +00:00
bugfix: Can't register to master more than once
This commit is contained in:
213
skynet_harbor.c
213
skynet_harbor.c
@@ -128,6 +128,7 @@ _hash_insert(struct hashmap * hash, const char * key, uint32_t handle, struct me
|
|||||||
hash->node[h & (HASH_SIZE-1)] = node;
|
hash->node[h & (HASH_SIZE-1)] = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// thread safe function
|
||||||
static void
|
static void
|
||||||
send_notice() {
|
send_notice() {
|
||||||
if (__sync_lock_test_and_set(&Z->notice_event,1)) {
|
if (__sync_lock_test_and_set(&Z->notice_event,1)) {
|
||||||
@@ -147,6 +148,7 @@ send_notice() {
|
|||||||
zmq_msg_close(&dummy);
|
zmq_msg_close(&dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// thread safe function
|
||||||
void
|
void
|
||||||
skynet_harbor_send(const char *name, struct skynet_message * message) {
|
skynet_harbor_send(const char *name, struct skynet_message * message) {
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
@@ -163,23 +165,28 @@ skynet_harbor_send(const char *name, struct skynet_message * message) {
|
|||||||
} else {
|
} else {
|
||||||
_lock();
|
_lock();
|
||||||
struct keyvalue * node = _hash_search(Z->map, name);
|
struct keyvalue * node = _hash_search(Z->map, name);
|
||||||
|
printf("send to %s %p\n",name,node);
|
||||||
if (node) {
|
if (node) {
|
||||||
uint32_t dest = node->value;
|
uint32_t dest = node->value;
|
||||||
_unlock();
|
_unlock();
|
||||||
if (dest == 0) {
|
if (dest == 0) {
|
||||||
|
printf("queue a unknown address %s\n",name);
|
||||||
// push message to unknown name service queue
|
// push message to unknown name service queue
|
||||||
skynet_mq_enter(node->queue, message);
|
skynet_mq_enter(node->queue, message);
|
||||||
} else {
|
} else {
|
||||||
message->destination = dest;
|
message->destination = dest;
|
||||||
if (!skynet_harbor_message_isremote(dest)) {
|
if (!skynet_harbor_message_isremote(dest)) {
|
||||||
// local message
|
// local message
|
||||||
|
printf("%s is a local adress\n",name);
|
||||||
skynet_mq_push(message);
|
skynet_mq_push(message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
printf("queue remote message %s to global queue\n",name);
|
||||||
skynet_mq_enter(Z->queue,message);
|
skynet_mq_enter(Z->queue,message);
|
||||||
send_notice();
|
send_notice();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
printf("Create new queue %s\n",name);
|
||||||
// never seen name before
|
// never seen name before
|
||||||
struct message_queue * queue = skynet_mq_create(DEFAULT_QUEUE_SIZE);
|
struct message_queue * queue = skynet_mq_create(DEFAULT_QUEUE_SIZE);
|
||||||
skynet_mq_enter(queue, message);
|
skynet_mq_enter(queue, message);
|
||||||
@@ -191,6 +198,7 @@ skynet_harbor_send(const char *name, struct skynet_message * message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// thread safe function
|
||||||
//queue a register message (destination = 0)
|
//queue a register message (destination = 0)
|
||||||
void
|
void
|
||||||
skynet_harbor_register(const char *name, uint32_t handle) {
|
skynet_harbor_register(const char *name, uint32_t handle) {
|
||||||
@@ -203,6 +211,7 @@ skynet_harbor_register(const char *name, uint32_t handle) {
|
|||||||
send_notice();
|
send_notice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always in main harbor thread
|
||||||
static void
|
static void
|
||||||
_register_name(const char *name, uint32_t addr) {
|
_register_name(const char *name, uint32_t addr) {
|
||||||
_lock();
|
_lock();
|
||||||
@@ -234,6 +243,8 @@ _register_name(const char *name, uint32_t addr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skynet_mq_release(queue);
|
||||||
|
|
||||||
node->queue = NULL;
|
node->queue = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,6 +255,8 @@ _register_name(const char *name, uint32_t addr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always in main harbor thread
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_remote_harbor_update(int harbor_id, const char * addr) {
|
_remote_harbor_update(int harbor_id, const char * addr) {
|
||||||
struct remote * r = &Z->remote[harbor_id-1];
|
struct remote * r = &Z->remote[harbor_id-1];
|
||||||
@@ -255,15 +268,22 @@ _remote_harbor_update(int harbor_id, const char * addr) {
|
|||||||
socket = NULL;
|
socket = NULL;
|
||||||
}
|
}
|
||||||
if (socket) {
|
if (socket) {
|
||||||
for (;;) {
|
void *old_socket = r->socket;
|
||||||
void *old_socket = r->socket;
|
if (old_socket) {
|
||||||
if (__sync_bool_compare_and_swap(&r->socket, old_socket, socket)) {
|
zmq_close(old_socket);
|
||||||
if (old_socket) {
|
|
||||||
zmq_close(old_socket);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
struct message_queue * queue = r->queue;
|
||||||
|
|
||||||
|
if (queue) {
|
||||||
|
struct skynet_message msg;
|
||||||
|
while (skynet_mq_leave(queue, &msg)) {
|
||||||
|
skynet_mq_enter(Z->queue, &msg);
|
||||||
|
}
|
||||||
|
skynet_mq_release(queue);
|
||||||
|
r->queue = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->socket = socket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,6 +295,7 @@ _report_zmq_error(int rc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always in main harbor thread
|
||||||
static void
|
static void
|
||||||
_name_update() {
|
_name_update() {
|
||||||
zmq_msg_t content;
|
zmq_msg_t content;
|
||||||
@@ -319,6 +340,7 @@ _name_update() {
|
|||||||
zmq_msg_close(&content);
|
zmq_msg_close(&content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always in main harbor thread
|
||||||
static void
|
static void
|
||||||
remote_query_harbor(int harbor_id) {
|
remote_query_harbor(int harbor_id) {
|
||||||
char tmp[32];
|
char tmp[32];
|
||||||
@@ -340,6 +362,69 @@ remote_query_harbor(int harbor_id) {
|
|||||||
zmq_msg_close(&reply);
|
zmq_msg_close(&reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always in main harbor thread
|
||||||
|
static void
|
||||||
|
_remote_register_name(const char *name, uint32_t source) {
|
||||||
|
char tmp[strlen(name) + 20];
|
||||||
|
int sz = sprintf(tmp,"%s=%X",name,source);
|
||||||
|
zmq_msg_t msg;
|
||||||
|
zmq_msg_init_size(&msg,sz);
|
||||||
|
memcpy(zmq_msg_data(&msg), tmp , sz);
|
||||||
|
zmq_send(Z->zmq_master_request, &msg,0);
|
||||||
|
zmq_msg_close(&msg);
|
||||||
|
zmq_msg_init(&msg);
|
||||||
|
int rc = zmq_recv(Z->zmq_master_request, &msg,0);
|
||||||
|
_report_zmq_error(rc);
|
||||||
|
zmq_msg_close(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always in main harbor thread
|
||||||
|
static void
|
||||||
|
_remote_query_name(const char *name) {
|
||||||
|
int sz = strlen(name);
|
||||||
|
zmq_msg_t msg;
|
||||||
|
zmq_msg_init_size(&msg,sz);
|
||||||
|
memcpy(zmq_msg_data(&msg), name , sz);
|
||||||
|
zmq_send(Z->zmq_master_request, &msg,0);
|
||||||
|
zmq_msg_close(&msg);
|
||||||
|
zmq_msg_init(&msg);
|
||||||
|
int rc = zmq_recv(Z->zmq_master_request, &msg,0);
|
||||||
|
_report_zmq_error(rc);
|
||||||
|
sz = zmq_msg_size(&msg);
|
||||||
|
char tmp[sz+1];
|
||||||
|
memcpy(tmp, zmq_msg_data(&msg),sz);
|
||||||
|
tmp[sz] = '\0';
|
||||||
|
|
||||||
|
uint32_t addr = strtoul(tmp,NULL,16);
|
||||||
|
_register_name(name,addr);
|
||||||
|
|
||||||
|
zmq_msg_close(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always in main harbor thread
|
||||||
|
static void
|
||||||
|
free_message (void *data, void *hint) {
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
remote_socket_send(void * socket, struct skynet_message *msg) {
|
||||||
|
struct remote_header rh;
|
||||||
|
rh.source = msg->source;
|
||||||
|
rh.destination = msg->destination;
|
||||||
|
zmq_msg_t part;
|
||||||
|
zmq_msg_init_size(&part,8);
|
||||||
|
uint8_t * buffer = zmq_msg_data(&part);
|
||||||
|
remote_header_to_buffer(&rh,buffer);
|
||||||
|
zmq_send(socket, &part, ZMQ_SNDMORE);
|
||||||
|
zmq_msg_close(&part);
|
||||||
|
|
||||||
|
zmq_msg_init_data(&part,msg->data,msg->sz,free_message,NULL);
|
||||||
|
zmq_send(socket, &part, 0);
|
||||||
|
zmq_msg_close(&part);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always in main harbor thread
|
||||||
|
|
||||||
// remote message has two part
|
// remote message has two part
|
||||||
// when part one is nil (size == 0), part two is name update
|
// when part one is nil (size == 0), part two is name update
|
||||||
// Or part one is source:destination (8 bytes little endian), part two is a binary block for message
|
// Or part one is source:destination (8 bytes little endian), part two is a binary block for message
|
||||||
@@ -380,80 +465,7 @@ _remote_recv() {
|
|||||||
skynet_mq_push(&msg);
|
skynet_mq_push(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
// Always in main harbor thread
|
||||||
skynet_harbor_message_open(struct skynet_message * message) {
|
|
||||||
return zmq_msg_data(message->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
skynet_harbor_message_close(struct skynet_message * message) {
|
|
||||||
zmq_msg_close(message->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
skynet_harbor_message_isremote(uint32_t handle) {
|
|
||||||
int harbor_id = handle >> HANDLE_REMOTE_SHIFT;
|
|
||||||
return !(harbor_id == 0 || harbor_id == Z->harbor);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_remote_register_name(const char *name, uint32_t source) {
|
|
||||||
char tmp[strlen(name) + 20];
|
|
||||||
int sz = sprintf(tmp,"%s=%X",name,source);
|
|
||||||
zmq_msg_t msg;
|
|
||||||
zmq_msg_init_size(&msg,sz);
|
|
||||||
memcpy(zmq_msg_data(&msg), tmp , sz);
|
|
||||||
zmq_send(Z->zmq_master_request, &msg,0);
|
|
||||||
zmq_msg_close(&msg);
|
|
||||||
zmq_msg_init(&msg);
|
|
||||||
int rc = zmq_recv(Z->zmq_master_request, &msg,0);
|
|
||||||
_report_zmq_error(rc);
|
|
||||||
zmq_msg_close(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_remote_query_name(const char *name) {
|
|
||||||
int sz = strlen(name);
|
|
||||||
zmq_msg_t msg;
|
|
||||||
zmq_msg_init_size(&msg,sz);
|
|
||||||
memcpy(zmq_msg_data(&msg), name , sz);
|
|
||||||
zmq_send(Z->zmq_master_request, &msg,0);
|
|
||||||
zmq_msg_close(&msg);
|
|
||||||
zmq_msg_init(&msg);
|
|
||||||
int rc = zmq_recv(Z->zmq_master_request, &msg,0);
|
|
||||||
_report_zmq_error(rc);
|
|
||||||
sz = zmq_msg_size(&msg);
|
|
||||||
char tmp[sz+1];
|
|
||||||
memcpy(tmp, zmq_msg_data(&msg),sz);
|
|
||||||
tmp[sz] = '\0';
|
|
||||||
|
|
||||||
uint32_t addr = strtoul(tmp,NULL,16);
|
|
||||||
_register_name(name,addr);
|
|
||||||
|
|
||||||
zmq_msg_close(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_message (void *data, void *hint) {
|
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
remote_socket_send(void * socket, struct skynet_message *msg) {
|
|
||||||
struct remote_header rh;
|
|
||||||
rh.source = msg->source;
|
|
||||||
rh.destination = msg->destination;
|
|
||||||
zmq_msg_t part;
|
|
||||||
zmq_msg_init_size(&part,8);
|
|
||||||
uint8_t * buffer = zmq_msg_data(&part);
|
|
||||||
remote_header_to_buffer(&rh,buffer);
|
|
||||||
zmq_send(socket, &part, ZMQ_SNDMORE);
|
|
||||||
zmq_msg_close(&part);
|
|
||||||
|
|
||||||
zmq_msg_init_data(&part,msg->data,msg->sz,free_message,NULL);
|
|
||||||
zmq_send(socket, &part, 0);
|
|
||||||
zmq_msg_close(&part);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_remote_send() {
|
_remote_send() {
|
||||||
struct skynet_message msg;
|
struct skynet_message msg;
|
||||||
@@ -493,6 +505,7 @@ _goback:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Main harbor thread
|
||||||
void *
|
void *
|
||||||
skynet_harbor_dispatch_thread(void *ud) {
|
skynet_harbor_dispatch_thread(void *ud) {
|
||||||
zmq_pollitem_t items[2];
|
zmq_pollitem_t items[2];
|
||||||
@@ -518,6 +531,7 @@ skynet_harbor_dispatch_thread(void *ud) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call only at init
|
||||||
static void
|
static void
|
||||||
register_harbor(void *request, const char *local, int harbor) {
|
register_harbor(void *request, const char *local, int harbor) {
|
||||||
char tmp[1024];
|
char tmp[1024];
|
||||||
@@ -539,10 +553,8 @@ register_harbor(void *request, const char *local, int harbor) {
|
|||||||
if (sz > 0) {
|
if (sz > 0) {
|
||||||
memcpy(tmp,zmq_msg_data(&reply),sz);
|
memcpy(tmp,zmq_msg_data(&reply),sz);
|
||||||
tmp[sz] = '\0';
|
tmp[sz] = '\0';
|
||||||
if (strcmp(tmp,local) != 0) {
|
fprintf(stderr, "Harbor %d is already registered by %s\n", harbor, tmp);
|
||||||
fprintf(stderr, "Harbor %d is already registered by %s [%s]\n", harbor, tmp, local);
|
exit(1);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
zmq_msg_close (&reply);
|
zmq_msg_close (&reply);
|
||||||
|
|
||||||
@@ -556,18 +568,6 @@ register_harbor(void *request, const char *local, int harbor) {
|
|||||||
zmq_msg_init (&reply);
|
zmq_msg_init (&reply);
|
||||||
rc = zmq_recv (request, &reply, 0);
|
rc = zmq_recv (request, &reply, 0);
|
||||||
_report_zmq_error(rc);
|
_report_zmq_error(rc);
|
||||||
|
|
||||||
sz = zmq_msg_size (&reply);
|
|
||||||
if (sz > 0) {
|
|
||||||
char * buffer = zmq_msg_data(&reply);
|
|
||||||
memcpy(tmp,buffer,sz);
|
|
||||||
tmp[sz] = '\0';
|
|
||||||
|
|
||||||
if (strcmp(local,tmp) !=0) {
|
|
||||||
fprintf(stderr, "Harbor %d is already registered by %s (%s)\n", harbor,tmp,local);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zmq_msg_close (&reply);
|
zmq_msg_close (&reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,3 +607,20 @@ skynet_harbor_init(const char * master, const char *local, int harbor) {
|
|||||||
|
|
||||||
Z = h;
|
Z = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// thread safe api
|
||||||
|
void *
|
||||||
|
skynet_harbor_message_open(struct skynet_message * message) {
|
||||||
|
return zmq_msg_data(message->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
skynet_harbor_message_close(struct skynet_message * message) {
|
||||||
|
zmq_msg_close(message->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
skynet_harbor_message_isremote(uint32_t handle) {
|
||||||
|
int harbor_id = handle >> HANDLE_REMOTE_SHIFT;
|
||||||
|
return !(harbor_id == 0 || harbor_id == Z->harbor);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user