static void _cache__add__fringe(SG_context * pCtx, SG_dagfrag * pFrag, const char* psz_id) { _my_data * pDataAllocated = NULL; _my_data * pDataCached = NULL; _my_data * pOldData = NULL; SG_NULLARGCHECK_RETURN(pFrag); // this is probably not necessary for an internal routine SG_NONEMPTYCHECK_RETURN(psz_id); // this is probably not necessary for an internal routine SG_ERR_CHECK( SG_alloc(pCtx, 1, sizeof(_my_data), &pDataAllocated) ); pDataAllocated->m_genDagnode = 0; pDataAllocated->m_state = SG_DFS_END_FRINGE; pDataAllocated->m_pDagnode = NULL; SG_ERR_CHECK( SG_rbtree__update__with_assoc(pCtx,pFrag->m_pRB_Cache,psz_id,pDataAllocated,(void **)&pOldData) ); pDataCached = pDataAllocated; pDataAllocated = NULL; // cache now owns pData and pDagnode. SG_ASSERT_RELEASE_RETURN2( (!pOldData), (pCtx,"Possible memory leak adding [%s] to dagfrag fringe.",psz_id) ); return; fail: // TODO is the following test and assignment really necessary? or did it get carried // TODO over from another change? we weren't given a pDagnode in the first place. if (pDataCached) // caller still owns pDagnode on errors even if we got pData pDataCached->m_pDagnode = NULL; // into the cache. This may cause problems later if you keep going. SG_ERR_IGNORE( _my_data__free(pCtx, pDataAllocated) ); // free pData if we did not get it stuck into the cache. }
static void _add_one_parent(SG_context * pCtx, SG_dagfrag* pFrag, const char * szHid) { _my_data * pDataCached = NULL; SG_bool bPresent = SG_FALSE; SG_ERR_CHECK_RETURN( _cache__lookup(pCtx,pFrag,szHid,&pDataCached,&bPresent) ); if (!bPresent) { // dagnode is not present in the cache. therefore, it's in the fringe SG_ERR_CHECK_RETURN( _cache__add__fringe(pCtx, pFrag, szHid) ); } else { // dagnode already present in the cache. therefore, we have already visited it // before. we can change our minds about the state of this dagnode if something // has changed (such as the fragment bounds being widened). switch (pDataCached->m_state) { default: //case SG_DFS_UNKNOWN: SG_ASSERT_RELEASE_RETURN2( (0), (pCtx,"Invalid state [%d] in DAGFRAG Cache for [%s]", pDataCached->m_state,szHid) ); case SG_DFS_START_MEMBER: // a dagnode has a parent that we are considering a START node. // this can happen when we were started from a non-leaf node and // then a subsequent call to __load is given a true leaf node or // a node deeper in the tree that has our original start node as // a parent. // // clear the start bit. (we only want true fragment-terminal // nodes marked as start nodes.) pDataCached->m_state = SG_DFS_INTERIOR_MEMBER; break; case SG_DFS_INTERIOR_MEMBER: /* nothing to do here */ break; case SG_DFS_END_FRINGE: /* nothing to do here */ break; } } }
static void _cache__add__dagnode(SG_context * pCtx, SG_dagfrag * pFrag, SG_int32 gen, SG_dagnode * pDagnode, // if successful, we take ownership of dagnode SG_uint32 state, _my_data ** ppData) // we retain ownership of DATA (but you may modify non-pointer values within it) { const char * szHid; _my_data * pDataAllocated = NULL; _my_data * pDataCached = NULL; _my_data * pOldData = NULL; SG_NULLARGCHECK_RETURN(pFrag); // this is probably not necessary for an internal routine SG_NULLARGCHECK_RETURN(pDagnode); // this is probably not necessary for an internal routine SG_ERR_CHECK_RETURN( SG_dagnode__get_id_ref(pCtx,pDagnode,&szHid) ); SG_ASSERT_RELEASE_RETURN2( (SG_DFS_END_FRINGE != state), (pCtx,"Adding end-fringe dagnode [%s] to dagfrag.",szHid) ); SG_ERR_CHECK( SG_alloc(pCtx, 1, sizeof(_my_data), &pDataAllocated) ); pDataAllocated->m_genDagnode = gen; pDataAllocated->m_state = state; SG_ERR_CHECK( SG_rbtree__update__with_assoc(pCtx,pFrag->m_pRB_Cache,szHid,pDataAllocated,(void **)&pOldData) ); SG_ASSERT_RELEASE_FAIL2( (!pOldData), (pCtx,"Possible memory leak adding [%s] to dagfrag.",szHid) ); // if everything is successful, the cache now owns pData and pDagnode. pDataCached = pDataAllocated; pDataAllocated = NULL; pDataCached->m_pDagnode = pDagnode; if (ppData) *ppData = pDataCached; return; fail: if (pDataCached) // caller still owns pDagnode on errors even if we got pData pDataCached->m_pDagnode = NULL; // into the cache. This may cause problems later if you keep going. SG_ERR_IGNORE( _my_data__free(pCtx, pDataAllocated) ); // free pData if we did not get it stuck into the cache. }
void SG_dagfrag__query(SG_context * pCtx, SG_dagfrag * pFrag, const char * szHid, SG_dagfrag_state * pQS, SG_int32 * pGen, SG_bool * pbPresent, const SG_dagnode ** ppDagnode) { _my_data * pMyData = NULL; SG_bool bPresent = SG_FALSE; SG_NULLARGCHECK_RETURN(pFrag); SG_NONEMPTYCHECK_RETURN(szHid); SG_NULLARGCHECK_RETURN(pbPresent); SG_ERR_CHECK_RETURN( _cache__lookup(pCtx, pFrag,szHid,&pMyData,&bPresent) ); *pbPresent = bPresent; if (!bPresent) return; if (pQS) *pQS = pMyData->m_state; if (pGen) *pGen = pMyData->m_genDagnode; switch (pMyData->m_state) { default: //case SG_DFS_UNKNOWN: SG_ASSERT_RELEASE_RETURN2( (0), (pCtx,"Invalid state [%d] in DAGFRAG Cache for [%s]", pMyData->m_state,szHid) ); case SG_DFS_START_MEMBER: case SG_DFS_INTERIOR_MEMBER: if (ppDagnode) *ppDagnode = pMyData->m_pDagnode; break; case SG_DFS_END_FRINGE: if (ppDagnode) *ppDagnode = NULL; break; } }
void sg_vv2__status__assert_in_work_queue(SG_context * pCtx, sg_vv2status * pST, sg_vv2status_od * pOD, SG_uint32 depthInQueue) { char buf[SG_GID_BUFFER_LENGTH + 20]; SG_bool bFound; sg_vv2status_od * pOD_test; SG_ERR_CHECK_RETURN( SG_sprintf(pCtx, buf,SG_NrElements(buf), "%08d.%s", depthInQueue,pOD->bufGidObject) ); SG_ERR_CHECK_RETURN( SG_rbtree__find(pCtx, pST->prbWorkQueue,buf,&bFound,(void **)&pOD_test) ); SG_ASSERT_RELEASE_RETURN2( (bFound), (pCtx, "Object [GID %s][depth %d] should have been in work-queue.", pOD->bufGidObject, depthInQueue) ); }