Esempio n. 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PathGroup"/> class.
        /// </summary>
        /// <param name="pathTable">The table of items in the group.</param>
        /// <param name="groupParentPath">The specified parent path.</param>
        public PathGroup(IReadOnlyDictionary <ITreeNodePath, IPathConnection> pathTable, IFolderPath groupParentPath)
        {
            if (groupParentPath == null)
            {
                throw new ArgumentNullException(nameof(groupParentPath));
            }
            if (pathTable == null)
            {
                throw new ArgumentNullException(nameof(pathTable));
            }

            Debug.Assert(HasNullCommonParent(pathTable));

            Dictionary <ITreeNodePath, IPathConnection> PathTable = new Dictionary <ITreeNodePath, IPathConnection>();

            foreach (KeyValuePair <ITreeNodePath, IPathConnection> Entry in pathTable)
            {
                ITreeNodePath       Path           = Entry.Key;
                IPathConnection     PathConnection = Entry.Value;
                IFolderPath?        ParentPath     = PathConnection.ParentPath;
                ITreeNodeProperties Properties     = PathConnection.Properties;
                bool IsExpanded = PathConnection.IsExpanded;

                if (ParentPath == null)
                {
                    ParentPath = GroupParentPath;
                }

                PathTable.Add(Path, new PathConnection(ParentPath, Properties, IsExpanded));
            }

            this.PathTable  = PathTable;
            GroupParentPath = groupParentPath;
        }
Esempio n. 2
0
        public PathGroup(IReadOnlyDictionary <ITreeNodePath, IPathConnection> pathTable, IFolderPath groupParentPath)
        {
            Assert.ValidateReference(pathTable);
            Assert.ValidateReference(groupParentPath);
            Assert.CheckCondition(HasNullCommonParent(pathTable));

            Dictionary <ITreeNodePath, IPathConnection> PathTable = new Dictionary <ITreeNodePath, IPathConnection>();

            foreach (KeyValuePair <ITreeNodePath, IPathConnection> Entry in pathTable)
            {
                ITreeNodePath       Path           = Entry.Key;
                IPathConnection     PathConnection = Entry.Value;
                IFolderPath         ParentPath     = PathConnection.ParentPath;
                ITreeNodeProperties Properties     = PathConnection.Properties;
                bool IsExpanded = PathConnection.IsExpanded;

                if (ParentPath == null)
                {
                    ParentPath = GroupParentPath;
                }

                PathTable.Add(Path, new PathConnection(ParentPath, Properties, IsExpanded));
            }

            this.PathTable       = PathTable;
            this.GroupParentPath = GroupParentPath;
        }
Esempio n. 3
0
        public void Init(IPathConnection connection)
        {
            // Get the current root,
            DataAddress currentRoot = connection.GetSnapshot();
            // Turn it into a transaction
            ITransaction transaction = connection.CreateTransaction(currentRoot);
            // Initialize the magic property set, etc
            IDataFile        df       = transaction.GetFile(DbTransaction.MagicKey, FileAccess.ReadWrite);
            StringDictionary magicSet = new StringDictionary(df);

            magicSet.SetValue("ob_type", "Deveel.Data.CloudBase");
            magicSet.SetValue("version", "1.0");
            // Flush and publish the change
            DataAddress finalRoot = connection.CommitTransaction(transaction);

            connection.Publish(finalRoot);
        }
Esempio n. 4
0
        public static bool HasNullCommonParent(IReadOnlyDictionary <ITreeNodePath, IPathConnection> pathTable)
        {
            Assert.ValidateReference(pathTable);

            foreach (KeyValuePair <ITreeNodePath, IPathConnection> Entry in pathTable)
            {
                IPathConnection PathConnection = Entry.Value;
                IFolderPath     ParentPath     = PathConnection.ParentPath;

                if (ParentPath != null && !pathTable.ContainsKey(ParentPath))
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 5
0
        /// <summary>
        /// Checks whether paths in a table have a common parent.
        /// </summary>
        /// <param name="pathTable">The table of items.</param>
        /// <returns>True if items have a common parent; otherwise, false.</returns>
        public static bool HasCommonParent(IReadOnlyDictionary <ITreeNodePath, IPathConnection> pathTable)
        {
            if (pathTable == null)
            {
                throw new ArgumentNullException(nameof(pathTable));
            }

            IFolderPath?GroupParentPath = null;
            bool?       IsNullParent    = null;

            foreach (KeyValuePair <ITreeNodePath, IPathConnection> Entry in pathTable)
            {
                IPathConnection PathConnection = Entry.Value;
                IFolderPath?    ParentPath     = PathConnection.ParentPath;

                if (ParentPath != null && pathTable.ContainsKey(ParentPath))
                {
                    continue;
                }

                if (!IsNullParent.HasValue)
                {
                    IsNullParent = ParentPath == null;
                }
                else if (IsNullParent.Value != (ParentPath == null))
                {
                    return(false);
                }

                if (ParentPath != null)
                {
                    if (GroupParentPath == null)
                    {
                        GroupParentPath = ParentPath;
                    }
                    else if (GroupParentPath != ParentPath)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Esempio n. 6
0
        public static bool HasCommonParent(IReadOnlyDictionary <ITreeNodePath, IPathConnection> pathTable)
        {
            Assert.ValidateReference(pathTable);

            IFolderPath GroupParentPath = null;
            bool?       IsNullParent    = null;

            foreach (KeyValuePair <ITreeNodePath, IPathConnection> Entry in pathTable)
            {
                IPathConnection PathConnection = Entry.Value;
                IFolderPath     ParentPath     = PathConnection.ParentPath;

                if (ParentPath != null && pathTable.ContainsKey(ParentPath))
                {
                    continue;
                }

                if (!IsNullParent.HasValue)
                {
                    IsNullParent = (ParentPath == null);
                }

                else if (IsNullParent.Value != (ParentPath == null))
                {
                    return(false);
                }

                if (ParentPath != null)
                {
                    if (GroupParentPath == null)
                    {
                        GroupParentPath = ParentPath;
                    }

                    else if (GroupParentPath != ParentPath)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        /// <summary>
        /// Removes a table of paths.
        /// </summary>
        /// <param name="pathTable">The table of paths.</param>
        protected virtual void Remove(IReadOnlyDictionary <ITreeNodePath, IPathConnection> pathTable)
        {
            if (pathTable == null)
            {
                throw new ArgumentNullException(nameof(pathTable));
            }

            IReadOnlyDictionary <IFolderPath, ISolutionFolder> FlatFolderTable = Root.FlatFolderChildren;
            List <ISolutionTreeNodeCollection> ModifiedCollectionList          = new List <ISolutionTreeNodeCollection>();

            foreach (KeyValuePair <ITreeNodePath, IPathConnection> Entry in pathTable)
            {
                ITreeNodePath   Path       = Entry.Key;
                IPathConnection Connection = Entry.Value;
                IFolderPath?    ParentPath = Connection.ParentPath;

                if (ParentPath != null)
                {
                    ISolutionFolder             ParentFolder       = FlatFolderTable[ParentPath];
                    ISolutionTreeNodeCollection ChildrenCollection = (ISolutionTreeNodeCollection)ParentFolder.Children;

                    foreach (ISolutionTreeNode Child in (IEnumerable <ISolutionTreeNode>)ChildrenCollection)
                    {
                        if (Child.Path.IsEqual(Path))
                        {
                            ChildrenCollection.Remove(Child);
                            break;
                        }
                    }

                    if (!ModifiedCollectionList.Contains(ChildrenCollection))
                    {
                        ModifiedCollectionList.Add(ChildrenCollection);
                    }
                }
            }

            foreach (ISolutionTreeNodeCollection ChildrenCollection in ModifiedCollectionList)
            {
                ChildrenCollection.Sort();
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Checks whether paths in a table have no parents.
        /// </summary>
        /// <param name="pathTable">The table of items.</param>
        /// <returns>True if items don't have any parent; otherwise, false.</returns>
        public static bool HasNullCommonParent(IReadOnlyDictionary <ITreeNodePath, IPathConnection> pathTable)
        {
            if (pathTable == null)
            {
                throw new ArgumentNullException(nameof(pathTable));
            }

            foreach (KeyValuePair <ITreeNodePath, IPathConnection> Entry in pathTable)
            {
                IPathConnection PathConnection = Entry.Value;
                IFolderPath?    ParentPath     = PathConnection.ParentPath;

                if (ParentPath != null && !pathTable.ContainsKey(ParentPath))
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 9
0
        protected virtual void Remove(IReadOnlyDictionary <ITreeNodePath, IPathConnection> pathTable)
        {
            Assert.ValidateReference(pathTable);

            IReadOnlyDictionary <IFolderPath, ISolutionFolder> FlatFolderTable = Root.FlatFolderChildren;
            List <ISolutionTreeNodeCollection> ModifiedCollectionList          = new List <ISolutionTreeNodeCollection>();

            foreach (KeyValuePair <ITreeNodePath, IPathConnection> Entry in pathTable)
            {
                ITreeNodePath   Path       = Entry.Key;
                IPathConnection Connection = Entry.Value;
                IFolderPath     ParentPath = Connection.ParentPath;

                ISolutionFolder             ParentFolder       = FlatFolderTable[ParentPath];
                ISolutionTreeNodeCollection ChildrenCollection = (ISolutionTreeNodeCollection)ParentFolder.Children;

                foreach (ISolutionTreeNode Child in ChildrenCollection)
                {
                    if (Child.Path.IsEqual(Path))
                    {
                        ChildrenCollection.Remove(Child);
                        break;
                    }
                }

                if (!ModifiedCollectionList.Contains(ChildrenCollection))
                {
                    ModifiedCollectionList.Add(ChildrenCollection);
                }
            }

            foreach (ISolutionTreeNodeCollection ChildrenCollection in ModifiedCollectionList)
            {
                ChildrenCollection.Sort();
            }
        }
Esempio n. 10
0
        public DataAddress Commit(IPathConnection connection, DataAddress rootNode)
        {
            // Turn the proposal into a proposed_transaction,
            ITransaction  t = connection.CreateTransaction(rootNode);
            DbTransaction proposedTransaction = new DbTransaction(null, rootNode, t);

            try {
                // Fetch the base root from the proposed_transaction log,
                TextReader reader      = proposedTransaction.GetLogReader();
                string     baseRootStr = reader.ReadLine();
                // If 'base_root_str' is "no base root" then it means we are commiting
                // an introduced transaction that is not an iteration of previous
                // snapshots.
                if (baseRootStr.Equals("no base root"))
                {
                    // In which case, we publish the proposed snapshot unconditionally
                    // and return.
                    connection.Publish(rootNode);
                    return(rootNode);
                }

                DataAddress baseRoot = DataAddress.Parse(baseRootStr);

                // Find all the entries since this base
                DataAddress[] roots = connection.GetSnapshots(baseRoot);

                // If there are no roots, we can publish the proposed_transaction
                // unconditionally
                if (roots.Length == 0)
                {
                    connection.Publish(rootNode);
                    return(rootNode);
                }

                // Check historical log for clashes, and if none, replay the commands
                // in the log.

                // For each previous root, we build a structure that can answer the
                // following questions;
                // * Is file [name] created, deleted or changed in this root?
                // * Is table [name] created or deleted in this root?
                // * Is table [name] structurally changed in this root?
                // * Has row [rowid] been deleted in table [name] in this root?

                RootEvents[] rootEventSet = new RootEvents[roots.Length];
                int          i            = 0;

                // TODO: RootEvents is pre-computed information which we could
                //   store in a local cache for some speed improvements, so we don't
                //   need to walk through through the same data multiple times.

                foreach (DataAddress root in roots)
                {
                    RootEvents rootEvents = new RootEvents();
                    rootEventSet[i] = rootEvents;
                    ++i;
                    // Create a transaction object for this root
                    ITransaction  rootT           = connection.CreateTransaction(root);
                    DbTransaction rootTransaction = new DbTransaction(null, root, rootT);
                    // Make a reader object for the log,
                    TextReader rootReader = rootTransaction.GetLogReader();
                    // Read the base root from this transaction,
                    String baseRootParent = rootReader.ReadLine();
                    // If 'bast_root_parent' is 'no base root' then it means a version
                    // has been introduced that is not an iteration of previous
                    // snapshots. In this case, it is not possible to merge updates
                    // therefore we generate a commit fault.
                    if (baseRootParent.Equals("no base root"))
                    {
                        throw new CommitFaultException("Transaction history contains introduced version.");
                    }

                    // Go through each log entry and determine if there's a clash,
                    string rootLine = rootReader.ReadLine();
                    while (rootLine != null)
                    {
                        String mfile = rootLine.Substring(2);
                        // This represents a file modification,
                        bool unknownCommand = false;
                        if (rootLine.StartsWith("F"))
                        {
                            rootEvents.SetFileChange(mfile);
                        }
                        // This is a table modification,
                        else if (rootLine.StartsWith("T"))
                        {
                            char c = rootLine[1];
                            // If this is a table create or delete event,
                            if (c == 'C' || c == 'D')
                            {
                                rootEvents.SetTableCreateOrDelete(mfile);
                            }
                            // This is a table structural change,
                            else if (c == 'S')
                            {
                                rootEvents.SetTableStructuralChange(mfile);
                            }
                            // This is a table data change event,
                            else if (c == 'M')
                            {
                                DbTable table = rootTransaction.GetTable(mfile);
                                rootEvents.SetTableDataChange(mfile, table);
                            }
                            else
                            {
                                unknownCommand = true;
                            }
                        }
                        else
                        {
                            unknownCommand = true;
                        }
                        if (unknownCommand)
                        {
                            throw new ApplicationException("Unknown transaction command: " + rootLine);
                        }
                        // Read the next log entry,
                        rootLine = rootReader.ReadLine();
                    }
                }

                // Now we have a set of RootEvents objects that describe what
                // happens in each previous root.

                // Now replay the events in the proposal transaction in the latest
                // transaction.

                // A transaction representing the current state,
                DataAddress   currentRoot        = connection.GetSnapshot();
                ITransaction  currentT           = connection.CreateTransaction(currentRoot);
                DbTransaction currentTransaction = new DbTransaction(null, currentRoot, currentT);
                String        entry = reader.ReadLine();
                while (entry != null)
                {
                    String mfile = entry.Substring(2);
                    // If it's a file entry, we need to check the file hasn't been
                    // changed in any way in any roots
                    if (entry.StartsWith("F"))
                    {
                        foreach (RootEvents events in rootEventSet)
                        {
                            events.CheckFileChange(mfile);
                        }

                        // All checks passed, so perform the operation
                        currentTransaction.ReplayFileLogEntry(entry, proposedTransaction);
                    }
                    // If it's a table entry,
                    else if (entry.StartsWith("T"))
                    {
                        // Check that a table with this name hasn't been created, deleted
                        // or modified,
                        foreach (RootEvents events in rootEventSet)
                        {
                            // This fails on any event on this table, except a data change
                            // (insert or delete)
                            events.CheckTableMetaChange(mfile);
                        }
                        // The type of operation,
                        char c = entry[1];
                        // Is it a table structural change?
                        if (c == 'S')
                        {
                            // A structural change can only happen if all the roots leave the
                            // table untouched,
                            foreach (RootEvents events in rootEventSet)
                            {
                                // This fails if it finds a delete event for this rowid
                                events.CheckTableDataChange(mfile);
                            }
                        }
                        // Is it a table modification command?
                        else if (c == 'M')
                        {
                            // This is a table modification, we need to check the rowid
                            // logs and look for possible clashes,
                            // The delete set from the proposed transaction,
                            DbTable      proposedTable = proposedTransaction.GetTable(mfile);
                            SortedIndex  deleteSet     = proposedTable.Deletes;
                            IIndexCursor dsi           = deleteSet.GetCursor();
                            while (dsi.MoveNext())
                            {
                                long rowid = dsi.Current;
                                foreach (RootEvents events in rootEventSet)
                                {
                                    // This fails if it finds a delete event for this rowid
                                    events.CheckTableDataDelete(mfile, rowid);
                                }
                            }
                        }
                        // Go through each root, if the data in the table was changed
                        // by any of the roots, we set 'has_data_changes' to true;
                        bool hasDataChanges = false;
                        foreach (RootEvents events in rootEventSet)
                        {
                            if (events.HasTableDataChanges(mfile))
                            {
                                hasDataChanges = true;
                            }
                        }

                        // Ok, checks passed, so reply all the data changes on the table
                        currentTransaction.ReplayTableLogEntry(entry, proposedTransaction, hasDataChanges);
                    }
                    else
                    {
                        throw new ApplicationException("Unknown transaction command: " + entry);
                    }

                    // Read the next log entry,
                    entry = reader.ReadLine();
                }

                // Refresh the transaction log
                currentTransaction.RefreshTransactionLog();

                // Flush and publish the change
                DataAddress finalRoot = connection.CommitTransaction(currentT);
                connection.Publish(finalRoot);

                // Done.
                return(finalRoot);
            } catch (IOException e) {
                throw new ApplicationException("IO Error: " + e.Message);
            }
        }
Esempio n. 11
0
 public string GetStats(IPathConnection connection, DataAddress snapshot)
 {
     throw new NotImplementedException();
 }
Esempio n. 12
0
        protected virtual void Add(IReadOnlyDictionary <ITreeNodePath, IPathConnection> pathTable)
        {
            Assert.ValidateReference(pathTable);

            ClearExpandedFolders();

            List <ISolutionTreeNodeCollection> ModifiedCollectionList = new List <ISolutionTreeNodeCollection>();

            List <ITreeNodePath> PathList = new List <ITreeNodePath>();

            foreach (KeyValuePair <ITreeNodePath, IPathConnection> Entry in pathTable)
            {
                PathList.Add(Entry.Key);
            }

            while (PathList.Count > 0)
            {
                IReadOnlyDictionary <IFolderPath, ISolutionFolder> FlatFolderTable = Root.FlatFolderChildren;

                int i = 0;
                while (i < PathList.Count)
                {
                    ITreeNodePath   Path       = PathList[i];
                    IPathConnection Connection = pathTable[Path];
                    IFolderPath     ParentPath = Connection.ParentPath;

                    if (FlatFolderTable.ContainsKey(ParentPath))
                    {
                        PathList.RemoveAt(i);

                        ISolutionFolder             ParentFolder       = FlatFolderTable[ParentPath];
                        ISolutionTreeNodeCollection ChildrenCollection = (ISolutionTreeNodeCollection)ParentFolder.Children;

                        IFolderPath AsFolderPath;
                        IItemPath   AsItemPath;

                        if ((AsFolderPath = Path as IFolderPath) != null)
                        {
                            IFolderProperties Properties = (IFolderProperties)Connection.Properties;

                            ISolutionFolder NewFolder = CreateSolutionFolder(ParentFolder, AsFolderPath, Properties);
                            ChildrenCollection.Add(NewFolder);

                            if (Connection.IsExpanded)
                            {
                                AddExpandedFolder(NewFolder);
                            }
                        }

                        else if ((AsItemPath = Path as IItemPath) != null)
                        {
                            IItemProperties Properties = (IItemProperties)Connection.Properties;

                            ISolutionItem NewItem = CreateSolutionItem(ParentFolder, AsItemPath, Properties);
                            ChildrenCollection.Add(NewItem);
                        }

                        else
                        {
                            Assert.InvalidExecutionPath();
                        }

                        if (!ModifiedCollectionList.Contains(ChildrenCollection))
                        {
                            ModifiedCollectionList.Add(ChildrenCollection);
                        }
                    }
                    else
                    {
                        i++;
                    }
                }
            }

            foreach (ISolutionTreeNodeCollection ChildrenCollection in ModifiedCollectionList)
            {
                ChildrenCollection.Sort();
            }
        }
        /// <summary>
        /// Adds a table of path.
        /// </summary>
        /// <param name="pathTable">The table to add.</param>
        protected virtual void Add(IReadOnlyDictionary <ITreeNodePath, IPathConnection> pathTable)
        {
            if (pathTable == null)
            {
                throw new ArgumentNullException(nameof(pathTable));
            }

            ClearExpandedFolders();

            List <ISolutionTreeNodeCollection> ModifiedCollectionList = new List <ISolutionTreeNodeCollection>();

            List <ITreeNodePath> PathList = new List <ITreeNodePath>();

            foreach (KeyValuePair <ITreeNodePath, IPathConnection> Entry in pathTable)
            {
                PathList.Add(Entry.Key);
            }

            while (PathList.Count > 0)
            {
                IReadOnlyDictionary <IFolderPath, ISolutionFolder> FlatFolderTable = Root.FlatFolderChildren;

                int i = 0;
                while (i < PathList.Count)
                {
                    ITreeNodePath   Path       = PathList[i];
                    IPathConnection Connection = pathTable[Path];
                    IFolderPath?    ParentPath = Connection.ParentPath;

                    if (ParentPath != null && FlatFolderTable.ContainsKey(ParentPath))
                    {
                        PathList.RemoveAt(i);

                        ISolutionFolder             ParentFolder       = FlatFolderTable[ParentPath];
                        ISolutionTreeNodeCollection ChildrenCollection = (ISolutionTreeNodeCollection)ParentFolder.Children;
                        bool IsHandled = false;

                        switch (Path)
                        {
                        case IFolderPath AsFolderPath:
                            IFolderProperties FolderProperties = (IFolderProperties)Connection.Properties;

                            ISolutionFolder NewFolder = CreateSolutionFolder(ParentFolder, AsFolderPath, FolderProperties);
                            ChildrenCollection.Add(NewFolder);

                            if (Connection.IsExpanded)
                            {
                                AddExpandedFolder(NewFolder);
                            }

                            IsHandled = true;
                            break;

                        case IItemPath AsItemPath:
                            IItemProperties ItemProperties = (IItemProperties)Connection.Properties;

                            ISolutionItem NewItem = CreateSolutionItem(ParentFolder, AsItemPath, ItemProperties);
                            ChildrenCollection.Add(NewItem);

                            IsHandled = true;
                            break;
                        }

                        Debug.Assert(IsHandled);

                        if (!ModifiedCollectionList.Contains(ChildrenCollection))
                        {
                            ModifiedCollectionList.Add(ChildrenCollection);
                        }
                    }
                    else
                    {
                        i++;
                    }
                }
            }

            foreach (ISolutionTreeNodeCollection ChildrenCollection in ModifiedCollectionList)
            {
                ChildrenCollection.Sort();
            }
        }