advertisement
Login | Register   
  Include Code  Search Tips
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Download the code for this article
Partners & Affiliates
advertisement
advertisement
advertisement
advertisement
Average Rating: 1.3/5 | Rate this item | 6 users have rated this item.
 

Implementing Object Pooling with .NET Remoting - Part II

In the first part of this article series, we developed a remoting based object broker that managed pools of objects. The max and min pool size of each poolable class was defined by placing on it a custom attribute. In this second part we are going to enhance the solution to provide transparent activation of pooled objects. 


advertisement
he Pool Manager described in the first part of this article series had a couple of problems. The process of acquiring a pooled object was not transparent to the client, which couldn’t simply new the object (provided that the required type had been registered in the remote configuration file). The client had to contact the broker explicitly to acquire a reference to an object in the pool.


The second problem lies in the fact that objects returned by the broker are CAO types. This is far from optimal. The client must explicitly release the object when done with the object calling Dispose. If it fails to do so, the object is returned to the pool only when the object Lease time is expired.

Properly designed pooled objects don’t keep any client specific state across calls, thus for this reason it would be highly desirable to pass back to clients SAO SingleCall object types. This optimize the pool management, not letting the client hold a reference to a pooled object longer than necessary.

Activation Transparency and SingleCall Behavior via a Custom Channel Sink
Remoting behavior can be customized in two ways: defining a custom proxy or inserting a custom sink in the default sink chain. The custom proxy approach is not so compelling, since you cannot insert a custom proxy transparently (the client must explicitly create it) and anything you can do with a custom proxy can actually be done using a custom sink.

We will then opt for a custom sink to enable transparent activation and SingleCall behavior for our pooled objects. The solution we will come out with won’t work for Client Activated objects, but as I said, CAO are not a desirable option when working with pooled objects.

Anyway, note you still can get CAO behaving objects when accessing the Pool Manager explicitly.

Custom Sinks and Custom Sink Providers
Setting up a custom sink requires the development of two classes: the custom sink class itself and a custom sink provider class. The latter has to be registered into the remoting infrastructure. The sole role of the sink provider is to return to the remoting infrastructure an instance of its associated custom sink when required.

Here is a remote configuration file where a custom sink provider is registered before the formatter

<configuration>
 <system.runtime.remoting>
  <application>
   <channels>
    <channel ref="tcp" port="1234">
     <serverProviders>
      <provider type="Sink.MySinkProviderBeforeFormatter, Sink" />
      <formatter ref="binary" />
     </serverProviders>
    </channel>
   </channels>
  </application>
 </system.runtime.remoting>
</configuration>

Client sinks providers must implement the IClientChannelSinkProvider and server sinks must implement the IServerChannelSinkProvider.

While setting up the channel, remoting reads the channel configuration and creates a linked chain of sinks accordingly.

All registered sinks will receive the message payload and given a chance to modify it, log it, or whatever they want to, before forwarding it to the next sink.

Note that sinks are somewhat logically equivalent to HTTP modules. There is still a great difference. HTTP modules are contacted via a callback mechanism (they are not in the HTTP Request processing call stack). On the contrary, custom sinks are right in the call stack chain and are given the responsibility to forward the message when they are done.

Setting up the sink chain is a two step process. In the first step, remoting set up a linked list of sink providers. It calls the Next method of all registered providers passing an instance of the next sink provider in the chain. The provider is required to memorize this object in an instance level variable since it is required for the following step.

In the second step remoting calls the CreateSink method of the first sink provider in the chain. In this method the provider must return an instance of the custom sink it acts as provider. Since the sinks must be chained as well, the custom sink must be passed an instance of its next sink as parameter constructor. To do that the provider must call the CreateSink method of the next provider whose instance was acquired in the previous step. Consequently, each provider calls the CreateSink methods of its next provider till all the provider chain is walked up.

Here is a code snippet of a standard implementation of the CreateSink method.


Private Function CreateSink(ByVal channel As IChannelReceiver) _
As IServerChannelSink
Implements IServerChannelSinkProvider.CreateSink
Dim nextSink As IServerChannelSink = Nothing
i_next is the next provider in the provider chain
If Not i_next Is Nothing Then
nextSink = i_next.CreateSink(channel)
End If
Return New MySinkBeforeFormatter(nextSink)
End Function

Implementing a custom sink is slightly more complicated. There are actually three different interfaces to implement, depending on where the custom sink has to be placed. On the client side the sink must implement the IMessageSink interface if it has to be placed before the formatter and the IClientChannelSink if it has to be place after the formatter. A server side custom sink must implement the IServerChannelSink, no matter if it is placed before or after the formatter.

In all the aforementioned cases the skeleton of a sink provider and of a custom sink is boiler plate code. Once you have the proper class template for each kind of provider and sink you can copy and past the template and go straight to the method where you can intercept the message and do the real work.

In this article we will concentrate on a custom sink placed before the formatter. This is where we will play with the message to make the process of getting a reference to a pooled object transparent to the client.

You may find samples of any kind of sink and sink provider in the code that comes with this article.

  Next Page: Modifying Messages and Headers


Page 1: IntroductionPage 2: Modifying Messages and Headers
Please rate this item (5=best)
 1  2  3  4  5
advertisement