A site devoted to discussing techniques that promote quality and ethical practices in software development.

Showing posts sorted by relevance for query aggregation. Sort by date Show all posts
Showing posts sorted by relevance for query aggregation. Sort by date Show all posts

Thursday, January 7, 2010

Cavaets in using Ellipse Business Connector

Ellipse Business Connector (MIMSX) is an integration component to allow developers to integrate with their ERP system.

This is a COM STA component originally designed to work in say Excel. However, this has found usage in many different type of applications, such as Web Servers or multi-threaded daemon process. This blog post is not to show how to use this component properly but to describe a number of the caveats that can cause problems - even when using in Excel.

The need for these caveats is because MIMSX, together with some of its internal components, can cause problems that generally are related to the absence of concurrency control. One may ask how can a STA component can have concurrency issues? Doesn't COM provides synchronization protection when an STA component is being access from multiple apartments?

Read on because MIMSX is not your COM spec conforming STA component.

Caveats on using MIMSX

MIMSX Reentrancy

The main problem of using MIMSX in a GUI application, including Excel, is that MIMSX is re-entrant; this problem is best illustrated using MSQDSK in Ellipse 6, which uses MIMSX. While many of the methods of the MIMSX interfaces do not return until results are ready as all normal COM methods should, they internally contain a message pump that is required by the legacy home-grown IPC mechanism based on window messaging technique. This message pump is the root cause of making MIMSX, inproc-COM component, reentrant. To be fair, it is not entirely MIMSX's problem. Whenever you have a modal method or code modality, you have a reentrant situation.

If your program, even in Excel, sends a command to the backend and expecting for some result, you should implement appropriate reentrancy control techniques. Failure to do so can cause unpredictable problem.

Using MIMSX in a multi-threaded program

More and more people are trying to use MIMSX in say ASP/ASP.Net, Web Service or Service Daemon programs to provide server-side integration solution. Or to move their scripts from desktop deployment to centralize server operation. All these environments operate in MTA and expect all the required COM components to support MTA.

However, MIMSX is an STA component. When MIMSX object is created in this situation, known as mixed-model, MIMSX objects have to be created in its STA while the clients of these objects are living in the MTA. The end effect is that the calls from these clients threads are serialized by COM to call these objects, nullifying the benefit of multi-threading.

When operating in mixed-model environment, COM does not raise any warning or error, all one would notice is the absence of performance when load is applied despite more threads are being used.

To alleviate this is quite straight forward without requiring re-architecting the solution. All one has to do is to apply COM aggregation technique to aggregate MIMSX in a specially crafted COM executable server. Mincom has made one called EllipseCOM but may not be generally available. If that is the case, just follow the instructions to build your own. COM is an open industry standard and there is nothing much a vendor can do to forbid you applying proper COM idiom.

This is actually a good technique to build your own ERP SOA server so that your application is not directly bound to Mincom's idiosyncrasies and products.

This technique is not optimal and certainly not perfect. It would be nicer if MIMSX object model was published by TpAgent, which acts as a COM local server. But this is not the case and using aggregation is the next best option.

While it alleviates serializing all calls from all these threads to MIMSX objects, this option has the following issues:
1) it incurs heavy tolls on marshalling and context swithing as MIMSX's object model is designed to be transverse in-process and hence it employs very chatty interfaces. But now, the in-process calls are discarded replaced by inter-process calls.

If code modification is an option, try to reduce the usage of dotted-expression to transverse the object model. Don't forget memory are allocated on the aggregation server and then marshalled across to the client process and then made available to the client. They can exert heavy toll.

But in comparison, the usage of aggregation server prevents one's call from blocking other threads from doing their work and to call the Ellipse back end and this on the balance has been measured to increase the throughput.

2) If the clients are .Net environment, you are now dealing with two memory management schemes - the COM one is deterministic based on reference count while the CLR one is base on garbage collection, which is non-deterministic. As a results, usage of the dotted-expression can cause large number of temporary CLR objects to be created each of them manages an associated COM object. These CLR objects will not release its associated COM objects until they are garbage collected. This can cause system memory demand to be greater than an operating environment based solely on reference counting.

The biggest attraction of using aggregation server is that you only have to change one line of code; just change from the ProgID or CLSID of MIMSX to that of the aggregation server. This assumes that your application is coded using MIMSX interfaces, as a well-written COM application should, and not using implementation language wrapper classes. If you are prepared to switch the entire server environment over to using the aggregation server, you do not even have to modify your code by leveraging the COM Emulation technique. 

While this solution uses multiple STA servers to remove the mixed-model problem, for MIMSX it is not the same as implementing a multiple STA server solution because MIMSX uses components that are downright dangerous in this kind of environment.They are covered by other caveats.

Caveat in using MSYMCACH

It is an internal optional COM component used by MIMSX. Its sole purpose is to 'cache' the host commands and their results on the client machine to avoid the expensive trips to the back end. The principle is sound but in practice not well executed.

The cached data are saved, rather in a primitive manner with little performance concerns, in files on the client's machine. They are not isolated by processes. That is if ApplicationA and ApplicationB are to cache data of a same identifier, they are then competing to access the same pair of files.

In well written multi-threaded program, such occurrence will be controlled by suitable synchronization mechanism to ensure orderly access. But not in MSYMCACH, which seems to be a leftover from Windows 3.x's era which was a non-preemptive operating system. In those olden days, only one application can run and no one, including Windows 3.x, can steal its sole usage of the CPU. Therefore why need to implement any synchronization mechanism to control concurrent access? However, the world has changed and we are now using preemptive OS running on Hyper-Threading or multi-core machines. Collision is just matter of when and not even if.

The usage of a set of very old, first generation, C IO functions give credence to this speculation despite newer ones which allow programmers to control file access mode.

So even if you have two Excel scripts running it can cause problem. Problem can range from one application over writing changes made by another application; or it can be access problem when two are trying to either write to the same pair of files.

Because of the poor implementation and doubtful benefit it brings, it is recommended a user to unregister this component to avoid unpredictable problem caused by the absence of any concurrency control.

EllipseCOM or aggregation server design is of no help in this situation. Files are essentially a singleton resource and should be treated as such.

Caveat for CBR32.DLL

Once again, this is internally used by MIMSX and is a mandatory component, unlike MSYMCACH. In brief it is basically Ellipse's marshaller and MIMSX offers a COM conforming object model representation of the Ellipse model.

Once again, it appears this is another leftover from days gone by coupled with gratuitous dependency on global variables (nasty) even when it is using dynamic heap. Naturally it lacks any basic form of concurrency control.

This component assumes that it is always living in a single thread process and possibly only one client using it. Single Thread does not equate to single client using a component; you could have several clients on a Window form using CBR32.

Because it is devoid of any concurrency control, one should never use it in a multi-threaded program or program with multiple STA to host MIMSX. Such environment can result in total CBR32 data corruption. Don't forget, CBR32 is not designed to be used only by MIMSX, it is used by other applications as it offers a C-Style exported functions.

If you need to have multiple STA to host MIMSX, it is recommended that each STA uses either EllipseCOM or MIMSX aggregation server.

The EllipseCOM or MIMSX aggregation server ensures that only one thread per process and that is the kind of the environment expected by CBR32. Failure to observe this will result in data corruption.

Wednesday, April 18, 2007

A simple way to build multiple STA COM server

In .Net, particularly when building Web Service provider, the prefer apartment type is MTA. Under this condition if you have to use functionality provided by a legacy COM in-proc server that has ThreadingModel=Apartment, the performance of the solution involving mixed model is severely impaired.

The problem is fully documented in MSDN under the Mixed Model Development section and interested reader should consult that article.

The way to overcome this is to construct a multi-STA server with each STA hosting just one STA com object. In this way each client living in a MTA can call the STA com object independently from other invocation.

This kind of construction requires some administrative work and hence not as simple as one may think.

However, for most COM in-proc server the way around this problem is a lot easier and the technique is to employ COM aggregation to host the STA COM component that you need to use by MTA client.

A step by steps guide to aggregate another COM component using ATL can be found here.

The construction recipe to use COM aggregation to build a multiple STA server is given below:
1) Create a standard COM local (executable) server that contains a COM component with an interface of your choosing. This interface needs not contain any useful method and is not used at all. If you are developing this with Delphi, beware of the problem.

I recommend the use of ATL as it is a nice and skinny framework.

2) Then use the COM development framework to aggregate the legacy STA COM in-proc server. It is often extremely difficult to tell if a COM component supports aggregation or not. Just build it and test it is a good way to determine that. Aggregation is a construction technique and hence does not contain any detectable COM registration information. Incidentally all managed COM component automatically support COM-style aggregation and this can be used to construct .Net COM local server.

3) Make sure when the COM local server contains only STA by calling CoInitialize() or CoInitializeEx( 0, COINIT_APARTMENTTHREADED ).

4) When COM server registers class object, make sure it uses the REGCLS_SINGLEUSE flag forcing this server support only one COM object, thus one STA in-proc server by virtue of aggregation.

This technique has one great advantage and that is you can leave the source code unchanged except in the server instantiation code. Instead of creating the in-proc STA server, you are creating the com object belonging to the aggregater server.

Because you are interested only in the interface belonging to the aggregated component, you can immediately cast the result into the target interface.

This technique is not without cost and they are:
* It trades off serialising calls to methods in STA components from MTA with context switching and data marshalling costs. Typically the STA component exposes a fine-grained object model and any navigation will incur these costs. Hence one should minimise the use of dotted expression.

* It uses more processes than otherwise required.

* Involvement of COM local server could result in a situation where the server does not terminate.

* Memory consumption can remain relatively high if the client is a .Net solution. This is due to the involvement of two object life-cycle management schemes - the .Net RCW relying on GC to reclaim resources and the COM which relies on reference counting. In this situation, particularly if the dotted expression is used to navigate down the object model, this kind of expression generates a lot internal RCW's and each level of the dotted expression corresponds to a COM object.

These internal RCW's will only be disposed when the GC collects them. If they are not disposed, the corresponding COM object is not removed. This situation increases memory demand above that if both client and server are unmanaged code. The way around this is to avoid using dotted expression.

Thursday, January 21, 2010

Cooking your own EllipseCOM

During a conversation with a reader on my blog post, it has come to my attention that I have missed a key piece of information with respect to MIMSX.

In order for one to build one's own aggregation server, apart from following the recipe you also need to use a version of MIMSX that is at least of version 2.2.4.2 or later. Earlier version contains an internal setting bug making it an invalid candidate to aggregate.

Unfortunately, one cannot tell from a COM component's registered attributes or type library if it is supporting aggregation. You need to build the aggregation server to see if you can successfully create the aggregated component and wired up the query interface mechanism.

Also during instantiation, you must create an instance of the aggregation server and then query the interface of IMimsxServer; you do not create an instance of MIMSX.

Sunday, September 14, 2008

Using Com Aggregation to help Web Services

Some times ago, I was consulting for a project for a friend that tried to use the SOA approach to expose functionality to the client using Web Services. The functionality is currently implemented as a bunch of .Net components that uses a COM connector component, provided by the vendor of their remote system; pretty much like Microsoft Dynamic AX connector and SAP connector.

Instead of having these components deployed to the desktop, they wanted to place them on a IIS and exposing them as ASMX web services. Things worked fine but performance sucked.

They approach the vendor for help and was told to redevelop the entire stuff using the vendor preferred Web Services. Sounds familiar? That meant tossing out years of work.

So I had a look it and recognise that it was the classic problem of Apartment mismatch with the Service component living in MTA while that STA connector is hosted in a STA resulting in serializing all calls to the STA. I therefore recommended them to follow my recipe for constructing multiple-STA servers.

In a haste, I suggested them to incorporate the interop assembly for the aggregator as well as that of the aggregatee and to alter their construction logic, assuming their connector is called SXServer and the aggregator is called AggregateSXServer, from

IServerObject svr = new SXServerLib.SXServerClass();
to
   IServerObject svr =
(IServerObject) AggregateSXServerLib.AggregateSXServerClass();

This worked like a charm alleviating the performance bottleneck except that I now believe that may be I do not need so much changes. There are a couple of techniques I can investigate.

Using Com Emulation
There is a technique that may offer a possibility of enlisting the aggregator without needing to touch the client code. This is known as Com Emulation technique. This technique allows silent redirection of CLSID_ORIGINAL to CLSID_NEWONE by means of a special registry key in the COM registry called TreatAs.

So it sounds like the right stuff to allow me to redirect coclass creation for CLSID_SXServer to CLSID_AggregateSXServer without requiring the rebuild of the web services components. However, it appears that this technique does not support aggregatable component. Even when creating object for IUnknown, the use of TreatAs returns E_NOINTERFACE. Weird.

Anyway that can be left for another day's challenge.

What is the minimal change required in the .Net solution?
So the next investigation is what is the minimal amount of changes require to the .Net solution. In the past, I recommended the inclusion of the interop assemblies for the aggregator as well as the aggregatee. Do I need all that? I know at a minimum I need the interop assembly of the aggregatee because I need to use those interfaces. Do I need that of the aggregator?

It turns out not if we are happy to replace the use of new operator and replacing that with the Activator call. So instead of
   IServerObject svr = new SXServerLib.SXServerClass();
We can change it to:
  IServerObject svr =
(IServerObject)Activator.CreateInstance
( Type.GetTypeFromCLSID
( new Guid( "6E537ABD-96B0-4BBC-9F1C-00924FBF1FB1" ) ) );
This is change is more than cosmetic as it can:
1) let you switch dynamically by providing that Guid as a string from anywhere: from config file or other means. Kind of home-made COM emulation.
2) It also means that you do not have to include and ship the interop assembly of the aggregator. A big plus!

Hence this is purely code changes and no need to add anything to the project references. Why I didn't think of this in the first place?

Of course when we approached the vendor with our solution, they were less than please because this had ruined their chance of selling their Web Service to my friend; no more upgrade fees, etc.

This kind of attitude is a clear sign of customer-neglect and exploitation. Instead of helping their users to make the best of their product, they were out there to take advantage of their customers ignorance of technology. Shame.

My help, utilising the COM technology and requiring no proprietary materials have, now stopped the exploitation dead in its track allowing my friend to continue with their SOA initiative without incurring great loss of discarding current implementation. This is a good design and provides an invaluable service. Any fool can recommend a rebuild approach as that does not need in-depth understanding of technology and design; recommending rebuild is a no brainer.

Incidentally, there is nothing in SOA definitions that say COM cannot be used to implement a SOA provider. After all the whole premise of SOA is to hide the implementation infrastructure. Requiring someone to up root one's design to chain in a vendor's SOA smacks a total misunderstanding of the SOA design philosophy and explotation. Don't you think so?

Blog Archive