add module skynet.harbor

This commit is contained in:
Cloud Wu
2014-06-19 15:43:41 +08:00
parent 33e51a4de9
commit ad9898a209
13 changed files with 253 additions and 46 deletions

View File

@@ -257,15 +257,42 @@ _send_name(struct dummy *h, uint32_t source, const char name[GLOBALNAME_LENGTH],
}
}
static void
dummy_command(struct dummy * h, const char * msg, size_t sz, int session, uint32_t source) {
switch(msg[0]) {
case 'R' : {
// register global name
const char * name = msg + 2;
int s = (int)sz;
s -= 2;
if (s <=0 || s>= GLOBALNAME_LENGTH) {
skynet_error(h->ctx, "Invalid global name %s", name);
return;
}
struct remote_name rn;
memset(&rn, 0, sizeof(rn));
memcpy(rn.name, name, s);
rn.handle = source;
_update_name(h, rn.name, rn.handle);
break;
}
case 'C' :
case 'M' :
skynet_error(h->ctx, "Don't support harbor monitor in cluster dummy mode");
skynet_send(h->ctx, 0, source, PTYPE_ERROR, session, NULL, 0);
break;
default:
skynet_error(h->ctx, "Unknown command %s", msg);
return;
}
}
static int
_mainloop(struct skynet_context * context, void * ud, int type, int session, uint32_t source, const void * msg, size_t sz) {
struct dummy * h = ud;
switch (type) {
case PTYPE_SYSTEM: {
// register name message
const struct remote_message *rmsg = msg;
assert (sz == sizeof(rmsg->destination));
_update_name(h, rmsg->destination.name, rmsg->destination.handle);
dummy_command(h, msg, sz, session, source);
return 0;
}
default: {

View File

@@ -47,6 +47,17 @@ struct remote_message_header {
uint32_t session;
};
struct monitor_response {
uint32_t addr;
int session;
};
struct monitor_set {
int cap;
int n;
struct monitor_response * resp;
};
// 12 is sizeof(struct remote_message_header)
#define HEADER_COOKIE_LENGTH 12
@@ -60,8 +71,61 @@ struct harbor {
int remote_fd[REMOTE_MAX];
bool connected[REMOTE_MAX];
char * remote_addr[REMOTE_MAX];
struct monitor_set * monitor[REMOTE_MAX];
};
static void
monitor_free(struct harbor *h) {
int i;
for (i=0;i<REMOTE_MAX;i++) {
struct monitor_set * m = h->monitor[i];
if (m) {
skynet_free(m->resp);
skynet_free(m);
h->monitor[i] = NULL;
}
}
}
static void
monitor_add(struct harbor *h, int id, uint32_t addr, int session) {
struct monitor_set * m = h->monitor[id];
if (m == NULL) {
m = skynet_malloc(sizeof(*m));
m->cap = 4;
m->n = 0;
m->resp = skynet_malloc(m->cap * sizeof(struct monitor_response));
h->monitor[id] = m;
}
if (m->n >= m->cap) {
assert(m->n == m->cap);
struct monitor_response * resp = skynet_malloc(m->cap * 2 * sizeof(struct monitor_response));
int i;
for (i=0;i<m->n;i++) {
resp[i] = m->resp[i];
}
m->cap *= 2;
skynet_free(m->resp);
m->resp = resp;
}
struct monitor_response * resp = &m->resp[m->n++];
resp->addr = addr;
resp->session = session;
}
static void
monitor_clear(struct harbor *h, int id) {
struct monitor_set * m = h->monitor[id];
if (m) {
int i;
for (i=0;i<m->n;i++) {
struct monitor_response * resp = &m->resp[i];
skynet_send(h->ctx, 0, resp->addr, PTYPE_RESPONSE, resp->session, NULL, 0);
}
m->n = 0;
}
}
// hash table
static void
@@ -211,6 +275,7 @@ harbor_create(void) {
h->remote_fd[i] = -1;
h->connected[i] = false;
h->remote_addr[i] = NULL;
h->monitor[i] = NULL;
}
h->map = _hash_new();
return h;
@@ -232,6 +297,7 @@ harbor_release(struct harbor *h) {
}
}
_hash_delete(h->map);
monitor_free(h);
skynet_free(h);
}
@@ -313,6 +379,14 @@ _send_remote(struct skynet_context * ctx, int fd, const char * buffer, size_t sz
}
}
static void
response_close(struct harbor *h, int id) {
if (h->connected[id]) {
monitor_clear(h, id);
}
h->connected[id] = false;
}
static void
_update_remote_address(struct harbor *h, int harbor_id, const char * ipaddr) {
if (harbor_id == h->id) {
@@ -326,7 +400,7 @@ _update_remote_address(struct harbor *h, int harbor_id, const char * ipaddr) {
h->remote_addr[harbor_id] = NULL;
}
h->remote_fd[harbor_id] = _connect_to(h, ipaddr, false);
h->connected[harbor_id] = false;
response_close(h, harbor_id);
}
static void
@@ -466,7 +540,7 @@ close_harbor(struct harbor *h, int fd) {
skynet_error(h->ctx, "Harbor %d closed",id);
skynet_socket_close(h->ctx, fd);
h->remote_fd[id] = -1;
h->connected[id] = false;
response_close(h,id);
}
static void
@@ -475,9 +549,63 @@ open_harbor(struct harbor *h, int fd) {
if (id == 0)
return;
assert(h->connected[id] == false);
monitor_clear(h, id);
h->connected[id] = true;
}
static void
harbor_command(struct harbor * h, const char * msg, size_t sz, int session, uint32_t source) {
const char * name = msg + 2;
int s = (int)sz;
s -= 2;
switch(msg[0]) {
case 'R' : {
// register global name
if (s <=0 || s>= GLOBALNAME_LENGTH) {
skynet_error(h->ctx, "Invalid global name %s", name);
return;
}
struct remote_name rn;
memset(&rn, 0, sizeof(rn));
memcpy(rn.name, name, s);
rn.handle = source;
_remote_register_name(h, rn.name, rn.handle);
break;
}
case 'C' :
case 'M' : {
if (s <= 0) {
skynet_error(h->ctx, "Invalid harbor montior");
skynet_send(h->ctx, 0, source, PTYPE_ERROR, session, NULL, 0);
return;
}
int hid = strtol(name, NULL, 10);
if (hid <= 0 || hid >= REMOTE_MAX) {
skynet_error(h->ctx, "Invalid harbor montior id : %s", name);
skynet_send(h->ctx, 0, source, PTYPE_ERROR, session, NULL, 0);
return;
}
if (msg[0] == 'M') {
if (!h->connected[hid]) {
skynet_send(h->ctx, 0, source, PTYPE_RESPONSE, session, NULL, 0);
return;
}
} else {
assert(msg[0] == 'C');
if (h->connected[hid]) {
skynet_send(h->ctx, 0, source, PTYPE_RESPONSE, session, NULL, 0);
return;
}
}
monitor_add(h, hid, source, session);
break;
}
default:
skynet_error(h->ctx, "Unknown command %s", msg);
return;
}
}
static int
_mainloop(struct skynet_context * context, void * ud, int type, int session, uint32_t source, const void * msg, size_t sz) {
struct harbor * h = ud;
@@ -536,10 +664,7 @@ _mainloop(struct skynet_context * context, void * ud, int type, int session, uin
return 0;
}
case PTYPE_SYSTEM: {
// register name message
const struct remote_message *rmsg = msg;
assert (sz == sizeof(rmsg->destination));
_remote_register_name(h, rmsg->destination.name, rmsg->destination.handle);
harbor_command(h, msg,sz,session,source);
return 0;
}
default: {