예제 #1
0
void SG_vfile__add__vhash(
	SG_context* pCtx,
	const SG_pathname* pPath, /**< The path of the file containing the JSON text */
	const char* putf8Key,
	const SG_vhash* pHashValue
	)
{
	SG_vfile* pvf = NULL;
	SG_vhash* pvh = NULL;
	SG_vhash* pvhCopy = NULL;

	SG_ERR_CHECK(  SG_vfile__begin(pCtx, pPath, SG_FILE_RDWR | SG_FILE_OPEN_OR_CREATE, &pvh, &pvf)  );
	if (!pvh)
	{
		SG_ERR_CHECK(  SG_VHASH__ALLOC(pCtx, &pvh)  );
	}
	SG_ERR_CHECK(  SG_VHASH__ALLOC__COPY(pCtx, &pvhCopy, pHashValue)  );
	SG_ERR_CHECK(  SG_vhash__add__vhash(pCtx, pvh, putf8Key, &pvhCopy)  );
	SG_ERR_CHECK(  SG_vfile__end(pCtx, &pvf, pvh)  );

	SG_VHASH_NULLFREE(pCtx, pvh);

	return;
fail:
	SG_ERR_IGNORE(  sg_vfile__dispose(pCtx, pvf)  );
	SG_VHASH_NULLFREE(pCtx, pvhCopy);
	SG_VHASH_NULLFREE(pCtx, pvh);
}
예제 #2
0
void SG_localsettings__foreach(
	SG_context* pCtx,
	const char* szPattern,
	SG_bool bIncludeDefaults,
	SG_localsettings_foreach_callback* pCallback,
	void* pCallerData
	)
{
	SG_vhash* pValues = NULL;
	SG_vhash* pDefaults = NULL;
	provide_matching_values__data ProvideMatchingValuesData = {NULL, NULL, NULL, NULL};

	SG_UNUSED(pCallback);
	SG_UNUSED(pCallerData);

	// get the settings
	SG_ERR_CHECK(  SG_localsettings__list__vhash(pCtx, &pValues)  );

	// if defaults were requested, get those too
	if (bIncludeDefaults)
	{
		SG_ERR_CHECK(  SG_localsettings__factory__list__vhash(pCtx, &pDefaults)  );
		SG_ERR_CHECK(  SG_vhash__add__vhash(pCtx, pValues, SG_LOCALSETTING__SCOPE__DEFAULT + 1, &pDefaults)  ); // +1 to remove the slash at the beginning
	}

	// sort the settings
	SG_ERR_CHECK(  SG_vhash__sort(pCtx, pValues, SG_TRUE, SG_vhash_sort_callback__increasing)  );

	// setup our callback data
	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &(ProvideMatchingValuesData.pPrefix))  );
	ProvideMatchingValuesData.szPattern = szPattern;
	ProvideMatchingValuesData.pCallback = pCallback;
	ProvideMatchingValuesData.pCallerData = pCallerData;

	// iterate through the vhash
	SG_ERR_CHECK(  SG_vhash__foreach(pCtx, pValues, provide_matching_values, &ProvideMatchingValuesData)  );

fail:
	SG_VHASH_NULLFREE(pCtx, pValues);
	SG_VHASH_NULLFREE(pCtx, pDefaults);
	SG_STRING_NULLFREE(pCtx, ProvideMatchingValuesData.pPrefix);
}
예제 #3
0
파일: sg_dagfrag.c 프로젝트: avar/veracity
static void _serialize_data_cb(SG_context * pCtx,
							   const char * szHid,
							   void * pAssocData,
							   void * pVoidSerializeData)
{
	struct _serialize_data * pSerializeData = (struct _serialize_data *)pVoidSerializeData;
	_my_data * pMyData = (_my_data *)pAssocData;

	SG_vhash * pvhMyData = NULL;
	SG_vhash * pvhDagnode = NULL;

	SG_ERR_CHECK(  SG_VHASH__ALLOC__SHARED(pCtx,&pvhMyData,5,pSerializeData->pvhFrag)  );

	SG_ERR_CHECK(  SG_vhash__add__int64(pCtx,pvhMyData,KEY_DFS_STATE,(SG_int64)pMyData->m_state)  );

    if (SG_DFS_END_FRINGE == pMyData->m_state)
    {
        SG_ERR_CHECK(  SG_vhash__add__string__sz(pCtx,pvhMyData,KEY_DAGNODE_ID,szHid)  );
    }
    else
    {
        SG_ERR_CHECK(  SG_dagnode__to_vhash__shared(pCtx,pMyData->m_pDagnode,pvhMyData,&pvhDagnode)  );
        SG_ERR_CHECK(  SG_vhash__add__vhash(pCtx,pvhMyData,KEY_ACTUAL_DAGNODE,&pvhDagnode)  );
    }

#if DEBUG && TRACE_DAGFRAG && 0
	SG_ERR_CHECK(  SG_vhash_debug__dump_to_console(pCtx, pvhMyData)  );
#endif
	SG_ERR_CHECK(  SG_varray__append__vhash(pCtx,pSerializeData->pvaMyData,&pvhMyData)  );

	return;

fail:
	SG_VHASH_NULLFREE(pCtx, pvhMyData);
	SG_VHASH_NULLFREE(pCtx, pvhDagnode);
}
static void _tree__add_next_node_to_results(SG_context * pCtx, _tree_t * pTree, SG_varray * pResults, SG_uint32 * pCountResults, SG_bool * pbLastResultWasIndented)
{
	SG_vhash * pResult = NULL;
	SG_varray * pChildren = NULL;
	SG_uint32 i;
	SG_varray * pTmp = NULL;

	// Add pTree->pNextResult to results list.
	SG_ERR_CHECK(  SG_varray__appendnew__vhash(pCtx, pResults, &pResult)  );
	SG_ERR_CHECK(  SG_vhash__add__int64(pCtx, pResult, "revno", pTree->pNextResult->revno)  );
	SG_ERR_CHECK(  SG_vhash__add__string__sz(pCtx, pResult, "changeset_id", pTree->pNextResult->pszHidRef)  );
	SG_ERR_CHECK(  SG_vhash__add__vhash(pCtx, pResult, "parents", &pTree->pNextResult->pVcParents)  );
	SG_ERR_CHECK(  SG_vhash__addnew__varray(pCtx, pResult, "displayChildren", &pChildren)  );
	for(i=0; i<pTree->pNextResult->displayChildren.count; ++i)
		SG_ERR_CHECK(  SG_varray__append__int64(pCtx, pChildren, pTree->pNextResult->displayChildren.p[i]->revno)  );
	if(pTree->pNextResult->displayChildren.count>1 && pTree->indentLevel>0)
	{
		SG_varray * pContinuationToken = NULL;
		SG_ERR_CHECK(  SG_vhash__addnew__varray(pCtx, pResult, "continuationToken", &pContinuationToken)  );
		SG_ERR_CHECK(  _tree__generate_continuation_token(pCtx, pTree, pContinuationToken)  );
	}
	SG_ERR_CHECK(  SG_vhash__add__int64(pCtx, pResult, "indent", pTree->indentLevel)  );
	*pbLastResultWasIndented = (pTree->indentLevel > 0);
	if(pTree->pNextResult->pDisplayParent!=NULL)
	{
		SG_ERR_CHECK(  SG_vhash__add__int64(pCtx, pResult, "displayParent", pTree->pNextResult->pDisplayParent->revno)  );
		SG_ERR_CHECK(  SG_vhash__add__int64(pCtx, pResult, "indexInParent", pTree->pNextResult->pDisplayParent->displayChildren.count)  );
		SG_ASSERT(*pbLastResultWasIndented);
	}
	else
	{
		SG_ASSERT(!*pbLastResultWasIndented);
	}
	++(*pCountResults);

	// Advance pTree->pNextResult pointer to next result.
	while(pTree->pNextResult->displayChildren.count==0 && pTree->pNextResult!=pTree->pRoot)
	{
		// We have already added this node and all children to the results.
		// Free the memory that will not be reused, and then put the node
		// on the "free list".
		_node__free_nonreusable_memory(pCtx, pTree->pNextResult);
		pTree->pNextResult->displayChildren.p[0] = pTree->pFreeList;
		pTree->pNextResult->displayChildren.count = 1;
		pTree->pFreeList = pTree->pNextResult;

		// Move back up up in the tree.
		pTree->pNextResult = pTree->pNextResult->pDisplayParent;

		if(pTree->pNextResult!=NULL)
		{
			// The node we just freed... Remove it from its display parent too.
			--pTree->pNextResult->displayChildren.count;

			// All children but the leftmost one are indented by 1 from the parent.
			if(pTree->pNextResult->displayChildren.count>0)
				--pTree->indentLevel;
		}
	}
	if(pTree->pNextResult->displayChildren.count>0)
	{
		SG_uint32 i = pTree->pNextResult->displayChildren.count-1;
		pTree->pNextResult = pTree->pNextResult->displayChildren.p[i];
		if(i>=1)
			++pTree->indentLevel;
	}
	else
	{
		pTree->pNextResult = NULL;
	}

	// If we advanced past root...
	if(pTree->pNextResult==NULL || pTree->pNextResult==pTree->pRoot->displayChildren.p[0])
	{
		// Out with the old root, in with the new...

		_node__free_nonreusable_memory(pCtx, pTree->pRoot);
		pTree->pRoot->displayChildren.p[0] = pTree->pFreeList;
		pTree->pRoot->displayChildren.count = 1;
		pTree->pFreeList = pTree->pRoot;

		pTree->pRoot = pTree->pNextResult;
		if(pTree->pRoot!=NULL)
			pTree->pRoot->pDisplayParent = NULL;
	}

	return;
fail:
	SG_VARRAY_NULLFREE(pCtx, pTmp);
}
예제 #5
0
/**
 * Add to the fragball request vhash (see SG_server_prototypes.h for format).
 */
void SG_pull__add(
	SG_context* pCtx,
	SG_pull* pPull,
	SG_uint32 iDagnum,
	SG_rbtree* prbDagnodes,
	SG_rbtree* prbTags,
	SG_rbtree* prbDagnodePrefixes)
{
	_sg_pull* pMyPull = NULL;
	char bufDagnum[SG_DAGNUM__BUF_MAX__DEC];
	SG_bool found = SG_FALSE;
	SG_vhash* pvhDags = NULL; // Needs to be freed
	SG_vhash* pvhDagsRef = NULL; // Does not need to be freed, owned by parent vhash
	SG_vhash* pvhDagnum = NULL; // Needs to be freed
	SG_vhash* pvhDagnumRef = NULL; // Does not need to be freed, owned by parent vhash
	SG_rbtree_iterator* pit = NULL;

	SG_NULLARGCHECK_RETURN(pPull);
	SG_ARGCHECK_RETURN(iDagnum, iDagnum);
	pMyPull = (_sg_pull*)pPull;

	if (!pMyPull->pvhFragballRequest)
		SG_ERR_CHECK(  SG_VHASH__ALLOC(pCtx, &pMyPull->pvhFragballRequest)  );

	SG_ERR_CHECK(  SG_dagnum__to_sz__decimal(pCtx, iDagnum, bufDagnum, sizeof(bufDagnum))  );

	/* Get dagnum vhash, adding it if necessary. */
	SG_ERR_CHECK(  SG_vhash__has(pCtx, pMyPull->pvhFragballRequest, SG_SYNC_STATUS_KEY__DAGS, &found)  );
	if (found)
		SG_ERR_CHECK(  SG_vhash__get__vhash(pCtx, pMyPull->pvhFragballRequest, SG_SYNC_STATUS_KEY__DAGS, &pvhDagsRef)  );
	else
	{
		SG_ERR_CHECK(  SG_VHASH__ALLOC(pCtx, &pvhDags)  );
		pvhDagsRef = pvhDags;
		SG_ERR_CHECK(  SG_vhash__add__vhash(pCtx, pMyPull->pvhFragballRequest, SG_SYNC_STATUS_KEY__DAGS, &pvhDags)  );
	}
	
	SG_ERR_CHECK(  SG_vhash__has(pCtx, pvhDagsRef, bufDagnum, &found)  );
	if (found)
		SG_ERR_CHECK(  SG_vhash__get__vhash(pCtx, pvhDagsRef, bufDagnum, &pvhDagnumRef)  );
	
	if (!pvhDagnumRef)
	{
		SG_ERR_CHECK(  SG_VHASH__ALLOC(pCtx, &pvhDagnum)  );
		pvhDagnumRef = pvhDagnum;
		SG_ERR_CHECK(  SG_vhash__add__vhash(pCtx, pvhDagsRef, bufDagnum, &pvhDagnum)  );
	}

	/* If dagnodes were provided, add them to the dagnum vhash */
	if (prbDagnodes)
	{
		const char* pszHid;
		SG_ERR_CHECK(  SG_rbtree__iterator__first(pCtx, &pit, prbDagnodes, &found, &pszHid, NULL)  );
		while (found)
		{
			SG_ERR_CHECK(  SG_vhash__update__null(pCtx, pvhDagnumRef, pszHid)  );
			SG_ERR_CHECK(  SG_rbtree__iterator__next(pCtx, pit, &found, &pszHid, NULL)  );
		}
		SG_RBTREE_ITERATOR_NULLFREE(pCtx, pit);
	}	
	/* If tags were provided, add them to the dagnum vhash */
	if (prbTags)
	{
		const char* pszTag;
		SG_ERR_CHECK(  SG_rbtree__iterator__first(pCtx, &pit, prbTags, &found, &pszTag, NULL)  );
		while (found)
		{
			SG_ERR_CHECK(  SG_vhash__update__string__sz(pCtx, pvhDagnumRef, pszTag, SG_SYNC_REQUEST_VALUE_TAG)  );
			SG_ERR_CHECK(  SG_rbtree__iterator__next(pCtx, pit, &found, &pszTag, NULL)  );
		}
		SG_RBTREE_ITERATOR_NULLFREE(pCtx, pit);
	}	
	/* If dagnode hid prefixes were provided, add them to the dagnum vhash */
	if (prbDagnodePrefixes)
	{
		const char* pszHidPrefix;
		SG_ERR_CHECK(  SG_rbtree__iterator__first(pCtx, &pit, prbDagnodePrefixes, &found, &pszHidPrefix, NULL)  );
		while (found)
		{
			SG_ERR_CHECK(  SG_vhash__update__string__sz(pCtx, pvhDagnumRef, pszHidPrefix, SG_SYNC_REQUEST_VALUE_HID_PREFIX)  );
			SG_ERR_CHECK(  SG_rbtree__iterator__next(pCtx, pit, &found, &pszHidPrefix, NULL)  );
		}
		SG_RBTREE_ITERATOR_NULLFREE(pCtx, pit);
	}	

	return;

fail:
	SG_VHASH_NULLFREE(pCtx, pvhDagnum);
	SG_VHASH_NULLFREE(pCtx, pvhDags);
	SG_RBTREE_ITERATOR_NULLFREE(pCtx, pit);
}
void SG_sync_remote__get_repo_info(
	SG_context* pCtx,
	SG_repo* pRepo,
	SG_bool bIncludeBranches,
    SG_bool b_include_areas,
    SG_vhash** ppvh)
{
    SG_vhash* pvh = NULL;
	char* pszRepoId = NULL;
	char* pszAdminId = NULL;
	char* pszHashMethod = NULL;
	SG_uint32  count_dagnums = 0;
	SG_uint64* paDagNums     = NULL;
    SG_uint32 i = 0;
    SG_vhash* pvh_dags = NULL;
    SG_vhash* pvh_areas = NULL;
	SG_vhash* pvhBranchPile = NULL;

	SG_bool bHasBranchDag = SG_FALSE;

	SG_NULLARGCHECK_RETURN(pRepo);

    SG_ERR_CHECK(  SG_VHASH__ALLOC(pCtx, &pvh)  );

	/* Protocol version */
	SG_ERR_CHECK(  SG_vhash__add__int64(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__PROTOCOL_VERSION, 1)  );


	/* Basic repository info */
	SG_ERR_CHECK(  SG_repo__get_repo_id(pCtx, pRepo, &pszRepoId)  );
    SG_ERR_CHECK(  SG_repo__get_admin_id(pCtx, pRepo, &pszAdminId)  );
    SG_ERR_CHECK(  SG_repo__get_hash_method(pCtx, pRepo, &pszHashMethod)  );
    SG_ERR_CHECK(  SG_vhash__add__string__sz(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__REPO_ID, pszRepoId)  );
    SG_ERR_CHECK(  SG_vhash__add__string__sz(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__ADMIN_ID, pszAdminId)  );
    SG_ERR_CHECK(  SG_vhash__add__string__sz(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__HASH_METHOD, pszHashMethod)  );

	/* All DAGs in the repository */
	SG_ERR_CHECK(  SG_repo__list_dags(pCtx, pRepo, &count_dagnums, &paDagNums)  );
    SG_ERR_CHECK(  SG_vhash__addnew__vhash(pCtx, pvh, "dags", &pvh_dags)  );
    for (i=0; i<count_dagnums; i++)
    {
        char buf_dagnum[SG_DAGNUM__BUF_MAX__HEX];

        SG_ERR_CHECK_RETURN(  SG_dagnum__to_sz__hex(pCtx, paDagNums[i], buf_dagnum, sizeof(buf_dagnum))  );
        SG_ERR_CHECK(  SG_vhash__add__null(pCtx, pvh_dags, buf_dagnum)  );

		/* Asking for a DAG for the first time in a repo will create that DAG.
		 * When pushing into an empty repo, we don't want this initial query to create 
		 * empty new DAGs, so we make sure they exist before we query them. */
		if (paDagNums[i] == SG_DAGNUM__VC_BRANCHES)
			bHasBranchDag = SG_TRUE;
    }
    
    // TODO the following code is a problem, because it requires that this repo
    // instance have indexes, and we would prefer to preserve the ability of
    // an index-free instance to support push, pull, and clone.

	/* All areas in the repository */
    if (b_include_areas)
    {
        SG_ERR_CHECK(  SG_area__list(pCtx, pRepo, &pvh_areas)  );
        if (pvh_areas)
        {
            SG_ERR_CHECK(  SG_vhash__add__vhash(pCtx, pvh, "areas", &pvh_areas)  );
        }
    }

	/* Branches */
	if (bIncludeBranches && bHasBranchDag)
	{
		SG_ERR_CHECK(  SG_vc_branches__cleanup(pCtx, pRepo, &pvhBranchPile)  );
		if (pvhBranchPile)
		{
			SG_bool bHasBranches;

			SG_ERR_CHECK(  SG_vhash__has(pCtx, pvhBranchPile, "branches", &bHasBranches)  );
			if (bHasBranches)
				SG_ERR_CHECK(  SG_vhash__add__vhash(pCtx, pvh, "branches", &pvhBranchPile)  );
		}
	}

    *ppvh = pvh;
    pvh = NULL;

	/* fall through */
fail:
	SG_NULLFREE(pCtx, paDagNums);
    SG_VHASH_NULLFREE(pCtx, pvh);
	SG_NULLFREE(pCtx, pszRepoId);
	SG_NULLFREE(pCtx, pszAdminId);
	SG_NULLFREE(pCtx, pszHashMethod);
	SG_VHASH_NULLFREE(pCtx, pvh_areas);
	SG_VHASH_NULLFREE(pCtx, pvhBranchPile);
}
예제 #7
0
static void _sg_workingdir__get_entry2(SG_context * pCtx,
									   SG_repo * pRepo,
									   const SG_pathname * pPathSub,
									   const char * pszGid,
									   SG_treenode_entry_type type,
									   const char * pszidHidContent,
									   const char * pszidHidXattrs,
									   SG_int64 iAttributeBits,
									   SG_vhash * pvhTimestamps)
{
	SG_file* pFile = NULL;
	SG_string* pstrLink = NULL;
	SG_byte* pBytes = NULL;
	SG_vhash * pvhGid = NULL;

    if (SG_TREENODEENTRY_TYPE_DIRECTORY == type)
    {
        /* create the directory and then recurse into it */
        SG_ERR_CHECK(  SG_fsobj__mkdir__pathname(pCtx, pPathSub)  );
        SG_ERR_CHECK(  _sg_workingdir__get_dir(pCtx, pRepo, pPathSub, pszidHidContent, pvhTimestamps)  );
    }
    else if (SG_TREENODEENTRY_TYPE_REGULAR_FILE == type)
    {
        SG_ERR_CHECK(  SG_file__open__pathname(pCtx, pPathSub, SG_FILE_RDWR | SG_FILE_CREATE_NEW, SG_FSOBJ_PERMS__MASK, &pFile)  );
        SG_ERR_CHECK(  SG_repo__fetch_blob_into_file(pCtx, pRepo, pszidHidContent, pFile, NULL)  );
        SG_ERR_CHECK(  SG_file__close(pCtx, &pFile)  );
    }
    else if (SG_TREENODEENTRY_TYPE_SYMLINK == type)
    {
        SG_uint64 iLenBytes = 0;

        SG_ERR_CHECK(  SG_repo__fetch_blob_into_memory(pCtx, pRepo, pszidHidContent, &pBytes, &iLenBytes)  );
        SG_ERR_CHECK(  SG_STRING__ALLOC__BUF_LEN(pCtx, &pstrLink, pBytes, (SG_uint32) iLenBytes)  );
        SG_ERR_CHECK(  SG_fsobj__symlink(pCtx, pstrLink, pPathSub)  );
        SG_NULLFREE(pCtx, pBytes);
        SG_STRING_NULLFREE(pCtx, pstrLink);
    }
    else
    {
        SG_ERR_THROW(SG_ERR_NOTIMPLEMENTED);
    }

    if (pszidHidXattrs)
    {
#ifdef SG_BUILD_FLAG_FEATURE_XATTR
        SG_ERR_CHECK(  _sg_workingdir__set_xattrs(pCtx, pRepo, pPathSub, pszidHidXattrs)  );
#else
		// TODO do we need to stuff something into the pendingtree to remind us
		// TODO that the entry originally had an XAttr and we just didn't restore
		// TODO it when we populated the WD on this Windows system?
#endif
    }

    SG_ERR_CHECK(  SG_attributes__bits__apply(pCtx, pPathSub, iAttributeBits)  );

	if (pvhTimestamps && (SG_TREENODEENTRY_TYPE_REGULAR_FILE == type))
	{
		SG_fsobj_stat stat;
		SG_int64 iTimeNow;

		SG_ERR_CHECK(  SG_fsobj__stat__pathname(pCtx, pPathSub, &stat)  );
		SG_ERR_CHECK(  SG_time__get_milliseconds_since_1970_utc(pCtx, &iTimeNow)  );

		SG_ERR_CHECK(  SG_VHASH__ALLOC(pCtx, &pvhGid)  );
		SG_ERR_CHECK(  SG_vhash__add__int64(pCtx, pvhGid, "mtime_ms", stat.mtime_ms)  );
		SG_ERR_CHECK(  SG_vhash__add__int64(pCtx, pvhGid, "clock_ms", iTimeNow)  );

		SG_ERR_CHECK(  SG_vhash__add__vhash(pCtx, pvhTimestamps, pszGid, &pvhGid)  );	// this steals our vhash
	}

fail:
	SG_VHASH_NULLFREE(pCtx, pvhGid);
}