Esempio n. 1
0
        public unsafe Tree CreateTree(Transaction tx, string name, bool keysPrefixing = false)
        {
            if (tx.Flags == (TransactionFlags.ReadWrite) == false)
            {
                throw new ArgumentException("Cannot create a new tree with a read only transaction");
            }

            Tree tree = tx.ReadTree(name);

            if (tree != null)
            {
                return(tree);
            }


            if (name.Equals(Constants.RootTreeName, StringComparison.InvariantCultureIgnoreCase) ||
                name.Equals(Constants.FreeSpaceTreeName, StringComparison.InvariantCultureIgnoreCase))
            {
                throw new InvalidOperationException("Cannot create a tree with reserved name: " + name);
            }


            Slice key = (Slice)name;

            // we are in a write transaction, no need to handle locks
            var header = (TreeRootHeader *)tx.State.Root.DirectRead(key);

            if (header != null)
            {
                tree      = Tree.Open(tx, header);
                tree.Name = name;
                tx.AddTree(name, tree);
                return(tree);
            }

            tree      = Tree.Create(tx, keysPrefixing);
            tree.Name = name;
            var space = tx.State.Root.DirectAdd(key, sizeof(TreeRootHeader));

            tree.State.CopyTo((TreeRootHeader *)space);
            tree.State.IsModified = true;
            tx.AddTree(name, tree);

            if (IsDebugRecording)
            {
                DebugJournal.RecordWriteAction(DebugActionType.CreateTree, tx, Slice.Empty, name, Stream.Null);
            }

            return(tree);
        }
Esempio n. 2
0
        public unsafe void RenameTree(Transaction tx, string fromName, string toName)
        {
            if (tx.Flags == (TransactionFlags.ReadWrite) == false)
            {
                throw new ArgumentException("Cannot rename a new tree with a read only transaction");
            }

            if (toName.Equals(Constants.RootTreeName, StringComparison.InvariantCultureIgnoreCase) ||
                toName.Equals(Constants.FreeSpaceTreeName, StringComparison.InvariantCultureIgnoreCase))
            {
                throw new InvalidOperationException("Cannot create a tree with reserved name: " + toName);
            }

            if (tx.ReadTree(toName) != null)
            {
                throw new ArgumentException("Cannot rename a tree with the name of an existing tree: " + toName);
            }

            Tree fromTree = tx.ReadTree(fromName);

            if (fromTree == null)
            {
                throw new ArgumentException("Tree " + fromName + " does not exists");
            }

            Slice key = (Slice)toName;

            tx.State.Root.Delete((Slice)fromName);
            var ptr = tx.State.Root.DirectAdd(key, sizeof(TreeRootHeader));

            fromTree.State.CopyTo((TreeRootHeader *)ptr);
            fromTree.Name             = toName;
            fromTree.State.IsModified = true;

            tx.RemoveTree(fromName);
            tx.RemoveTree(toName);

            tx.AddTree(toName, fromTree);

            if (IsDebugRecording)
            {
                DebugJournal.RecordWriteAction(DebugActionType.RenameTree, tx, (Slice)toName, fromName, Stream.Null);
            }
        }
        public unsafe Tree CreateTree(Transaction tx, string name, bool keysPrefixing = false)
        {
            Tree tree = tx.ReadTree(name);

            if (tree != null)
            {
                return(tree);
            }

            if (name.Equals(Constants.RootTreeName, StringComparison.InvariantCultureIgnoreCase))
            {
                return(tx.Root);
            }
            if (name.Equals(Constants.FreeSpaceTreeName, StringComparison.InvariantCultureIgnoreCase))
            {
                return(tx.FreeSpaceRoot);
            }

            if (tx.Flags == (TransactionFlags.ReadWrite) == false)
            {
                throw new InvalidOperationException("No such tree: " + name + " and cannot create trees in read transactions");
            }

            Slice key = name;

            tree      = Tree.Create(tx, keysPrefixing);
            tree.Name = name;
            var space = tx.Root.DirectAdd(key, sizeof(TreeRootHeader));

            tree.State.CopyTo((TreeRootHeader *)space);
            tree.State.IsModified = true;
            tx.AddTree(name, tree);

            if (IsDebugRecording)
            {
                DebugJournal.RecordWriteAction(DebugActionType.CreateTree, tx, Slice.Empty, name, Stream.Null);
            }

            return(tree);
        }
Esempio n. 4
0
        private void HandleOperations(Transaction tx, List <OutstandingWrite> writes, CancellationToken token)
        {
            var trees = new HashSet <string>();

            foreach (var write in writes)
            {
                trees.UnionWith(write.Trees);
            }

            foreach (var treeName in trees)
            {
                token.ThrowIfCancellationRequested();

                var tree = tx.State.GetTree(tx, treeName);
                foreach (var write in writes)
                {
                    foreach (var operation in write.GetOperations(treeName))
                    {
                        token.ThrowIfCancellationRequested();

                        operation.Reset();

                        try
                        {
                            if (ShouldRecordToDebugJournal)
                            {
                                DebugActionType actionType;
                                switch (operation.Type)
                                {
                                case WriteBatch.BatchOperationType.Add:
                                    actionType = DebugActionType.Add;
                                    break;

                                case WriteBatch.BatchOperationType.Delete:
                                    actionType = DebugActionType.Delete;
                                    break;

                                case WriteBatch.BatchOperationType.MultiAdd:
                                    actionType = DebugActionType.MultiAdd;
                                    break;

                                case WriteBatch.BatchOperationType.MultiDelete:
                                    actionType = DebugActionType.MultiDelete;
                                    break;

                                case WriteBatch.BatchOperationType.Increment:
                                    actionType = DebugActionType.Increment;
                                    break;

                                case WriteBatch.BatchOperationType.AddStruct:
                                    actionType = DebugActionType.AddStruct;
                                    break;

                                default:
                                    throw new ArgumentOutOfRangeException();
                                }

                                _debugJournal.RecordWriteAction(actionType, tx, operation.Key, treeName, operation.GetValueForDebugJournal());
                            }

                            switch (operation.Type)
                            {
                            case WriteBatch.BatchOperationType.Add:
                                if (operation.ValueStream != null)
                                {
                                    tree.Add(operation.Key, operation.ValueStream, operation.Version);
                                }
                                else
                                {
                                    tree.Add(operation.Key, operation.ValueSlice, operation.Version);
                                }
                                break;

                            case WriteBatch.BatchOperationType.Delete:
                                tree.Delete(operation.Key, operation.Version);
                                break;

                            case WriteBatch.BatchOperationType.MultiAdd:
                                tree.MultiAdd(operation.Key, operation.ValueSlice, operation.Version);
                                break;

                            case WriteBatch.BatchOperationType.MultiDelete:
                                tree.MultiDelete(operation.Key, operation.ValueSlice, operation.Version);
                                break;

                            case WriteBatch.BatchOperationType.Increment:
                                tree.Increment(operation.Key, operation.ValueLong, operation.Version);
                                break;

                            case WriteBatch.BatchOperationType.AddStruct:
                                tree.WriteStruct(operation.Key, operation.ValueStruct, operation.Version);
                                break;

                            default:
                                throw new ArgumentOutOfRangeException();
                            }
                        }
                        catch (Exception e)
                        {
                            if (operation.ExceptionTypesToIgnore.Contains(e.GetType()) == false)
                            {
                                throw;
                            }
                        }
                    }
                }
            }
        }