skynet harbor

This commit is contained in:
云风
2012-08-03 18:20:05 +08:00
parent 4bcd81bcb6
commit 58101c5be4
29 changed files with 1197 additions and 135 deletions

7
master/Makefile Normal file
View File

@@ -0,0 +1,7 @@
all : master test
master : master.c
gcc -g -Wall -o $@ $^ -lzmq
test : test.c
gcc -g -Wall -o $@ $^ -lzmq

250
master/master.c Normal file
View File

@@ -0,0 +1,250 @@
#include <zmq.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#define HASH_SIZE 4096
#define MAX_SLAVE 255
static uint32_t
calc_hash(const char *name) {
int i;
uint32_t h = 0;
for (i=0;name[i];i++) {
h = h ^ ((h<<5)+(h>>2)+(uint8_t)name[i]);
}
h ^= i;
return h;
}
struct keyvalue {
struct keyvalue * next;
uint32_t hash;
char * key;
size_t value_size;
char * value;
};
struct hashmap {
struct keyvalue *node[HASH_SIZE];
void * zmq;
void * slave[MAX_SLAVE];
};
static struct hashmap *
_hash_new(void *zmq) {
struct hashmap * hash = malloc(sizeof(*hash));
memset(hash, 0, sizeof(*hash));
hash->zmq = zmq;
return hash;
}
static struct keyvalue *
_hash_search(struct hashmap * hash, const char * key) {
uint32_t h = calc_hash(key);
struct keyvalue * n = hash->node[h & (HASH_SIZE-1)];
while (n) {
if (n->hash == h && strcmp(n->key, key) == 0) {
return n;
}
n = n->next;
}
return NULL;
}
static void
_hash_insert(struct hashmap * hash, const char * key, const char *value) {
uint32_t h = calc_hash(key);
struct keyvalue * node = malloc(sizeof(*node));
node->next = hash->node[h & (HASH_SIZE-1)];
node->hash = h;
node->key = strdup(key);
node->value_size = strlen(value);
node->value = malloc(node->value_size+1);
memcpy(node->value, value, node->value_size+1);
hash->node[h & (HASH_SIZE-1)] = node;
}
static void
_hash_delete(struct hashmap * hash, const char * key) {
uint32_t h = calc_hash(key);
struct keyvalue ** ptr = &hash->node[h & (HASH_SIZE-1)];
while(*ptr) {
struct keyvalue *n = *ptr;
if (n->hash == h && strcmp(n->key, key) == 0) {
*ptr = n->next;
free(n->key);
free(n->value);
free(n);
return ;
}
ptr = &(n->next);
}
}
static int
_hash_bind(struct hashmap * hash, int slave, const char *addr) {
void *pub = NULL;
if (addr) {
pub = zmq_socket(hash->zmq, ZMQ_PUSH);
int r = zmq_connect(pub, addr);
if (r<0) {
fprintf(stderr,"Can't connect to [%d] %s\n",slave,addr);
return -1;
}
printf("Connect to [%d] %s\n",slave,addr);
}
void * old_pub = hash->slave[slave-1];
hash->slave[slave-1] = pub;
if (old_pub) {
zmq_close(old_pub);
}
return 0;
}
static void
broadcast(struct hashmap * hash, zmq_msg_t * msg) {
int i;
for (i=0;i<MAX_SLAVE;i++) {
void * pub = hash->slave[i];
if (pub) {
zmq_msg_t part;
zmq_msg_init(&part);
int rc = zmq_send(pub, &part, ZMQ_SNDMORE);
if (rc != 0) {
fprintf(stderr,"Can't publish to %d : %s",i+1,zmq_strerror(errno));
}
zmq_msg_close(&part);
zmq_msg_init(&part);
zmq_msg_copy(&part,msg);
rc = zmq_send(pub, &part, 0);
if (rc != 0) {
fprintf(stderr,"Can't publish to %d : %s",i+1,zmq_strerror(errno));
}
zmq_msg_close(&part);
}
}
}
static void
replace(void * responder, struct hashmap * map, const char *key, const char *value) {
// printf("Replace %s %s\n",key,value);
struct keyvalue * node = _hash_search(map, key);
zmq_msg_t reply;
if (node == NULL) {
_hash_insert(map, key, value);
zmq_msg_init_size (&reply, 0);
} else {
zmq_msg_init_size (&reply, node->value_size);
memcpy (zmq_msg_data (&reply), node->value, node->value_size);
free(node->value);
node->value_size = strlen(value);
node->value = malloc(node->value_size + 1);
memcpy(node->value, value, node->value_size +1);
}
zmq_send (responder, &reply, 0);
zmq_msg_close (&reply);
}
static void
erase(void * responder, struct hashmap *map, const char *key) {
// printf("Erase %s\n",key);
struct keyvalue * node = _hash_search(map, key);
zmq_msg_t reply;
if (node == NULL) {
zmq_msg_init_size (&reply, 0);
} else {
zmq_msg_init_size (&reply, node->value_size);
memcpy (zmq_msg_data (&reply), node->value, node->value_size);
_hash_delete(map, key);
}
zmq_send (responder, &reply, 0);
zmq_msg_close (&reply);
}
static void
query(void * responder, struct hashmap *map, const char * key) {
struct keyvalue * node = _hash_search(map, key);
zmq_msg_t reply;
if (node == NULL) {
zmq_msg_init_size (&reply, 0);
} else {
zmq_msg_init_size (&reply, node->value_size);
memcpy (zmq_msg_data (&reply), node->value, node->value_size);
}
zmq_send (responder, &reply, 0);
zmq_msg_close (&reply);
}
static void
update(void * responder, struct hashmap *map, zmq_msg_t * msg) {
size_t sz = zmq_msg_size (msg);
const char * command = zmq_msg_data (msg);
int i;
for (i=0;i<sz;i++) {
if (command[i] == '=') {
char key[i+1];
memcpy(key, command, i);
key[i] = '\0';
int slave = strtol(key, NULL, 10);
if (sz-i == 1) {
if (slave > 0 && slave <= MAX_SLAVE) {
_hash_bind(map, slave, NULL);
}
erase(responder, map,key);
broadcast(map, msg);
} else {
char value[sz-i];
memcpy(value, command+i+1, sz-i-1);
value[sz-i-1] = '\0';
if (slave > 0 && slave <= MAX_SLAVE) {
_hash_bind(map, slave, value);
}
replace(responder, map, key,value);
broadcast(map, msg);
}
return;
}
}
char key[sz+1];
memcpy(key, command, sz);
key[sz] = '\0';
query(responder, map, key);
}
int
main (int argc, char * argv[]) {
const char * default_port = "tcp://127.0.0.1:2012";
if (argc > 1) {
default_port = argv[2];
}
void *context = zmq_init (1);
void *responder = zmq_socket (context, ZMQ_REP);
int r = zmq_bind(responder, default_port);
if (r < 0) {
fprintf(stderr, "Can't bind to %s\n",default_port);
return 1;
}
printf("Start master on %s\n",default_port);
struct hashmap *map = _hash_new(context);
for (;;) {
zmq_msg_t request;
zmq_msg_init (&request);
zmq_recv (responder, &request, 0);
update(responder, map, &request);
zmq_msg_close (&request);
}
zmq_close (responder);
zmq_term (context);
return 0;
}

124
master/test.c Normal file
View File

@@ -0,0 +1,124 @@
#include <zmq.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
static char *
send_command(void * request, const char * command) {
size_t size = strlen(command);
zmq_msg_t req;
zmq_msg_init_size(&req, size);
memcpy(zmq_msg_data(&req) , command, size);
zmq_send (request, &req, 0);
zmq_msg_close (&req);
zmq_msg_t reply;
zmq_msg_init (&reply);
zmq_recv (request, &reply, 0);
size = zmq_msg_size (&reply);
char * ret = malloc(size+1);
memcpy(ret,zmq_msg_data(&reply),size);
ret[size]='\0';
zmq_msg_close (&reply);
return ret;
}
static void
pull_sub(void * local) {
zmq_msg_t part;
zmq_msg_init (&part);
zmq_recv (local, &part, 0);
zmq_msg_close(&part);
zmq_msg_init (&part);
zmq_recv (local, &part, 0);
size_t sz = zmq_msg_size(&part);
char tmp[sz+1];
memcpy(tmp,zmq_msg_data(&part),sz);
tmp[sz]='\0';
printf("%s\n",tmp);
zmq_msg_close(&part);
}
int
main (int argc, char * argv[]) {
const char * default_master = "tcp://127.0.0.1:2012";
int slave = 100;
const char * default_local = "tcp://127.0.0.1:5001";
if (argc > 1) {
default_master = argv[1];
if (argc > 2) {
slave = strtol(argv[2],NULL,10);
if (slave < 1 || slave> 255) {
fprintf(stderr,"Slave id must be in [1,255]\n");
return 1;
}
if (argc > 3) {
default_local = argv[3];
}
}
}
printf("master = %s\n",default_master);
printf("local = [%d]%s\n",slave,default_local);
void *context = zmq_init (1);
void *request = zmq_socket (context, ZMQ_REQ);
void *local = zmq_socket( context, ZMQ_PULL);
int r = zmq_connect(request, default_master);
if (r < 0) {
fprintf(stderr, "Can't connect to %s\n",default_master);
return 1;
}
r = zmq_bind(local, default_local);
if (r < 0) {
fprintf(stderr, "Can't bind to %s\n",default_local);
return 1;
}
char tmp[1024];
sprintf(tmp,"%d=%s",slave,default_local);
char * result = send_command(request,tmp);
free(result);
zmq_pollitem_t items[2];
items[0].socket = local;
items[0].events = ZMQ_POLLIN;
items[1].socket = NULL;
items[1].fd = STDIN_FILENO;
items[1].events = ZMQ_POLLIN;
for (;;) {
int rc = zmq_poll(items,2,-1);
assert (rc >= 0);
if (items[0].revents) {
pull_sub(local);
}
if (items[1].revents) {
char tmp[1024];
fgets(tmp,sizeof(tmp),stdin);
char * cr = strchr(tmp,'\r');
if (cr) {
*cr = '\0';
}
cr = strchr(tmp,'\n');
if (cr) {
*cr = '\0';
}
result = send_command(request, tmp);
printf("%s\n",result);
free(result);
}
}
zmq_close (request);
zmq_term (context);
return 0;
}