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
- ClickablePoint.cs
- DbConnectionOptions.cs
- IconBitmapDecoder.cs
- AttributeSetAction.cs
- NonVisualControlAttribute.cs
- COM2ExtendedTypeConverter.cs
- Bezier.cs
- Converter.cs
- ErrorStyle.cs
- RelatedPropertyManager.cs
- ScriptControl.cs
- SqlCachedBuffer.cs
- RelationshipEndCollection.cs
- ProviderManager.cs
- TypeDelegator.cs
- MetadataPropertyAttribute.cs
- XmlSchemaChoice.cs
- HexParser.cs
- FunctionDetailsReader.cs
- ByValueEqualityComparer.cs
- ZipIOCentralDirectoryBlock.cs
- ExpandedWrapper.cs
- DataTableReader.cs
- DataBindingCollection.cs
- DataServiceContext.cs
- DashStyle.cs
- RuntimeArgumentHandle.cs
- NetworkInformationPermission.cs
- _Win32.cs
- SocketStream.cs
- DataObjectCopyingEventArgs.cs
- ThicknessConverter.cs
- WebConfigurationFileMap.cs
- LocalFileSettingsProvider.cs
- FlowDocumentReader.cs
- TextDecoration.cs
- EditBehavior.cs
- Int64Storage.cs
- XmlArrayItemAttributes.cs
- CapabilitiesUse.cs
- DictionaryBase.cs
- PatternMatcher.cs
- RangeBase.cs
- TrackingLocation.cs
- SafeFindHandle.cs
- SimpleColumnProvider.cs
- graph.cs
- TdsParserSessionPool.cs
- SqlUdtInfo.cs
- XPathDocumentBuilder.cs
- LiteralControl.cs
- IncrementalReadDecoders.cs
- TextSegment.cs
- XmlRawWriter.cs
- IDictionary.cs
- Label.cs
- HtmlTextArea.cs
- MultiByteCodec.cs
- SchemaImporterExtensionElementCollection.cs
- Vector3DValueSerializer.cs
- FacetDescription.cs
- Geometry.cs
- GridLengthConverter.cs
- CategoryAttribute.cs
- XmlNode.cs
- ReadOnlyDataSource.cs
- Help.cs
- FolderBrowserDialog.cs
- EventLog.cs
- HostExecutionContextManager.cs
- Latin1Encoding.cs
- VersionPair.cs
- ErrorReporting.cs
- TrackBarRenderer.cs
- PeerObject.cs
- ProgressBar.cs
- UdpUtility.cs
- Int64AnimationUsingKeyFrames.cs
- StdValidatorsAndConverters.cs
- ScriptResourceInfo.cs
- DtdParser.cs
- WmlValidationSummaryAdapter.cs
- AttributeEmitter.cs
- Double.cs
- CacheAxisQuery.cs
- AppAction.cs
- CultureTable.cs
- SoapIgnoreAttribute.cs
- IndentedWriter.cs
- SqlProvider.cs
- SponsorHelper.cs
- SimpleType.cs
- ListenDesigner.cs
- PauseStoryboard.cs
- ActivityMarkupSerializationProvider.cs
- HatchBrush.cs
- _PooledStream.cs
- BooleanAnimationBase.cs
- ViewPort3D.cs
- SEHException.cs