I've updated the remote logging framework with a bugfix; if you're using it (or curious to see how it works/what it can be used for) feel free to download it and have a look.
I've also started hacking away at the PostXING v2.0 sources in my spare time, which unfortunately is very sparse at the moment. If anyone has tricks on how to get through HEDVA (differential/integral mathematics, A.K.A infinitesemal calculus outside the Technion...) successfully without commiting every waking moment, do share.
So I got to see a bunch more movies lately (right now it's the only
thing keeping me sane in the face of the dreaded Technion HEDVA/1t
course). Here's a brief review on each:
- Ridley Scott's Kingdom of Heaven is a rather belated attempt to capitalize on the "psuedo-historical epos" trend of the last few years which was ironically started by Scott's own Gladiator (in case you were wondering, Braveheart
was not a little too early for its own good, having come out in 1995).
Synopsis: Balian, the son of Lord Godfrey, is knighted, takes up the
task of defending Jerusalem from the forces of Saladin and ends up
saving the day etc. Throw in a bunch of clichés about love, what it
takes to be a humane leader back in the crusades and some generic
morality crap and you've got a seriously badly written film. In its
defense it does feature some superb photography, OK action and a huge
cast consisting of some favourite actors of mine: Orlando Bloom (who
finally appars capable of acting), Alexander Siddig (of DS9
fame), Brendan Gleeson, Jeremy Irons, Edward Norton (who does not
appear visually), David Thewlis and finally Liam Neeson, who isn't
actually on my list but does deserve a mention. Too bad the movie just
plain sucked.
- Nicolas Cage's latest movie Lord of War
was an absolute blast. It is an amasingly cynical, mostly funny and
quite surprising satire of what makes third world countries wage war,
as well as what makes greedy people tick. It doesn't make any excuses
for the clichés it employs, and in my opinion it hits the spot
precisely: some messages simply do not come across until you bang them
into someone's head with an allegorical hammer. My only issue with it
is that it fails to keep the satire simply as that, and culminates in a
verbal political message which is an exercise in redundancy.
- Instead of making a long point I'll skip to the very end with a summary of The Exorcism of Emily Rose:
good acting (particularly by Laura Linney and Tom Wilkinson),
reasonable dialog, crappy predictable storyline and no boobs at all. In
short, a movie not worth your time; if you're interested in the
legal/judicial aspects do yourself a favour and go watch Law &
Order, it's what they do.
- I've heard a lot of conflicting opinions on I, Robot. Maddox went as far as to say:
Here's how I would have changed this film: start out with a
shot of Will Smith in a grocery store buying a 6 pack of Dos Equis
beer, except instead of paying, the cashier is a Dos Equis marketing
rep who hands Smith a thick wad of bills. Next shot: Smith finishes the
last of the beer, walks over to Isaac Asimov's grave and lets loose.
Why not? Same message, none of the bullshit.
I won't deny that this movie has some serious issues (particularly with product placements; here it was even worse than The Island, if that's even possible) but I would take an opposite view to Maddox's: I enjoyed the movie immensely. Having read the book
quite recently I find that the only place where the movie deviated
completely from what is detailed in the stories (because I, Robot is
not a single coherent storyline, rather comprised of several short
tales) is in the depiction of Susan Calvin's character, who is actually
very true-to-form in the beginning of the movie. Regardless, the movie
features rather imaginative photography, some great action sequences, a
plot which ultimately doesn't suck and some of the funniest dialogue
I've heard in years (the only competition comes from the underrated Constantine). Bottom line? Recommended.
Chris Frazier has been kind
enough to let me in on the PostXING v2.0
alpha program. I tried PostXING v1.0 ages ago and it struck me as an open-source
program with lots of potential but (like many other open source projects) not
nearly ready for prime-time. I very much hope to be able to help Chris make v2.0
a practical contender to my regular blogging tool, w.bloggar. It certinaly seems on the right
track, and as you can see is already reasonably usable.
If anyone has anything they wished for in a blogging tool, let Chris know -
he may yet make it worth your while 
Despite a lot of work by various people (including, but not limited to, Jeff Atwood at CodingHorror.com and Colin Coller), creating syntax-highlit HTML from code with Visual Studio is still extremely annoying; you don't get the benefit of background colours (as explained by Jeff), you face bizarre issues (try Jeff's plugin on configuration files for instance) and finally, ReSharper-enhanced syntax highlighting can not be supported by either of these solutions.
I've submitted a feature request to the JetBrains bugtracker for ReSharper; since I regard ReSharper as an absolute must-have and it already does source parsing and highlighting, features powerful formatting rules and templates etc., I figure it's the definitive platform for such a feature. Read the FR and comment here; I reckon if it gets enough attention they probably will implement it in one of the next builds.
As a side-note, I'm still keeping the ReSharper 2.0 EAP post up-to-date on the latest builds. Make sure to have a look every now and then.
Introduction
Update (27/11/2005, 15:40): After putting the remote logging framework to use on an actual commercial project I've found that the hack I used for mapping a method to its concrete (nonvirtual) implementation wasn't working properly for explicit interface implementations. One horrible hack (which fortunately never saw the light of day) and a little digging later I've come across a useful trick on Andy Smith's weblog and added some special code to handle interfaces. The new version is available from the download section.
Introduction
As part of the ongoing project I'm working on I was asked to implement a sort of macro recording feature into the product engine. The "keyboard" (as it were) is implemented as an abstract, remotable CAO interface which is registered in the engine via a singleton factory. I figured that the easiest way to record a macro would be to save a list of all remoting calls from when recording begins to when recording ends; the simplest way would be to add code to the beginning of every remote method implementation to save the call and its parameters. Obviously, that is an ugly solution.
About a year ago when I was working on a different project (a web-service back end for what would hopefully become a very popular statistics-gathering service) I faced a similar issue: the QA guys asked for a log of every single Web Service method call for performance and usability analysis. At the time I implemented this as a SOAP extension which infers some details using Reflection and saves everything to a specific log (via log4net). A couple of hours of research, 30 minutes of coding and I was done - the code even worked on the first try! - which only served to boost my confidence in my choice of frameworks for this project. My point is, I figured I would do something along the same lines for this project, and went on to do some research.
If you're just interested in the class library and instuctions skip to instructions or download.
Hurdles ahoy
I eventually settled on writing a Remoting server channel sink to do the work for me. I'll save you the nitty-gritty details; suffice to say that the entire process of Remoting sink providers is not trivial and not in any way sufficiently documented. There are some examples around the internet and even a pretty impressive article by Motti Shaked which proved useful, but didn't solve my problem. I eventually got to the point where I could, for a given type, say which methods on that type were invoked via Remoting and with which parameters, but I couldn't tell the object instance for which they were invoked no matter what. A sink may access the IMethodMessage interface which gives you a wealth of information, including arguments, the MethodBase for the method call etc., but the only indication of which object is actually being called is its URI (the interface's Uri property). Unfortunately I couldn't find any way of mapping a URI back to its ObjRef (something like the opposite of RemotingServices.GetObjectUri), only its type.
After a long period of frustrating research and diving into CLR implementation with the use of Reflector I came to the conclusion that the only way to convert the URI back to an object (outside of messing with framework internals via Reflection) would be to implement ITrackingHandler and maintain a URI-object cache. Another annoying hurdle was that the framework internally adds an application ID to its URIs and forwards the calls accordingly; for example, connecting to a server at URI tcp://localhost:1234/test would in fact connect to the object at local URI /3f4fd025_377a_4fda_8d50_2b76f0494d52/test. It took a bit of further digging to find out that this application ID is available in the property RemotingConfiguration.ApplicationID (obvious in retrospect, but there was nothing to point me in the right direction), which allowed me to normalize the incoming URIs and match them to the cache.
Finally, inferring virtual method implementations and URI server types are relatively costly operations, so I've added a caching mechanism for both in order to cut down on the performance loss. I haven't benchmarked this solution, but I believe the performance hit after the first method call should be negligible compared to "regular" remoting calls.
How to use this thing
Obviously the first thing to do would be to download the source and add a reference to the class library. I've built and tested it with Visual Studio 2003; I'm pretty confident that it would work well with 2005 RTM, and probably not work with 1.0 or Mono (although I would be delighted to find out otherwise, if anyone bothers to check...)
Next you must configure Remoting to actually make use of the new provider. You would probably want the logging sink provider as the last provider in the server chain (meaning just before actual invocation takes place); if you're configuring Remoting via a configuration file, this is very easy:
<serverProviders>
<!-- Note that ordering is absolutely crucial here - our provider must come AFTER -->
<!-- the formatter -->
<formatter ref="binary" typeFilterLevel="Full" />
<provider type="TomerGabel.RemoteLogging.RemoteLoggingSinkProvider, RemoteLogging" />
</serverProviders>
Doing it programmatically is slightly less trivial but certainly possible:
Hashtable prop = new Hashtable();
prop[ "port" ] = 1234;
BinaryServerFormatterSinkProvider prov = new BinaryServerFormatterSinkProvider();
prov.TypeFilterLevel = TypeFilterLevel.Full;
prov.Next = new TomerGabel.RemoteLogging.RemoteLoggingSinkProvider();
ChannelServices.RegisterChannel( new TcpChannel( prop, null, prov ) );
Now it is time to decide which types and/or methods get logged. Do this by attaching a [LogRemoteCall] attribute; you can use this attribute with classes (which would log all method calls
made to instances of that class) or with specific methods:
[LogRemoteCall]
public class ImpCAOObject : MarshalByRefObject, ICAOObject
{
public void DoSomething() ...
}
class ImpExample : MarshalByRefObject, IExample
{
// ...
[LogRemoteCall]
public ICAOObject SendMessage( string message ) ...
}
Next you should implement IRemoteLoggingConsumer:
class Driver : IRemoteLoggingConsumer
{
// ...
public void HandleRemoteCall( object remote, string method, object[] args )
{
Console.WriteLine( "Logging framework intercepted a remote call on object {0}, method {1}",
remote.GetHashCode(), method );
int i = 0;
foreach ( object arg in args )
Console.WriteLine( "\t{0}: {1}", i++, arg == null ? "null" : arg );
}
}
Finally you must register with the remote call logging framework via RemoteLoggingServices.Register. You can register as many consumers as you like; moreover, each consumer can be set to receive notification for all remotable types (for generic logging) or a particular type (for example, macro recording as outlined above).
// Register ourselves as a consumer
RemoteLoggingServices.Register( new Driver() );
Download
Source code and examples can be downloaded here. Have fun and do let me know what you think!
|