+void Stream::add_data(const char *data, ssize_t bytes)
+{
+ if (encoding == Stream::STREAM_ENCODING_RAW) {
+ add_data_raw(data, bytes);
+ } else if (encoding == STREAM_ENCODING_METACUBE) {
+ metacube_block_header hdr;
+ memcpy(hdr.sync, METACUBE_SYNC, sizeof(hdr.sync));
+ hdr.size = htonl(bytes);
+ hdr.flags = htonl(0);
+
+ char *block = new char[bytes + sizeof(hdr)];
+ memcpy(block, &hdr, sizeof(hdr));
+ memcpy(block + sizeof(hdr), data, bytes);
+ add_data_raw(block, bytes + sizeof(hdr));
+ delete[] block;
+ } else {
+ assert(false);
+ }
+}
+
+void Stream::add_data_raw(const char *data, ssize_t bytes)
+{
+ size_t pos = bytes_received % backlog_size;
+ bytes_received += bytes;
+
+ if (pos + bytes > backlog_size) {
+ ssize_t to_copy = backlog_size - pos;
+ while (to_copy > 0) {
+ int ret = pwrite(data_fd, data, to_copy, pos);
+ if (ret == -1 && errno == EINTR) {
+ continue;
+ }
+ if (ret == -1) {
+ log_perror("pwrite");
+ // Dazed and confused, but trying to continue...
+ break;
+ }
+ pos += ret;
+ data += ret;
+ to_copy -= ret;
+ bytes -= ret;
+ }
+ pos = 0;
+ }
+
+ while (bytes > 0) {
+ int ret = pwrite(data_fd, data, bytes, pos);
+ if (ret == -1 && errno == EINTR) {
+ continue;
+ }
+ if (ret == -1) {
+ log_perror("pwrite");
+ // Dazed and confused, but trying to continue...
+ break;
+ }
+ pos += ret;
+ data += ret;
+ bytes -= ret;
+ }
+}
+