Thunderclap, the Newsletter of Rolling Thunder
Volume 1, Number 4 Summer 1999
In this issue:
Feature Article: Our Friend the DTC in COM+
New Book on COM+ by David Platt, published by Microsoft Press
Blatant Self Promotion: Rolling Thunder Goes Down Under
Contest with Prizes: Geeky Country Western Song Titles
Results of Last Contest: Computer Haiku
This is the fourth issue of my (more or less) quarterly newsletters. Each will bring you a technical article on COM or COM+ development, which I hope you will find useful. Each will also bring you a contest, allowing you to show off your intelligence and creativity to win prizes, which I hope you will find funny (although some readers have reported the reverse.) In between you will find my own blatant self promotional material, telling you about the latest ways I've come up with to separate you from your money. (I could have said "carefully selected products and services that we feel might interest you", or other mealy-mouthed horsepuckey. You want the truth or you want me to waste my time and yours dressing it up?)
I'd like to hear what you think about this newsletter and what types of articles you'd like to see in the future. Would you prefer technical programming articles, such as the one in this current issue? Future topics on this track might be, "What the Heck Is the Free-Threaded Marshaler, Anyway?" or "Our Friend, the Causality ID". Or would you prefer higher-level conceptual articles, like "With All the Fuss About COM+, What's In It For Me Today?" Send your e-mail comments to firstname.lastname@example.org.
This newsletter may be freely redistributed, provided that it is sent in its entirety. If you enjoyed it, can I ask you to please forward it to a friend who might also enjoy it? The subscription roll has grown to over 800 for this issue.
Thunderclap is free, and is distributed via e-mail only. We never rent, sell or give away our mailing list. Subscription and unsubscription are handled by a human operator reading e-mail messages. To subscribe or unsubscribe, jump to the Rolling Thunder Web site and fill in the subscription form.
(This article assumes a conceptual familiarity with transactioning in COM)
The main advantage of a tool like Visual Basic is that it abstracts away the low-level details of dealing with COM. For example, you never need to touch or even think about the IUnknown interface when you program in VB. In fact, many VB users don't know that such a thing exists. The developers of VB have provided a generic implementation that solves most programmer's problems most of the time. The problem with this abstraction is that many users are misled into thinking it's all they need to get their work done, and it's not. They think that since the language is such a good life preserver, they don't need to learn how to swim. That's great, until their life preserver springs a leak. Then they call me, and when I hear the note of panic in their voices, I double my price. Knowing the the underlying infrastructure of COM is necessary, not just desirable, for programming VB at a professional level (as opposed to hobbyist level, at which far too many so-called commercial apps are written. See the winning entry in the haiku contest below.)
Users of COM+ encounter a similar problem. COM+ does an excellent job of abstracting away the details of dealing with low-level portions of the operating system, such as the Distributed Transaction Coordinator (DTC), that is responsible for creating transactions and orchestrating the two-phase commit process that commits them. It's great (at least my creditors think so) for you to read a high-level book like my Understanding COM+ as a top-level conceptual introduction. But to use the technology at a professional level, to wisely spend your inheritance, you really need to understand what it's doing under the hood, even though you are rarely going to program at that level. This article examines the ways in which COM+ deals with the transactioning system, showing you how COM+ creates, commits, and aborts transactions. You may never need to play any of these tricks yourself -- you are probably wise to design your system in such a manner as you don't have to. But they're there if you need them, and understanding what COM+ is doing on your behalf is necessary, not just desirable, if you intend to use its abstraction intelligently.
You tell COM+ what you want it to do on your behalf by making administrative entries in the COM+ Catalog (think of the registry on steroids). For example, you can use the Component Services snap-in to mark a component as requiring a transaction or requiring a new transaction. When a client creates an object that is so marked, COM+, operating behind the scenes, goes to the DTC and creates a transaction on your behalf when an object marked "Requires Transaction" is created in a context that doesn't already have a transaction, and every time any object is created that is marked "Requires New Transaction". What gyrations does COM+ perform on your behalf to create this transaction?
This article contains a sample program called txdispenser.exe that uses the DTC to create transactions in the same manner that COM+ does. You can download the sample code by clicking here. It allows you to create transactions with different attributes; it also allows you to commit or abort them (as does COM+ when all your components have signaled their completion), or allow them to time out. It requires Windows 2000 Workstation or higher, or Windows NT 4.0 Workstation or higher with MTS installed from the Windows NT Option Pack. Compiling and linking the program requires the latest header files from the Microsoft Platform SDK. When you unpack and run the program, it will look like this:
When you click the "Create Transaction" button, the sample program connects to the DTC via the API function DtcGetTransactionManager( ). This function allows the caller to specify the interface that it desires in return. The only one used by clients is ITransactionDispenser; the others are for the use of resource managers (RMs) that participate in the two-phase commit process of a transaction. The ITransactionDispenser interface contains the following methods:
|BeginTransaction||Create a new transaction|
|GetOptionsObject||Obtain ITransactionOptions interface used for customizing a transaction at creation time|
The one we care about is ITransactionDispenser::BeginTransaction( ). When we call it, the DTC creates a new transaction internally and returns a pointer to the ITransaction interface used for controlling the new transaction. As will be discussed and demonstrated later in this article, this interface allows us to commit or abort the transaction. The COM+ runtime hides this interface away in your object's context, propagating it to transactional components downstream in accordance with the transactional settings that you have made in the COM+ catalog. A COM+ component can obtain its ITransaction interface via the method IObjectContextInfo::GetTransaction( ). The sample application's code for creating a transaction looks like this:
HRESULT hr ;
ITransactionDispenser *pTxDisp ;
Get connection to the transaction manager.
hr = DtcGetTransactionManager (
NULL, // host system, NULL == local
NULL, // reserved
IID_ITransactionDispenser, // desired interface
0, 0, NULL, // all reserved
(void **)&pTxDisp) ; // output pointer
Get the default transaction options object from the TM.
ITransactionOptions *pTxOptions ;
hr = pTxDisp->GetOptionsObject (&pTxOptions) ;
Create an XACTOPT structure, fill out its fields according to the control values specified by the user, and set it into the transaction options object.
XACTOPT xactopt ;
CString str ;
m_EditTimeout.GetWindowText (str) ;
xactopt.ulTimeout = atoi (str) * 1000 ; // convert text to milliseconds
m_EditDescription.GetWindowText(xactopt.szDescription, sizeof (xactopt.szDescription )) ;
pTxOptions->SetOptions (&xactopt) ;
Tell the DTC to begin the transaction
hr = pTxDisp->BeginTransaction (
NULL, // aggregation, here none
ISOLATIONLEVEL_SERIALIZABLE, // isolation level
0, // flags
pTxOptions , // ITransactionOptions object
&m_pTrans) ; // output variable
Clean up and handle user interface.
< Code omitted for space.>
This middle two paragraphs of this code look a little complex because there are a number of different customizations that we can specify when we create this transaction. For example, every DTC transaction requires a timeout interval, which is specified in the call to ITransactionDispenser::BeginTransaction( ). If the transaction is not explicitly committed or aborted by the time this interval expires, the DTC will automatically abort it. The timeout is used to avoid deadlock between two transactions that request concurrent access to the same resource. Remember transactional isolation -- two different transactions can't see the same record (or other resource requiring isolation) at the same time. Suppose transaction T1 locks record A and requests record B. Meanwhile, transaction T2 locks record B and requests record A. This is a deadlock situation, a "deadly embrace". Neither transaction can move, both clients are hung, and your phone support line gets a very nasty phone call. We could conceivably write a lock manager that would be smart enough to detect the deadlock situation heuristically and fail one of the transactions. However, this would be hellishly difficult to write and to verify for every conceivable situation, and would be especially tricky to implement across the multi-RM, multi-vendor world that Microsoft hopes will grow up around COM+. Instead, Microsoft chose the the easier-to-implement but more blunt option of a timeout interval. If a transaction does not complete within the specified interval, the DTC assumes that there is a deadlock and aborts the transaction. The drawbacks of this approach are obvious -- transactions will time out needlessly if the interval is too short, and bottlenecks will slow the system down if it is too long. COM+ uses the same timeout interval for all the transactions that it creates on the same machine. The setting is located on the "Options" tab of the "My Computer" property sheet. The default is 60 seconds, which is probably OK for debugging but is very long for a production environment. You'll get bottlenecks with it set that high. You probably want it to be in the ballpark of 1 - 5 seconds, unless your operations are long and your contention very low. If your operations take a long time to complete (for example, selling tickets over the Web, where you have to wait for a user to type in a credit card number), it is better to split them up into multiple operations by means of a compensating transaction.
You specify a transaction's timeout interval in a very roundabout kind of way. Working backwards in the source code listing above, as the fourth parameter to ITransactionDispenser::BeginTransaction( ), you pass a COM object supporting the ITransactionOptions interface. This in turn contains an XACTOPT structure, which contains the timeout interval. You don't have to implement the ITransactionOptions object yourself, you can get it from the DTC via the method ITransactionDispenser::GetOptionsObject( ), and you place the XACTOPT structure in it via the method ITransactionOptions::SetOptions( ). Hey, I didn't design it. I would bet they were hedging their options for passing different parameters in the future. The XACTOPT structure can also contain a description of the transaction, which will show up in the system utilities. Note that this is one of the very few places in all of COM (the shell extensions in Windows 95 are the only other one I know of) where you pass an ANSI string instead of Unicode.
When we call ITransactionDispenser::BeginTransaction( ), we need to specify the Isolation Level of the new transaction. Remember that transactions have to pass the ACID test, in which the 'I' stands for isolation. The isolation level tells any resource managers that enlist in the transaction how hard they need to work to ensure isolation. Essentially, it tells any RM that enlists in the transaction what type of locking it needs to use on its records. The automatic transaction mechanism of COM+ always demands an isolation level of ISOLATIONLEVEL_SERIALIZABLE, the most rigorous type, as shown in the example above. It's safe for any type of operation, read or write, that a component might perform, which is why COM+ chooses it. You need this level for any transaction that involves writing records, but it can lead to unnecessary bottlenecks if you have lots of read-only operations that don't require this degree of safety. You can specify other values (available values can be found in the ISOLATIONLEVEL enumeration, currently in system header file "transact.h") if your intimate knowledge of this transaction's operations tells you that a lower level would be faster but still safe. For a discussion of the different types of isolation levels and the operations for which they are and are not safe, consult Chapter 6 of Principles of Transaction Processing, by Philip A. Bernstein and Eric Newcomer (1997, Morgan Kaufmann, ISBN 1-55860-415-4). Note that the DTC itself makes no use of the isolation level, does not think about it at all. It merely passes the specified level on to any RMs that enlist in the transaction. It is up to the RM to read the transaction's isolation level from the DTC and provide the proper locking operation for the specified isolation level.
Once we have the created transaction, it will be visible in the DTC's transaction list in the Component Services snap-in, as shown below. It will stay there only as long as it is active, until you commit it or abort it, or its timeout interval expired. If you want to see it with the default 5-second timeout of the sample program, you probably need to have the snap-in already open to the proper frame when you create the transaction. Thus:
A transaction is represented by the ITransaction interface. Its methods are:
|Commit||Signal the DTC to attempt to commit the transaction|
|Abort||Signal the DTC to abort the transaction|
|GetTransactionInfo||Retrieve information about the transaction|
When it's time to commit or abort the transaction, we do it by calling the methods ITransaction::Commit( ) or ITransaction::Abort( ). COM+ does this based on the settings of the context flags (SetAbort, SetComplete, etc.) that the individual components in a transaction have made. If all of them are happy, COM+ calls ITransaction::Commit( ), otherwise it calls ITransaction::Abort( ). The sample program does this when the user clicks the "Commit" or "Abort" buttons. Thus:
HRESULT hr ;
hr = m_pTrans->Commit (
FALSE , // reserved, must be FALSE
XACTTC_SYNC_PHASEONE, // synchronization flags
0 ) ; // reserved, must be zero
<cleanup omitted for space>
HRESULT hr ;
hr = m_pTrans->Abort (
NULL, // ptr to GUID giving reason for abort, here none
FALSE, // reserved, must be false
FALSE // is abort asynchronous? here not.
<cleanup omitted for space>
When we do this, the results will be displayed in the statistics on the Component Services snap-in tab, thus:
We've now seen where transactions come from and where they go. What we haven't yet discussed is the interaction of the DTC with its resource managers during the commit or abort process. COM+ components don't know anything about the results of other operations in the same transaction. The next issue of this newsletter will probably discuss the issue of how we can inject our own code into the two-phase commit process by writing a Compensating Resource Manager. It's not nearly as hard as it looks.
In the meantime, enjoy playing with the DTC. Give me a call if I can help you out. And as Red Green would say, until next time, "Keep your stick on the ice."
New Book: Understanding COM+
by David S. Platt, President of Rolling Thunder Computing
Published by Microsoft Press
It's been a long haul, but I finally finished my book on COM+. It's entitled Understanding COM+, published by Microsoft Press, ISBN 0-73560-666-8. It's a different approach than my other books, more of a conceptual overview than a wealth of cut-and-paste code. I'm using the same format that David Chappell did in his very successful Understanding ActiveX and OLE, published by Microsoft Press in 1996.
The table of contents of Understanding COM+ is:
1. Introduction to COM+
2. COM+ Architecture
4. Queued Components
6. In-Memory Database
7. Load Balancing
Blatant Self Promotion
New In-House Training Class on COM+
Rolling Thunder Computing is pleased to announce its new in-house training class on COM+. This three or four day training class will cover all the portions of COM+, including that catalog, security, synchronization and threading, transactions, queued components, events, in-memory database, and load balancing. You can read all about it on Rolling Thunder Computing's web site, http://www.rollthunder.com.
David Platt is Byte Magazine's COM/ActiveX Columnist
Remember Byte magazine? Most geeks that I know have fond memories of it from the early days of microcomputing, as do I. Most people know that it ceased publication a while back. But not many people seem to know that it's been resurrected on the Web, at http://www.byte.com. And fewer still seem to know that it features yours truly as the new ActiveX/COM columnist. My first column was entitled "What the Heck is ActiveX, Anyway?", and the second, "What the Heck is COM+, Anyway?" The columns on the front page change weekly. Mine appears on the front page during the fourth week of even-numbered months (April, June, August, etc.). All columns are available at all times on-line by searching -- try that with a print magazine.
See You in September In Singapore (or Kuala Lumpur, or Tokyo)
I hate Labor Day traffic jams. So to avoid them, I'm heading to Asia at the end of the summer to speak to Microsoft audiences about COM and COM+. If you're in the neighborhood, why not stop by? I'll be at Tech Ed Asia in Singapore on Sep 1-3, see http://www.microsoft.com/singapore/events/teched99.asp for full information. Then to Malaysia, where I'll be speaking on September 6-7 at the Microsoft office in Kuala Lumpur. Contact Joo Shian Shirley Leong for more information. Then to Japan, where I'll be speaking at the Microsoft offices in Tokyo on September 14-15. Contact Kazunori Koda for more information.
OLE for Life Insurance in Miami in October
I'll be teaching the next public class on OLE for Life Insurance in Miami in October, sponsored by FDP Corp. For more information on this class or OLifE in general, see http://www.acord.com.
Rolling Thunder goes Down Under (again)
The response was so good during my trip to Australia last year that I've decided to do it again. I'll be available for consultations in Australia from about mid-November to the end of the year. Contact me now (email@example.com) to make arrangements for training or consulting.
ActiveX for Health Care
We've been so busy with COM+ that we're not going to run a public class on AHC until next winter. But if you'd like it in-house at your company, we'd be more than happy to bring it to you. For more information, see http://www.rollthunder.com/ahc.htm.
New Contest with Prizes: Geeky Country Western Song TitlesComputer programming is the Rodney Dangerfield of professions. We get very little respect in our society, far less than we deserve, especially when you consider that the head geek, Bill Gates, is the richest man in the world. I think that's because we're not celebrated in song and story -- for example, how many songs do you know about geeks, versus truck drivers and railroad engineers? I only know one, The Ballad of Silicon Slim, by John Forster. This HAS TO CHANGE, my fellow geeks. This contest is the first step on that long road.
I've always admired country-western song titles, like How Can I Miss You If You Won't Go Away, or Get Your Tongue Out Of My Mouth, I'm Kissing You Good-Bye, or I've Got Tears In My Ears (From Lying On My Back In My Bed When I Cry Over You). This contest lets you show off your creativity and cleverness by coming up with titles for country-western songs that celebrate geekery in some manner. If you're feeling really flush, you can also submit the band name and some lyrics. For example:
My Wife Ran Off with My Notebook PC, and Gosh, I Sure Do Miss It
I Still Miss My QA Tech, But My Aim's Getting Better
Ain't It Hard When You're Floppy, by the Ones and Zeroes
Your entries must be computer-related and original. This isn't a family newsletter, so they don't have to be clean or politically correct. Submitting more than one increases your chances of winning. First prize is $100, second prize $50. Winners will be announced in the next issue of Thunderclap, and the judge's decision (mine) is final. In the event of duplicate or similar entries, the earliest wins. All entries become property of Rolling Thunder Computing. All authors will be identified by first and last names, but not by company. Authors names will be withheld if you so request. Submit your entries via e-mail to firstname.lastname@example.org.
Results of Last Contest: Computer Haiku
Here are the results of the second contest, in which you were asked to supply the last words of a famous person, living or dead, real or fictional:.
The first prize winner, $100 to Tana Sabatino, who counts many VB programmers among her soon-to-be-ex-clients:
Haiku is brainless.
Like a VB programmer.
A dime a dozen.
The second prize winner, $50 to Jon C. Libby, for the geekiest haiku ever written or likely to be written. It's scary as hell when you realize that you actually understand it:
vtable now filled
with horde of 0xCC's.
Doh! forgot AddRef.
Honorable mention to all:
Sox chart new Fenway:
Website tour, Williams-like horns...
still no World Series.
Co Marshal Inter -
Thread In Stream or you'll make R
P C _ E _ WRONG _ THREAD.
Sorry, an error
occurred while generating
the object. Why, Merlin?
-- Jon C Libby
they will pay my bills
the client is my best friend
i hate them alot
talk to me white box.
don't you like me any more now?
fuck you white box, click.
one gig, two gig, more
technology is so quick
rather be knitting
i need to get fit
upon my butt i do sit
no time to run, shit
the sun shines today
i plan to stay in and work
yes, i am stupid
-- Ted Herron
Degree? No... the boot!!!
Mom wants building in ivy.
Pay "Bill", Crimson does.
-- Kelley Sullivan
Crash goes my system.
Protection failure again.
The meaning of life.
The truth about love.
-- Tana Sabatino
One cool cat, that Platt
Very mean, his COM code lean
No one disputes that!
-- Perry Dillard
a fatal error
laughing blue screen of death glows
must be time for beer
-- Al Mele
And it is indeed time for beer, dear readers. I'll hoist one for you if you do the same for me. Until next time, be firm, fly low, and stay cool. -- Dave
Thunderclap does not accept advertising; nor do we sell, rent, or give away our subscriber list. We will make every effort to keep the names of subscribers private; however, if served with a court order, we will sing like a whole flock of canaries. If this bothers you, don't subscribe.
Source code and binaries supplied via this newsletter are provided "as-is", with no warranty of functionality, reliability or suitability for any purpose.
This newsletter is Copyright © 1999 by Rolling Thunder Computing, Inc., Ipswich MA. It may be freely redistributed provided that it is redistributed in its entirety, and that absolutely no changes are made in any way, including the removal of these legal notices.
Thunderclap is a registered trademark ® of Rolling Thunder Computing, Inc., Ipswich MA. All other trademarks are owned by their respective companies.