+ MutexLock lock(&queued_data_mutex);
+ assert(suitable_for_stream_start == SUITABLE_FOR_STREAM_START ||
+ suitable_for_stream_start == NOT_SUITABLE_FOR_STREAM_START);
+
+ DataElement data_element;
+ data_element.suitable_for_stream_start = suitable_for_stream_start;
+
+ if (encoding == Stream::STREAM_ENCODING_METACUBE) {
+ // Add a Metacube block header before the data.
+ metacube2_block_header hdr;
+ memcpy(hdr.sync, METACUBE2_SYNC, sizeof(hdr.sync));
+ hdr.size = htonl(bytes);
+ hdr.flags = htons(0);
+ if (suitable_for_stream_start == NOT_SUITABLE_FOR_STREAM_START) {
+ hdr.flags |= htons(METACUBE_FLAGS_NOT_SUITABLE_FOR_STREAM_START);
+ }
+ hdr.csum = htons(metacube2_compute_crc(&hdr));
+
+ data_element.data.iov_base = new char[bytes + sizeof(hdr)];
+ data_element.data.iov_len = bytes + sizeof(hdr);
+
+ memcpy(data_element.data.iov_base, &hdr, sizeof(hdr));
+ memcpy(reinterpret_cast<char *>(data_element.data.iov_base) + sizeof(hdr), data, bytes);
+
+ queued_data.push_back(data_element);
+ } else if (encoding == Stream::STREAM_ENCODING_RAW) {
+ // Just add the data itself.
+ data_element.data.iov_base = new char[bytes];
+ memcpy(data_element.data.iov_base, data, bytes);
+ data_element.data.iov_len = bytes;
+
+ queued_data.push_back(data_element);
+ } else {
+ assert(false);
+ }
+}
+
+void Stream::process_queued_data()
+{
+ std::vector<DataElement> queued_data_copy;
+
+ // Hold the lock for as short as possible, since add_data_raw() can possibly
+ // write to disk, which might disturb the input thread.
+ {
+ MutexLock lock(&queued_data_mutex);
+ if (queued_data.empty()) {
+ return;
+ }
+
+ swap(queued_data, queued_data_copy);
+ }
+
+ // Update the last suitable starting point for the stream,
+ // if the queued data contains such a starting point.
+ size_t byte_position = bytes_received;
+ for (size_t i = 0; i < queued_data_copy.size(); ++i) {
+ if (queued_data_copy[i].suitable_for_stream_start == SUITABLE_FOR_STREAM_START) {
+ last_suitable_starting_point = byte_position;
+ }
+ byte_position += queued_data_copy[i].data.iov_len;
+ }
+
+ add_data_raw(queued_data_copy);
+ for (size_t i = 0; i < queued_data_copy.size(); ++i) {
+ char *data = reinterpret_cast<char *>(queued_data_copy[i].data.iov_base);
+ delete[] data;
+ }
+
+ // We have more data, so wake up all clients.