2 * Copyright (C) 2007 Andre Noll <maan@systemlinux.org>
4 * Licensed under the GPL v2. For licencing details see COPYING.
7 /** \file chunk_queue.c Queuing functions for paraslash senders. */
16 * Senders may use the chunk queue facility to deal with laggy connections. It
17 * allows them to enqueue chunks if they can not be sent out immediately.
19 * Chunk queues are "cheap" in the sense that only reference to the audio file
20 * data is stored, but not the data itsself.
23 /** The list of pending chunks for this client. */
25 /** The number of pending bytes for this client. */
26 unsigned long num_pending
;
27 /** Enqueueing more than that many bytes is an error. */
28 unsigned long max_pending
;
31 /** Describes one queued chunk in a chunk queue. */
33 /** The number of the queued chunk, -1U means header. */
35 /** The number of bytes already sent. */
37 /** Position of the chunk in the chunk queue. */
38 struct list_head node
;
42 * Add a chunk to the given queue.
44 * \param cq the queue to add the chunk to.
45 * \param chunk_num The number of the chunk to be queued.
46 * \param sent The number of bytes of this chunk that the sender was able to
49 * \return Positive on success, negative on errors.
51 int cq_enqueue(struct chunk_queue
*cq
, long unsigned chunk_num
,
54 struct queued_chunk
*qc
;
59 if (chunk_num
!= -1U) {
60 ret
= vss_get_chunk(chunk_num
, &buf
, &len
);
64 buf
= vss_get_header(&len
);
65 if (cq
->num_pending
+ len
> cq
->max_pending
)
67 qc
= para_malloc(sizeof(struct queued_chunk
));
68 cq
->num_pending
+= len
;
69 qc
->chunk_num
= chunk_num
;
71 list_add_tail(&qc
->node
, &cq
->q
);
72 PARA_DEBUG_LOG("%lu bytes queued for %p\n", cq
->num_pending
, &cq
->q
);
77 * Lookup the next chunk in the queue.
79 * \param cq The chunk queue.
81 * \return The next queued chunk, or \p NULL if there is no chunk awailable.
83 struct queued_chunk
*cq_peek(struct chunk_queue
*cq
)
85 if (list_empty(&cq
->q
))
87 return list_entry(cq
->q
.next
, struct queued_chunk
, node
);
91 * Remove the current chunk from the queue.
93 * \param cq The chunk to remove.
95 void cq_dequeue(struct chunk_queue
*cq
)
97 struct queued_chunk
*qc
= cq_peek(cq
);
104 * Change the number of bytes send for the current queued chunk.
106 * \param cq The chunk queue.
107 * \param sent Number of bytes successfully sent.
109 void cq_update(struct chunk_queue
*cq
, size_t sent
)
111 struct queued_chunk
*qc
= cq_peek(cq
);
114 cq
->num_pending
-= sent
;
118 * Get a pointer to the given queued chunk.
120 * \param qc The queued chunk.
121 * \param buf Result pointer.
122 * \param len Number of bytes of \a buf.
124 * \return Positive on success, negative on errors.
126 int cq_get(struct queued_chunk
*qc
, char **buf
, size_t *len
)
130 if (qc
->chunk_num
!= -1U) {
131 ret
= vss_get_chunk(qc
->chunk_num
, buf
, len
);
135 *buf
= vss_get_header(len
);
136 assert(*len
> qc
->sent
);
143 * Allocate and initialize a chunk queue.
145 * \param max_pending Maximal number of bytes that will be queued.
147 * \return A pointer to the new queue.
149 struct chunk_queue
*cq_new(size_t max_pending
)
151 struct chunk_queue
*cq
= para_malloc(sizeof(*cq
));
152 INIT_LIST_HEAD(&cq
->q
);
153 cq
->max_pending
= max_pending
;
159 * Deallocate all resources of this queue.
161 * \param cq The chunk queue.
163 void cq_destroy(struct chunk_queue
*cq
)
165 struct queued_chunk
*qc
, *tmp
;
166 list_for_each_entry_safe(qc
, tmp
, &cq
->q
, node
) {