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); }
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); }
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; } } } } } }