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; }
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; }
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; }
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; }