struct queue_item * queueitem_make_byquery(struct query_params *qp) { struct db_media_file_info dbmfi; struct queue_item *item_head; struct queue_item *item_tail; struct queue_item *item_temp; int ret; ret = db_query_start(qp); if (ret < 0) { DPRINTF(E_LOG, L_PLAYER, "Could not start query\n"); return NULL; } DPRINTF(E_DBG, L_PLAYER, "Player queue query returned %d items\n", qp->results); item_head = NULL; item_tail = NULL; while (((ret = db_query_fetch_file(qp, &dbmfi)) == 0) && (dbmfi.id)) { item_temp = queue_item_new(&dbmfi); if (!item_temp) { DPRINTF(E_LOG, L_PLAYER, "Error creating new queue_item for id '%s'\n", dbmfi.id); continue; } if (!item_head) item_head = item_temp; if (item_tail) { item_tail->next = item_temp; item_temp->prev = item_tail; item_tail->shuffle_next = item_temp; item_temp->shuffle_prev = item_tail; } item_tail = item_temp; DPRINTF(E_DBG, L_PLAYER, "Added song id %s (%s)\n", dbmfi.id, dbmfi.title); } db_query_end(qp); if (ret < 0) { DPRINTF(E_LOG, L_PLAYER, "Error fetching results\n"); return NULL; } item_head->prev = item_tail; item_tail->next = item_head; item_head->shuffle_prev = item_tail; item_tail->shuffle_next = item_head; return item_head; }
int main(int argc, char **argv) { int i; /* Read input arguments */ read_input_args(argc, argv); if (g_verbose > 1) { fprintf(stdout, "g_daemon = %d\n", g_daemon); fprintf(stdout, "g_udp_port = %d\n", g_udp_port); fprintf(stdout, "g_nr_working_threads = %d\n", g_nr_working_threads); fprintf(stdout, "g_queue_size = %d\n", g_queue_size); fprintf(stdout, "g_tcp_port = %d\n", g_tcp_port); fprintf(stdout, "g_tcp_ipv4_addr = %s\n", g_tcp_ipv4_addr); fprintf(stdout, "g_tcp_answer_timeout = %d\n", g_tcp_answer_timeout); fprintf(stdout, "g_tcp_conn_retry = %d\n", g_tcp_conn_retry); fprintf(stdout, "g_verbose = %d\n", g_verbose); } /* Daemonize server */ if (g_daemon) { umask(0); int pid = fork(); if (pid < 0) error_exit("%s", strerror(errno)); else if (pid != 0) return 0; g_verbose = 0; setsid(); chdir("/"); close(0); close(1); close(2); open("/dev/null", O_RDWR); dup(0); dup(0); } /* Number of read bytes */ int rb; /* UDP client IP, port, size and frame requested */ struct sockaddr_in * from; socklen_t * fromlen; /* UDP server socket descriptor, local to the main thread */ int ussd = open_udp_server_socket(); /* UDP server socket poll'ed */ struct pollfd pfds[1]; pfds[0].fd = ussd; pfds[0].events = POLLIN; /* Input event */ /* Queue for each thread */ struct queue * queues; queues = (struct queue *) malloc(g_nr_working_threads * sizeof(struct queue)); if (queues == NULL) error_exit("Memory allocation failed!\n"); for (i = 0; i < g_nr_working_threads; i++) queue_new(&queues[i], g_queue_size); /* Index of the next queue used to store the data of a new connection */ int sel_queue = 0; /* Set of threads */ pthread_t * consumers; consumers = (pthread_t *) malloc(g_nr_working_threads * sizeof(pthread_t)); if (consumers == NULL) error_exit("Memory allocation failed!\n"); for (i = 0; i < g_nr_working_threads; i++) pthread_create(&consumers[i], NULL, consumer_main, &queues[i]); // TODO it would be nice to manage some signal to break out this while while (1) { int rv = poll(pfds, 1, g_udp_timeout); /* poll error */ if (rv == -1) { error_exit("syscall poll %s", strerror(errno)); } /* poll timeout */ else if (rv == 0) { if (g_verbose > 1) fprintf(stdout, "timeout expired\n"); /* poll data ready */ } else { if (pfds[0].revents & POLLIN) { if (g_verbose > 0) fprintf(stdout, "MAIN: client request received\n"); /* allocate resources for the client request */ if (g_verbose > 1) fprintf(stdout, "MAIN: allocating resources for the new request\n"); char * req = (char *) malloc(UDP_FRAME_SIZE * sizeof(char)); if (req == NULL) error_exit("Memory allocation failed!\n"); bzero(req, UDP_FRAME_SIZE * sizeof(char)); from = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in)); if (from == NULL) error_exit("Memory allocation failed!\n"); bzero(from, sizeof(struct sockaddr)); fromlen = (socklen_t *) malloc(sizeof(socklen_t)); if (fromlen == NULL) error_exit("Memory allocation failed!\n"); bzero(fromlen, sizeof(socklen_t)); *fromlen = sizeof(struct sockaddr_in); /* must be initialized again */ /* receive incoming data */ rb = recvfrom(ussd, /* udp socket descriptor */ &req[0], UDP_FRAME_SIZE-1, /* frame received and its size */ 0, (struct sockaddr *)from, fromlen); if (g_verbose > 1) fprintf(stdout, "MAIN: %s:%d --> recvfrom %d bytes\n", inet_ntoa(from->sin_addr), ntohs(from->sin_port), rb); struct queue_item * item = (struct queue_item *) malloc(sizeof(struct queue_item)); if (item == NULL) error_exit("Memory allocation failed!\n"); queue_item_new(item, req, rb, from, fromlen); /* Enqueue the new item in the proper queue */ queue_head_add(&queues[sel_queue], item); /* Easier lock-free queue balancing */ sel_queue = (sel_queue + 1) % g_nr_working_threads; if (g_verbose > 1) { for (i = 0; i < g_nr_working_threads; i++) { fprintf(stdout, "MAIN: == Thread number %d queue dumped ==\n", i); queue_debug(&queues[i]); } } } } } /* Wait all the threads before continuing */ for (i = 0; i < g_nr_working_threads; i++) pthread_join(consumers[i], NULL); free(queues); free(consumers); }