Chapter 1: Type Information and Interception
This chapter starts by explaining what interception is and what it is used for. Interception requires that MTS produces a wrapper object that looks exactly like your component and to do so it needs to know what interfaces your component implements. This means that there must be some description of your component and this is held in type information.
There are two ways of recording type information: type libraries and fast format strings. Both have their strengths and short comings. This chapter describes both and explains how and when they are used.
The final part of the chapter has a detailed look at interception and does this by describing several ways that you can do this. It starts by explaining the interception that COM will give you (and always has, even before MTS was released) in the form of interface remoting. It then explains how you can get a more flexible interception through Keith Brown's Universal Delegator and finally this lead on to a description of how MTS applies interception and the facilities that it provides.
Chapter 2: MTS and COM
MTS is build upon COM, all MTS components are COM components. This chapter starts with a general overview of COM with respect to the code modules that are used to package COM components and how these modules are loaded. This leads on to a general discussion about process launch permissions and access permissions to code in processes and to a discussion on COM surrogates. The chapter then applies this to MTS, using it to explain the MTS surrogate and contrast how this is launched compared to how COM surrogates are launched.
Although MTS components can be run as COM components, the opposite is not necessarily true. The main reason is that MTS components must be written in such a way as to allow interception to occur. These requirements, and the reason for them are explained in full.
The rest of the chapter explains how MTS extends the facilities of COM. It explains how MTS is used to give access to components distributed across the network, in such a way as to make both the component client and the client's developer ignorant about the component's location.
MTS components are created with a context object. The remaining part of the chapter explains what MTS context is and the sort of information that this holds as well as explaining how to obtain this information from the context. Interception requires the use of a context wrapper object, that actually does the interception and this is important in Just-In-Time activation. JIT activation is a requirement to keep the work performed in one transaction isolated from another transaction and MTS does this by deactivating components between method calls while keeping the context wrapper object alive.
Finally, the chapter goes through a detailed look at how MTS actually activates a component, peeking under the covers to look at the low level objects that are used.
Chapter 3: Programming Issues
To use MTS component's effectively you have to change how you program. Part of the reason is that clients must access the context wrapper object and so you must not allow the client to get direct access to the component. The chapter starts by looking into JIT in more depth and explaining how you should program components to use JIT to your advantage.
One of the main reasons that you will want to use MTS is because of the excellent facilities it gives you to write distributed applications. However, distribution comes at a cost, and the chapter explains what these issues are and how to avoid writing components that suffer performance degradation due to excessive network usage.A further issue is how to marshal data in an efficient manner, and I present some results to guide you in deciding how to design your interfaces.
Transactions are used to group together actions into one unit of work. If the transaction aborts, then all the work will be undone. One of the reasons for a transaction to abort is if an error occurs and this chapter explains how to manage errors, both in terms of operating system exceptions and error objects. Transactions must be kept isolated from one another — this is one of the so-called ACID criteria. One area that you can break isolation is by using COM callbacks, commonly known as events. Events are useful and therefore there must be some way to allow them to be generated without compromising your transaction. Another area where isolation can be compromised is in how components manage state and this leads to an explanation of the Shared Property Manager. Both of these issues are investigated in this chapter.
Visual C++ does give you some facilities to develop MTS components, but because MTS components are merely COM components these facilities are fairly thin. Indeed, the ATL MTS Component Object Wizard type removes some important facilities from you. I present a new Object Wizard type that returns those facilities to you. This section of the chapter also describes the little documented and rarely discussed Component Registrar (as opposed to the ATL Registrar). This appears to have been designed for MTS, but has never been used. I explain how it works and suggests ways that you can use it.
Chapter 4: Packages and Deployment
Packages group together components that will run in the same process. They are defined in the MTS Catalog and this chapter explains how to administer the Catalog both through the MTS explorer and using the Catalog API.
It starts by explaining where the Catalog is saved and the various pieces of information that it contains and how they inter-relate. It then explains packages in detail and how to create them and export them so that the can be installed on other machines. Server packages are run using the MTS surrogate which will appear as mtx.exe in the task manager with no indication as to the package ID. The chapter explains how to use the MTS API to determine which packages are running.
As I have indicated earlier MTS Explorer is a facility to allow you to deploy components on remote machine. MTS calls this pulling and pushing components, which essentially means that an administrator, from a single machine, can install components on another machine, or install the necessary marshalling code and registry entries to allow those remote machines to access components remote to them.
Finally, the chapter describes in details the various component and libraries that are installed on your machine with MTS. Most of these libraries are used to manipulate the Catalog and I explain how to use them. The chapter concludes with an example that allows you to refresh components and to selectively shutdown packages.
Chapter 5: Distributed Transaction Coordinator
MS DTC is the service that creates and manages transactions. It is MS DTC that distributes transactions across the network and performs two phase commit. MTS acts merely as client code that obtains transactions from MS DTC, auto- enlists components and initiates committal.
MS DTC will give access to both its native OLE transactions and XA transactions. OLE transactions are a COM-based wrapper around the transactions, but are not marshalable. To distribute transactions to another machine it has to be exported so that the other machine can import it. This is carried out using MS DTC which records which machines a transaction is exported to (and conversely where it is imported from) to build up a commit tree. This means that when a transaction completes the commit message can be sent to all machines involved in the transaction and each machine will inform the appropriate processes that have work performed under the transaction. The chapter explains these objects in details and explains how the participate in the working of a transaction.
These 'appropriate processes' are called resource managers. Resource managers are written specifically to work with MS DTC and provide various call back objects that MS DTC can use to inform it of transaction outcomes. Resource managers maintain durable, transactional state and this means that if the transaction commits then they must make the work persistent. The chapter explains how this is performed and how resource managers handle network and machines failures.
MTS provides auto-enlistment, that is, when a component, configured to use a transaction, is activated MTS ensures that a transaction exists and that the component is enlisted in it. It does this using code called Resource Dispensers that run inprocess to the component. A resource dispenser actuall has two roles. It is both a inprocess 'proxy' to a resource manager, providing a simple API to access the resource managers facilities under a transaction; and they are also used to provide pools of non-transactional resources. Both aspects are covered.
Chapter 6: Security
A distributed application means that you will access components on another machine, which may mean that a process will be started. This brings up two important considerations: does the caller account have the permission to start the package (process) that contains the component, and does the caller have permission to access the component. One of the most frequent problems encountered when people write straight DCOM based distributed applications is to make sure that the correct security is applied. MTS simplifies security by defining roles and applying access checks to callers against these roles through interception.
The chapter starts by explaining how security is applied using COM, it explains the meager (and quirky) tools that are supplied with NT. It then explains how to apply access checks programmatically using ATL to make access checks on a per-process, per-component, per-interface and per-method call basis.
The chapter then explains how MTS does the same thing. What is apparent from the discussion is that most of the security administration is performed in the MTS explorer and to a large extent the component developer does not need to write any security code. If the programmer does need to make programmatic access checks then these are done using an MTS provided API, that is so simple to use that a VB programmer can use it!
The chapter concludes by explaining the security required for MTS administration, principally for importing and exporting components and administrating remote machines.
Chapter 7: MTS Debugging
Distributing components across many machines presents problems to a developer when they come to debug an application. How does the developer gather information from all machines in a manner that makes it useful? This chapter explains the various tools available to debug distributed applications.
MTS will generate connection point based events and the MTS SDK provides a tool called the MTSSpy that can be used to monitor these events on a single machine. I show you the types of events that are generated and how to generate your own custom events.
NT also provides generic tools to monitor processes and one such tool is the performance monitor. However, this does not have the facility to monitor MTS, until now. I show you how to write a performance monitor DLL using statistics gained from catching MTS events.
Another NT tool is the event log. This is used by MTS to log information when something exceptional happens (the MTS events are given in Appendix A). This is more useful than many people expect because it can be used to monitor the NT event log events generated on remote machines, and so the developer can trace a transaction failure through the various components across the network and determine where the failure originated. However, although this facility is offered to the developer it is not presented in a way that is easily used.
The solution is to use the Visual Studio Analyser. This tool is provided with the Enterprise Edition of Visual Studio and takes advantage of special (and largely undocumented) statistics generated by operating system libraries. VSA comes in two parts, the first sits on client machines and gather these messages and send them to the other part, the server that collects and collates these messages. SA can then be used to filter and analyse this data to determine which components, on which machine takes part in a method call.
Chapter 8: The Way Forward
MTS lays the foundation for COM+. COM+ is the runtime that is present on every Windows 2000 machine and is clearly intended to be the future of COM development. COM+ represents the integration of COM and MTS. Indeed, you no longer have to worry in your code about whether the interface pointer you are about to marshal is a raw interface pointer or whether you have given MTS the opportunity to apply a context wrapper. You don't have this worry because COM now knows about context and will automatically determine if an object is a COM+ component and if so apply context to it.
Windows 2000 also integrates MSMQ within the operating system and provides a new event system, both of which are available to COM+ components. Following the lead of MTS these, and other services of COM+, are applied to components using interception, leaving the component with the bare minimum of code to use them. COM+ also changes the way that components are activated and managed in that it provides object pooling, synchronization, a new threading model and compensating resource managers. COM+ has an expanded Catalog and new tools to administer it, including new administration objects.
In this chapter I outline all of the new facilities of COM+ and explain how this will change your programming life.
If you are debugging an MTS application one thing that you'll come across regularly is that when you detect a problem in your object and stop debugging the client the component will still be running. This is because a server package is hosted by the surrogate, mtx.exe. Of course, if you are actually debugging the component code, then you will have this process attached to the debugger and hence when you stop debugging the process will stop. If your component is still running under mtx.exe when you try to rebuild the server then you will find that the link step will not work because write access is denied on the DLL.
If this is the case it means that before you can successfully perform the link step you need to stop the server either by using MTS Explorer or by running the command line tool mtxstop.exe. The advantage of the former is that it you can just stop the specified server process, whereas the latter will stop all server processes. However, the advantage of using mtxstop.exe is that you can add it as a pre-link step in the project settings:
However, mtxstop works by posting the message WM_USER to the channel window of each STA apartment in all instances of mtx.exe. Since the message is posted mtxstop will return without checking that the instances of mtx.exe have stopped. The result is that the link step will still fail, however, rebuilding the project a second time, when the server has had a chance to finish, will succeed. Incidentally, this posted message is not the result of a COM method because, as explained in Professional DCOM Programming, COM calls result in a message with a WPARAM of 0xbabe and mtxstop does not use this value.
The MTSAdmin example solves this problem by obtaining the process handle of the specified package and after asking the package to die it waits on the process handle until it is signaled, indicating that the process has finished. To build this, create a console application in VC6 and replace the main() with the code given here.