Esempio n. 1
0
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' : '-');
}
Esempio n. 2
0
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);
		}
	}