Exemple #1
0
// TODO consider the possible perf benefits of changing this routine
// to accept lots of changeset ids instead of just one, so it
// can handle them all at once.
void SG_treendx__update__multiple(
        SG_context* pCtx,
        SG_treendx* pTreeNdx,
        SG_stringarray* psa
        )
{
    SG_changeset* pcs = NULL;
	sqlite3_stmt* pStmt = NULL;
    SG_vhash* pvh_treepaths = NULL;
    SG_uint32 count_treepaths = 0;
    SG_uint32 count_changesets = 0;
    SG_uint32 ics = 0;

	SG_NULLARGCHECK_RETURN(psa);
	SG_NULLARGCHECK_RETURN(pTreeNdx);

    SG_ERR_CHECK(  SG_stringarray__count(pCtx, psa, &count_changesets)  );

    SG_ERR_CHECK(  sg_sqlite__exec__va(pCtx, pTreeNdx->psql, "BEGIN TRANSACTION; ")  );
    SG_ERR_CHECK(  sg_sqlite__prepare(pCtx, pTreeNdx->psql, &pStmt, "INSERT OR IGNORE INTO treendx (gid, strpath) VALUES (?, ?)")  );
    for (ics=0; ics<count_changesets; ics++)
    {
        const char* psz_hid = NULL;
        SG_uint32 i = 0;

        SG_ERR_CHECK(  SG_stringarray__get_nth(pCtx, psa, ics, &psz_hid)  );
        SG_ERR_CHECK(  SG_changeset__load_from_repo(pCtx, pTreeNdx->pRepo, psz_hid, &pcs)  );
        SG_ERR_CHECK(  SG_changeset__get_treepaths(pCtx, pcs, &pvh_treepaths)  );

        if (pvh_treepaths)
        {
            SG_ERR_CHECK(  SG_vhash__count(pCtx, pvh_treepaths, &count_treepaths)  );


            for (i=0; i<count_treepaths; i++)
            {
                const char* psz_gid = NULL;
                const SG_variant* pv = NULL;
                const char* psz_path = NULL;

                SG_ERR_CHECK(  SG_vhash__get_nth_pair(pCtx, pvh_treepaths, i, &psz_gid, &pv)  );
                SG_ERR_CHECK(  SG_variant__get__sz(pCtx, pv, &psz_path)  );

                SG_ERR_CHECK(  sg_sqlite__reset(pCtx, pStmt)  );
                SG_ERR_CHECK(  sg_sqlite__clear_bindings(pCtx, pStmt)  );
                SG_ERR_CHECK(  sg_sqlite__bind_text(pCtx, pStmt, 1, psz_gid)  );
                SG_ERR_CHECK(  sg_sqlite__bind_text(pCtx, pStmt, 2, psz_path)  );
                SG_ERR_CHECK(  sg_sqlite__step(pCtx, pStmt, SQLITE_DONE)  );
            }
        }
        SG_CHANGESET_NULLFREE(pCtx, pcs);
    }
    SG_ERR_CHECK(  sg_sqlite__nullfinalize(pCtx, &pStmt)  );
    SG_ERR_CHECK(  sg_sqlite__exec__va(pCtx, pTreeNdx->psql, "COMMIT TRANSACTION; ")  );

fail:
    SG_CHANGESET_NULLFREE(pCtx, pcs);
}
Exemple #2
0
void SG_treendx__get_path_in_dagnode(SG_context* pCtx, SG_treendx* pTreeNdx, const char* psz_search_item_gid, const char* psz_changeset, SG_treenode_entry ** ppTreeNodeEntry)
{
	SG_rbtree_iterator * rb_it = NULL;
	const char * pPath = NULL;
	SG_changeset * pChangeset = NULL;
	SG_stringarray * pPaths = NULL;
	const char* pszHidTreeNode = NULL;
	SG_treenode * pTreenodeRoot = NULL;
	char* pszReturnedGID = NULL;
	SG_uint32 i = 0;
	SG_uint32 count = 0;

	SG_ERR_CHECK_RETURN(  SG_gid__argcheck(pCtx, psz_search_item_gid)  );

	SG_ERR_CHECK(  SG_treendx__get_all_paths(pCtx, pTreeNdx, psz_search_item_gid, &pPaths)   );
	*ppTreeNodeEntry = NULL;
	SG_ERR_CHECK(  SG_changeset__load_from_repo(pCtx, pTreeNdx->pRepo, psz_changeset, &pChangeset)  );
	SG_ERR_CHECK(  SG_changeset__get_root(pCtx, pChangeset, &pszHidTreeNode) );
	SG_ERR_CHECK(  SG_treenode__load_from_repo(pCtx, pTreeNdx->pRepo, pszHidTreeNode, &pTreenodeRoot)  );
	SG_ERR_CHECK(  SG_stringarray__count(pCtx, pPaths, &count )  );
	for (i = 0; i < count; i++)
	{
		SG_ERR_CHECK(  SG_stringarray__get_nth(pCtx, pPaths, i, &pPath)  );
		SG_ERR_CHECK(  SG_treenode__find_treenodeentry_by_path(pCtx, pTreeNdx->pRepo, pTreenodeRoot, pPath, &pszReturnedGID, ppTreeNodeEntry)  );
		if (*ppTreeNodeEntry != NULL && strcmp(pszReturnedGID, psz_search_item_gid) == 0)
		{
			break;
		}
		else if (*ppTreeNodeEntry != NULL)
		{
			SG_TREENODE_ENTRY_NULLFREE(pCtx, *ppTreeNodeEntry);
			*ppTreeNodeEntry = NULL; //It's not the right GID, even though it's in the right spot.
		}
	}

	SG_NULLFREE(pCtx, pszReturnedGID);
	SG_CHANGESET_NULLFREE(pCtx, pChangeset);
	SG_TREENODE_NULLFREE(pCtx, pTreenodeRoot);
	SG_STRINGARRAY_NULLFREE(pCtx, pPaths);
	SG_RBTREE_ITERATOR_NULLFREE(pCtx, rb_it);
	return;
fail:
	SG_NULLFREE(pCtx, pszReturnedGID);
	SG_CHANGESET_NULLFREE(pCtx, pChangeset);
	SG_STRINGARRAY_NULLFREE(pCtx, pPaths);
	SG_RBTREE_ITERATOR_NULLFREE(pCtx, rb_it);
	return;

}
static void _do_since(
	SG_context* pCtx,
	SG_repo* pRepo,
    SG_vhash* pvh_since,
    SG_fragball_writer* pfb
    )
{
    SG_uint32 count_dagnums = 0;
    SG_uint32 i_dagnum = 0;
    SG_ihash* pih_new = NULL;
    SG_rbtree* prb = NULL;
    SG_vhash* pvh_blobs = NULL;
    SG_changeset* pcs = NULL;

    SG_NULLARGCHECK_RETURN(pRepo);
    SG_NULLARGCHECK_RETURN(pvh_since);
    SG_NULLARGCHECK_RETURN(pfb);

    // TODO do we need to deal with dags which are present here but not in pvh_since?

    SG_ERR_CHECK(  SG_vhash__count(pCtx, pvh_since, &count_dagnums)  );
    for (i_dagnum=0; i_dagnum<count_dagnums; i_dagnum++)
    {
        const char* psz_dagnum = NULL;
        SG_varray* pva_nodes = NULL;
        SG_uint64 dagnum = 0;

        SG_ERR_CHECK(  SG_vhash__get_nth_pair__varray(pCtx, pvh_since, i_dagnum, &psz_dagnum, &pva_nodes)  );

        SG_ERR_CHECK(  SG_dagnum__from_sz__hex(pCtx, psz_dagnum, &dagnum)  );

        SG_ERR_CHECK(  SG_repo__find_new_dagnodes_since(pCtx, pRepo, dagnum, pva_nodes, &pih_new)  );

        if (pih_new)
        {
            SG_uint32 count = 0;

            SG_ERR_CHECK(  SG_ihash__count(pCtx, pih_new, &count)  );

            if (count)
            {
                SG_uint32 i = 0;

                SG_ERR_CHECK(  SG_rbtree__alloc(pCtx, &prb)  );
                SG_ERR_CHECK(  SG_vhash__alloc(pCtx, &pvh_blobs)  );

                for (i=0; i<count; i++)
                {
                    const char* psz_node = NULL;

                    SG_ERR_CHECK(  SG_ihash__get_nth_pair(pCtx, pih_new, i, &psz_node, NULL)  );
                    SG_ERR_CHECK(  SG_rbtree__add(pCtx, prb, psz_node)  );
                    SG_ERR_CHECK(  SG_vhash__add__null(pCtx, pvh_blobs, psz_node)  );
                    SG_ERR_CHECK(  SG_changeset__load_from_repo(pCtx, pRepo, psz_node, &pcs)  );
                    SG_ERR_CHECK(  _add_necessary_blobs(pCtx, pcs, pvh_blobs)  );
                    SG_CHANGESET_NULLFREE(pCtx, pcs);
                }

                // put all these new nodes in the frag
                SG_ERR_CHECK(  SG_fragball__write__dagnodes(pCtx, pfb, dagnum, prb)  );

                // and the blobs
				SG_ERR_CHECK(  SG_sync__add_blobs_to_fragball(pCtx, pfb, pvh_blobs)  );

                SG_VHASH_NULLFREE(pCtx, pvh_blobs);
                SG_RBTREE_NULLFREE(pCtx, prb);
            }
            SG_IHASH_NULLFREE(pCtx, pih_new);
        }
    }

fail:
    SG_CHANGESET_NULLFREE(pCtx, pcs);
    SG_VHASH_NULLFREE(pCtx, pvh_blobs);
    SG_RBTREE_NULLFREE(pCtx, prb);
    SG_IHASH_NULLFREE(pCtx, pih_new);
}
Exemple #4
0
void SG_workingdir__create_and_get(
	SG_context* pCtx,
	const char* pszDescriptorName,
	const SG_pathname* pPathDirPutTopLevelDirInHere,
	SG_bool bCreateDrawer,
    const char* psz_spec_hid_cs_baseline
	)
{
	SG_repo* pRepo = NULL;
	SG_rbtree* pIdsetLeaves = NULL;
	SG_uint32 count_leaves = 0;
	SG_changeset* pcs = NULL;
	const char* pszidUserSuperRoot = NULL;
	SG_bool b = SG_FALSE;
    char* psz_hid_cs_baseline = NULL;
	SG_pendingtree * pPendingTree = NULL;
	SG_vhash * pvhTimestamps = NULL;

	/*
	 * Fetch the descriptor by its given name and use it to connect to
	 * the repo.
	 */
	SG_ERR_CHECK(  SG_repo__open_repo_instance(pCtx, pszDescriptorName, &pRepo)  );


	if (psz_spec_hid_cs_baseline)
	{
		SG_ERR_CHECK(  SG_strdup(pCtx, psz_spec_hid_cs_baseline, &psz_hid_cs_baseline)  );
	}
	else
    {
        const char* psz_hid = NULL;
        /*
         * If you do not specify a hid to be the baseline, then this routine
         * currently only works if there is exactly one leaf in the repo.
         */
        SG_ERR_CHECK(  SG_repo__fetch_dag_leaves(pCtx, pRepo,SG_DAGNUM__VERSION_CONTROL,&pIdsetLeaves)  );
        SG_ERR_CHECK(  SG_rbtree__count(pCtx, pIdsetLeaves, &count_leaves)  );

		if (count_leaves != 1)
			SG_ERR_THROW(  SG_ERR_MULTIPLE_HEADS_FROM_DAGNODE  );

        SG_ERR_CHECK(  SG_rbtree__iterator__first(pCtx, NULL, pIdsetLeaves, &b, &psz_hid, NULL)  );

        SG_ERR_CHECK(  SG_STRDUP(pCtx, psz_hid, &psz_hid_cs_baseline)  );
    }

	/*
	 * Load the desired changeset from the repo so we can look up the
	 * id of its user root directory
	 */
	SG_ERR_CHECK(  SG_changeset__load_from_repo(pCtx, pRepo, psz_hid_cs_baseline, &pcs)  );
	SG_ERR_CHECK(  SG_changeset__get_root(pCtx, pcs, &pszidUserSuperRoot)  );

	if (bCreateDrawer)
	{
		SG_ERR_CHECK(  SG_VHASH__ALLOC(pCtx, &pvhTimestamps)  );

		// Retrieve everything into the WD and capture the timestamps on the files that we create.
		SG_ERR_CHECK(  sg_workingdir__do_get_dir__top(pCtx, pRepo, pPathDirPutTopLevelDirInHere, pszidUserSuperRoot, pvhTimestamps)  );

		// this creates "repo.json" with the repo-descriptor.
		SG_ERR_CHECK(  SG_workingdir__set_mapping(pCtx, pPathDirPutTopLevelDirInHere, pszDescriptorName, NULL)  );

		// this creates an empty "wd.json" file (which doesn't know anything).
		SG_ERR_CHECK(  SG_PENDINGTREE__ALLOC(pCtx, pPathDirPutTopLevelDirInHere, SG_TRUE, &pPendingTree)  );

		// force set the initial parents to the current changeset.
		SG_ERR_CHECK(  SG_pendingtree__set_single_wd_parent(pCtx, pPendingTree, psz_hid_cs_baseline)  );

		// force initialize the timestamp cache to the list that we just built; this should
		// be the only timestamps in the cache since we just populated the WD.
		SG_ERR_CHECK(  SG_pendingtree__set_wd_timestamp_cache(pCtx, pPendingTree, &pvhTimestamps)  );	// this steals our vhash

		SG_ERR_CHECK(  SG_pendingtree__save(pCtx, pPendingTree)  );
	}
	else
	{
		// Retrieve everything into the WD but do not create .sgdrawer or record timestamps.
		// This is more like an EXPORT operation.
		SG_ERR_CHECK(  sg_workingdir__do_get_dir__top(pCtx, pRepo, pPathDirPutTopLevelDirInHere, pszidUserSuperRoot, NULL)  );
	}


fail:
	SG_VHASH_NULLFREE(pCtx, pvhTimestamps);
    SG_NULLFREE(pCtx, psz_hid_cs_baseline);
	SG_CHANGESET_NULLFREE(pCtx, pcs);
	SG_RBTREE_NULLFREE(pCtx, pIdsetLeaves);
	SG_REPO_NULLFREE(pCtx, pRepo);
	SG_PENDINGTREE_NULLFREE(pCtx, pPendingTree);
}
static void loop_innards_make_delta(
    SG_context* pCtx,
    SG_repo* pRepo,
    SG_varray* pva_path,
    SG_uint32 i_path_step,
    SG_vhash* pvh_add,
    SG_vhash* pvh_remove
    )
{
    SG_changeset* pcs = NULL;

    const char* psz_csid_cur = NULL;
    const char* psz_csid_parent = NULL;
    SG_vhash* pvh_changes = NULL;
    SG_vhash* pvh_one_parent_changes = NULL;
    SG_vhash* pvh_cs_add = NULL;
    SG_vhash* pvh_cs_remove = NULL;

    SG_ERR_CHECK(  SG_varray__get__sz(pCtx, pva_path, i_path_step, &psz_csid_cur)  );
    SG_ERR_CHECK(  SG_varray__get__sz(pCtx, pva_path, i_path_step + 1, &psz_csid_parent)  );
    SG_ERR_CHECK(  SG_changeset__load_from_repo(pCtx, pRepo, psz_csid_cur, &pcs)  );

    SG_ERR_CHECK(  SG_changeset__db__get_changes(pCtx, pcs, &pvh_changes)  );

    SG_ERR_CHECK(  SG_vhash__get__vhash(pCtx, pvh_changes, psz_csid_parent, &pvh_one_parent_changes)  );

    SG_ERR_CHECK(  SG_vhash__check__vhash(pCtx, pvh_one_parent_changes, "add", &pvh_cs_remove)  );
    SG_ERR_CHECK(  SG_vhash__check__vhash(pCtx, pvh_one_parent_changes, "remove", &pvh_cs_add)  );

    if (pvh_cs_add)
    {
        SG_uint32 count = 0;
        SG_uint32 i = 0;

        SG_ERR_CHECK(  SG_vhash__count(pCtx, pvh_cs_add, &count)  );
        for (i=0; i<count; i++)
        {
            const char* psz_hid_rec = NULL;
            SG_bool b = SG_FALSE;

            SG_ERR_CHECK(  SG_vhash__get_nth_pair(pCtx, pvh_cs_add, i, &psz_hid_rec, NULL)  );
            SG_ERR_CHECK(  SG_vhash__remove_if_present(pCtx, pvh_remove, psz_hid_rec, &b)  );
            if (!b)
            {
                SG_ERR_CHECK(  SG_vhash__update__null(pCtx, pvh_add, psz_hid_rec)  );
            }
        }
    }

    if (pvh_cs_remove)
    {
        SG_uint32 count = 0;
        SG_uint32 i = 0;

        SG_ERR_CHECK(  SG_vhash__count(pCtx, pvh_cs_remove, &count)  );
        for (i=0; i<count; i++)
        {
            const char* psz_hid_rec = NULL;
            SG_bool b = SG_FALSE;

            SG_ERR_CHECK(  SG_vhash__get_nth_pair(pCtx, pvh_cs_remove, i, &psz_hid_rec, NULL)  );
            SG_ERR_CHECK(  SG_vhash__remove_if_present(pCtx, pvh_add, psz_hid_rec, &b)  );
            if (!b)
            {
                SG_ERR_CHECK(  SG_vhash__update__null(pCtx, pvh_remove, psz_hid_rec)  );
            }
        }
    }


fail:
    SG_CHANGESET_NULLFREE(pCtx, pcs);
}
Exemple #6
0
void sg_pack__do_changeset(SG_context* pCtx, SG_repo* pRepo, const char* psz_hid_cs, SG_rbtree* prb_blobs)
{
	SG_changeset* pcs = NULL;
    SG_int32 gen = 0;
    SG_uint32 count_blobs = 0;
    SG_uint32 count_parents = 0;
    SG_varray* pva_parents = NULL;
    SG_uint32 i;
    SG_rbtree* prb_new = NULL;
	const char* psz_hid_root_treenode = NULL;
    const char* psz_key = NULL;
    SG_vhash* pvh_lbl = NULL;
    SG_vhash* pvh_blobs = NULL;

	SG_ERR_CHECK(  SG_changeset__load_from_repo(pCtx, pRepo, psz_hid_cs, &pcs)  );
	SG_ERR_CHECK(  SG_changeset__get_root(pCtx, pcs, &psz_hid_root_treenode)  );
    SG_ERR_CHECK(  SG_changeset__get_generation(pCtx, pcs, &gen)  );

    SG_ERR_CHECK(  SG_RBTREE__ALLOC__PARAMS(pCtx, &prb_new, count_blobs, NULL)  );

    SG_ERR_CHECK(  SG_changeset__get_list_of_bloblists(pCtx, pcs, &pvh_lbl)  );

    /* add all the tree user file blobs */
    SG_ERR_CHECK(  SG_changeset__get_bloblist_name(pCtx, SG_BLOB_REFTYPE__TREEUSERFILE, &psz_key)  );
    SG_ERR_CHECK(  SG_vhash__get__vhash(pCtx, pvh_lbl, psz_key, &pvh_blobs)  );
    SG_ERR_CHECK(  SG_vhash__count(pCtx, pvh_blobs, &count_blobs)  );
    /* now write all the blobs */
    for (i=0; i<count_blobs; i++)
    {
        const char* psz_hid = NULL;

        SG_ERR_CHECK(  SG_vhash__get_nth_pair(pCtx, pvh_blobs, i, &psz_hid, NULL)  );
        SG_ERR_CHECK(  SG_rbtree__add(pCtx, prb_new, psz_hid)  );
    }

    /* and the treenode blobs */
    SG_ERR_CHECK(  SG_changeset__get_bloblist_name(pCtx, SG_BLOB_REFTYPE__TREENODE, &psz_key)  );
    SG_ERR_CHECK(  SG_vhash__get__vhash(pCtx, pvh_lbl, psz_key, &pvh_blobs)  );
    SG_ERR_CHECK(  SG_vhash__count(pCtx, pvh_blobs, &count_blobs)  );
    /* now write all the blobs */
    for (i=0; i<count_blobs; i++)
    {
        const char* psz_hid = NULL;

        SG_ERR_CHECK(  SG_rbtree__add(pCtx, prb_new, psz_hid)  );
    }

    SG_ERR_CHECK(  sg_pack__do_get_dir__top(pCtx, pRepo, gen, psz_hid_root_treenode, prb_blobs, prb_new)  );

    SG_RBTREE_NULLFREE(pCtx, prb_new);

    SG_ERR_CHECK(  SG_changeset__get_parents(pCtx, pcs, &pva_parents)  );
    if (pva_parents)
    {
        SG_ERR_CHECK(  SG_varray__count(pCtx, pva_parents, &count_parents)  );
        for (i=0; i<count_parents; i++)
        {
            const char* psz_hid = NULL;

            SG_ERR_CHECK(  SG_varray__get__sz(pCtx, pva_parents, i, &psz_hid)  );

            SG_ERR_CHECK(  sg_pack__do_changeset(pCtx, pRepo, psz_hid, prb_blobs)  );
        }
    }

    SG_CHANGESET_NULLFREE(pCtx, pcs);

    return;

fail:
    SG_RBTREE_NULLFREE(pCtx, prb_new);
}