// return 1 if chain has been fully sent, 0 otherwise int processChain( BufferedWriter* self, BufferChain* chain ) { uint8_t* buf = mbuf_rdptr(chain->mbuf); size_t size = mbuf_message_offset(chain->mbuf) - mbuf_read_offset(chain->mbuf); size_t sent = 0; chain->reading = 1; oml_unlock(&self->lock, "processChain"); /* don't keep lock while transmitting */ MBuffer* meta = self->meta_buf; while (size > sent) { long cnt = self->writeFunc(self->writeFuncHdl, (void*)(buf + sent), size - sent, meta->rdptr, meta->fill); if (cnt > 0) { sent += cnt; } else { /* ERROR: Sleep a bit and try again */ /* To be on the safe side, we rewind to the beginning of the * chain and try to resend everything - this is especially important * if the underlying stream needs to reopen and resync. */ mbuf_reset_read(chain->mbuf); size = mbuf_message_offset(chain->mbuf) - mbuf_read_offset(chain->mbuf); sent = 0; sleep(1); } } // get lock back to see what happened while we were busy oml_lock_persistent(self); mbuf_read_skip(chain->mbuf, sent); if (mbuf_write_offset(chain->mbuf) == mbuf_read_offset(chain->mbuf)) { // seem to have sent everything so far, reset chain // mbuf_clear2(chain->mbuf, 0); mbuf_clear2(chain->mbuf, 1); chain->reading = 0; return 1; } return 0; }
/** Read the marshalling header information contained in an MBuffer. * * \param mbuf MBuffer to read from * \param header pointer to an OmlBinaryHeader into which the data from the * mbuf should be unmarshalled * \return 1 on success, the size of the missing section as a negative number * if the buffer is too short, or 0 if something failed */ int unmarshal_init(MBuffer* mbuf, OmlBinaryHeader* header) { uint8_t header_str[PACKET_HEADER_SIZE + 2]; uint8_t stream_header_str[STREAM_HEADER_SIZE]; int result, n; OmlValue seqno; OmlValue timestamp; oml_value_init(&seqno); oml_value_init(×tamp); result = mbuf_begin_read (mbuf); if (result == -1) { logerror("Couldn't start unmarshalling packet (mbuf_begin_read())\n"); return 0; } result = mbuf_read (mbuf, header_str, 3); if (result == -1) { return mbuf_rd_remaining (mbuf) - 3; } if (! (header_str[0] == SYNC_BYTE && header_str[1] == SYNC_BYTE)) { logdebug("Cannot find sync bytes in binary stream, out of sync; first 3 bytes: %#0x %#0x %#0x\n", header_str[0], header_str[1], header_str[2]); return 0; } header->type = (OmlBinMsgType)header_str[2]; if (header->type == OMB_DATA_P) { // Read 2 more bytes of the length field uint16_t nv16 = 0; result = mbuf_read (mbuf, (uint8_t*)&nv16, sizeof (uint16_t)); if (result == -1) { n = mbuf_rd_remaining (mbuf) - 2; mbuf_reset_read (mbuf); return n; } header->length = (int)ntohs (nv16); } else if (header->type == OMB_LDATA_P) { // Read 4 more bytes of the length field uint32_t nv32 = 0; result = mbuf_read (mbuf, (uint8_t*)&nv32, sizeof (uint32_t)); if (result == -1) { n = mbuf_rd_remaining (mbuf) - 4; mbuf_reset_read (mbuf); return n; } header->length = (int)ntohl (nv32); } else { logwarn ("Unknown packet type %d\n", (int)header->type); return 0; } int extra = mbuf_rd_remaining (mbuf) - header->length; if (extra < 0) { mbuf_reset_read (mbuf); return extra; } result = mbuf_read (mbuf, stream_header_str, LENGTH (stream_header_str)); if (result == -1) { n = mbuf_rd_remaining (mbuf) - LENGTH (stream_header_str); mbuf_reset_read (mbuf); return n; } header->values = (int)stream_header_str[0]; header->stream = (int)stream_header_str[1]; if (unmarshal_typed_value (mbuf, "seq-no", OML_INT32_VALUE, &seqno) == -1) return 0; if (unmarshal_typed_value (mbuf, "timestamp", OML_DOUBLE_VALUE, ×tamp) == -1) return 0; header->seqno = omlc_get_int32(*oml_value_get_value(&seqno)); header->timestamp = omlc_get_double(*oml_value_get_value(×tamp)); oml_value_reset(&seqno); oml_value_reset(×tamp); return 1; }