Queue *queue_new (void) { Queue *newQueue = mem_new(Queue,1); queue_head(newQueue) = NULL; queue_tail(newQueue) = NULL; return newQueue; }
void queue_foreach (Queue *queue, VisitorFunc visit, void *extra_data) { DList *tail = queue_tail(queue); while (tail != NULL) { visit (dlist_data(tail),extra_data); tail = dlist_previous(tail); } }
/* * find the middle queue element if the queue has odd number of elements * or the first element of the queue's second part otherwise */ queue_t * queue_middle(queue_t *queue) { queue_t *middle, *next; middle = queue_head(queue); if (middle == queue_tail(queue)) { return middle; } next = queue_head(queue); for ( ;; ) { middle = queue_next(middle); next = queue_next(next); if (next == queue_tail(queue)) { return middle; } next = queue_next(next); if (next == queue_tail(queue)) { return middle; } } /* no reached */ }
/* the stable insertion sort */ void queue_sort(queue_t *queue, int (*cmp)(const queue_t *, const queue_t *)) { queue_t *q, *prev, *next; q = queue_head(queue); if (q == queue_tail(queue)) { return; } for (q = queue_next(q); q != queue_sentinel(queue); q = next) { prev = queue_prev(q); next = queue_next(q); queue_remove(q); do { if (cmp(prev, q) <= 0) { break; } prev = queue_prev(prev); } while (prev != queue_sentinel(queue)); queue_insert_head(prev, q); } }
void * consumer_main(void *own_queue) { /* Pointer to my own queue */ struct queue * q; q = (struct queue *)own_queue; /* Pointer to the current item consumed */ struct queue_item * consumed_item; /* Address of the TCP server to connect to */ struct sockaddr_in servaddr; bzero(&servaddr, sizeof(struct sockaddr_in)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(g_tcp_port); inet_pton(AF_INET, g_tcp_ipv4_addr, &servaddr.sin_addr); /* Buffer to store the response from servaddr */ unsigned char response[TCP_FRAME_SIZE]; /* TODO is the allocated space enough? */ /* Structure used to poll the socket descriptor connected with remote TCP server */ struct pollfd pfd[1]; pfd[0].events = POLLIN; /* Interested in input events */ /* Wait until the first item is enqueued */ pthread_mutex_lock(&q->mux); pthread_cond_wait(&q->not_empty, &q->mux); pthread_mutex_unlock(&q->mux); while (1) { /* get next consumed item */ consumed_item = queue_tail(q); if (g_verbose > 1) fprintf(stdout, "THR: item consumed from my own queue is: %s\n", consumed_item->frame); int tsd = reconnect_tcp_server(&servaddr); /* poll input events on tsd */ pfd[0].fd = tsd; /* send answer to TCP server */ if (-1 == send_tcp_safe(tsd, consumed_item->frame, consumed_item->frame_len, 0)) { /* Close bidirectional tcp socket */ shutdown(tsd, SHUT_RDWR); close(tsd); /* Delete connection from my queue */ queue_tail_del(q); continue; } /* Poll the TCP server socket descriptor for the response */ int rv = poll(pfd, 1, g_tcp_answer_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, "THR: response timeout expired, connection discarted\n"); /* Close bidirectional tcp socket */ shutdown(tsd, SHUT_RDWR); close(tsd); /* Delete connection from my queue */ queue_tail_del(q); continue; } /* poll data ready */ else if (pfd[0].revents & POLLIN) { if (g_verbose > 0) fprintf(stdout, "THR: response received from TCP server\n"); /* receive response from TCP server */ bzero(response, TCP_FRAME_SIZE * sizeof(char)); int rb = recv(tsd, &response, TCP_FRAME_SIZE, 0); if (rb < 0) { error_exit("message received from the TCP socket failed!\n"); } else if (rb == 0) { // peer shutdown if (g_verbose > 0) fprintf(stdout, "THR: connection closed by peer\n"); } else if (rb > 0) { /* valid data */ if (g_verbose > 0) fprintf(stdout, "THR: sending response back to UDP client: %s\n", response); /* Create UDP socket */ int usd = socket(AF_INET, SOCK_DGRAM, 0); if (usd == -1) error_exit("udp socket at consumer_main: %s", strerror(errno)); struct sockaddr_in sin; bzero(&sin, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = htons(g_udp_port); sin.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(usd, (struct sockaddr*) &sin, sizeof(sin)) == -1) error_exit("bind at consumer_main: %s", strerror(errno)); /* Send response to the client */ sendto_udp_safe(usd, response, rb, 0, (struct sockaddr *)consumed_item->from, *consumed_item->fromlen); /* Close UDP socket */ shutdown(usd, SHUT_RDWR); close(usd); } /* Close bidirectional tcp socket */ shutdown(tsd, SHUT_RDWR); close(tsd); /* Delete connection from my queue */ queue_tail_del(q); } /* POLLIN */ } /* while */ }