Exemple #1
0
static int
nc_event_init(struct nc_event *event)
{
    struct nc_event_state *e_state;

    e_state = nc_alloc(sizeof(*e_state));
    if (e_state == NULL) {
        return -1;
    }
    e_state->events = nc_calloc(event->nevent, sizeof(struct epoll_event));
    if (e_state->events == NULL) {
        nc_free(e_state);
        return -1;
    }
    e_state->ep = epoll_create(event->nevent);
    if (e_state->ep < 0) {
        nc_free(e_state->events);
        nc_free(e_state);
        log_error("epoll create of size %d failed: %s", event->nevent, 
                strerror(errno));
        return -1;
    }
    log_debug(LOG_INFO, "e %d with nevent %d", e_state->ep, event->nevent);
    event->event_data = e_state;
    return 0;
}
Exemple #2
0
cursor_t *
cursor_create(store_t *store)
{
    cursor_t *cursor;

    cursor = nc_alloc(sizeof(*cursor));
    if (cursor == NULL) {
        return NULL;
    }

    cursor->iter = leveldb_create_iterator(store->db, store->roptions);
    if (cursor->iter == NULL) {
        nc_free(cursor);
        return NULL;
    }

    leveldb_iter_seek_to_first(cursor->iter);

    cursor->id = g_cursor_id++;
    cursor->owner = store;

    ncursor++;
    STAILQ_INSERT_HEAD(&cursorq, cursor, next);

    return cursor;
}
Exemple #3
0
/**
 * eval a statement, leave value in the stack
 * like luaL_xxx functions, return 0 on success.
 */
static int
_lua_eval(lua_State *L, const char *expr)
{
    char       *buf;
    int         status;

    buf = nc_alloc(strlen(expr) + sizeof("return "));
    strcpy(buf, "return ");
    strcat(buf, expr);
    status = luaL_loadbuffer(L, buf, strlen(buf), "eval");
    if (status) {
        log_stderr("nc_conf: error on loadbuffer: %s", lua_tostring(L, -1));
        lua_pop(L, 1);
        goto out;
    }

    status = lua_pcall(L, 0, 1, 0);
    if (status) {
        log_stderr("nc_conf: error on lua_pcall: %s", lua_tostring(L, -1));
        lua_pop(L, 1);
        goto out;
    }

    if (lua_isnil(L, -1)) {
        log_stderr("nc_conf: value is nil: %s", expr);
        status = NC_ERROR;
    }
    status = NC_OK;

out:
    nc_free(buf);
    return status;
}
Exemple #4
0
static struct mbuf *
_mbuf_get_proxy_adm(void)
{
    struct mbuf *mbuf;
    uint8_t *buf;

    if (!STAILQ_EMPTY(&free_mbufq_proxy_adm)) {
        ASSERT(nfree_mbufq_proxy_adm > 0);

        mbuf = STAILQ_FIRST(&free_mbufq_proxy_adm);
        nfree_mbufq_proxy_adm--;
        STAILQ_REMOVE_HEAD(&free_mbufq_proxy_adm, next);

        ASSERT(mbuf->magic == MBUF_MAGIC);
        goto done;
    }

    buf = nc_alloc(mbuf_chunk_size);
    if (buf == NULL) {
        return NULL;
    }

#if 1 //shenzheng 2015-7-9 proxy administer
#ifdef NC_DEBUG_LOG
	ntotal_mbuf_proxy_adm ++;
#endif
#endif //shenzheng 2015-7-9 proxy administer

    mbuf = (struct mbuf *)(buf + mbuf_offset);
    mbuf->magic = MBUF_MAGIC;

done:
    STAILQ_NEXT(mbuf, next) = NULL;
    return mbuf;
}
Exemple #5
0
struct event_base *
event_base_create(int nevent, event_cb_t cb)
{
    struct event_base *evb;
    int status, kq;
    struct kevent *change, *event;

    ASSERT(nevent > 0);

    kq = kqueue();
    if (kq < 0) {
        log_error("kqueue failed: %s", strerror(errno));
        return NULL;
    }

    change = nc_calloc(nevent, sizeof(*change));
    if (change == NULL) {
        status = close(kq);
        if (status < 0) {
            log_error("close kq %d failed, ignored: %s", kq, strerror(errno));
        }
        return NULL;
    }

    event = nc_calloc(nevent, sizeof(*event));
    if (event == NULL) {
        nc_free(change);
        status = close(kq);
        if (status < 0) {
            log_error("close kq %d failed, ignored: %s", kq, strerror(errno));
        }
        return NULL;
    }

    evb = nc_alloc(sizeof(*evb));
    if (evb == NULL) {
        nc_free(change);
        nc_free(event);
        status = close(kq);
        if (status < 0) {
            log_error("close kq %d failed, ignored: %s", kq, strerror(errno));
        }
        return NULL;
    }

    evb->kq = kq;
    evb->change = change;
    evb->nchange = 0;
    evb->event = event;
    evb->nevent = nevent;
    evb->nreturned = 0;
    evb->nprocessed = 0;
    evb->cb = cb;

    log_debug(LOG_INFO, "kq %d with nevent %d", evb->kq, evb->nevent);

    return evb;
}
Exemple #6
0
static struct conn *
_conn_get(void)
{
    struct conn *conn;

    if (!TAILQ_EMPTY(&free_connq)) {
        ASSERT(nfree_connq > 0);

        conn = TAILQ_FIRST(&free_connq);
        nfree_connq--;
        TAILQ_REMOVE(&free_connq, conn, conn_tqe);
    } else {
        conn = nc_alloc(sizeof(*conn));
        if (conn == NULL) {
            return NULL;
        }
    }

    conn->owner = NULL;

    conn->sd = -1;
    /* {family, addrlen, addr} are initialized in enqueue handler */

    TAILQ_INIT(&conn->imsg_q);
    TAILQ_INIT(&conn->omsg_q);
    conn->rmsg = NULL;
    conn->smsg = NULL;

    /*
     * Callbacks {recv, recv_next, recv_done}, {send, send_next, send_done},
     * {close, active}, parse, {ref, unref}, {enqueue_inq, dequeue_inq} and
     * {enqueue_outq, dequeue_outq} are initialized by the wrapper.
     */

    conn->send_bytes = 0;
    conn->recv_bytes = 0;

    conn->events = 0;
    conn->err = 0;
    conn->recv_active = 0;
    conn->recv_ready = 0;
    conn->send_active = 0;
    conn->send_ready = 0;

    conn->client = 0;
    conn->proxy = 0;
    conn->connecting = 0;
    conn->connected = 0;
    conn->eof = 0;
    conn->done = 0;
    conn->redis = 0;
    conn->need_auth = 0;

    ntotal_conn++;
    ncurr_conn++;

    return conn;
}
Exemple #7
0
int
nc_connect_init(struct context *ctx)
{
    ctx->cb = nc_alloc(sizeof(struct conn_base));
    if (ctx->cb == NULL) {
        return NC_ENOMEM;
    }

    conn_init(ctx->cb);
    return NC_OK;
}
Exemple #8
0
static struct mbuf *
_mbuf_get(void)
{
    struct mbuf *mbuf;
    uint8_t *buf;

    if (!STAILQ_EMPTY(&free_mbufq)) {
        ASSERT(nfree_mbufq > 0);

        mbuf = STAILQ_FIRST(&free_mbufq);
        nfree_mbufq--;
        STAILQ_REMOVE_HEAD(&free_mbufq, next);

        ASSERT(mbuf->magic == MBUF_MAGIC);
        goto done;
    }

    buf = nc_alloc(mbuf_chunk_size);
    if (buf == NULL) {
        return NULL;
    }

#if 1 //shenzheng 2015-3-23 common
#ifdef NC_DEBUG_LOG
	ntotal_mbuf ++;
#endif
#endif //shenzheng 2015-3-23 common

    /*
     * mbuf header is at the tail end of the mbuf. This enables us to catch
     * buffer overrun early by asserting on the magic value during get or
     * put operations
     *
     *   <------------- mbuf_chunk_size ------------->
     *   +-------------------------------------------+
     *   |       mbuf data          |  mbuf header   |
     *   |     (mbuf_offset)        | (struct mbuf)  |
     *   +-------------------------------------------+
     *   ^           ^        ^     ^^
     *   |           |        |     ||
     *   \           |        |     |\
     *   mbuf->start \        |     | mbuf->end (one byte past valid bound)
     *                mbuf->pos     \
     *                        \      mbuf
     *                        mbuf->last (one byte past valid byte)
     *
     */
    mbuf = (struct mbuf *)(buf + mbuf_offset);
    mbuf->magic = MBUF_MAGIC;

done:
    STAILQ_NEXT(mbuf, next) = NULL;
    return mbuf;
}
Exemple #9
0
static struct conf *
conf_open(char *filename)
{
    rstatus_t status;
    struct conf *cf;
    FILE *fh;

    fh = fopen(filename, "r");
    if (fh == NULL) {
        log_error("conf: failed to open configuration '%s': %s", filename,
                  strerror(errno));
        return NULL;
    }

    cf = nc_alloc(sizeof(*cf));
    if (cf == NULL) {
        fclose(fh);
        return NULL;
    }

    status = array_init(&cf->arg, CONF_DEFAULT_ARGS, sizeof(struct string));
    if (status != NC_OK) {
        nc_free(cf);
        fclose(fh);
        return NULL;
    }

    status = array_init(&cf->pool, CONF_DEFAULT_POOL, sizeof(struct conf_pool));
    if (status != NC_OK) {
        array_deinit(&cf->arg);
        nc_free(cf);
        fclose(fh);
        return NULL;
    }

    cf->fname = filename;
    cf->fh = fh;
    cf->depth = 0;
    /* parser, event, and token are initialized later */
    cf->seq = 0;
    cf->valid_parser = 0;
    cf->valid_event = 0;
    cf->valid_token = 0;
    cf->sound = 0;
    cf->parsed = 0;
    cf->valid = 0;

    log_debug(LOG_VVERB, "opened conf '%s'", filename);

    return cf;
}
Exemple #10
0
struct evbase * 
evbase_create(int nevent, void (*callback_fp)(void *, uint32_t))
{

    struct evbase *evb;
    int status, ep;
    struct epoll_event *event;

    if (nevent <= 0) {
        log_error("nevent has to be positive %d", nevent);
        return NULL;
    }

    ep = epoll_create(nevent);
    if (ep < 0) {
        log_error("epoll create of size %d failed: %s", nevent, strerror(errno));
        return NULL;
    }

    event = nc_calloc(nevent, sizeof(*event));
    if (event == NULL) {
        status = close(ep);
        if (status < 0) {
            log_error("close e %d failed, ignored: %s", ep, strerror(errno));
        }
        return NULL;
    }

    evb = nc_alloc(sizeof(*evb));
    if (evb == NULL) {
        nc_free(event);
        status = close(ep);
        if (status < 0) {
            log_error("close e %d failed, ignored: %s", ep, strerror(errno));
        }
        return NULL;

    }

    evb->nevent = nevent;
    evb->ep = ep;
    evb->event = event;
    evb->callback_fp = callback_fp;

    log_debug(LOG_INFO, "e %d with nevent %d", evb->ep,
              evb->nevent);

    return evb;
}
Exemple #11
0
static struct conn *
_conn_get(void)
{
    struct conn *conn;

    if (!TAILQ_EMPTY(&free_connq)) {
        ASSERT(nfree_connq > 0);

        conn = TAILQ_FIRST(&free_connq);
        nfree_connq--;
        TAILQ_REMOVE(&free_connq, conn, conn_tqe);
    } else {
        conn = nc_alloc(sizeof(*conn));
        if (conn == NULL) {
            return NULL;
        }
    }

    STAILQ_INIT(&conn->recv_queue);
    STAILQ_INIT(&conn->send_queue);
    conn->recv_queue_bytes = 0;
    conn->send_queue_bytes = 0;

    conn->owner = NULL;
    conn->data = NULL;

    conn->fd = -1;

    conn->send_bytes = 0;
    conn->recv_bytes = 0;

    conn->events = 0;
    conn->err = 0;
    conn->recv_active = 0;
    conn->recv_ready = 0;
    conn->send_active = 0;
    conn->send_ready = 0;

    conn->eof = 0;
    conn->done = 0;

    /* for client conn */
    conn->recv = conn_recv;
    conn->send = conn_send;
    conn->close = conn_close;

    return conn;
}
Exemple #12
0
/* Returns a new netconnection (Input and Output buffers) for a
   socket connection on fd */
netconnection_t *net_new_connection(int fd)
{
    netconnection_t *nc;

    if( (nc = nc_alloc()) ) {
	net_connection_reset(nc);
	nc->fd = fd;
	nc->record_fd = 0;
	nc->incoming = 0;
	nc->fake = 0;
	nc->remote_address = net_remote_address(fd);
    }

    return nc;

}
Exemple #13
0
struct replicaset* 
ffi_replicaset_new(void)
{
    int i;
    struct replicaset *rs;

    rs = nc_alloc(sizeof(struct replicaset));
    if (rs == NULL) {
        log_error("failed to allocate memory");
        return NULL;
    }

    for (i = 0; i < NC_MAXTAGNUM; i++) {
        array_init(&rs->tagged_servers[i], 2, sizeof(struct server *));
    }

    return rs;
}
Exemple #14
0
/* Create a new slowlog entry.
 * Incrementing the ref count of all the objects retained is up to
 * this function. */
static slowlog_entry *slowlog_create_entry(struct msg *r, long long duration) {
    slowlog_entry *se = nc_alloc(sizeof(*se));
    uint32_t j, keys_count, keys_count_input;

    se->cmdtype = r->type;

    keys_count_input = keys_count = r->keys==NULL?0:array_n(r->keys);

    if (keys_count_input > SLOWLOG_ENTRY_MAX_KEYS) keys_count_input = SLOWLOG_ENTRY_MAX_KEYS;
    se->keys_count = (int)keys_count;
    if (keys_count_input > 0) {
        se->keys = array_create(keys_count_input, sizeof(struct string));
        for (j = 0; j < keys_count_input; j ++) {
            struct keypos *kp = array_get(r->keys, j);
            struct string *key = array_push(se->keys);
            uint32_t key_len = (uint32_t)(kp->end-kp->start);
            string_init(key);
            if (key_len > SLOWLOG_ENTRY_MAX_STRING) {
                int len;
                uint8_t buf[SLOWLOG_ENTRY_MAX_STRING+50];
                memcpy(buf,kp->start,SLOWLOG_ENTRY_MAX_STRING);
                len = nc_scnprintf(buf+SLOWLOG_ENTRY_MAX_STRING,
                    50,"... (%lu more bytes)",
                    key_len-SLOWLOG_ENTRY_MAX_STRING);            
                if (len > 0) {
                    string_copy(key,buf,SLOWLOG_ENTRY_MAX_STRING+(uint32_t)len);
                } else {
                    string_copy(key,kp->start,SLOWLOG_ENTRY_MAX_STRING);
                }
            } else {
                string_copy(key,kp->start,key_len);
            }
        }
    }else {
        se->keys = NULL;
    }
    
    se->time = time(NULL);
    se->duration = duration;

    STAILQ_NEXT(se, next) = NULL;
    
    return se;
}
Exemple #15
0
struct server*
ffi_server_new(struct server_pool *pool, char *name, char *id, char *ip, int port)
{
    struct server *s;
    struct string address;
    rstatus_t status;

    s = nc_alloc(sizeof(struct server));
    if (s == NULL) {
        log_error("failed to allocate memory");
        return NULL;
    }

    s->owner = pool;
    s->idx = 0;
    s->weight = 1;
    /* set name */
    string_init(&s->name);
    string_copy(&s->name, (uint8_t*)name, (uint32_t)nc_strlen(name));
    string_init(&s->pname);
    string_copy(&s->pname, (uint8_t*)name, (uint32_t)nc_strlen(name));
    string_init(&address);
    string_copy(&address, (uint8_t*)ip, (uint32_t)nc_strlen(ip));
    /* set port */
    s->port = (uint16_t)port;

    status = nc_resolve(&address, s->port, &s->sockinfo);
    if (status != NC_OK) {
        log_error("conf: failed to resolve %.*s:%d", address.len, address.data, s->port);
        return NULL;
    }

    s->family = s->sockinfo.family;
    s->addrlen = s->sockinfo.addrlen;
    s->addr = (struct sockaddr *)&s->sockinfo.addr;

    s->ns_conn_q = 0;
    TAILQ_INIT(&s->s_conn_q);

    s->next_retry = 0LL;
    s->failure_count = 0;
    return s;
}
Exemple #16
0
struct event_base *
event_base_create(int nevent, event_cb_t cb)
{
    struct event_base *evb;
    int status, ep;
    struct epoll_event *event;

    ASSERT(nevent > 0);

    ep = epoll_create(nevent);
    if (ep < 0) {
        log_error("epoll create of size %d failed: %s", nevent, strerror(errno));
        return NULL;
    }

    event = nc_calloc(nevent, sizeof(*event));
    if (event == NULL) {
        status = close(ep);
        if (status < 0) {
            log_error("close e %d failed, ignored: %s", ep, strerror(errno));
        }
        return NULL;
    }

    evb = nc_alloc(sizeof(*evb));
    if (evb == NULL) {
        nc_free(event);
        status = close(ep);
        if (status < 0) {
            log_error("close e %d failed, ignored: %s", ep, strerror(errno));
        }
        return NULL;
    }

    evb->ep = ep;
    evb->event = event;
    evb->nevent = nevent;
    evb->cb = cb;

    log_debug(LOG_INFO, "e %d with nevent %d", evb->ep, evb->nevent);

    return evb;
}
Exemple #17
0
struct event_base *
event_base_create(int nevent, event_cb_t cb)
{
    struct event_base *evb;
    int status, evp;
    port_event_t *event;

    ASSERT(nevent > 0);

    evp = port_create();
    if (evp < 0) {
        log_error("port create failed: %s", strerror(errno));
        return NULL;
    }

    event = nc_calloc(nevent, sizeof(*event));
    if (event == NULL) {
        status = close(evp);
        if (status < 0) {
            log_error("close evp %d failed, ignored: %s", evp, strerror(errno));
        }
        return NULL;
    }

    evb = nc_alloc(sizeof(*evb));
    if (evb == NULL) {
        nc_free(event);
        status = close(evp);
        if (status < 0) {
            log_error("close evp %d failed, ignored: %s", evp, strerror(errno));
        }
        return NULL;
    }

    evb->evp = evp;
    evb->event = event;
    evb->nevent = nevent;
    evb->cb = cb;

    log_info("evp %d with nevent %d", evb->evp, evb->nevent);

    return evb;
}
Exemple #18
0
/* Start a fake net connection (used for demos on CLIENT) */
netconnection_t *net_fake_connection(char *demoname, demo_header *header)
{
    int fd;
    ssize_t size;
    netconnection_t *nc;

    if( !(fd = open(demoname, O_RDONLY)) ) {
	perror("open");
	return NULL;
    }

    size = read(fd, header, sizeof(demo_header));
    if( size != sizeof(demo_header) ) {
	printf("Couldn't Read header information from \"%s\"\n", demoname);
	if( size < 0 )
	    perror("read");
	else
	    printf("Read only %d bytes of %d.\n", size, sizeof(demo_header));

	close(fd);
	return NULL;
    }

    NTOHS( header->x_tiles );
    NTOHS( header->y_tiles );
    NTOHS( header->fps );

    if( (nc = nc_alloc()) ) {
	net_connection_reset(nc);
	nc->fd = fd;
	nc->record_fd = 0;
	nc->fake = 1;
	nc->remote_address = fake_address;
    }

    return nc;

}
Exemple #19
0
struct stats *
stats_create(uint16_t stats_port, char *stats_ip, int stats_interval,
             char *source, struct array *server_pool)
{
    rstatus_t status;
    struct stats *st;
    char *server_name;

    st = nc_alloc(sizeof(*st));
    if (st == NULL) {
        return NULL;
    }

    st->port = stats_port;
    st->interval = stats_interval;
    string_set_raw(&st->addr, stats_ip);

    st->start_ts = (int64_t)time(NULL);

    st->buf.len = 0;
    st->buf.data = NULL;
    st->buf.size = 0;

    array_null(&st->current);
    array_null(&st->shadow);
    array_null(&st->sum);

    st->tid = (pthread_t) -1;
    st->sd = -1;

    string_set_text(&st->service_str, "service");
    //string_set_text(&st->service, "bilitw");

    server_name = nc_alloc(100);
    memset(server_name, 0, 100);
    sprintf(server_name, "bilitw worker %d", nc_worker_index);
    string_set_raw(&st->service, server_name);
    //&st->service->len = strlen(server_name) + 1;
    //&st->service->data = (uint8_t *)server_name;


    string_set_text(&st->source_str, "source");
    string_set_raw(&st->source, source);

    string_set_text(&st->version_str, "version");
    string_set_text(&st->version, NC_VERSION_STRING);

    string_set_text(&st->uptime_str, "uptime");
    string_set_text(&st->timestamp_str, "timestamp");

    string_set_text(&st->ntotal_conn_str, "total_connections");
    string_set_text(&st->ncurr_conn_str, "curr_connections");

    st->updated = 0;
    st->aggregate = 0;

    /* map server pool to current (a), shadow (b) and sum (c) */

    status = stats_pool_map(&st->current, server_pool);
    if (status != NC_OK) {
        goto error;
    }

    status = stats_pool_map(&st->shadow, server_pool);
    if (status != NC_OK) {
        goto error;
    }

    status = stats_pool_map(&st->sum, server_pool);
    if (status != NC_OK) {
        goto error;
    }

    status = stats_create_buf(st);
    if (status != NC_OK) {
        goto error;
    }

    status = stats_start_aggregator(st);
    if (status != NC_OK) {
        goto error;
    }

    return st;

error:
    stats_destroy(st);
    return NULL;
}
Exemple #20
0
static rstatus_t
stats_create_buf(struct stats *st)
{
    uint32_t int64_max_digits = 20; /* INT64_MAX = 9223372036854775807 */
    uint32_t key_value_extra = 8;   /* "key": "value", */
    uint32_t pool_extra = 8;        /* '"pool_name": { ' + ' }' */
    uint32_t server_extra = 8;      /* '"server_name": { ' + ' }' */
    size_t size = 0;
    uint32_t i;

    ASSERT(st->buf.data == NULL && st->buf.size == 0);

    /* header */
    size += 1;

    size += st->service_str.len;
    size += st->service.len;
    size += key_value_extra;

    size += st->source_str.len;
    size += st->source.len;
    size += key_value_extra;

    size += st->version_str.len;
    size += st->version.len;
    size += key_value_extra;

    size += st->uptime_str.len;
    size += int64_max_digits;
    size += key_value_extra;

    size += st->timestamp_str.len;
    size += int64_max_digits;
    size += key_value_extra;

    size += st->ntotal_conn_str.len;
    size += int64_max_digits;
    size += key_value_extra;

    size += st->ncurr_conn_str.len;
    size += int64_max_digits;
    size += key_value_extra;

    /* server pools */
    for (i = 0; i < array_n(&st->sum); i++) {
        struct stats_pool *stp = array_get(&st->sum, i);
        uint32_t j;

        size += stp->name.len;
        size += pool_extra;

        for (j = 0; j < array_n(&stp->metric); j++) {
            struct stats_metric *stm = array_get(&stp->metric, j);

            size += stm->name.len;
            size += int64_max_digits;
            size += key_value_extra;
        }

        /* servers per pool */
        for (j = 0; j < array_n(&stp->server); j++) {
            struct stats_server *sts = array_get(&stp->server, j);
            uint32_t k;

            size += sts->name.len;
            size += server_extra;

            for (k = 0; k < array_n(&sts->metric); k++) {
                struct stats_metric *stm = array_get(&sts->metric, k);

                size += stm->name.len;
                size += int64_max_digits;
                size += key_value_extra;
            }
        }
    }

    /* footer */
    size += 2;

    size = NC_ALIGN(size, NC_ALIGNMENT);

    st->buf.data = nc_alloc(size);
    if (st->buf.data == NULL) {
        log_error("create stats buffer of size %zu failed: %s", size,
                  strerror(errno));
        return NC_ENOMEM;
    }
    st->buf.size = size;

    log_debug(LOG_DEBUG, "stats buffer size %zu", size);

    return NC_OK;
}
Exemple #21
0
rstatus_t
stats_master_server(uint16_t stats_port, char *stats_ip)
{
    rstatus_t status;
    //struct stats *st;
	struct sockinfo si;
	struct string addr;
	//int sd;
   
	
    string_set_raw(&addr, stats_ip);
    status = nc_resolve(&addr, stats_port, &si);
    if (status < 0) {
        return status;
    }

    nc_stats_listen_sd = socket(si.family, SOCK_STREAM, 0);
    if (nc_stats_listen_sd < 0) {
        log_error("socket failed: %s", strerror(errno));
        return NC_ERROR;
    }

    status = nc_set_reuseaddr(nc_stats_listen_sd);
    if (status < 0) {
        log_error("set reuseaddr on m %d failed: %s", nc_stats_listen_sd, strerror(errno));
        return NC_ERROR;
    }


	pthread_t *ptid = nc_alloc(sizeof(pthread_t));	
	*ptid = (pthread_t) -1;
	
	log_error("master sd %d", nc_stats_listen_sd);
	status = pthread_create(ptid, NULL, stats_master_loop, (void*)(&nc_stats_listen_sd));
	if (status < 0) {
		log_error("stats aggregator create failed: %s", strerror(status));
		return NC_ERROR;
	}
	log_debug(LOG_NOTICE, "pthread stats master create success %d'", status);



    status = bind(nc_stats_listen_sd, (struct sockaddr *)&si.addr, si.addrlen);
    if (status < 0) {
        log_error("bind on m %d to addr '%.*s:%u' failed: %s", nc_stats_listen_sd,
                  addr.len, addr.data, stats_port, strerror(errno));
        return NC_ERROR;
    }

    status = listen(nc_stats_listen_sd, SOMAXCONN);
    if (status < 0) {
        log_error("listen on m %d failed: %s", nc_stats_listen_sd, strerror(errno));
        return NC_ERROR;
    }

    log_debug(LOG_NOTICE, "m %d listening on '%.*s:%u'",nc_stats_listen_sd,
              addr.len, addr.data, stats_port);
	
	

    return NC_OK;
}
Exemple #22
0
static struct context *
core_ctx_create(struct instance *nci)
{
    rstatus_t status;
    struct context *ctx;
    struct conn *sentinel_conn;

    ctx = nc_alloc(sizeof(*ctx));
    if (ctx == NULL) {
        return NULL;
    }
    ctx->id = ++ctx_id;
    ctx->cf = NULL;
    ctx->stats = NULL;
    array_null(&ctx->pool);
    ctx->ep = -1;
    ctx->nevent = EVENT_SIZE_HINT;
    ctx->max_timeout = nci->stats_interval;
    ctx->timeout = ctx->max_timeout;
    ctx->event = NULL;
    ctx->server_reconnect_interval = nci->server_reconnect_interval;
    ctx->whitelist = nci->whitelist;

    /* parse and create configuration */
    ctx->cf = conf_create(nci->conf_filename);
    if (ctx->cf == NULL) {
        nc_free(ctx);
        return NULL;
    }

    /* initialize server pool from configuration */
    status = server_pool_init(&ctx->pool, &ctx->cf->pool, ctx);
    if (status != NC_OK) {
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /* initialize sentinel server */
    ctx->sentinel = sentinel_init(nci->sentinel_port, nci->sentinel_addr);
    if (ctx->sentinel == NULL) {
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /* create stats per server pool */
    ctx->stats = stats_create(nci->stats_port, nci->stats_addr, nci->stats_interval,
                              nci->hostname, &ctx->pool);
    if (ctx->stats == NULL) {
        sentinel_deinit(ctx->sentinel);
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /* initialize event handling for client, proxy and server */
    status = event_init(ctx, EVENT_SIZE_HINT);
    if (status != NC_OK) {
        stats_destroy(ctx->stats);
        sentinel_deinit(ctx->sentinel);
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /* preconnect? servers in server pool */
    status = server_pool_preconnect(ctx);
    if (status != NC_OK) {
        server_pool_disconnect(ctx);
        event_deinit(ctx);
        stats_destroy(ctx->stats);
        sentinel_deinit(ctx->sentinel);
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /* initialize sentinel server conn */
    sentinel_conn = sentinel_connect(ctx);
    if (sentinel_conn == NULL) {
        server_pool_disconnect(ctx);
        event_deinit(ctx);
        stats_destroy(ctx->stats);
        sentinel_deinit(ctx->sentinel);
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
    }

    /* initialize proxy per server pool */
    status = proxy_init(ctx);
    if (status != NC_OK) {
        sentinel_conn->close(ctx, sentinel_conn);
        server_pool_disconnect(ctx);
        event_deinit(ctx);
        stats_destroy(ctx->stats);
        sentinel_deinit(ctx->sentinel);
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    log_debug(LOG_VVERB, "created ctx %p id %"PRIu32"", ctx, ctx->id);

    return ctx;
}
Exemple #23
0
static struct context *
core_ctx_create(struct instance *nci)
{
    rstatus_t status;
    struct context *ctx;
    int64_t now;
    uint32_t npool;

    ctx = nc_alloc(sizeof(*ctx));
    if (ctx == NULL) {
        return NULL;
    }

    now = nc_msec_now();
    if (now < 0) {
        nc_free(ctx);
        return NULL;
    }

    ctx->id = ++ctx_id;
    ctx->cf = NULL;
    ctx->stats = NULL;
    ctx->evb = NULL;
    array_null(&ctx->pool);
    ctx->max_timeout = nci->stats_interval;
    ctx->timeout = ctx->max_timeout;
    ctx->next_tick = now + NC_TICK_INTERVAL;

    /* parse and create configuration */
    ctx->cf = conf_create(nci->conf_filename);
    if (ctx->cf == NULL) {
        nc_free(ctx);
        return NULL;
    }

    npool = array_n(&ctx->cf->pool);
    
    /* initialize server pool from configuration */
    if (npool != 0) {
        status = server_pool_init(&ctx->pool, &ctx->cf->pool, ctx);
        if (status != NC_OK) {
            conf_destroy(ctx->cf);
            nc_free(ctx);
            return NULL;
        }
    }

    /* create stats per server pool */
    if (npool != 0) {
        ctx->stats = stats_create(nci->stats_port, nci->stats_addr, nci->stats_interval,
                                  nci->hostname, &ctx->pool);
        if (ctx->stats == NULL) {
            server_pool_deinit(&ctx->pool);
            conf_destroy(ctx->cf);
            nc_free(ctx);
            return NULL;
        }
    }

    /* initialize event handling for client, proxy and server */
    ctx->evb = evbase_create(NC_EVENT_SIZE, &core_core);
    if (ctx->evb == NULL) {
        stats_destroy(ctx->stats);
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /* preconnect? servers in server pool */
    if (npool != 0) {
        status = server_pool_preconnect(ctx);
        if (status != NC_OK) {
            server_pool_disconnect(ctx);
            evbase_destroy(ctx->evb);
            stats_destroy(ctx->stats);
            server_pool_deinit(&ctx->pool);
            conf_destroy(ctx->cf);
            nc_free(ctx);
            return NULL;
        }
    }

    /* initialize proxy per server pool */
    if (npool != 0) {
        status = proxy_init(ctx);
        if (status != NC_OK) {
            server_pool_disconnect(ctx);
            evbase_destroy(ctx->evb);
            stats_destroy(ctx->stats);
            server_pool_deinit(&ctx->pool);
            conf_destroy(ctx->cf);
            nc_free(ctx);
            return NULL;
        }
    }

    log_debug(LOG_VVERB, "created ctx %p id %"PRIu32"", ctx, ctx->id);

    return ctx;
}
Exemple #24
0
struct evbase *
evbase_create(int nevent, void (*callback_fp)(void *, uint32_t))
{

    struct evbase *evb;
    int status, kq;
    struct kevent *changes, *kevents;

    if (nevent <= 0) {
        log_error("nevent has to be positive %d", nevent);
        return NULL;
    }

    /* Initialize the kernel queue */
    if ((kq = kqueue()) == -1) {
        log_error("kernel queue create failed: %s", kq, strerror(errno));
        return NULL;
    }

    changes = nc_calloc(nevent, sizeof(*changes));
    if (changes == NULL) {
        status = close(kq);
        if (status < 0) {
            log_error("close kq %d failed, ignored: %s", kq, strerror(errno));
        }
        return NULL;
    }

    kevents = nc_calloc(nevent, sizeof(*kevents));
    if (kevents == NULL) {
        nc_free(changes);
        status = close(kq);
        if (status < 0) {
            log_error("close kq %d failed, ignored: %s", kq, strerror(errno));
        }
        return NULL;
    }

    evb = (struct evbase *) nc_alloc(sizeof(*evb));
    if (evb == NULL) {
        nc_free(changes);
        nc_free(kevents);
        status = close(kq);
        if (status < 0) {
            log_error("close kq %d failed, ignored: %s", kq, strerror(errno));
        }
        return NULL;
    }

    evb->kq = kq;
    evb->changes = changes;
    evb->kevents  = kevents;
    evb->nevent = nevent;
    evb->callback_fp = callback_fp;
    evb->n_changes = 0;

    log_debug(LOG_INFO, "kq %d with nevent %d", evb->kq,
              evb->nevent);

    return evb;
}
struct stats *
stats_create(uint16_t stats_port, char *stats_ip, int stats_interval,
             char *source, struct array *server_pool) 
{
    rstatus_t status;
    struct stats *st;

    st = nc_alloc(sizeof(*st));
    if (st == NULL) {
        return NULL;
    }

    st->port = stats_port;
    st->interval = stats_interval;
    string_set_raw(&st->addr, stats_ip);

    st->start_ts = (int64_t)time(NULL);

    st->buf.len = 0;
    st->buf.data = NULL;
    st->buf.size = 0;

    array_null(&st->current);
    array_null(&st->shadow);
    array_null(&st->sum);

    st->tid = (pthread_t) -1;
    st->sd = -1;

    string_set_text(&st->service_str, "service");
    string_set_text(&st->service, "nutcracker");

    string_set_text(&st->source_str, "source");
    string_set_raw(&st->source, source);

    string_set_text(&st->version_str, "version");
    string_set_text(&st->version, NC_VERSION_STRING);

    string_set_text(&st->uptime_str, "uptime");
    string_set_text(&st->timestamp_str, "timestamp");

    string_set_text(&st->ntotal_conn_str, "total_connections");
    string_set_text(&st->ncurr_conn_str, "curr_connections");

    st->updated = 0;
    st->aggregate = 0;

    /* map server pool to current (a), shadow (b) and sum (c) */

    status = stats_pool_map(&st->current, server_pool);
    if (status != NC_OK) {
        goto error;
    }

    status = stats_pool_map(&st->shadow, server_pool);
    if (status != NC_OK) {
        goto error;
    }

    status = stats_pool_map(&st->sum, server_pool);
    if (status != NC_OK) {
        goto error;
    }

    status = stats_create_buf(st); //为stats格式信息分配buf空间
    if (status != NC_OK) {
        goto error;
    }

    //stats状态信息专门起一个线程来处理
    status = stats_start_aggregator(st);
    if (status != NC_OK) {
        goto error;
    }

    return st;

error:
    stats_destroy(st);
    return NULL;
}
Exemple #26
0
/*
 * read the comment in proto/nc_redis.c
 */
static rstatus_t
memcache_fragment_retrieval(struct msg *r, uint32_t ncontinuum,
                            struct msg_tqh *frag_msgq,
                            uint32_t key_step)
{
    struct mbuf *mbuf;
    struct msg **sub_msgs;
    uint32_t i;
    rstatus_t status;

    sub_msgs = nc_zalloc(ncontinuum * sizeof(*sub_msgs));
    if (sub_msgs == NULL) {
        return NC_ENOMEM;
    }

    ASSERT(r->frag_seq == NULL);
    r->frag_seq = nc_alloc(array_n(r->keys) * sizeof(*r->frag_seq));
    if (r->frag_seq == NULL) {
        nc_free(sub_msgs);
        return NC_ENOMEM;
    }

    mbuf = STAILQ_FIRST(&r->mhdr);
    mbuf->pos = mbuf->start;

    /*
     * This code is based on the assumption that 'gets ' is located
     * in a contiguous location.
     * This is always true because we have capped our MBUF_MIN_SIZE at 512 and
     * whenever we have multiple messages, we copy the tail message into a new mbuf
     */
    for (; *(mbuf->pos) != ' ';) {          /* eat get/gets  */
        mbuf->pos++;
    }
    mbuf->pos++;

    r->frag_id = msg_gen_frag_id();
    r->nfrag = 0;
    r->frag_owner = r;

    for (i = 0; i < array_n(r->keys); i++) {        /* for each  key */
        struct msg *sub_msg;
        struct keypos *kpos = array_get(r->keys, i);
        uint32_t idx = msg_backend_idx(r, kpos->start, kpos->end - kpos->start);

        if (sub_msgs[idx] == NULL) {
            sub_msgs[idx] = msg_get(r->owner, r->request, r->redis);
            if (sub_msgs[idx] == NULL) {
                nc_free(sub_msgs);
                return NC_ENOMEM;
            }
        }
        r->frag_seq[i] = sub_msg = sub_msgs[idx];

        sub_msg->narg++;
        status = memcache_append_key(sub_msg, kpos->start, kpos->end - kpos->start);
        if (status != NC_OK) {
            nc_free(sub_msgs);
            return status;
        }
    }

    for (i = 0; i < ncontinuum; i++) {     /* prepend mget header, and forward it */
        struct msg *sub_msg = sub_msgs[i];
        if (sub_msg == NULL) {
            continue;
        }

        /* prepend get/gets */
        if (r->type == MSG_REQ_MC_GET) {
            status = msg_prepend(sub_msg, (uint8_t *)"get ", 4);
        } else if (r->type == MSG_REQ_MC_GETS) {
            status = msg_prepend(sub_msg, (uint8_t *)"gets ", 5);
        }
        if (status != NC_OK) {
            nc_free(sub_msgs);
            return status;
        }

        /* append \r\n */
        status = msg_append(sub_msg, (uint8_t *)CRLF, CRLF_LEN);
        if (status != NC_OK) {
            nc_free(sub_msgs);
            return status;
        }

        sub_msg->type = r->type;
        sub_msg->frag_id = r->frag_id;
        sub_msg->frag_owner = r->frag_owner;

        TAILQ_INSERT_TAIL(frag_msgq, sub_msg, m_tqe);
        r->nfrag++;
    }

    nc_free(sub_msgs);
    return NC_OK;
}
Exemple #27
0
static struct context *
core_ctx_create(struct instance *nci)
{
    rstatus_t status;
    struct context *ctx;

    ctx = nc_alloc(sizeof(*ctx));
    if (ctx == NULL) {
        return NULL;
    }
    ctx->id = ++ctx_id;
    ctx->cf = NULL;
    ctx->stats = NULL;
    ctx->evb = NULL;
    array_null(&ctx->pool);
    ctx->max_timeout = nci->stats_interval;
    ctx->timeout = ctx->max_timeout;
    ctx->max_nfd = 0;
    ctx->max_ncconn = 0;
    ctx->max_nsconn = 0;

    /* parse and create configuration */
    ctx->cf = conf_create(nci->conf_filename);
    if (ctx->cf == NULL) {
        nc_free(ctx);
        return NULL;
    }

    /* initialize server pool from configuration */
    status = server_pool_init(&ctx->pool, &ctx->cf->pool, ctx);
    if (status != NC_OK) {
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /*
     * Get rlimit and calculate max client connections after we have
     * calculated max server connections
     */
    status = core_calc_connections(ctx);
    if (status != NC_OK) {
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /* create stats per server pool */
    ctx->stats = stats_create(nci->stats_port, nci->stats_addr, nci->stats_interval,
                              nci->hostname, &ctx->pool);
    if (ctx->stats == NULL) {
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /* initialize event handling for client, proxy and server */
    ctx->evb = event_base_create(EVENT_SIZE, &core_core);
    if (ctx->evb == NULL) {
        stats_destroy(ctx->stats);
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /* preconnect? servers in server pool */
    status = server_pool_preconnect(ctx);
    if (status != NC_OK) {
        server_pool_disconnect(ctx);
        event_base_destroy(ctx->evb);
        stats_destroy(ctx->stats);
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    /* initialize proxy per server pool */
    status = proxy_init(ctx);
    if (status != NC_OK) {
        server_pool_disconnect(ctx);
        event_base_destroy(ctx->evb);
        stats_destroy(ctx->stats);
        server_pool_deinit(&ctx->pool);
        conf_destroy(ctx->cf);
        nc_free(ctx);
        return NULL;
    }

    log_debug(LOG_VVERB, "created ctx %p id %"PRIu32"", ctx, ctx->id);

    return ctx;
}
Exemple #28
0
struct server *
sentinel_init(uint16_t sentinel_port, char *sentinel_ip)
{
    rstatus_t status;
    struct server *sentinel;
    struct string address;
    struct sockinfo info;
    char pname[NC_PNAME_MAXLEN];

    string_init(&address);

    sentinel_status = SENTINEL_CONN_DISCONNECTED;

    sentinel = (struct server *)nc_alloc(sizeof(*sentinel));
    if(sentinel == NULL) {
        goto error;
    }

    /* sentinel server don't have owner server pool */
    sentinel->owner = NULL;
    sentinel->ns_conn_q = 0;
    TAILQ_INIT(&sentinel->s_conn_q);
    sentinel->addr = NULL;
    string_init(&sentinel->pname);
    string_init(&sentinel->name);

    nc_snprintf(pname, NC_PNAME_MAXLEN, "%s:%d:0", sentinel_ip, sentinel_port);
    status = string_copy(&sentinel->pname, pname, (uint32_t)(nc_strlen(pname)));
    if (status != NC_OK) {
        goto error;
    }

    string_copy(&sentinel->name, pname, (uint32_t)(nc_strlen(pname)) - 2);
    if (status != NC_OK) {
        goto error;
    }

    sentinel->port = sentinel_port;

    status = string_copy(&address, sentinel_ip, (uint32_t)(nc_strlen(sentinel_ip)));
    if (status != NC_OK) {
        goto error;
    }

    status = nc_resolve(&address, sentinel_port, &info);
    if (status != NC_OK) {
        goto error;
    }

    sentinel->family = info.family;
    sentinel->addrlen = info.addrlen;
    sentinel->addr = (struct sockaddr*)nc_alloc(info.addrlen);
    if (sentinel->addr == NULL) {
        goto error;
    }
    nc_memcpy(sentinel->addr, &info.addr, info.addrlen);

done:
    string_deinit(&address);
    return sentinel;

error:
    sentinel_deinit(sentinel);
    sentinel = NULL;
    goto done;
}
Exemple #29
0
static rstatus_t
stats_master_send_rsp(int *psd)
{
    int n;
	ssize_t len;
    int sd;
	int i;
	nc_channel_msg_t     message;
	char buf[1000];
	memset(buf, 0, sizeof(char)*1000);
	char *snd_buf = NULL;

	memset(&message, 0, sizeof(nc_channel_msg_t));
	message.command = NC_CMD_GET_STATS;
	
	if (*psd) {
		sd = accept(*psd, NULL, NULL);
		if (sd < 0) {
	        log_error("accept on m %d failed: %s", sd, strerror(errno));
	        return NC_ERROR;
	    }
	}
	
	// still in reconfiguration process 
	if (nc_reload_start) {
		sprintf(buf, "%s", "no stats get due to still during reconfiguration period.");
		if (*psd) {
			len = nc_strlen(buf)+1;
			len = nc_sendn(sd, buf, len);
			if (len < 0) {
				log_error("send stats on sd %d failed: %s", sd, strerror(errno));

			}
			close(sd);
		}
		return NC_OK;
	}

	//broadcast
    for (i = 0; i < nc_last_process; i++) 
	{
        if (nc_processes[i].pid == -1 || nc_processes[i].pid == 0) 
		{
            continue;
        }
       
        if (nc_write_channel(nc_processes[i].channel[0],
                                  &message, sizeof(nc_channel_msg_t))
           == NC_OK)
        {
			if (nc_set_blocking(nc_processes[i].channel[0]) < 0) {
		    	log_error("set channel %d block failed while core timeout %s", 
		        nc_processes[i].channel[0] , strerror(errno));
				continue;
			}
		
			n = nc_read_channel(nc_processes[i].channel[0], &env_global.ctrl_msg, sizeof(nc_channel_msg_t));
			if (env_global.ctrl_msg.command != NC_CMD_GET_STATS || n < 0) {
				log_error("failure: get stats from worker %d receive length,  %s", 
		        nc_processes[i].channel[0] , strerror(errno));
			} else {
				log_error("success: get stats from worker %d receive length, %d", 
		        nc_processes[i].channel[0] , n);

				snd_buf = nc_alloc(n + n);				
				len = nc_recvn(nc_processes[i].channel[0], snd_buf, n);
				if (len < 0) {
					if (*psd) {
						log_error("recv stats on sd %d failed: %s", sd, strerror(errno));
					}
					nc_free(snd_buf);
					snd_buf = NULL;
        			continue;
				}
				if (*psd) {
					len = nc_sendn(sd, snd_buf, len);
					if (len < 0) {
						log_error("send stats on sd %d failed: %s", sd, strerror(errno));
						nc_free(snd_buf);
						snd_buf = NULL;
						continue;
					}
				}
	
				len = nc_write(env_global.stats_fd, snd_buf, len);
				if (len < 0) {
					log_error("nc_write %d failed: %s", env_global.stats_fd, strerror(errno));
					continue;
			    }

				
				nc_free(snd_buf);
				snd_buf = NULL;

			}

			

			if (nc_set_nonblocking(nc_processes[i].channel[0]) < 0) {
				log_error("set channel %d nonblock failed while core timeout %s", 
				        nc_processes[i].channel[0] , strerror(errno));
			}

        }
    }
	
	if (*psd) {
		shutdown(sd, SHUT_RDWR);
		close(sd);
	}
    return NC_OK;
}