Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Dispatcher / QueryTreeBuilder.cs / 1 / QueryTreeBuilder.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Dispatcher { using System.Diagnostics; internal class QueryTreeBuilder { Diverger diverger; Opcode lastOpcode; internal QueryTreeBuilder() { } internal Opcode LastOpcode { get { return this.lastOpcode; } } internal Opcode Build(Opcode tree, OpcodeBlock newBlock) { if (null == tree) { this.lastOpcode = newBlock.Last; return newBlock.First; } this.diverger = new Diverger(tree, newBlock.First); if (!this.diverger.Find()) { // The opcodes in newBlock already have equivalents or identical opcodes // in the query tree that can do the job DiagnosticUtility.DebugAssert(this.diverger.TreePath.Count > 0, ""); this.lastOpcode = this.diverger.TreePath[this.diverger.TreePath.Count - 1]; return tree; } DiagnosticUtility.DebugAssert(this.diverger.TreePath.Count == this.diverger.InsertPath.Count, ""); // We can reuse opcodes upto this.diverger.TreePath[this.diverger.TreePath.Count - 1] // The remainder of the code in newBlock must be executed as is... if (null == this.diverger.TreeOpcode) { // We reached a leaf in the query tree // Simply add the remainder of the inserted code to the end of the tree path.. this.diverger.TreePath[this.diverger.TreePath.Count - 1].Attach(this.diverger.InsertOpcode); } else { // Merge in the remaider of the new code block into the query tree // The first diverging opcodes follow the last entry in each path this.diverger.TreeOpcode.Add(this.diverger.InsertOpcode); } this.lastOpcode = newBlock.Last; if (OpcodeID.MatchMultipleFilterResult == this.diverger.InsertOpcode.ID) { // The complete new block was merged in, except for the the actual result opcode, which never // automatically merges. This means that the new block found all of its opcodes in common with // the tree if (OpcodeID.Branch == this.diverger.TreeOpcode.ID) { OpcodeList branches = (((BranchOpcode) this.diverger.TreeOpcode).Branches); for (int i = 0, count = branches.Count; i < count; ++i) { if (OpcodeID.MatchMultipleFilterResult == branches[i].ID) { this.lastOpcode = branches[i]; break; } } } else if (OpcodeID.MatchMultipleFilterResult == this.diverger.TreeOpcode.ID) { this.lastOpcode = this.diverger.TreeOpcode; } } // Since we'll be diverging, any jumps that preceeded and leapt past the divergence point // will have to be branched this.FixupJumps(); return tree; } void FixupJumps() { QueryBuffertreePath = this.diverger.TreePath; QueryBuffer insertPath = this.diverger.InsertPath; for (int i = 0; i < insertPath.Count; ++i) { if (insertPath[i].TestFlag(OpcodeFlags.Jump)) { DiagnosticUtility.DebugAssert(treePath[i].ID == insertPath[i].ID, ""); JumpOpcode insertJump = (JumpOpcode) insertPath[i]; // Opcodes in 'insertPath' have equivalent opcodes in the query tree: i.e. the query tree contains an // an equivalent execution path (upto the point of divergence naturally) that will produce in an identical // result. The remainder of the query tree (anything that lies beyond the point of divergence) represents // a distinct execution path and is grafted onto the tree as a new branch. In fact, we simply break off // the remainder from the query being inserted and graft it onto the query tree. // If there are jumps on the insert path that jump to opcodes NOT in the insert path, then the jumps // will reach opcodes in the new branch we will add(see above). However, because the actual jump opcodes // are shared (used as is from the query tree), the actual jump must also be branched. One jump will // continue to jump to the original opcode and the second new one will jump to an opcode in the grafted branch. if (-1 == insertPath.IndexOf(insertJump.Jump, i + 1)) { DiagnosticUtility.DebugAssert(insertJump.Jump.ID == OpcodeID.BlockEnd, ""); BlockEndOpcode jumpTo = (BlockEndOpcode) insertJump.Jump; // no longer jumping from insertJump to jumpTo insertJump.RemoveJump(jumpTo); // Instead, jumping from treePath[i] to jumpTo JumpOpcode treeJump = (JumpOpcode) treePath[i]; treeJump.AddJump(jumpTo); } } } } // Can handle queries being merged into trees but not trees merged into trees. // In other words, no branch opcodes in the query being inserted internal struct Diverger { Opcode treeOpcode; QueryBuffer treePath; QueryBuffer insertPath; Opcode insertOpcode; internal Diverger(Opcode tree, Opcode insert) { this.treePath = new QueryBuffer (16); this.insertPath = new QueryBuffer (16); this.treeOpcode = tree; this.insertOpcode = insert; } internal Opcode InsertOpcode { get { return this.insertOpcode; } } internal QueryBuffer InsertPath { get { return this.insertPath; } } internal Opcode TreeOpcode { get { return this.treeOpcode; } } internal QueryBuffer TreePath { get { return this.treePath; } } // Stops at the last common node on each internal bool Find() { Opcode treeNext = null; while (true) { if (null == this.treeOpcode && null == this.insertOpcode) { return false; // no diverge. both ran out at the same time } if (null == this.insertOpcode) { return false; // Ran out before tree did. No divergence. } if (null == this.treeOpcode) { return true; // tree ran out before insert. Divergence } if (this.treeOpcode.TestFlag(OpcodeFlags.Branch)) { treeNext = this.treeOpcode.Locate(this.insertOpcode); if (null == treeNext) { return true; // divergence } this.treeOpcode = treeNext; treeNext = treeNext.Next; } else { if (!this.treeOpcode.Equals(this.insertOpcode)) { return true; // divergence, obviously } treeNext = this.treeOpcode.Next; } // No divergence. Add to paths this.treePath.Add(this.treeOpcode); this.insertPath.Add(this.insertOpcode); this.insertOpcode = this.insertOpcode.Next; this.treeOpcode = treeNext; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SizeLimitedCache.cs
- UnsafeNativeMethods.cs
- StaticResourceExtension.cs
- ThreadAbortException.cs
- BehaviorEditorPart.cs
- GenericWebPart.cs
- SQLStringStorage.cs
- ToolStripMenuItem.cs
- ProtocolsSection.cs
- NameValueFileSectionHandler.cs
- PolicyManager.cs
- CommonGetThemePartSize.cs
- ContentPropertyAttribute.cs
- AppDomainAttributes.cs
- PlainXmlWriter.cs
- ChannelManagerService.cs
- XmlElementCollection.cs
- PlanCompiler.cs
- CLRBindingWorker.cs
- DiscoveryClientOutputChannel.cs
- AssemblyBuilder.cs
- TreeViewCancelEvent.cs
- PageContent.cs
- CustomTrackingRecord.cs
- PriorityChain.cs
- ContextStaticAttribute.cs
- SystemIcmpV4Statistics.cs
- PackageFilter.cs
- DataSetMappper.cs
- EffectiveValueEntry.cs
- ImageSourceConverter.cs
- EntityKey.cs
- WorkflowControlEndpoint.cs
- UserPersonalizationStateInfo.cs
- PackagePart.cs
- QilStrConcatenator.cs
- RowType.cs
- AssertUtility.cs
- SqlDataSourceStatusEventArgs.cs
- QilParameter.cs
- UserControl.cs
- InfoCardSymmetricCrypto.cs
- HyperLinkStyle.cs
- DetailsViewDeleteEventArgs.cs
- ContentOperations.cs
- CodeAccessPermission.cs
- CodeConstructor.cs
- BulletedList.cs
- Expression.cs
- _CacheStreams.cs
- ConstantCheck.cs
- Knowncolors.cs
- TripleDESCryptoServiceProvider.cs
- RegistrationProxy.cs
- XmlMemberMapping.cs
- XmlUtil.cs
- Vector.cs
- DisableDpiAwarenessAttribute.cs
- ScrollEvent.cs
- Switch.cs
- StreamedWorkflowDefinitionContext.cs
- InfoCardArgumentException.cs
- InputMethodStateTypeInfo.cs
- ParserExtension.cs
- RuntimeCompatibilityAttribute.cs
- MenuBase.cs
- webeventbuffer.cs
- Inline.cs
- ChangeTracker.cs
- Compiler.cs
- TokenizerHelper.cs
- ControlBuilder.cs
- SByte.cs
- ConditionalBranch.cs
- PageFunction.cs
- SafeFileHandle.cs
- OutKeywords.cs
- GridViewRowEventArgs.cs
- LogAppendAsyncResult.cs
- UInt16Converter.cs
- GenerateHelper.cs
- PopupEventArgs.cs
- HtmlObjectListAdapter.cs
- Encoding.cs
- DeploymentSection.cs
- TextChange.cs
- SafeArrayRankMismatchException.cs
- TextModifierScope.cs
- SvcMapFileSerializer.cs
- EncryptedType.cs
- RoleServiceManager.cs
- EventManager.cs
- DataGridViewImageColumn.cs
- CommonDialog.cs
- ClickablePoint.cs
- _ListenerResponseStream.cs
- MouseGestureConverter.cs
- CollectionContainer.cs
- LockedAssemblyCache.cs
- XmlnsDictionary.cs