static void rtps_gap_dump (GapSMsg *gp, unsigned flags) { SequenceNumber_t snr; unsigned i; log_printf (RTPS_ID, 0, "%u.%u", gp->gap_start.high, gp->gap_start.low); snr = gp->gap_list.base; SEQNR_DEC (snr); if (SEQNR_GT (snr, gp->gap_start)) log_printf (RTPS_ID, 0, "..%u.%u", snr.high, snr.low); if (gp->gap_list.numbits) log_printf (RTPS_ID, 0, "/%u:", gp->gap_list.numbits); for (i = 0; i < gp->gap_list.numbits; i++) if (SET_CONTAINS (gp->gap_list.bitmap, i)) log_printf (RTPS_ID, 0, " .%u", i + gp->gap_list.base.low); log_printf (RTPS_ID, 0, ") %c%c%c\r\n", (flags & SMF_DATA) ? 'D' : '-', (flags & SMF_KEY) ? 'K' : '-', (flags & SMF_INLINE_QOS) ? 'Q' : '-'); }
static void sfr_rel_data (RemWriter_t *rwp, Change_t *cp, SequenceNumber_t *cpsnr, const KeyHash_t *hp, const unsigned char *key, size_t keylen, #ifdef RTPS_FRAGMENTS DataFragSMsg *fragp, FragInfo_t **finfo, #endif int ignore) { ENDPOINT *ep = &rwp->rw_reader->endpoint; CCREF *rp, *gap_rp; HCI hci; Change_t *ncp; InstanceHandle h; SequenceNumber_t gap_first, gap_last, seqnr_first, seqnr_last; RejectCause_t cause; /*unsigned max;*/ int error, ooo; ctrc_printd (RTPS_ID, RTPS_SFR_REL_DATA, &rwp, sizeof (rwp)); prof_start (rtps_rr_data); #if defined (RTPS_FRAGMENTS) && defined (EXTRA_STATS) if (fragp) STATS_INC (rwp->rw_ndatafrags); else #endif STATS_INC (rwp->rw_ndata); RW_SIGNAL (rwp, "REL-Data"); #ifdef RTPS_MARKERS if (rwp->rw_reader->endpoint.mark_data) rtps_marker_notify (rwp->rw_reader->endpoint.endpoint, EM_DATA, "sfr_rel_data"); #endif #ifdef RTPS_INIT_ACKNACK /* If first Data: accept it and become alive. */ if (!rwp->rw_peer_alive) sfr_rel_alive (rwp); #endif rwp->rw_hb_no_data = 0; /* If seqnr already in cache: ignore sample. */ if (SEQNR_LT (*cpsnr, rwp->rw_seqnr_next)) { RW_SIGNAL (rwp, "REL-Data: ignore (SNR < hcache.SNR)"); return; } ooo = !SEQNR_EQ (rwp->rw_seqnr_next, *cpsnr); /* Create a new instance already, if possible. */ if (ignore #ifdef RTPS_FRAGMENTS || fragp #endif ) hci = NULL; else if (ep->multi_inst) { hci = hc_lookup_hash (ep->endpoint->cache, hp, key, keylen, &h, 1, ooo, &cause); if (!hci) { /* Don't see this as rejected -- since there is no ack given, sample will be retransmitted! dcps_sample_rejected ((Reader_t *) ep->endpoint, (DDS_SampleRejectedStatusKind) cause, h);*/ if (!ooo) rwp->rw_blocked = 1; return; } } else { if (!hc_accepts (ep->endpoint->cache, ooo)) { /* Don't see this as rejected -- since there is no ack given, sample will be retransmitted! dcps_sample_rejected ((Reader_t *) ep->endpoint, DDS_REJECTED_BY_SAMPLES_LIMIT, 0);*/ if (!ooo) rwp->rw_blocked = 1; return; } h = 0; hci = NULL; } /* Add to changes list of proxy writer context. */ if (LIST_NONEMPTY (rwp->rw_changes)) { /* Already some samples queued. */ RW_SIGNAL (rwp, "REL-Data: changes-queued"); if (hci) hc_inst_inform (ep->endpoint->cache, hci); if (rwp->rw_changes.head->relevant) seqnr_first = rwp->rw_changes.head->u.c.change->c_seqnr; else seqnr_first = rwp->rw_changes.head->u.range.first; if (rwp->rw_changes.tail->relevant) seqnr_last = rwp->rw_changes.tail->u.c.change->c_seqnr; else seqnr_last = rwp->rw_changes.tail->u.range.last; if (SEQNR_GT (*cpsnr, seqnr_last)) { /* Seqnr > last in list! */ /* Add new data sample node after tail of list. */ RW_SIGNAL (rwp, "REL-Data: add-missing>last"); gap_first = seqnr_last; SEQNR_INC (gap_first); if (!SEQNR_EQ (gap_first, *cpsnr)) { /* Gap between tail and data: add MISSING sample node between current tail of list and to be added data sample node. */ gap_last = *cpsnr; SEQNR_DEC (gap_last); if (!rwp->rw_changes.tail->relevant && rwp->rw_changes.tail->state == CS_MISSING) { /* Extend previous gap node. */ rwp->rw_changes.tail->u.range.last = gap_last; RW_SIGNAL (rwp, "REL-Data: extend-gap"); } else { /* Add new gap node. */ gap_rp = ccref_add_gap (&rwp->rw_changes, &gap_first, &gap_last, 1, CS_MISSING); if (!gap_rp) return; RW_SIGNAL (rwp, "REL-Data: add-gap"); } } /* Append data sample node. */ if (ignore) rp = ccref_add_gap (&rwp->rw_changes, cpsnr, cpsnr, 1, CS_RECEIVED); else rp = ccref_add_received (&rwp->rw_changes, cp, cpsnr, hci, h, 1); if (!rp) return; rwp->rw_reader->data_queued++; #ifdef RTPS_FRAGMENTS if (fragp) { sfr_fragment (rwp, rp, fragp, finfo, hp, cp, ooo, ignore); return; } #endif RANGE_CHECK (&rwp->rw_changes, "REL-Data: >last"); } else if (SEQNR_LT (*cpsnr, seqnr_first)) { /* Seqnr < first! */ /* Add new data sample node before head of list. */ RW_SIGNAL (rwp, "REL-Data: add-missing<first"); gap_last = seqnr_first; SEQNR_DEC (gap_last); if (!SEQNR_EQ (gap_last, *cpsnr)) { /* Gap between data and head: add MISSING sample node between to be added data sample and current head of list. */ gap_first = *cpsnr; SEQNR_INC (gap_first); if (!rwp->rw_changes.head->relevant && rwp->rw_changes.tail->state == CS_MISSING) { /* Extended following gap node. */ rwp->rw_changes.head->u.range.first = gap_first; RW_SIGNAL (rwp, "REL-Data: extend-gap"); } else { /* Add new gap node. */ gap_rp = ccref_add_gap (&rwp->rw_changes, &gap_first, &gap_last, 0, CS_MISSING); if (!gap_rp) return; RW_SIGNAL (rwp, "REL-Data: add-gap"); } } /* Prepend data sample node. */ if (ignore) rp = ccref_add_gap (&rwp->rw_changes, cpsnr, cpsnr, 0, CS_RECEIVED); else rp = ccref_add_received (&rwp->rw_changes, cp, cpsnr, hci, h, 0); if (!rp) return; rwp->rw_reader->data_queued++; #ifdef RTPS_FRAGMENTS if (fragp) { sfr_fragment (rwp, rp, fragp, finfo, hp, cp, ooo, ignore); return; } #endif RANGE_CHECK (&rwp->rw_changes, "REL-Data: <first"); } else { /* Seqnr somewhere in list - lets find it. */ LIST_FOREACH (rwp->rw_changes, rp) if (rp->relevant) { if (SEQNR_EQ (rp->u.c.change->c_seqnr, *cpsnr)) break; } else if (!SEQNR_LT (*cpsnr, rp->u.range.first) && !SEQNR_GT (*cpsnr, rp->u.range.last)) break; if (LIST_END (rwp->rw_changes, rp) || (rp->state != CS_MISSING #ifdef RTPS_FRAGMENTS && !rp->fragments #endif )) return; #ifdef RTPS_FRAGMENTS if (rp->fragments) { sfr_fragment (rwp, rp, fragp, finfo, hp, cp, ooo, ignore); return; } #endif RW_SIGNAL (rwp, "REL-Data: in-range"); RANGE_CHECK (&rwp->rw_changes, "REL-Data: in-range"); if (SEQNR_GT (*cpsnr, rp->u.range.first)) { /* Prepend gap node: range.first .. *cpsnr -1 */ gap_first = rp->u.range.first; gap_last = *cpsnr; SEQNR_DEC (gap_last); gap_rp = ccref_insert_gap (&rwp->rw_changes, rp->prev, &gap_first, &gap_last, CS_MISSING); if (!gap_rp) return; RW_SIGNAL (rwp, "REL-Data: prepend-gap"); } if (SEQNR_LT (*cpsnr, rp->u.range.last)) { /* Append gap node: *cpsnr + 1 .. range.last */ gap_first = *cpsnr; SEQNR_INC (gap_first); gap_last = rp->u.range.last; gap_rp = ccref_insert_gap (&rwp->rw_changes, rp, &gap_first, &gap_last, CS_MISSING); if (!gap_rp) return; RW_SIGNAL (rwp, "REL-Data: append-gap"); } /* Reuse gap node for data. */ #ifdef RTPS_FRAGMENTS rp->fragments = NULL; #endif if (ignore) { rp->relevant = 0; rp->u.range.first = *cpsnr; rp->u.range.last = *cpsnr; } else { if (cp->c_nrefs > 1) { ncp = hc_change_clone (cp); if (!ncp) { warn_printf ("sfr_rel_data (): out of memory for change clone!\r\n"); return; } } else { rcl_access (cp); cp->c_nrefs++; rcl_done (cp); ncp = cp; } ncp->c_handle = h; ncp->c_seqnr = *cpsnr; rp->relevant = 1; rp->u.c.hci = hci; rp->u.c.change = ncp; rwp->rw_reader->data_queued++; } rp->state = CS_RECEIVED; #ifdef RTPS_FRAGMENTS if (fragp) { sfr_fragment (rwp, rp, fragp, finfo, hp, cp, ooo, ignore); return; } #endif RW_SIGNAL (rwp, "REL-Data: missing::received"); RANGE_CHECK (&rwp->rw_changes, "REL-Data: missing::received"); } /* If the received data sample caused some samples to be valid, add these samples to the history cache and remove them from the changes list. */ rp = LIST_HEAD (rwp->rw_changes); if (rp && (rp->state == CS_RECEIVED || rp->state == CS_LOST) && #ifdef RTPS_FRAGMENTS !rp->fragments && #endif rwp->rw_heartbeats) { RW_SIGNAL (rwp, "REL-Data: process-samples"); RANGE_CHECK (&rwp->rw_changes, "REL-Data: process-samples"); sfr_process_samples (rwp); } }