예제 #1
0
void mx_watch_handler(mx_connection_t *conn, mx_token_t *tokens, int tokens_count)
{
    mx_queue_t *queue;
    mx_queue_item_t *item;
    
    if (hash_lookup(mx_daemon->table, tokens[1].value, (void **)&queue) == -1)
    {
        if (!(queue = mx_queue_create(tokens[1].value, tokens[1].length))) {
            mx_send_reply_return(conn, MX_NOT_ENOUGH_MEMORY);
        }
        hash_insert(mx_daemon->table, tokens[1].value, queue);
    }
    
    if (!mx_queue_fetch_head(queue, (void **)&item)) {
        list_add_tail(&conn->watch, &queue->watcher); /* add to watcher list */
        conn->flag = MX_CONNECTION_WATCHER;
    } else {
        mx_send_item(conn, item);
        mx_queue_delete_head(queue);
        mx_dirty_update();
    }
    return;
}
예제 #2
0
void mx_init_daemon()
{
    struct linger ling = {0, 0};
    struct sockaddr_in addr;
    int flags = 1;

    mx_daemon->log_fd = fopen(mx_daemon->log_file, "a+");
    if (!mx_daemon->log_file) {
        fprintf(stderr, "[failed] failed to open log file\n");
        exit(-1);
    }

    mx_daemon->fd = socket(AF_INET, SOCK_STREAM, 0);
    if (mx_daemon->fd == -1) {
        mx_write_log(mx_log_error, "Unable create listening server socket");
        exit(-1);
    }

    if (mx_set_nonblocking(mx_daemon->fd) == -1) {
        mx_write_log(mx_log_error, "Unable set socket to non-blocking");
        exit(-1);
    }

    setsockopt(mx_daemon->fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
    setsockopt(mx_daemon->fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags));
    setsockopt(mx_daemon->fd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
#if !defined(TCP_NOPUSH)
    setsockopt(mx_daemon->fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags));
#endif

    addr.sin_family = AF_INET;
    addr.sin_port = htons(mx_daemon->port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(mx_daemon->fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
        mx_write_log(mx_log_error, "Unable bind socket");
        close(mx_daemon->fd);
        exit(-1);
    }

    if (listen(mx_daemon->fd, 1024) == -1) {
        mx_write_log(mx_log_error, "Unable listen socket");
        close(mx_daemon->fd);
        exit(-1);
    }

    mx_daemon->event = aeCreateEventLoop();
    if (!mx_daemon->event) {
        mx_write_log(mx_log_error, "Unable create EventLoop");
        exit(-1);
    }

    mx_daemon->table = hash_alloc(32);
    if (!mx_daemon->table) {
        mx_write_log(mx_log_error, "Unable create HashTable");
        exit(-1);
    }

    mx_daemon->delay_queue = mx_queue_create("__delay__", sizeof("__delay__") - 1);
    if (!mx_daemon->table) {
        mx_write_log(mx_log_error, "Unable create delay queue");
        exit(-1);
    }
    
    mx_daemon->recycle = mx_recycle_create();
    if (!mx_daemon->recycle) {
        mx_write_log(mx_log_error, "Unable create recycle");
        exit(-1);
    }

    if (aeCreateFileEvent(mx_daemon->event, mx_daemon->fd,
            AE_READABLE, mx_accept_connection, NULL) == -1) {
        mx_write_log(mx_log_error, "Unable create accpet file event");
        exit(-1);
    }

    aeCreateTimeEvent(mx_daemon->event, 1, mx_core_timer, NULL, NULL);

    time(&mx_current_time);

    return;
}
예제 #3
0
static void mx_push_common_handler(mx_connection_t *conn, mx_token_t *tokens, int is_timer)
{
    mx_queue_t *queue;
    mx_queue_item_t *item;
    int job_length, prio_value, delay_time;
    int remain;
    char *msg;
    
    prio_value = atoi(tokens[2].value);  /* job item's priority */
    job_length = atoi(tokens[4].value);  /* job item's size */

    /* job item's delay time */
    if (is_timer) {
        if (mx_strtotime(&delay_time, tokens[3].value, "%d-%d-%d/%d:%d:%d") == 0) {
            delay_time = delay_time - mx_current_time;
            if (delay_time < 0) {
                delay_time = 0;
            }
        } else {
            mx_send_reply_return(conn, MX_DATE_FORMAT_INVAILD);
        }
    } else {
        delay_time = atoi(tokens[3].value);
    }

    if ((job_length <= 0 && (msg = MX_JOB_SIZE_INVAILD)) || 
        (tokens[1].length >= 128 && (msg = MX_QUEUE_NAME_TOOLONG)))
    {
        mx_send_reply_return(conn, msg);
    }

    /* find the queue from queues table */
    if (hash_lookup(mx_daemon->table, tokens[1].value, (void **)&queue) == -1) {
        /* not found the queue and create it */
        if (!(queue = mx_queue_create(tokens[1].value, tokens[1].length))) {
            mx_send_reply_return(conn, MX_NOT_ENOUGH_MEMORY);
        }
        hash_insert(mx_daemon->table, tokens[1].value, queue);
    }

    /* create new job item */
    if (!(item = mx_queue_item_create(prio_value, delay_time, queue, job_length))) {
        mx_send_reply_return(conn, MX_NOT_ENOUGH_MEMORY);
    }

    conn->item = item;
    conn->itemptr = mx_item_data(item);
    conn->itembytes = mx_item_size(item) + 2;

    remain = conn->recvlast - conn->recvpos;
    if (remain > 0) {
        int tocpy = remain > job_length + 2 ? job_length + 2 : remain;

        memcpy(conn->itemptr, conn->recvpos, tocpy);
        conn->itemptr += tocpy;
        conn->itembytes -= tocpy;
        conn->recvpos += tocpy;   /* fix receive position */

        if (conn->itembytes <= 0) {
            mx_finish_recv_body(conn);
            mx_send_reply_return(conn, "+OK"); /* success and return */
        }
    }

    conn->rev_handler = mx_recv_client_body;
    return;
}
예제 #4
0
파일: db.c 프로젝트: yangchaogit/mx-queued
int mx_load_queues()
{
    struct mx_job_header header;
    mx_queue_t *queue;
    mx_job_t *job;
    time_t current_time = time(NULL);
    int count = 0;
    char tbuf[128];
    FILE *fp;
    int retval;

    if (!mx_global->bgsave_filepath || 
        !(fp = fopen(mx_global->bgsave_filepath, "rb")))
    {
        return 0;
    }

    if (fread(tbuf, sizeof(MX_BGSAVE_HEADER) - 1, 1, fp) != 1) {
        goto failed;
    }

    if (strncmp(tbuf, MX_BGSAVE_HEADER, sizeof(MX_BGSAVE_HEADER) - 1) != 0) {
        mx_write_log(mx_log_debug, "(%s) was a invaild database file", mx_global->bgsave_filepath);
        fclose(fp);
        return -1;
    }

    while (1)
    {
        if (fread(&header, sizeof(header), 1, fp) != 1) {
            goto failed;
        }

        /* finish and break */
        if (header.qlen == 0 || header.jlen == 0) {
            break;
        }

        if (fread(tbuf, header.qlen, 1, fp) != 1) {
            goto failed;
        }

        tbuf[header.qlen] = 0;

        /* find the queue from queue table */
        if (hash_lookup(mx_global->queue_table, tbuf, (void **)&queue) == -1)
        {
            /* not found and create it */
            if (!(queue = mx_queue_create(tbuf, header.qlen))) {
                goto failed;
            }

            if (hash_insert(mx_global->queue_table, tbuf, queue) != 0) {
                goto failed;
            }
        }

        job = mx_job_create(queue, header.prival, header.timeout, header.jlen);
        if (!job) {
            goto failed;
        }

        if (fread(job->body, job->length, 1, fp) != 1) {
            goto failed;
        }

        job->body[job->length] = CR_CHR;
        job->body[job->length+1] = LF_CHR;

        if (job->timeout > 0 && job->timeout > current_time) {
            retval = mx_skiplist_insert(mx_global->delay_queue, job->timeout, job);

        } else {
            job->timeout = 0;
            retval = mx_skiplist_insert(queue->list, job->prival, job);
        }

        if (retval != 0) {
            goto failed;
        }

        count++;
    }

    mx_write_log(mx_log_debug, "finish load (%d)jobs from disk", count);
    fclose(fp);
    return 0;

failed:
    mx_write_log(mx_log_error, "failed to read jobs from disk, message(%s)", strerror(errno));
    fclose(fp);
    return -1;
}