Esempio n. 1
0
        public void Process(ExecutionContext context)
        {
            CmdStore  cs        = context.Store;
            StoreInfo storeInfo = cs.Store;
            string    upLoc     = storeInfo.UpstreamLocation;

            if (String.IsNullOrEmpty(upLoc))
            {
                throw new ApplicationException("There is no upstream location");
            }

            // Collate the number of commands we have in local branches
            IdCount[] have = cs.Branches.Values
                             .Where(x => !x.IsRemote)
                             .Select(x => new IdCount(x.Id, x.Info.CommandCount))
                             .ToArray();

            IRemoteStore rs = context.GetRemoteStore(upLoc);

            // We don't care about new branches in the origin, but we do care
            // about local branches that have been created since the last push
            IdRange[] toPush = rs.GetMissingRanges(cs.Id, have, false).ToArray();

            // How many commands do we need to push
            uint total = (uint)toPush.Sum(x => x.Size);

            Log.Info($"To push {total} command`s in {toPush.Length} branch`es".TrimExtras());

            foreach (IdRange idr in toPush)
            {
                Branch b = cs.FindBranch(idr.Id);
                if (b == null)
                {
                    throw new ApplicationException("Cannot locate branch " + idr.Id);
                }

                Log.Info($"Push [{idr.Min},{idr.Max}] from {b}");

                CmdData[] data = b.TakeRange(idr.Min, idr.Max).ToArray();
                rs.Push(cs.Name, b.Info, data);

                // Remember how much we were ahead at the time of the push
                b.Info.LastPush = idr.Max + 1;
                b.Store.SaveBranchInfo(b);
            }

            Log.Info("Push completed");
        }
Esempio n. 2
0
        public void Process(ExecutionContext context)
        {
            CmdStore  cs        = context.Store;
            StoreInfo storeInfo = cs.Store;
            string    upLoc     = storeInfo.UpstreamLocation;

            if (String.IsNullOrEmpty(upLoc))
            {
                throw new ApplicationException("There is no upstream location");
            }

            // Collate how much we already have in all remote branches.
            // We may have previously pushed some local branches to the remote
            // store, but nothing is supposed to mutate those remote copies.

            IdCount[] have = cs.Branches.Values
                             .Where(x => x.IsRemote)
                             .Select(x => new IdCount(x.Id, x.Info.CommandCount))
                             .ToArray();

            // Open a channel to the upstream store
            IRemoteStore rs = context.GetRemoteStore(upLoc);

            // Determine what we are missing (including any new branches in the remote)
            IdRange[] toFetch = rs.GetMissingRanges(cs.Id, have, true);

            // How many commands do we need to fetch
            uint total = (uint)toFetch.Sum(x => x.Size);

            Log.Info($"To fetch {total} command`s from {toFetch.Length} branch`es".TrimExtras());

            // Retrieve the command data from the remote, keeping new branches
            // apart from appends to existing branches.

            var newBranchData  = new Dictionary <BranchInfo, CmdData[]>();
            var moreBranchData = new Dictionary <BranchInfo, CmdData[]>();

            foreach (IdRange idr in toFetch)
            {
                // Fetch the remote AC file
                BranchInfo ac = rs.GetBranchInfo(idr.Id);
                if (ac == null)
                {
                    throw new ApplicationException("Could not locate remote branch " + idr.Id);
                }

                // And the relevant data
                Log.Info($"Fetch [{idr.Min},{idr.Max}] for {ac.BranchName} ({ac.BranchId})");
                CmdData[] branchData = rs.GetData(idr).ToArray();

                if (cs.FindBranch(ac.BranchId) == null)
                {
                    newBranchData.Add(ac, branchData);
                }
                else
                {
                    moreBranchData.Add(ac, branchData);
                }
            }

            // All done with the remote store

            // Copy any brand new branches (ensuring they get created in the
            // right order so that parent/child relationships can be formed
            // as we go).

            foreach (KeyValuePair <BranchInfo, CmdData[]> kvp in newBranchData.OrderBy(x => x.Key.CreatedAt))
            {
                cs.CopyIn(kvp.Key, kvp.Value);
            }

            // Append command data for branches we previously had (the order
            // shouldn't matter)

            foreach (KeyValuePair <BranchInfo, CmdData[]> kvp in moreBranchData)
            {
                cs.CopyIn(kvp.Key, kvp.Value);
            }

            Log.Info("Fetch completed");

            // Reload the current command stream (from scratch, kind of brute force,
            // not sure whether appending the new commands would really be sufficient)
            // TODO: Is this really necessary? Perhaps only if the current branch has
            // been fetched (the stuff we're fetching should only come from remotes,
            // but the current branch could be one of those remotes)
            //cs.Stream = new CmdStream(cs.Current);
        }
Esempio n. 3
0
        public void Process(ExecutionContext context)
        {
            Guid     sourceId = (Input as IMerge).FromId;
            CmdStore cs       = context.Store;
            Branch   target   = cs.Current;
            Branch   source   = cs.FindBranch(sourceId);

            if (source == null)
            {
                throw new ApplicationException($"Cannot locate branch {sourceId}");
            }

            // Merges can only be done between branches that are part
            // of the local store (fetches from remote stores should
            // involve a totally different set of branches)
            //if (target.Info.StoreId != source.Info.StoreId)
            //    throw new NotSupportedException("Attempt to merge with a remote store");

            // Determine the first command that needs to be merged from
            // the source branch. The source branch doesn't know anything
            // about merges that have already been done, so figuring this
            // out involves scanning back from the end of the target branch
            // to locate the last merge (if any).

            // How far we go back depends on whether we're merging from
            // a child branch to its parent, or vice versa. If the target
            // is the child we go back as far as command 0. If the target
            // is the parent, we go back as far the command that followed
            // the branch start point.

            bool targetIsParent = target.Id.Equals(source.Info.ParentId);

            // Define the range of commands to be merged from the source

            uint minCmd = 0;

            if (targetIsParent)
            {
                // Merging into the parent, so start from the command immediately
                // after the last command that was previously merged (or 0 if this
                // is the first time the parent has merged from the child).

                if (target.Info.LastMerge.TryGetValue(sourceId, out MergeInfo mi))
                {
                    minCmd = mi.ChildCount;
                }
            }
            else
            {
                // Merging from the parent into the child, so start from the command
                // immediately after the last command that was previously merged (it
                // could potentially be 0)

                minCmd = target.Info.RefreshCount;
            }

            uint maxCmd = (uint)source.Info.CommandCount - 1;

            // TODO: Round about here we need to actually include the new stuff
            // as part of the current stream. Replaying the commands may then
            // lead to some sort of conflict (things are not guaranteed to work),
            // so there needs to be some way to preview the results.

            // Write the command data
            Input.Add(nameof(IMerge.MinCmd), minCmd);
            Input.Add(nameof(IMerge.MaxCmd), maxCmd);
            target.SaveData(Input);
        }