| |
||||
|
Welcome to Sabbasoft |
||||
![]()
|
|
1) Why is dangerous the use of the New keyword in VB to create COM objects registrered under MTS ? |
||||||||||||||||||
|
The New keyword is the only way to go when you want to create objects
that are defined as PublicnotCreatable or Private (CreateObject doesn't
work). 1) In the situation where the
caller and the callee are in the same EXE/DLL COM component VB perform an internal creation
of the COM object bypassing the COM run-time (and the MTS run-time if the
object is registered under MTS). 2) When you
declare an object (Interface) with the syntax Consider the following code:
|
|
|
2) What's difference between a MTS transaction and an MTS activity ? |
| An activity is a logical thread of
execution. An activity
spawns across threads, processes (packages) and machines. An object shares
the same activity with its father object (provided it's not the root of
the activity) if the father used CreateInstance to create it. This is true
no matter the father and child transaction settings are. The concept of
activity is used by MTS to handle concurrent access and re-entrancy. The objects involved in an MTS transaction are all part of the same activity. The objects involved in an MTS transaction are a subset (that can match with the whole) of the objects that share the same activity, this because there could be some objects that are declared as "Does Not Support Transaction". |
|
|
3) When do I have to use CreateObject and when CreateInstance? |
| You have to use CreateInstance
if: - You are in a component running under MTS AND the object you want to create is registered under MTS AND you want that the transaction (the activity in the most general case when no transactional objects are involved) flows from the father object to the child object. You have to use CreateObject if: - The caller hasn't got a TransactionContext, that is, you want to instantiate the root object of a transaction from the base-client OR - The caller has got a TransactionContext but you want that the child object lives in a new different transaction (read activity in the most general case). Note that you would have achieved the same effect if you had used CreateInstance but the child object had been declared under MTS as "Requires New Transaction". |
|
|
4) Statefull - stateless programming - How to store state across transaction boundaries |
| The MTS programming model suggests to call SetComplete as
often as possible to achieve scalability via the "release resources as soon
as you can" paradigma. This is called "stateless programming"
cause your object is destroied after each method call that invoked SetComplete
(or SetAbort). There are lot of discussion & misunderstandings about this. As long as you don't want MTS to handle the transaction issues involved in DB writings operations this paradigma is just a reccomandation to scale, MTS doesn't force you to follow these guide-lines. If you want to use MTS as the way to coordinate the commit of DB operations (mark the objects as Support/Requires transaction) then the Setcomplete/SetAbort call as one more effect: it makes your component vote for a commit of DB writings operation. I want to point your attention to what is said above: the same call has 2 effects that are (apparently) unrelated, we could reprhase it in this way: In the MTS nations if citizens want to vote then they they have to die (sounds like some south America places .. doesn't it ? :) ) By the way: If noone votes then the transaction is committed, but this is a very bad programming practice and it works only if the root object of the transaction is released by the base-client within the DTC transaction time-out (default 60 seconds) After you have mastered this new programming model you realize that,
nevertheless "stateless" is good, you can't develop an
application that doesn't requires some pieces of
informations that spawns across transactions boundaries in the business-logic
tier. The "data" you need to store are divided
into two categories: Two main guide lines should be given : About session data: you can decide what to store at the client side and
what at the server side. The more you store at the client side the less you
charge you server but the more you stress your network (these datas have to
travel with each method call to the server)If you choose to store your session data in the middle
tier you have two approaches available: As you can see there are different architettural
solutions. Here is now what you have available in the Wintel platform: Data chaching (in access speed order): The SPM looks appealing but remember that: It sounds tempting to store COM objects in the SPM, doesn't it ? The problem is
that the SPM let's you do so but then know you are getting into serious
"random" troubles. A good way to go is using the GIT (Global Interface
Table). It basically works like this: you pass the GIT a pointer to an object
and the GIT gives you back a cookie. Whoever in the same process has this cookie
can ask for the
object pointer back. It's apparently like SPM, BUT the GIT provides all the
marshalling/unmarshalling operations that are needed when it detects that the
object is required by someone running in an apartment that is not the one where
the object in the GIT was created. For Internet/Intranet development only: To summarize we can say that the GIT is the best way to goif you want to cache COM objects, just remember that the GIT is process (read package) wide. Different packages won't share the same GIT. Personally i wrapped the D. Box wrapper around another COM object and deploied such COM object in a separate, dedicated package. I think it could work deploying the D. Box wrapper directly in a package but i didn't try. If you try doing this let me know if it works. |
|
|
5) What is the best setting of the "Run as" option in a server package ? |
| When you deploy COM objects in dlls no security issues arise since
dlls run in the process of the caller. On the contrary, when you deploy your COM objects into an .EXE, you have to deal with such issues. (D)COM needs to know under what security principal (read identity) the process, where your COM objects lives in, has to be associated with. (D)COM wants to know other details as well, like who has the rights to launch and to access the COM objects and what's the lowest level of security your COM objects must accept when it negotiates a connection from a caller. These options can be set at run-time (but you have to deal with DCOM APIs) or can be configured at deployment time using the Dcomfig utility. If there are no security settings defined for your Component then (D)COM uses default access permission. The settings you have available in (D)COM for the Run as setting are: If what is described above is clear, there is just one more thing to know when you come to MTS: Each MTS server package is a separate surrogate process where your dlls run in. If you decide to deploy your dlls into an MTS Server package you have to remember that every access to the COM objects implemented in such dlls will have to deal with (D)COM security if the caller is outside the same MTS package. |
|
6) Should I use Createinstance or CreateObject for ADO objects ? |
|
| Use CreateObject or the New keyword to create ADO objects. They are not COM objects registered under MTS. |
| 7) MTS Internal flags, that is how MTS tracks transaction outcome | |
| Most of the text of this FAQ (#11) is taken from the Ted
Pattison article on MSJ - October 1999
The Above figure shows a diagram of the root object,
its context wrapper, and the MTS transaction in which they are running. It
also shows some important internal flags maintained by MTS. These
variables aren’t directly exposed to you, but you should understand how
they influence the MTS runtime’s decision to commit or abort the
transaction. |
| 8) How do I debug components under the VC++ IDE ? | |
| First read Q166275 - HOWTO Debug a Native Code Visual Basic Component in VC++ from the Microsoft KB, then read the following tips that swhite@barkbark.demon.co.uk kindly let me publish in these FAQ. Some notes I made about this. Hope they help.
Can't debug? Make sure any components you wish to debug are registered with a Server Package and not a Library Package in MTS. For instance, in production the Data Server will be registered with a Library Package so that it will activate in its Client's process, thus preventing cross-process calls. But to debug it, change its Package activation to Server. Can't debug? On the Debug tab of your project's Settings, set the executable to C:\WINNT\system32\mtx.exe, and the Program arguments to /p:"Your Package". If you wish to debug data and business servers at once, open two instances of Visual C++ and set the packages accordingly. Can't debug? The only way to placate the
bad-tempered god of MTS debugging is to remember to go through the
laborious ritual of: confirm packages are Library, confirm Debug Project
Settings are correct, build data and business servers, Refresh All
Components, Shut down Server Processes on My Computer, Shut down each
Package you're debugging, set breakpoints in each project you wish to
debug, start debugging (F5) in each project you wish to debug, and finally
open your Client and start debugging. If the debugger doesn't stop at your
breakpoints then make sure MSDTC is running. If it is then reboot and
start again. If that doesn't work, format and rebuild NT (I'm serious!). |
| 9) What are the security extension features MTS adds to standard DCOM ? | |
| MTS security model is based on Roles. Roles are
entities under which you gather together a number of NT users that are
logically equivalent regarding the security requirements of your
component. This means that the MTS security model is based on the assumption that the original caller identity is available when you hit the package boundary. In a distributed environment this security model seems to be clashing with the way COM passes identity principals across processes and hosts. Suppose Alice in the host A makes a call to a COM object in hosts B running as BOB. BOB authenticates Alice, enter a new thead and calls CoImpersonateClient using Alice identity token. Now within this thread there is an outgoing call to a COM object running as Charlie in host C. Since COM knows that NTLM (the WNT 4.0 built-in authentication protocol) doesn't support cross-host delegation, it calls into Charlie using the Process token, not thread token. MTS role based security model seems then to turn completely unusefull (think about components accessed from IIS where the process token is IWAM_MACHINE for all the users that surf into your App from the Web). Clearly there is a way out from this. It turns out that MTS has an interesting feaure that uses to fix this problem. If your process token is included include into the "MTS Impersonator" alias (added as a local group by the Option Pack setup) or if you are running under the system account, MTS makes some interesting out-of-band work to propagate via the objectcontext the thread token to the process of the callee. This is the identity token MTS uses to perform its declarative and programmatic (IsCallerInRole) security checking. In this situation COM and MTS will disagree on the identity of the caller but since you have developed your Application security policy using roles this is of no concern for you. |
| 10) What about syncronization issues in MTS ? | |
| MTS keeps under the same Activity ID calls that flow through the same logical thread of execution. Thus the Activity ID flows correctly through process and host boundaries. Unfortunately MTS cannot guarantee more syncronization features than the ones that are provided by the STA threading model, that is, it guarantees that all the objects within the same process (package) running in the same Activity (that is STA) will not be accessed concurrently. BUT when your activity flows cross process and host boundaries MTS doesn't guarantee you that metod calls within the same activity will be syncronized. Anyway such a fact is unlikely to be a problem if your client is not a multithreaded one (like standard VB client App). (thank to Doctor Richard Grimes' book about MTS programming for this explanation) |
| 11) Can i administer the MTS Catalog in a programmatic way ? | |
| The MTS Catalog can be admnistered in a programmatic
way via the MTS 2.0 Admin Type Library implemented in the MTXADMIN.DLL.
There is a lower-level access interface exposed by the MTS 2.0 Catalog
Server Type Library (mtxcatex.dll) but you can't fully access its
funcionalities from VB cause it exposes some non-Automation compatible
method signatues ([out] SAFEARRAY). The hierarchical object model exposed by the Admin Type Library to map the catalog structure is kinda unusual, different from the ones you are used to work with. The whole MTS catalog is exposed using only three classes (that implement a single interface): - Catalog - CatalogCollection - CatalogObject To connect to an MTS catalog you use the Connect method
specifing the server name. The GetCollection method doesn't populate the collection. You have to call
the Populate method to do this. Dim Cat as New Catalog As you can see, in the case of the root collection
the second parameter of the GetCollection method is blank. This happens
when the requested collection is hierarchicaly a child of another
collection and not of an item. This applies for:
To facilitate the navigation in to this "poored
typed" object model there are two helper CatalogCollections
available: CatalogCollections let you navigate,
enumerate,remove and, in some cases, add objects in the catalog. To
perform a number of tasks that need more info to be accomplished you need
to use some Utility objects. - PackageUtil (GetUtilInterface on the
Packages collection) |
| 12) I want to use MTS only for its component deployment facilities. Is there any issue I should be warned about ? | |
| Let's suppose you have a bunch of COM DLLs that have
not been written with MTS in mind. Now you want to deploy these dlls into
an MTS server package just to easy the pain of - turning them into EXE COM objects - use Dcomfig.exe to have them accessible via DCOM remotely. This means that your COM objects will be registered as "Does not Support Transaction" and they will never call any MTS API method. Probably this is not a good choice from an architectural point of view. If your interfaces have not been designed with distribution in mind, they will perform very poorly over the network, but this is not the point i want to stress out here, cause i want to answer to the following question here: will my COM objects will work "as before" after i deployed them under MTS ? The answer is generally yes, they will work as before but with much less performance. Each call to Createobject starts a new activity when the created object is registered under MTS. A new activity means the creation of a new STA where the created object is placed. I suppose there are a lot of cross activations & calls among these dlls you have deployed under MTS. It turns out that what was running under the same thread/STA before the deployment, now spans plenty of activities (threads); so that the code flow is slowed down by lot of cross apartment comunication. Unfortunately there is one situation where things gets even worst: when you use disconnected recordsets (that marshal by value) in your dlls. When disconnected recordsets are passed among components they change their behaviour depending on the fact that they are marshaled or not (check out the visible number of records in a filtered recordset before and after being marshaled, as you have suspected, the filter property is lost after the marshaling, all records are visible again). In such situation, then, you Application can behave differently, not only performance more poorly. Conclusion: quick and dirty deployment under MTS is most of the time not a good choice. Changing CreateObject with GetObjectContext.CreateInstance at the proper places is a must to have things working in an acceptable way. |
| 13) Why is it a bad idea to use "Global" variables, that is Public (and private) variables at module level ? | |
| All variables at module level are thread specific.
Each new thread starts get a new fresh & uninitialized copy of such
variables. I've verified that all the activities that are born from the
same object context always run in the same apartment (I checked the thread
id) as the object context had thread affinity. What i mean is this: suppose you have an mts object that has a method that returns the thread id and then calls set complete. Each call to the method starts a new activity but the thread id returned is always the same. This could sound tempting to store some state across activity boundaries but since the number of thread available for a package is limited (100 by default) you would end up having, under heavy stress, different activities sharing the same apartment and then the same public .bas variables. with unpredictable results. |
| 14) Problems exporting Packages with classes that implements interfaces defined in "external" Type Libraries | |
| MTS Packages are exported for two reasons: 1) Clone the package on another server 2) Produce a setup program that you run on the client computers to configure in a way they can access the server components via DCOM This procedure is generally a "one click"
one, but there are some problems when your classes implements interfaces
that are defined in external Type Libraries. When you export the package
these Type Libraries are not included in the export directory. This makes
unusable the export files for both uses i described above. |
|
15) A few words from Michael D. Long about connection pooling |
|
|
With MDAC 2.1 SP2 and prior, I have observed that
when relying on
the OLE DB Provider for ODBC that connection pooling
does not appear
to work with SQL Server when the OLEDB_Services entry
for MSDASQL
is set to the default. My conclusion is based on two
observations - first,
the timing of the .Open method of the connection
object and second, the
data presented in Magagement \ Current Activity \
Process Info of SS7
Enterprise Manager. Simply changing the OLEDB_Services entry for MSADSQL to 0 resolves the issue. As a side benefit you can see activity in the ODBC Connection counters under the NT Performance Monitor.
There is a second issue that renders the connection
pool ineffective, which is load related. In a heavily utilized environment
new connections are handed
out even though there are free connections available.
---------- Follow up thank michael, a couple of additionqal questions : is there any problem related to mdac 2.1 sp2 using nativeoledb provider for sql server ? about the 2nd problem u talk about, does this applies to both sqloledb & msdasql providers ? I have not performed very much testing with OLE DB for SQL Server with MDAC 2.1 SP2 and prior, as the performance was not up to the level of the equivalent ODBC driver. The second issue applies to both OLE DB and MSDASQL providers. When running against Oracle the same type of session loss was observed, but at a much higher frequency. This appears to be better in MDAC 2.5, though all Oracle sessions will eventually bleed out (no matter how high the value is set) when under heavy load. I have submitted a repro that demonstrates similar behavior with SQL Server 7 SP2 to the MDAC Beta group, and with some luck the issue will be resolved either in 2.6 or the following release. |
|
Received from Joseph
Geretz
|
| 17) Where is MTS in W2K ? | |
| MTS is a set of services (object brokering and
Transaction coordination) built on top of COM. It is available on WN4 if
you install the Option Pack. These services have been brought inside the new release of the COM Services, that are named COM+. COM+ is available in the W2K platform, you don't need any additional software. |
| 18) Everything works fine on both client machines when somebody is logged in on the server machine. But when nobody is logged in, we get an error. | |
| If your package is set to run under the identity of the selected "InteractiveUser" it means that it has to run under the identity of the user that is currently logged in. If no one is logged in, there is no "Interactive User", so the call will fail. "Interactive user" is usefull only for debugging on a developer machine. |
| 19) Why do I get an Access Denied Error when I try to raise an event from my MTS component to my client ? | |
| The client executable doesn't have the proper DCOM
security settings to let the server call it back. In order to have it
working you have two solutions:
1) Open wide DCOM security settings on the client side 2) Add the proper DCOM security settings for the
client executable in the registry (you cannot call CoInitializeSecurity in
a VB client). Example: REGEDIT4] [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\yourclient.exe]
@="YourClient" See http://msdn.microsoft.com/library/psdk/com/reg_33y1.htm for further info. |
| 20) Connection Pooling | |
| Connection pooling is an essential feature for
distributed scalable applications. Note that database connection pooling
is provided by the ODBC or OLEDB drivers not by MTS/COM+, still it's in
MTS or COM+ that connection pooling shows its greatest benefits.
Connection pooling reduces overall overhead that appears due to rather often open/close
operations on database connections. But, to ensure that an application
(read - component) is "pooling compliant", design and
implementation of the application should consider following restrictions: 1) Connections should be opened using the same identity (UserName/Password). A connection opened with one identity cannot be reused for a request with another identity. Opening connections with different identities increases pool size and makes its usage worthless. 2) Connection can not be reused across processes. Hence each MTS package holds it own pool of connections. 3) Underlying database should be "MTS compatible". 4) ODBC driver(s) or OLE DB Provider(s) being used should support MTS. MDAC versions related issues: 1) MDAC 1.5. Provides only (?) ODBC pooling 2) MDAC 2.0. OLE DB pooling is disabled by default for OLE DB Provider for ODBC. ODBC pooling is being used 3) MDAC 2.1. OLE DB pooling is being used for all providers by default. OLE DB connection pooling timeout has a fixed value - 60 seconds. For ODBC sources you can get back to ODBC pooling by deleting OLEDB_SERVICES registry entry. To do it - run REGEDIT utility, choose Edit/Find, type "Microsoft OLE DB Provider for ODBC Drivers" (omit quotes). Find will show entries under the provider's CLSID. Click on the CLSID and delete OLEDB_SERVICES value (not just set to zero). 4) MDAC 2.5. In beta stage, not released yet. Overall performance will be increased (at least Microsoft says so). OLE DB connection pooling timeout will be changeable. |
| 21) MTS compatibility of databases | |
| The phrase "a database is MTS compatible"
generally means that the database supports distributed transactions (XA or
OLE DB protocol) and there is an ODBC driver or/and OLE DB provider that
could be used by a component in MTS environment. The main requirement for
an MTS compliant ODBC driver is to be thread-safe. If a database doesn't support MTS, one won't get advantages of MTS transaction management architecture. Though it's still possible to perform any operations on the database and use "traditional" BeginTrans/Commit/Rollback. Current list of databases that support MTS: Microsoft SQL Server 6.5 IBM DB2 Informix Oracle 7.3.3 and later releases Sybase Adaptive Server Enterprise Very often developers mistakenly are trying to use MS Access as an underlying database. MS Access does not support MTS. |
| 22) Debugging of components under the VB IDE | |
|
It was and it is easy to debug MTS components written on Visual C++
version 5 and higher. Debugging components written on Visual Basic 5 is
possible under VC IDE. Since version 6 Visual Basic allows to do
debugging under its own IDE. Things that a developer should keep in mind
while preparing to debug session: |
| 23) Load balancing in MTS | |
|
MTS2.0 does not provide load balancing (LB). Microsoft
suggests us to implement custom LB. For example, by dividing users into
the groups and referring those groups to different MTS nodes. Or, in
case of usage of IIS, implement "smart redirecting" among
different IISs (like it's done on hotmail.com). COM+ has built-in LB. It is realized as a component wich receives client requests and redirects them to a less loaded server. This component may be replaced by a custom component which provides more complicated custom rules of LB. |
![]()
Comments, suggestions .. whatever .. drop me a line if you wish
| You are visitor number | Since 2001/01/01 |
|
Contact us at sabbadin@sabbasoft.com |