Perfect virtual desktops. Almost...

Like most Windows devs I really like the Sysinternals family of products.  So when I caught wind this morning of a new product called Desktops that creates a virtual workspace of up to 4 desktops I just knew it was the product I was looking for.  Well, it sort of is.

You can't ask for an easier installation.  Unzip it and drop it on a folder and run it.  In the dialog that appears you can select whether to run it at startup.  Here's a shot of that dialog.

image 

It has a nice selection of options to select which desktop you are using but sadly it doesn't support the most important one -- the arrow keys!  Someone who is using virtual desktop software is enough of a power user that they will want to switch desktops on-the-fly without looking at the keyboard.  Sure I can whack a number key without looking but the T-shape arrow keypad just fits with the metaphor a bit better.  A simple Ctrl+Shift+Arrow would do the trick.

The other problem is the speed. It's a bit slow and has no nice swipes or transitions but it is free software so I'm really not griping about that too much.

All in all a welcome bit of software.  Thanks Mark!


MySQL Connector/Net 5.1.7 has been released

MySQL Connector/Net 5.1.7 a new version of the all-managed .NET driver for MySQL has been released. This is a minor release involving mainly bug fixes.

Version 5.1.7 works with all versions of MySQL including MySQL-4.1,  MySQL-5.0, MySQL-5.1 beta or the MySQL-6.0 beta releases.

It is now available in source and binary form from [http://dev.mysql.com/downloads/connector/net/5.1.html] and mirror sites (note that not all mirror sites may be up to date at this point of time - if you can't find this version on some mirror, please try again later or choose another download site.)

IMPORTANT
Unless a major, data-loss type bug is found, we expect this to be the last release of the 5.1 product.  We encourage all new work to use the newly released 5.2 product

Bugs Fixed

  • Fixed problem with DDEX provider that could sometimes prevent table altering when working with 4.1 servers (bug #30603)
  • Fixed problem with pooling code where connections pooled from the pool were added twice to the in use pool.  This would cause a semaphore full exception when an attempt is made to release them back to the pool (bug #36688)
  • Reversed order of Datetime and DateTime enums for MySqlDbType so that VB users won't get autocorrection to Datetime (bug #37406)
  • Uncommented access denied error enumeration value (bug #37398)
  • Improved documentation concerning autoincrement columns and the DataColumn class (bug #37350)
  • Fixed problem where executing a command that results in a fatal exception would not close the connection.  (bug #37991)
  • Fixed problem where executing a command with a null connection object would result in a null reference exception instead of an InvalidOp (bug #38276)

Enjoy and thanks for the support!
Reggie


Connector/Net 5.2.3 GA has been released

MySQL Connector/Net 5.2.3, a new version of the all-managed .NET driver for MySQL has been released.  This release is of GA quality and is suitable for  use in production environments.  We strongly urge you to  review the change log that is shipped with the product for a thorough review of the changes.

Version 5.2.3 works with all versions of MySQL including MySQL-4.1,  MySQL-5.0, MySQL-5.1 beta or the MySQL-6.0 Falcon "Preview".

It is now available in source and binary form from [http://dev.mysql.com/downloads/connector/net/5.2.html] and mirror sites (note that not all mirror sites may be up to date at this point of time - if you can't find this version on some mirror, please try again later or choose another download site.)

Changes since 5.2.2

  • Increased the speed of MySqlDataReader.GetOrdinal dramatically by using a couple of hashes for lookups
  • Fixed problem where some tables that support the web providers used the latin1 character set instead of the database default.  (bug #36444)
  • Changed how the procedure schema collection is retrieved.  If 'use procedure bodies=true' then we select on the mysql.proc table directly as this is up to 50x faster than our current IS implementation.  If 'use procedure bodies=false', then the IS collection is queried.  (bug #36694)
  • Fixed problem with our GetOrdinal speedup where we would attempt to add an already existing key to a hash when a resultset had more than 1 column with the same name. (bug #37239)
  • small fix to how we were allowing in/out and out parameters to slide through parameter serialization.  Before we were setting the AllowUserVariables connection setting but that had the unfortunate side effect of setting the value for all connections that shared that connection string.  This way we isolate it just to our particular command.  This may fix bug #37104
  • Fixed documentation surrounding use of ? vs @ for parameters (bug #37349)
  • Reduced network traffic for the normal case where the web provider schema is up to date (bug #37469)
  • Improved error reporting when a timeout occurs.  It no longer uses a message like 'reading from stream failed'.  (bug #38119)
  • fixed problem where adding a non-existent user to a role would not auto-create the user record (bug #38243)
  • moved string escaping routine from the MySqlString class to the MySqlHelper class and made it public and static.  (bug #36205)
  • Fixed problem where column metadata was not being read with the correct character set  (bug #38721)
  • Fixed problem where the uninstall was not cleaning up the state files (bug #38534)
  • Added 'Functions Return String' connection string option
  • Several other fixes merged in from 5.0 and 5.1

Windows Home Server and blog self-hosting

I recently setup one of my old machines using Windows Home Server and thought it would be nice to run my blog on it instead of GoDaddy.  The obvious approach was to use the terrific Whiist add-in and that's exactly what I did at first.

I encountered the first problem when setting up the web site because my site had to be a subsite under the main site.  I didn't really want my site to be found at xxxx.homeserver.com/reggie so I started playing with domain forwarding and masking at GoDaddy.  With the help of their fine support I managed to get www.reggieburnett.com redirected to my sub-web but none of the sub-links worked (photos, archives, etc).  Plus I didn't really like the CNAME redirect.

So this morning I set out to fix that and fix it I did.  Here's what I did:

  1. Removed forwarding of my site at GoDaddy
  2. Signed up for the free trial at www.zoneedit.com.  You get free dynamic DNS support for up to 5 sites and 200 MB of DNS traffic (apparently that is *ALOT*)
  3. I was already using the excellent dd-wrt firmware on my Linksys router so I just needed to tell it to update zoneedit when my IP changes (and give it my hostname and credentials)
  4. Then I disabled my site using the Whiist add-in
  5. And finally redirected the default site under IIS properties to point to my blog folder.  The /home and /remote subwebs are still there and point to the correct place.

Now you can go to www.reggieburnett.com and land on my self-hosted blog and I can also reach the WHS goodies through subweb URLs.

**EDIT** looks like my home link is broken but I can fix that with some web.config hacking.  No time right now though.  :)


Racing a jet engine

I've spent the last few days working on a support case where a customer was comparing the speed of Connector/Net with an application that uses our native C api.  His test was using a server side prepared statement to insert 3 sets of values in a loop that executed 600,000 times.  The table is a simple 3 column table and the SQL looks like this:

INSERT INTO test VALUES (@p1, @p2, @p3), (@p4, @p5, @p6), (@p7, @p8, @p9)

He was seeing 34,529 records / second using libmysql.dll but only about 24,000 records / second using Connector/Net.  He  understandably wanted to know why there was such a difference and if we could do something about it.  Absolutely!

We solved this problem through a combination of optimizations made to our code and some changes made to the testing application.  I won't say much about the optimizations.  We made some obvious changes like moving a lot more of the prepared statement work to the prepare phase and out of the execute phase.  We also discovered that BitConverter.ToBytes() is a lot slower than our hand-coded methods for reading and writing integer values.  We replaced usages of ArrayList with generic equivalents (it's pretty amazing how much faster generics are actually).

One of the bigger changes we made was to use a second hash for parameter name lookups.  When you are talking about loops with lots of iterations even the smallest inefficiencies can kill you.  Since .NET supports name lookup for parameters we use a hashtable to map parameter names to indices (we made this change when one of our customer was complaining that parameter lookup was slow on one of his commands that had > 30,000 parameters.  Yeah.).  Name lookup should be case-insensitive so we use a case-insensitive comparer with our hashtable.  So the optimization we made this time is to use two hash tables.  The first is case sensitive and is checked first.  If that fails then we check the second and return failure only if both fail.

That's what we did in our code.  We also made some changes to the testing app to make sure the comparison is truly apples to apples.  Let's first look at the loop code in each case.

C API

Connector/Net

			while (count < 600000)
			
			{    
			
			    for (int row = 0; row < 3; ++row)
			
			    {
			
			        *(p1 + row) = count;
			
			        *(p2 + row) = count;
			
			        *(p3 + row) = count;
			
			        ++count;
			
			    }
			
			    mysql_stmt_execute(stmt);
			
			}
			
			while (count < numberOfRows)
			
			{
			
			    for (int row = 0; row < 3; ++row)
			
			    {
			
			        cmd.Parameters[row].Value = count;
			
			        cmd.Parameters[row+3].Value = count;
			
			        cmd.Parameters[row+6].Value = count++;
			
			    }
			
			    cmd.ExecuteNonQuery();
			
			}
			
Don't get hung up on the output of these being slightly different.  The point here is that the C code is using simple pointer arithmetic during each loop where the C# code is doing array lookup.  The array lookup code is quite a bit slower because the get accessor for the parameter collection does some bounds checking so that a nicer exception will be thrown in the event of an out-of-bounds index.
Another change that was made to the testing app was to disable the command timeout in the C# code.  This is a small point but when the command timeout is greater than zero then a timer is constructed and started during each execution.  In this case that is 600,000 timers!  Again, since the C code doesn't provide any type of command timeout it's not a true apples-to-apples comparison.

So, in a nutshell, benchmarking against libmysql is sort of like racing a jet engine.  Very fast but not a great deal of "safety features".  Still, after many hours with dotTrace the results speak for themselves.     
C app = 35,294 records per second.
C# app = 35,321 records per second.

How I found out that mixed mode is cool

We ship a DDEX provider with Connector/Net.  This provider plugs into Visual Studio and integrates into server explorer allowing a user to create data connections to MySQL from within the IDE.  This integration is handled, in large part, by a lengthy series of registry entries.  Until 5.2.2, these entries were made by my installer which is written in WiX.  Having the registry changes made in the installer has two problems.  First, I often need to register the provider during debugging and I don't want to do a full install of the product so I end up hand editing a registry file and manually merging that file.  This a awkward at best.  Second I plan to ship a stand-alone configuration utility in 5.3 that will allow the user to configure which installed version of Connector/Net should be used for VS integration. Currently you can only have one instance installed at a time.

My approach to solving this was to write an installer class that made the registry changes for me and just use installutil to register the assembly.  I was already doing this with my core and web assemblies so this is nothing new.  The problem is that installutil will scan the assembly and all referenced assemblies for types looking for installer classes.  This fails when some of the Microsoft assemblies are scanned.  After much effort I gave up and decided to write my own installutil that I would ship with my installer. 

I had no trouble creating this application and then set about executing it from within my installer.  I attempted to use the CAQuietExec custom action available with WiX v3 but just couldn't make it work right.  So I gave up and decided to write my own execute custom action.

So I cracked open Visual Studio 2008 and read a couple of blogs about custom action writing.  One of them mentioned mixing managed and unmanaged code, the unmanaged code being necessary for the proper DLL exports.  I decided I had to see this work.

Within minutes I had a DLL project setup with the /clr option and had hacked out the following code:

   1: extern "C" __declspec(dllexport) UINT InstallAssembly(MSIHANDLE hMSI)
   2: {
   3:     System::Windows::Forms::MessageBox::Show("boo");
   4:     TCHAR name[261]={0};
   5:     DWORD len=261;
   6:  
   7:     UINT result = ::MsiGetProperty(hMSI, TEXT("CustomActionData"), name, &len);
   8:     InstallVSAssembly(name, true);
   9:     return ERROR_SUCCESS;
  10: }
  11:  
  12: bool InstallVSAssembly(char *assemblyName)
  13: {
  14:     String^ str = gcnew String(assemblyName);
  15:     bool uninstalling = false;
  16:     IDictionary mySavedState = new Hashtable();
  17:     int arg = 0;
  18:  
  19:     InstallContext context = new InstallContext();
  20:     while (arg < args.Length)
  21:     {
  22:         string[] parts = args[arg++].Split('=');
  23:         context.Parameters.Add(parts[0], parts[1]);
  24:     }
  25:  
  26:     Installer installer = null;
  27:     try
  28:     {
  29:         Assembly assem = Assembly.LoadFrom(file);
  30:         installer = (Installer)assem.CreateInstance("MySql.Data.VisualStudio.MyInstaller");
  31:         if (installer == null)
  32:         {
  33:             Console.WriteLine("Unable to find an installer in that assembly.");
  34:             return;
  35:         }
  36:         installer.Context = context;
  37:         if (uninstalling)
  38:             installer.Uninstall(mySavedState);
  39:         else
  40:             installer.Install(mySavedState);
  41:     }
  42:     catch (Exception e)
  43:     {
  44:         Console.WriteLine(e.Message);
  45:     }
  46:     return true;

47: }

Yes, that is managed code and unmanaged code *in the same function*!  Now this code might not compile as it is not what I wound up using and I just grabbed it out of an old folder but you get the idea (and yes I did test a version of this so I know the concept works).  I didn't use this approach because the /clr switch requires the dynamic CRT and I didn't feel like bundling that up.

And, in case you were wondering about the "boo" messagebox on line 3, that is my debugging trap.  You run the installer until that pops up, attach to the proper msiexec using Visual Studio, set a break point, and go.  Yup, that's cool.


MySQL Connector/Net 5.1.6 has been released

Hi,
MySQL Connector/Net 5.1.6 a new version of the all-managed .NET driver for MySQL has been released. This is a minor release involving mainly bug fixes.
Version 5.1.6 works with all versions of MySQL including MySQL-4.1,  MySQL-5.0, MySQL-5.1 beta or the MySQL-6.0 Falcon "Preview".


It is now available in source and binary form from [http://dev.mysql.com/downloads/connector/net/5.1.html] and mirror sites (note that not all mirror sites may be up to date at this point of time - if you can't find this version on some mirror, please try again later or choose another download site.)


Bugs fixed

  • Fixed problem where parameters lists were not showing when you tried to alter a routine in server explorer.  (bug #34359)
  • Fixed a problem in procedure cache where it was possible to get into a race condition and cause a memory leak (bug #34338)
  • Fixed problem where attempting to use an isolation level other than the default with a transaction scope would use the default instead (bug #34448)
  • Fixed problem that causes the TableAdapter wizard to only generate insert statements.  The problem was that our code to retrieve index columns was broken. (bug #31338)
  • Fixed problem with connections staying open after being used with SqlDataSource.  The problem was that we were not returning an enumerator for our reader with the  closeReader option set to true when we were supposed to.  (Bug #34460)
  • Fixed problem where the bit data type would continue to return null values once it saw a null value in a previous row (bug #36313)     
  • Fixed problem with MembershipUser.GetPassword where attempting to retrieve a  password on a user where password Q&A is not required would throw an exception (bug #36159)     
  • Fixed a problem with MembershipUser.GetNumberOfUsersOnline.  It actually works now  :) (bug #36157)
  • Fixed documentation that still stated that setting port to -1 was necessary for a named pipe connection (bug #35356)     
  • Fixed data type processing so that geometry fields are returned as binary.  (bug #36081)     
  • Fixed problem that kept our provider from showing up in the provider list when configuring a new connection from a SqlDataSource     
  • Fixed problem where setting the ConnectionString property of MySqlConnection to null would throw an exception (bug #35619)

Enjoy and thanks for the support!


MySQL Connector/Net 5.2.2 beta has been released

Hi,
MySQL Connector/Net 5.2.2, a new version of the all-managed .NET driver for MySQL has been released.  This release is a beta and may contain bugs with some of them possibly being severe.  You are strongly urged to not use this release in production environments.  This release is intended only for testing and feedback purposes.


Version 5.2.2 works with all versions of MySQL including MySQL-4.1,  MySQL-5.0, MySQL-5.1 beta or the MySQL-6.0 Falcon "Preview".


It is now available in source and binary form from [http://dev.mysql.com/downloads/connector/net/5.2.html] and mirror sites (note that not all mirror sites may be up to date at this point of time - if you can't find this version on some mirror, please try again later or choose another download site.)


Features or behavior changes

  • Added support for using the new PARAMETERS I_S view when running against a 6.0 server
  • Implemented interactive session connection string option 
  • The procedure parameters schema collection has been altered to match what is coming with MySQL 6.0.  Some fields have been removed and others combined.  Please review your application for incompatibilities.


Bugs fixed

  • Fixed profile provider that would throw an exception if you were updating a profile that already existed.
  • Fixed problem where new parameter code prevented stored procedures from being altered in Visual Studio (bug #34940)
  • Fixed problem where the TableAdapter wizard was no longer able to generate commands using stored procedures because of our change to using @ instead of ? (bug #34941)
  • Fixed problem in datagrid code related to creating a new table.  This problem may have been introduced with .NET 2.0 SP1.  
  • Fixed guid type so that a null value is still returned as guid type (bug #35041)
  • Fixed bug with the membership provider where the min non alpha numeric option was not working correctly.   
  • Fixed bug where calling GetPassword on a membership user when the password answer is null would cause an exception (bug #35332)
  • Fixed bug where retrieving passwords that are encrypted was not returning proper passwords (bug #35336)   
  • Fixed problem with profile provider where properties that were specified without a given type could not be retrieved properly (bug #36000) 
  • Removed some unnecessary locking from the pool manager and also reworked the pooling code to not use a semaphore (bug #34001)


Enjoy and thanks for the support!


Still no trackpad love in latest Boot Camp

So Boot Camp 2.1 came out yesterday.  This release has official Vista x64 support but the trackpad issues (no two finger right click, erratic two finger scrolling) have not been fixed.  This is starting to smell bad and it has Steve Jobs' name all over it.


MySQL Connector/Net 5.0.9 has been released

MySQL Connector/Net 5.0.9, a new version of the all-managed .NET driver for MySQL has been released. This release is an update to the existing production-quality 5.0 series.

We plan for this to be the last release in the 5.0 series. We will only be updating the 5.0 product in the event a "data-loss" type bug is discovered. We encourage all new products to use the new 5.1 product.

Version 5.0.9 works with all versions of MySQL including MySQL-4.1, MySQL-5.0, MySQL-5.1 beta or the MySQL-6.0 Alpha.

It is now available in source and binary form from here and mirror sites (note that not all mirror sites may be up to date at this point of time - if you can't find this version on some mirror, please try again later or choose another download site.) 

Features or behavior changes

  • added implementation of MySqlCommandBuilder methods QuoteIdentifier and UnquoteIdentifier (bug #35492)


Bugs fixed

  • Fixed problem where fields that were blobs but did not include the BLOB flag were treated as binary when they should have been treated as text. (Bug #30233)
  • Changed from using Array.Copy to Buffer.BlockCopy in MySqlDataReader.GetBytes. This helps with memory usage as we expect the source and destination arrays to not be overlapping. (Bug #31090)
  • Fixed problem that prevented commands from being executed from the state change handler. Not sure why you would want to do this but... (bug #30964)
  • Fixed issue where column name metadata was not using the charset given on the connection string (Bug #31185)
  • Fixed problem with installer where the installation might report a failure to remove the performance counters if the performance counter category had already been removed for some reason
  • Fixed problem with installer where attempting to install over a failed uninstall could leave multiple clients registered in machine.config. (Bug #31731)
  • Fixed problem with connection string caching where our collection class was using case insensitive semantics and this causes cases where a user originally used the wrong case for a user id and then fixed it to still get access denied errors. (Bug #31433)
  • improved the speed of load data local infile significantly
  • fixed MySqlDateTime.ToString() to properly return the date value (Bug #32010)
  • fixed problem where string parameters who have their size set after their value could cause exceptions (Bug #32094)
  • fixed problem where old code was preventing creating parameter objects with non-input direction using just a constructor (Bug #32093)
  • fixed problem where a syntax error in a set of batch statements could leave the data adapter in a state that appears hung (bug #31930)
  • fixed the MySqlException class to set the server error code in the Data[] hash so that DbProviderFactory users can access the server error code (Bug #27436)
  • fixed problem where changing the connection string of a connection to one that changes the parameter marker after the connection had been assigned to a command but before the connection is opened can cause parameters to not be found (bug #13991)
  • some fixes to cancel and timeout operations so that they are more dependable
  • fixed problem where cloning a parameter that has not yet had its type set would yield a cloned parameter that would no longer infer it's type from the value set

  • Search

    Tags

    None

      Disclaimer

      The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

      © Copyright 2008