Want to show your appreciation?
Please a cup of tea.

Saturday, October 09, 2010

IIS Web Site Redirect with Announcement Page

It is common that when you have moved your site from one host to another and you want to redirect all the traffic going to old host to be redirect to the new host before the old host is completely unavailable.

This can be easily done with any major web server. For IIS, Microsoft has a page about this and all you need to do is follow the instruction in the section of “to redirect requests to another Web site or directory”.

Redirect requests to another Web site or directory

Sweet, now you type in a URL going to your old site and you automatically landed to the correct page on your new site. But wait, what’s going to happen if one day you have to shutdown the old site completely. Your user’s bookmark and external link from other site will still be pointing to your old site because the redirect was so transparent that they would have never notice the need to correct their bookmark. When the day comes, they’ll suddenly end up with a broken error page.

Redirect all requests to a single file

Yes, we want to put up a page to let our user know about it so they can update their bookmark during the transition period when both old and new site are up and running. Fine, let’s use the method mentioned in the section “to redirect all requests to a single file”. Now our user can see the nicely written notice that the site was moved to a new home. But wait again, what should use do next after reading our notice, they want to go to that particular page on your site! Where should they click?

Redirect requests to a program

Well, according to Microsoft, we still have last option. That is redirecting to a program that is smart enough to tell user about the move and then send the user to the right page!? This sounds like what we wanted but does it really justify to write a binary executable for such a simple task? No, there got to be a simpler and better way!

Redirect to a smart HTML page

The solution is not difficult. We’re going to tweak the “redirect to program” method by creating an html page with Javascript instead of an binary executable. Let’s call the page “move.html”, you can host the move at anywhere, a virtual dir under old site, anywhere in new site, or a third site.

First, configure you old site’s properties to redirect the site to exactly “http://server/move.html?$P&URI=” without quotes. Make sure none of the checkbox options in the redirect to is checked. See the screenshot below:

image

Then create the move.html page with below content:

<html>
<script type="text/javascript">
var hu = window.location.search;
var position = hu.lastIndexOf('&URI=');
var query = hu.substring(0, position);
var path = hu.substring(position+5);
if (query == '?') query = '';
var url = 'http://thenewcoolsite' + path + query;
linkstring = '<a href="' + url + '">' + url + '</a>';
</script>
<title>The Cool Site Moved</title>
<body>
<h1>The Cool Site Moved</h1>
Please always use the <a href="http://thenewcoolsite/">http://thenewcoolsite/</a> 
to access the the cool site.
<p>
You just landed on the old host of the cool site. This host will be taken offline 
soon and you will get an error instead of this page when it happens. Please take
one of the actions below:
<ul>
<li>
If you access from your web browswer's bookmark or faviorate, please update it 
now with the new link below.
<li>
If you clicked on a link from an email, please notify the sender to correct the link.
<li>
If you are brought to this page by an application or another web site, please notiffy
the owner of the application ASAP.
</ul>
<p>
The new link to your request is in below. Please click on the link, it will take you
to the page that you are looking for.
<p>
<script type="text/javascript">document.write(linkstring);</script>
</body>
</html>

Now if user access http://oldcoolsite/somedeeplylinked/pagewithparameter.aspx?p1=abc&p2=789, you should get the page below with messages that you want to give to user, as well as a link to the new site that that the user attempted to access.

image

Limitations and Enhancements

For this to work, your user’s browser must support Javascript. This is the only limitation but can be a serious limitation for some web sites. But the logic in the Javascript can easily moved to server side with an ASP or JSP.

Wednesday, October 06, 2010

Install Snow Leopard on VirtualBox with Core i5 CPU

There are a few good articles explaining how to install Mac OS X on VirtualBox and a lot of people had reported success:

http://www.taranfx.com/install-snow-leopard-virtualbox
http://www.sysprobs.com/mac-os-guest-virtualbox-326-snow-leopard-1064-windows-7-32-bit
http://www.sysprobs.com/install-mac-snow-leopard-1063-oracle-virtualbox-32-apple-intel-pc

But unfortunately, when I try to install on my Lenovo ThinkPad X201 with Core i5 M520 CPU, none of those guide worked. I couldn’t boot up the Mac Installer DVD from the virtual machine. After a number of hours try and error, I finally got to the conclusion that all my failures were because, the boot loader and OS X version combinations that I tried, none of them supports my Core i5 CPU.

I then searched up and down for the support of Core i5 boot loaders. With help from my friend, I found this page. It has no mention of VirtualBox but the tools and instructions worked for me. When I was about to write a full blog of the detail steps, I came to know from Dinesh that he actually had a post about using iBoot with VirtualBox, which was pretty much what I did.

Now you have two options to go. a) Use a pre-built VirtualBox disk image (.vdi) that has both Snow Leopard 10.6.4 and boot loader pre-installed; b) install manually step by step yourself.

Using Pre-built Disk Image

This is an easiest option to go,

  1. Download the the disk image following the links provided in the end of all steps. Total 7.5G compressed and 12G expanded.
  2. Unzip it using 7-Zip, a really cool free utility that can open almost any compressed file including .iso image.
  3. Rename the downloaded vdi file to something reads better to you, say SnowLeopard.vdi and place it in the your virtual disk image folder. You can find your Default Hard Disk Folder in settings of the VirtualBox console (File->Preferences or Ctrl-G)
    image
  4. Complete only the step 1 of the instruction here to create the Virtual Machine, except that do NOT create the hard disk as we already have one, acknowledge to the warning message and continue.
    sn2
  5. Go to setting of the newly create VM and selected the Storage on left. Keep the CD/DVD drive and delete all Virtual Hard Disks if you accidently created in last step. Add a SATA Controller and select the newly downloaded vdi file. Use the folder icon with green arrow to add the disk if it is not already in the Hard Disk dropdown list.
    sn4
  6. Start the VM and have your Mac OS X running, the user id and password are both “vbox”.
  7. To change the screen resolution, follow the instructions in the manual install option.

Snow Leopard 10.6.4 pre-installed bootable VirtualBox disk image download links from fileserve:

Install Using iBoot and Snow Leopard Retail DVD image

Somebody may prefer this option because it allows you customize the installer where you can select if you would install the additional languages and print drivers. I’ll save my time by introducing you to that post for most of it and just noting down things that you need to watch out here.

My Environment

Lenovo ThinkPad X201, Core i5 M520 CPU, 4GB RAM, Integrated Graphics, Windows 7 Ultimate 32bit, VirtualBox 3.2.8

I have Snow Leopard 10.6.3 Install DVD iso image on hand and so that’s what I used. I believe 10.6.4 will sure work and 10.6.2 is the first version supports Core i series CPU so it “should” work too. Anything older than that won’t work, don’t bother trying.

Install Boot Loader to HDD

It is very important that you must update to 10.6.4 before installing the boot loader from MultiBeast package. Otherwise, your Mac won’t boot at all, not even from the iBoot boot loader iso. Always take a snapshot of your VM before you do this.

Screen Resolution

There are three methods described on this page. I tried first one, doesn’t work, than I tried 2nd one, I cannot start VM. So eventually, that’s how I made it work.

  • You need both method 1 and 2, any one along won’t work.
  • You must have the boot loader installed to HDD first, i.e. you must be able to boot directly from HDD.
  • For method 1, you must edit the plist file under /Extra, not the one under /Library/Preferences/SystemConfiguration.
  • The command line described in method 2 will corrupt your machine XML file. I had to edit the file manually. To edit the XML file:
    1. Find the location of the xml file by going to File->Preferences of you VirtualBox console and get the value of Default Machine Folder (see the image above). Go to that folder and see <Your Machine Name> sub folder. The XML file is there.
    2. Shutdown all VM instances and also close VirtualBox console. This is very important as otherwise your change will be overwritten.
    3. Backup <Your Machine Name>.xml file.
    4. Use any text edit to add below line right under <ExtraData>, and set the resolution that you want, make sure it is the same resolution was what you set in the com.apple.Boot.plist file.
      <ExtraDataItem name="CustomVideoMode1" value="1280x800x32"/>

The final xml should look something like below:

... ...
    <ExtraData>
      <ExtraDataItem name="CustomVideoMode1" value="1280x800x32"/>
      <ExtraDataItem name="GUI/LastCloseAction" value="powerOff"/>
... ...

 

Good luck and your mileage may vary.

Saturday, May 15, 2010

SubWiki macro for Trac 0.11

Glad to know that the patch I provided near two years ago are now finally applied to the source control. http://trac-hacks.org/ticket/3566

Friday, April 30, 2010

SpringExtension: Extends DbProvider to Provide Hook to Connection Open and Close

This is inspired by the need of populating ODP.Net's OracleConnection.ClientId property with current thread identity when Spring.Net's ADO Support is used in the data access layer.

The major difference between Java’s DataSource and its Spring.Net’s counterpart, DbProvider, is that the connection returned from DbProvider is not open. With Java’s  DataSource, you can easily make a wrapper to set up the connection before it’s used by the application code. But things become difficult with DbProvider, you just cannot do this. If you open the connection in the wrapper, the subsequent call to open the connection by the Spring.Net framework will fail (you wish it will check the status before calling open? nope, that’s not the case).

But there is a workaround. We can use an event handler to setup the connection at the moment Spring.Net framework opens the connection. Although IDbConnection doesn't provide any mean to let you react when a database connection is opened and/or closed, but the System.Data.Common.DbConnection object, which is the base class of most ADO implementation, has an event called StateChange. This gives us the hook to extend the DbProvider so that application code can react on connection open and/or close event. We can do many things with this, for example call a stored procedure to setup the connection options, tell database the current thread’s identity name, even setup the in-memory database for unit testing and etc.

The good new is we have implemented the hook in SpringExtension, so you don’t have to re-do the work. Using SpringExtension, you can easily achieve what I have described in my earlier post about setting oracle CLIENT_IDENTIFIER database session information, by just below configuration settings. No c# program needs to be written.

  <object id="DbProvider" type="Spring.Data.Common.ExtendedDbProvider, Spring.Data.Extension">
    <property name="TargetDBProvider" ref="TargetDbProvider"/>
    <property name="ConnectionStateListener">
      <object type="Spring.Data.Support.OdpNetClientIdentifierSetter,  Spring.Data.Extension"/>
    </property>
  </object>
  
  <db:provider id="TargetDbProvider" provider="OracleODP-2.0" connectionString="${DB.IMM.ConnectionString}"/>

You can further customize the action by replacing the OdpNetClientIdentifierSetter with any implementation of IDbConnectionStateListener, defined in SpringExtension as:

    /// <summary>
    /// Interface to receive the database connection state change.
    /// </summary>
    /// <author>Kenneth Xu</author>
    public interface IDbConnectionStateListener
    {
        /// <summary>
        /// To be called when the <paramref name="connection"/> state changed
        /// from <paramref name="original"/> to <paramref name="current"/>.
        /// </summary>
        /// <param name="connection">
        /// The database connection that its state has changed. 
        /// </param>
        /// <param name="original">
        /// The original state of the connection before change.
        /// </param>
        /// <param name="current">
        /// Current state of the connection.
        /// </param>
        void AfterStateChange(IDbConnection connection, ConnectionState original, ConnectionState current);
    }

Or if all you care is open and/or close event, you can extend DbConnectionStateListenerBase by override any of the below two virtual methods:

        /// <summary>
        /// This method is called after database is opened.
        /// </summary>
        /// <param name="connection">
        /// The connection that was just opened.
        /// </param>
        public virtual void AfterConnectionOpen(IDbConnection connection)
        {
            
        }
 
        /// <summary>
        /// This method is called after database is closed.
        /// </summary>
        /// <param name="connection">
        /// The connection that was just closed.
        /// </param>
        public virtual void AfterConnectionClose(IDbConnection connection)
        {
            
        }

Welcome comments and suggestions

Wednesday, April 28, 2010

SpringExtension: Declarative Transaction Management and Unit Test

Declarative transaction management is one of the compelling reasons to using Spring.Net. But there are still cases where you need to programmatically rollback a transaction without throwing an exception. Spring.Net let you do so with below method call:

TransactionInterceptor.CurrentTransactionStatus.SetRollbackOnly();

The problem with this call emerges when you unit test your business objects containing such statement. You got an exception when you run your test because there is no transaction context exists.

The solution to this problem is dependency injection. We need to introduce an interface that can give us the transaction status.

    public interface ITransactionStatusProvider
    {
        ITransactionStatus CurrentTransactionStatus { get; }
    }

We can then use the interface to rollback current transaction in our business objects:

   1:      public class BusinessObject
   2:      {
   3:          ITransactionStatusProvider TransactionStatusProvider { get; set; }
   4:          public void BusinessMethod()
   5:          {
   6:              // Do some work.
   7:              if (something is wrong)
   8:              {
   9:                  TransactionStatusProvider.CurrentTransactionStatus.SetRollbackOnly();
  10:              }
  11:          }
  12:      }

In line 3, we declared a property so the provider can be injected; In line 9, we used the provider to rollback the transaction in error condition.

Since both provider and status are interfaces, we can easily mock them in our unit test:

   1:          [Test] public void BusinessMethodRollBackTransactionWhenSomethingIsWrong()
   2:          {
   3:              var mockProvider = MockRepository.GenerateMock<ITransactionStatusProvider>();
   4:              var mockStatus = MockRepository.GenerateMock<ITransactionStatus>();
   5:              mockProvider.Stub(p => p.CurrentTransactionStatus).Return(mockStatus);
   6:   
   7:              var sut = new BusinessObject {TransactionStatusProvider = mockProvider};
   8:              // sut.SetUpWrongCondition
   9:              sut.BusinessMethod();
  10:   
  11:              mockStatus.AssertWasCalled(x=>x.SetRollbackOnly());
  12:          }

The last thing left is to write a real implementation that actually works with the Spring.Net’s declarative transaction management:

    public class TransactionInterceptorStatusProvider : ITransactionStatusProvider
    {
        public ITransactionStatus CurrentTransactionStatus
        {
            get { return TransactionInterceptor.CurrentTransactionStatus; }
        }
    }

We then use Spring.Net’s dependency inject feature to set the the BusinessObject.TransactionStatusProvider to an instance of TransactionInterceptorStatusProvider. Problem resolved!

This is part of SpringExtension, both source and binary are available on Google Code.

Tuesday, January 19, 2010

Always Override Equals of Your Value Type

ReSharper had been reminding me to override the Equals method and operator for value types that I have created. Every time I took the advice and let ReSharper do the work for me.

But I kept wondering how bad is the default implementation? The default implementation of Equals method is in the ValueType abstract class that every .Net value type inherits from. Initially I though it must use some sort of native memory comparison so it got to be fast. But after I looked at the code in Reflector, I’m no longer sure how true is this. It calls a native method CanCompareBits to check if current instance eligible for FastEqualsCheck. If yes great, otherwise it falls back to reflection. I don’t know what qualifies for fast equals check, but I start to realized that members with Equals method overridden cannot not use bit comparison. The reflection code told me that it uses Equals to compare members.

Enough talk, lets test the performance with two simplest value types, one has Equals overridden and another relays on the default implementation.

I used NUnit test case for simplicity but the code below can be easily changed to a console application.

   1:  private const int _sampleSize = 100;
   2:   
   3:  [Test] public static void Main()
   4:  {
   5:      var defaultEqualsStruct = new DefaultEqualsStruct[_sampleSize];
   6:      var overriddenEqualsStruct = new OverriddenEqualsStruct[_sampleSize];
   7:      for (int i = 0; i < _sampleSize; i++)
   8:      {
   9:          defaultEqualsStruct[i] = new DefaultEqualsStruct { Foo = i };
  10:          overriddenEqualsStruct[i] = new OverriddenEqualsStruct { Foo = i };
  11:      }
  12:      RunBenchMark(defaultEqualsStruct, new DefaultEqualsStruct { Foo = _sampleSize });
  13:      RunBenchMark(overriddenEqualsStruct, new OverriddenEqualsStruct { Foo = _sampleSize });
  14:  }
  15:   
  16:  public static void RunBenchMark<T>(T[] items, T e)
  17:  {
  18:      Console.WriteLine("==========" + typeof(T).Name + "=========");
  19:      // Warn up
  20:      Assert.IsTrue(ArrayIndexOf(items, items[5]));
  21:      Assert.IsTrue(LoopEquals(items, items[5]));
  22:      Clock(null, 1, () => Assert.IsFalse(ArrayIndexOf(items, e)));
  23:      Clock(null, 1, () => Assert.IsFalse(LoopEquals(items, e)));
  24:      // Run benchmark.
  25:      const int repeat = 100000;
  26:      Clock("Array.IndexOf", repeat, () => ArrayIndexOf(items, e));
  27:      Clock("Loop + Equals", repeat, () => LoopEquals(items, e));
  28:  }
  29:   
  30:  private static void Clock(string message, int repeat, Action a)
  31:  {
  32:      Stopwatch stopwatch = new Stopwatch();
  33:      stopwatch.Start();
  34:      for (int i = 0; i < repeat; i++) a();
  35:      stopwatch.Stop();
  36:      if (message != null)
  37:          Console.WriteLine(message + ": " + stopwatch.ElapsedTicks);
  38:  }
  39:   
  40:  private static bool ArrayIndexOf<T>(T[] items, T element)
  41:  {
  42:      return (Array.IndexOf(items, element) >= 0);
  43:  }
  44:   
  45:  private static bool LoopEquals<T>(T[] items, T element)
  46:  {
  47:      int size = items.Length;
  48:      for (int i = 0; i < size; i++)
  49:      {
  50:          if (Equals(element, items[i])) return true; // found
  51:      }
  52:      return false;
  53:  }
  54:   
  55:  public struct DefaultEqualsStruct
  56:  {
  57:      public int Foo { get; set; }
  58:  }
  59:   
  60:  public struct OverriddenEqualsStruct
  61:  {
  62:      public int Foo { get; set; }
  63:   
  64:      public bool Equals(OverriddenEqualsStruct other)
  65:      {
  66:          return other.Foo == Foo;
  67:      }
  68:   
  69:      public override bool Equals(object obj)
  70:      {
  71:          if (ReferenceEquals(null, obj)) return false;
  72:          if (obj.GetType() != typeof(OverriddenEqualsStruct)) return false;
  73:          return Equals((OverriddenEqualsStruct)obj);
  74:      }
  75:   
  76:      public override int GetHashCode()
  77:      {
  78:          return Foo;
  79:      }
  80:  }

And here goes the test result in release build:

   1:  ==========DefaultEqualsStruct=========
   2:  Array.IndexOf: 2863736
   3:  Loop + Equals: 1424624
   4:  ==========OverriddenEqualsStruct=========
   5:  Array.IndexOf: 289861
   6:  Loop + Equals: 509123

That’s really a lot of difference! Thanks ReSharper!

Monday, January 18, 2010

How Fast Are Methods In .Net Array Class

It’s very fast.

When I was porting the CopyOnWriteArrayList class from Java to .Net, I came across the implementation of the AddIfAbsent method. In Java it was written as:

   1:  public boolean addIfAbsent(E e) {
   2:      final ReentrantLock lock = this.lock;
   3:      lock.lock();
   4:      try {
   5:          // Copy while checking if already present.
   6:          // This wins in the most common case where it is not present
   7:          Object[] elements = getArray();
   8:          int len = elements.length;
   9:          Object[] newElements = new Object[len + 1];
  10:          for (int i = 0; i < len; ++i) {
  11:          if (eq(e, elements[i]))
  12:              return false; // exit, throwing away copy
  13:          else
  14:              newElements[i] = elements[i];
  15:          }
  16:          newElements[len] = e;
  17:          setArray(newElements);
  18:          return true;
  19:      } finally {
  20:          lock.unlock();
  21:      }
  22:  }

If you read the comment in the code above, the implementation creates a new array regardless of whether the element exists or not. If it finds out that the element exists during the copying of existing elements between arrays, it simply discards the newly created array.

Comparing this to the typical approach that search first then create new array if not found, it wins in the case when the element doesn’t exist by eliminating the search.

If I directly translate the same code into .Net, I won’t be able use any of utility methods provided by Array class in .Net framework. So I have to choose between a) sticking with the Java’s implementation, or  b) using Array.IndexOf then Array.Copy if found.

Let’s set out and run a benchmark (I’m using NUnit test case but the code can be easily called by a Program.cs file).

Let’s only test the use case where the element is not found, to see if the Array.IndexOf+Array.Copy implementation (let’s call it “Find Then Copy”) can compete with find when copying implementation (“Copy With Find”) of Java.

   1:      [TestFixture(typeof(int))]
   2:      [TestFixture(typeof(string))]
   3:      public class CopyOnWriteListTest<T>
   4:      {
   5:          private static readonly T[] _items = TestData<T>.MakeTestArray(100);
   6:   
   7:          [Test] public void RunBenchMark()
   8:          {
   9:              Console.WriteLine("==========" + typeof (T).Name + "=========");
  10:   
  11:              // Confirm that Array.IndexOf use value equals, not reference equals.
  12:              T value = TestData<T>.MakeData(5);
  13:              int index = Array.IndexOf(_items, value);
  14:              Assert.That(index, Is.EqualTo(5));
  15:              Assert.That(value, Is.Not.SameAs(_items[index]));
  16:              Assert.That(value, Is.EqualTo(_items[index]));
  17:   
  18:              T e = TestData<T>.MakeData(_items.Length);
  19:              // Warn up
  20:              Clock(null, 1, () => FindThenCopy(e));
  21:              Clock(null, 1, () => CopyWithFind(e));
  22:              // Run benchmark.
  23:              const int repeat = 100000;
  24:              Clock("Find Then Copy", repeat, () => FindThenCopy(e));
  25:              Clock("Copy With Find", repeat, () => CopyWithFind(e));
  26:          }
  27:   
  28:          private static void Clock(string message, int repeat, Action a)
  29:          {
  30:              Stopwatch stopwatch = new Stopwatch();
  31:              stopwatch.Start();
  32:              for (int i = 0; i < repeat; i++) a();
  33:              stopwatch.Stop();
  34:              if (message != null)
  35:                  Console.WriteLine(message + ": " + stopwatch.ElapsedTicks);
  36:          }
  37:   
  38:          private static void FindThenCopy(T element)
  39:          {
  40:              T[] items = _items;
  41:              var index = Array.IndexOf(items, element);
  42:              if (index >= 0) return; // found
  43:              int size = items.Length;
  44:              var newItems = new T[size + 1];
  45:              Array.Copy(items, 0, newItems, 0, size);
  46:              newItems[size] = element;
  47:          }
  48:   
  49:          private static void CopyWithFind(T element)
  50:          {
  51:              T[] items = _items;
  52:              int size = items.Length;
  53:              var newItems = new T[size + 1];
  54:              for (int i = 0; i < size; i++)
  55:              {
  56:                  if (Equals(element, items[i])) return; // found
  57:                  newItems[i] = items[i];
  58:              }
  59:              newItems[size] = element;
  60:          }
  61:      }

And here is the result:

   1:  ==========Int32=========
   2:  Find Then Copy: 129702
   3:  Copy With Find: 547511
   4:  ==========String=========
   5:  Find Then Copy: 274798
   6:  Copy With Find: 375962

Although it is two pass approach using Array class, native code is still significantly faster than looping in managed code. Value type showing larger difference is because the boxing when calling the Equals method.

Result changes a little when the array size is getting smaller. When we run it with array size of 20:

   1:  ==========Int32=========
   2:  Find Then Copy: 82526
   3:  Copy With Find: 112597
   4:  ==========String=========
   5:  Find Then Copy: 107412
   6:  Copy With Find: 108321

And 10:

   1:  ==========Int32=========
   2:  Find Then Copy: 36767
   3:  Copy With Find: 84236
   4:  ==========String=========
   5:  Find Then Copy: 68216
   6:  Copy With Find: 57618

This is because the overhead of calling the method into Array class starts to play the game. The “Copy With Find” implementation gets faster for reference type when array size is below 20. But both implementations are fast when array is small anyway so I don’t see much benefit of using “Copy With Find” approach in .Net.

I have also tested with custom reference type and value types, the result is comparable to int and string test.

Conclusion: Array class won the race! Yes, array operations using methods in Array class are indeed very fast.