Пример #1
0
        /// <summary>
        /// Serializes all data.
        /// </summary>
        /// <param name="child">The child node to serialize.</param>
        /// <param name="ms">The binary writer backed by memory.</param>
        /// <param name="writeStat">If the node stat should be serialized along with node data</param>
        private static void SerializeAllData(Node child, BinaryWriter ms, bool writeStat)
        {
            ms.Write(child.Name);
            if (child.Data == null)
            {
                ms.Write(-1);
            }
            else
            {
                ms.Write(child.Data.Length);
                ms.Write(child.Data);
            }

            ms.Write(writeStat);
            if (writeStat)
            {
                child.NodeStat.Write(ms);
            }

            CompleteNode cn = child as CompleteNode;

            if (cn != null)
            {
                foreach (IPersistedData n in cn.ChildrenNodes)
                {
                    SerializeAllData(n.Node, ms, writeStat);
                }
            }

            ms.Write(string.Empty);
        }
Пример #2
0
        /// <summary>
        /// Serializes all data in a depth-first manner sorted by node name, supporting continuations.
        /// </summary>
        /// <param name="child">Node to serialize all the data under.</param>
        /// <param name="ms">Binary writer to serialize the data to.</param>
        /// <param name="writeStat">Whether to write stats for each node or not.</param>
        /// <param name="startingPath">Continuation path to resume from.</param>
        /// <param name="continuationPathBuilder">Continuation path result if we hit max number of nodes limit.</param>
        /// <param name="maxNodes">Maximum number of new nodes to serialize.</param>
        /// <returns>True if enumeration was fully completed, false if the max nodes limit was hit.</returns>
        private static bool SerializeAllDataSorted(Node child, BinaryWriter ms, bool writeStat, Queue <string> startingPath, Stack <string> continuationPathBuilder, ref int maxNodes)
        {
            ms.Write(child.Name);

            if (startingPath != null && startingPath.Count > 0)
            {
                var nextNodeName = startingPath.Dequeue();
                if (child.Name != nextNodeName)
                {
                    throw new ArgumentException($"Invalid starting path specified. Current node is {child.Name}, but starting name is {nextNodeName}", nameof(startingPath));
                }

                // not including data for this node as it was part of previous continuation
                ms.Write(-1);

                // not including stat for this node as it was part of previous continuation
                ms.Write(false);
            }
            else
            {
                maxNodes--;

                if (child.Data == null)
                {
                    ms.Write(-1);
                }
                else
                {
                    ms.Write(child.Data.Length);
                    ms.Write(child.Data);
                }

                ms.Write(writeStat);
                if (writeStat)
                {
                    child.NodeStat.Write(ms);
                }
            }

            if (maxNodes <= 0)
            {
                continuationPathBuilder.Push(child.Name == "/" ? "/" : string.Concat("/", child.Name));
                ms.Write(string.Empty);
                return(false);
            }

            CompleteNode cn = child as CompleteNode;

            if (cn != null)
            {
                string nextNodeName = string.Empty;
                if (startingPath != null && startingPath.Count > 0)
                {
                    nextNodeName = startingPath.Peek();

                    IPersistedData n;
                    if (cn.ChildrenMapping.TryGetValue(nextNodeName, out n))
                    {
                        if (!SerializeAllDataSorted(n.Node, ms, writeStat, startingPath, continuationPathBuilder, ref maxNodes))
                        {
                            continuationPathBuilder.Push(string.Concat("/", child.Name));
                            ms.Write(string.Empty);
                            return(false);
                        }
                    }
                    else
                    {
                        // this subtree was deleted so we can forget about it and continue with next node in order
                        startingPath.Clear();
                    }
                }

                var sortedChildren = cn.RetrieveChildren($">:{maxNodes}:{nextNodeName}");

                foreach (var childNodeName in sortedChildren)
                {
                    IPersistedData n = cn.ChildrenMapping[childNodeName];
                    if (!SerializeAllDataSorted(n.Node, ms, writeStat, startingPath, continuationPathBuilder, ref maxNodes))
                    {
                        continuationPathBuilder.Push(string.Concat("/", child.Name));
                        ms.Write(string.Empty);
                        return(false);
                    }
                }
            }

            ms.Write(string.Empty);

            return(true);
        }