Example #1
0
void SG_dagfrag__eat_other_frag(SG_context * pCtx,
								SG_dagfrag* pConsumerFrag,
								SG_dagfrag** ppFragToBeEaten)
{
	SG_rbtree_iterator* pit = NULL;
	SG_bool b = SG_FALSE;
	_my_data * pMyData = NULL;
	const char* psz_id = NULL;
	SG_dagfrag* pFragToBeEaten = NULL;

	SG_NULLARGCHECK_RETURN(pConsumerFrag);
	SG_NULLARGCHECK_RETURN(ppFragToBeEaten);
	SG_NULLARGCHECK_RETURN(*ppFragToBeEaten);

	pFragToBeEaten = *ppFragToBeEaten;

#if DEBUG && TRACE_DAGFRAG
	SG_ERR_CHECK(  SG_dagfrag_debug__dump__console(pCtx, pFragToBeEaten, "frag to be eaten", 0, SG_CS_STDOUT)  );
	SG_ERR_CHECK(  SG_rbtree_debug__dump_keys_to_console(pCtx, pFragToBeEaten->m_pRB_Cache)  );
	SG_ERR_CHECK(  SG_console__flush(pCtx, SG_CS_STDERR)  );
	SG_ERR_CHECK(  SG_dagfrag_debug__dump__console(pCtx, pConsumerFrag, "new frag before meal", 0, SG_CS_STDOUT)  );
	SG_ERR_CHECK(  SG_rbtree_debug__dump_keys_to_console(pCtx, pConsumerFrag->m_pRB_Cache)  );
	SG_ERR_CHECK(  SG_console__flush(pCtx, SG_CS_STDERR)  );
#endif

	if (
		(pConsumerFrag->m_iDagNum != pFragToBeEaten->m_iDagNum)
		|| (0 != strcmp(pConsumerFrag->m_sz_repo_id, pFragToBeEaten->m_sz_repo_id))
		|| (0 != strcmp(pConsumerFrag->m_sz_admin_id, pFragToBeEaten->m_sz_admin_id))
		)
	{
		SG_ERR_THROW_RETURN(  SG_ERR_REPO_MISMATCH  );
	}

	SG_ERR_CHECK(  SG_rbtree__iterator__first(pCtx, &pit,pFragToBeEaten->m_pRB_Cache,&b,&psz_id,(void **)&pMyData)  );
	while (b)
	{
		if (pMyData->m_pDagnode)
		{
			SG_ERR_CHECK(  SG_dagfrag__add_dagnode(pCtx, pConsumerFrag, &pMyData->m_pDagnode)  );
		}
		SG_ERR_CHECK(  SG_rbtree__iterator__next(pCtx, pit,&b,&psz_id,(void **)&pMyData)  );
	}
	SG_RBTREE_ITERATOR_NULLFREE(pCtx, pit);

	SG_DAGFRAG_NULLFREE(pCtx, pFragToBeEaten);
	*ppFragToBeEaten = NULL;

#if DEBUG && TRACE_DAGFRAG
	SG_ERR_CHECK(  SG_dagfrag_debug__dump__console(pCtx, pConsumerFrag, "new frag after meal", 0, SG_CS_STDOUT)  );
	SG_ERR_CHECK(  SG_rbtree_debug__dump_keys_to_console(pCtx, pConsumerFrag->m_pRB_Cache)  );
	SG_ERR_CHECK(  SG_console__flush(pCtx, SG_CS_STDERR)  );
#endif

	return;

fail:
	SG_RBTREE_ITERATOR_NULLFREE(pCtx, pit);
}
void SG_sync__build_best_guess_dagfrag(
	SG_context* pCtx,
	SG_repo* pRepo,
	SG_uint64 iDagNum,
	SG_rbtree* prbStartFromHids,
	SG_vhash* pvhConnectToHidsAndGens,
	SG_dagfrag** ppFrag)
{
	SG_uint32 i, countConnectTo;
	SG_rbtree_iterator* pit = NULL;
	SG_dagnode* pdn = NULL;
	SG_dagfrag* pFrag = NULL;
	SG_repo_fetch_dagnodes_handle* pdh = NULL;

	SG_int32 minGen = SG_INT32_MAX;
	SG_int32 maxGen = 0;
	SG_uint32 gensToFetch = 0;

	char* psz_repo_id = NULL;
	char* psz_admin_id = NULL;

	SG_bool bNextHid;
	const char* pszRefHid;
	SG_int32 gen;

#if TRACE_SYNC
	SG_int64 startTime;
	SG_int64 endTime;
#endif

	SG_NULLARGCHECK_RETURN(prbStartFromHids);

	/* Find the minimum generation in pertinent "connect to" nodes. */
	if (pvhConnectToHidsAndGens)
	{
		SG_ERR_CHECK(  SG_vhash__count(pCtx, pvhConnectToHidsAndGens, &countConnectTo)  );
		for (i = 0; i < countConnectTo; i++)
		{
			SG_int32 gen;
			SG_ERR_CHECK(  SG_vhash__get_nth_pair__int32(pCtx, pvhConnectToHidsAndGens, i, &pszRefHid, &gen)  );
			if (gen < minGen)
				minGen = gen;
		}
	}

	/* Happens when pulling into an empty repo, or when an entire dag is specifically requested. */
	if (minGen == SG_INT32_MAX)
		minGen = -1;

	SG_ERR_CHECK(  SG_repo__fetch_dagnodes__begin(pCtx, pRepo, iDagNum, &pdh)  );

	/* Find the maximum generation in pertinent "start from" nodes. */
	SG_ERR_CHECK(  SG_rbtree__iterator__first(pCtx, &pit, prbStartFromHids, &bNextHid, &pszRefHid, NULL)  );
	while (bNextHid)
	{
		SG_ERR_CHECK(  SG_repo__fetch_dagnodes__one(pCtx, pRepo, pdh, pszRefHid, &pdn)  );
		SG_ERR_CHECK(  SG_dagnode__get_generation(pCtx, pdn, &gen)  );
		if (gen > maxGen)
			maxGen = gen;
		SG_DAGNODE_NULLFREE(pCtx, pdn);

		SG_ERR_CHECK(  SG_rbtree__iterator__next(pCtx, pit, &bNextHid, &pszRefHid, NULL)  );
	}
	SG_RBTREE_ITERATOR_NULLFREE(pCtx, pit);

	if (maxGen <= minGen)
		gensToFetch = FALLBACK_GENS_PER_ROUNDTRIP;
	else
		gensToFetch = maxGen - minGen;

#if TRACE_SYNC
	{
		char buf_dagnum[SG_DAGNUM__BUF_MAX__HEX];
		SG_uint32 count;

		SG_ERR_CHECK(  SG_dagnum__to_sz__hex(pCtx, iDagNum, buf_dagnum, sizeof(buf_dagnum))  );

		SG_ERR_CHECK(  SG_console(pCtx, SG_CS_STDERR, "Building best guess dagfrag for dag %s...\n", buf_dagnum)  );
		SG_ERR_CHECK(  SG_console(pCtx, SG_CS_STDERR, "Starting from nodes:\n")  );
		SG_ERR_CHECK(  SG_rbtree_debug__dump_keys_to_console(pCtx, prbStartFromHids)  );
		SG_ERR_CHECK(  SG_vhash_debug__dump_to_console__named(pCtx, pvhConnectToHidsAndGens, "Connecting to nodes")  );

		SG_ERR_CHECK(  SG_rbtree__count(pCtx, prbStartFromHids, &count)  );

		SG_ERR_CHECK(  SG_console(pCtx, SG_CS_STDERR, "result has %d generations from %u starting nodes.\n",
			gensToFetch, count)  );
		SG_ERR_CHECK(  SG_console__flush(pCtx, SG_CS_STDERR)  );

		SG_ERR_CHECK(  SG_time__get_milliseconds_since_1970_utc(pCtx, &startTime)  );
	}
#endif

	/* Return a frag with the corresponding generations filled in. */
	SG_ERR_CHECK(  SG_repo__get_repo_id(pCtx, pRepo, &psz_repo_id)  );
	SG_ERR_CHECK(  SG_repo__get_admin_id(pCtx, pRepo, &psz_admin_id)  );
	SG_ERR_CHECK(  SG_dagfrag__alloc(pCtx, &pFrag, psz_repo_id, psz_admin_id, iDagNum)  );

	SG_ERR_CHECK(  SG_dagfrag__load_from_repo__multi(pCtx, pFrag, pRepo, prbStartFromHids, gensToFetch)  );
#if TRACE_SYNC
	SG_ERR_CHECK(  SG_time__get_milliseconds_since_1970_utc(pCtx, &endTime)  );
	{
		SG_uint32 dagnodeCount;
		double seconds = ((double)endTime-(double)startTime)/1000;

		SG_ERR_CHECK(  SG_dagfrag__dagnode_count(pCtx, pFrag, &dagnodeCount)  );
		SG_ERR_CHECK(  SG_console(pCtx, SG_CS_STDERR, " - %u nodes in frag, built in %1.3f seconds\n", dagnodeCount, seconds)  );
		SG_ERR_CHECK(  SG_dagfrag_debug__dump__console(pCtx, pFrag, "best-guess dagfrag", 0, SG_CS_STDERR)  );
	}
#endif

	*ppFrag = pFrag;
	pFrag = NULL;

	/* Common cleanup */
fail:
	SG_NULLFREE(pCtx, psz_repo_id);
	SG_NULLFREE(pCtx, psz_admin_id);
	SG_RBTREE_ITERATOR_NULLFREE(pCtx, pit);
	SG_DAGNODE_NULLFREE(pCtx, pdn);
	SG_DAGFRAG_NULLFREE(pCtx, pFrag);
	SG_ERR_IGNORE(  SG_repo__fetch_dagnodes__end(pCtx, pRepo, &pdh)  );
}