Tuesday, November 23, 2010

Mike Galbraith's Linux kernel patch that does wonders...

Last week I came across a blog post "The Linux desktop may soon be a lot faster" by Steven J. Vaughan-Nichols. It's about the patch done by Linux kernel developer Mike Galbraith who adds a mere 233 lines of code to the kernel's scheduler that cuts desktop latency down by a factor of ten. Even Linus Torvalds himself praised the performance boost he gets from the patch.

Two days later, another post appear on Google News. Alternative To The "200 Lines Kernel Patch That Does Wonders" Which You Can Use Right Away by Andrew. Lennart Poettering, a RedHat developer replied to Linus Torvalds on a maling list with an alternative to this patch that does the same thing yet all you have to do is run 2 commands and paste 4 lines in your ~/.bashrc file.

Everybody seems excited with the improvement. As for the champ at the bit, they've started implement the workaround and I believe some even recompile the kernel with the patch. Wow!!!

Sunday, November 21, 2010

Customizing plymouth login screen background, fonts and gtk...

1) Open terminal, copy and paste the following command.
    $ sudo cp /usr/share/applications/gnome-appearance-properties.desktop /usr/share/gdm/autostart/LoginWindow
2) Close terminal and log out. Once at login screen you'll see an Appearance pop up. Make your changes and log in.

3) Now to disable Appearance pop up from login screen. Open terminal, copy and paste the following command.
    $ sudo unlink /usr/share/gdm/autostart/LoginWindow/gnome-appearance-properties.desktop
Note :
Tested on Ubuntu 10.04 and Linux Mint 10.

Monday, November 15, 2010

First Ubuntu and now Fedora, dumping X for Wayland...

When I first read about the news, as normal user I can't really tell what impact might hit to people like me. My understanding, it seems like there's a claim that X is too complicated, too slow, too filled with archaic junk and so on. That trigger the movement from X to Wayland, an OpenGL-based display management system.

I'm more concern about the apps that I love to use on Linux, because to run natively on Wayland it needs to be ported. Otherwise, it is stated that:
"If they don't, you can run a nested X server like on OSX. They'll still work as well as they ever did, and you even get to keep ssh [Secure Shell] forwarding of them. You can run a wayland server that does nothing but run a nested X server and you wouldn't ever know the difference."

Questions in my head:
  • How long will it take for all apps to get ported?
  • If need to run a nested X server, do I need to configure it myself?
  • With the hassle on the ported part (by developers of course) so that all apps can run natively on Wayland, is it going to improve graphical performance tremendously?
  • Since it is an OpenGL-based, is it going to improve gaming experience as well?

Changes are good but at what stake? If I hate to change, hell I'll just stick with Windows for the rest of my life. I don't mind learning, the advantages of using Linux are too enormous to be ignore. But if the change is too huge for me, I guess I'll stay on the safe side by reading more experience story by others. I'll do my best to avoid running a nested X server on Wayland because if I did that I personally feel it beats the purpose of the transition in the first place.

Sunday, November 14, 2010

Sharing html table with sum formula that works on Excel and web page...



I'm in a situation where I need to include Excel SUM formula when exporting data from html. Questions raised in my head. What's the purpose of exporting it to Excel in the first place? It gives us the ability to manipulate data with whatever formulas available in Excel. Then why do we want to have it in html? I have no idea but at least I've found a way that I won't need to generate it twice. That matters to me.

Here's the trick. When generating an html, add the id to the cell that needs to be calculate exactly like cell in Excel. As for the cell with the sum value, add css class to it (doesn't need to be exist in css, it's just for the sake of searching later on).
<table>
        <thead>
            <th>header 1</th>
            <th>header 2</th>
            <th>header 3</th>
            <th>total</th>
        </thead>
        <tr>
            <td id='A2'>1</td>
            <td id='B2'>2</td>
            <td id='C2'>3</td>
            <td id='D2' class='sum'>=SUM(A2,B2,C2)</td>
        </tr>
        <tr>
            <td id='A3'>4</td>
            <td id='B3'>5</td>
            <td id='C3'>6</td>
            <td id='D3' class='sum'>=SUM(A3,B3,C3)</td>
        </tr>
        <tr>
            <td id='A4'>7</td>
            <td id='B4'>8</td>
            <td id='C4'>9</td>
            <td id='D4' class='sum'>=SUM(A4,B4,C4)</td>
        </tr>
        <tr>
            <td class='sum'>=SUM(A2,A3,A4)</td>
            <td class='sum'>=SUM(B2,B3,B4)</td>
            <td class='sum'>=SUM(C2,C3,C4)</td>
            <td class='sum'>=SUM(D2,D3,D4)</td>
        </tr>
    </table>
Now if you copy the html above, paste it into a notepad and save it to .xls. You'll get an Excel sheet with calculated value based on the SUM formula provided. But then of course the formula won't work on the web site. You'll see table like shown below.

Demo

header 1 header 2 header 3 total
1 2 3 =SUM(A2,B2,C2)
4 5 6 =SUM(A3,B3,C3)
7 8 9 =SUM(A4,B4,C4)
=SUM(A2,A3,A4) =SUM(B2,B3,B4) =SUM(C2,C3,C4) =SUM(D2,D3,D4)


This is where JQuery come in handy. The logic,
  • Search for all the elements that has 'sum' class
  • Convert the formula into something that is understandable by JQuery
  • Loop through the elements and change the value from formula into calculated value
$(document).ready( function() {
        // search the elements that has 'sum' class
        $('.sum').each(function() {
            // convert the formula from =SUM(A2,B2,C2) into #A2,#B2,#C2
            var formula = convert($(this).html());
            var total = 0;

            $(formula).each(function() {
                total += parseInt($(this).html());
            });

            // replace with calculated value
            $(this).html(total);
        });
    });
    
    // converting from =SUM(A2,B2,C2) into #A2,#B2,#C2
    function convert(formula)
    {
        var newform = formula.substring(formula.indexOf("(") + 1, formula.indexOf(")"));
        var arrayform = newform.split(",");
        return "#" + arrayform.join(",#");
    }
JQuery save the day...again...

Friday, November 12, 2010

Converting int to base26 string in C#...

For my own reference.
    public string ToBase26(int number)
    {
        char[] base26 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };

        int remainder = number % base26.Length;
        int value = number / base26.Length;

        return value == 0 ?
            String.Format("{0}", base26[remainder]) :
            String.Format("{0}{1}", ToBase26(value - 1), base26[remainder]);
    }
Alternatively I can code it this way
    public string ToBase26(int number)
    {
        if (number < 0) return String.Empty;

        int remainder = number % 26;
        int value = number / 26;

        return value == 0 ?
            String.Format("{0}", Convert.ToChar(65 + remainder)) :
            String.Format("{0}{1}", ToBase26(value - 1), Convert.ToChar(65 + remainder));
    }

Wednesday, November 10, 2010

Highlighting table row on mouse over using JQuery...



<table border='0'>
        <thead>
            <tr>
                <th>head 1</th>
                <th>head 2</th>
                <th>head 3</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
            </tr>
        </tbody>
    </table>
Demo

head 1 head 2 head 3
data 1 data 2 data 3
data 1 data 2 data 3
data 1 data 2 data 3
data 1 data 2 data 3

Piece of cake...
$(document).ready( function() {
        $('tbody tr').hover(
            function() { $(this).css('background', '#cecece'); },
            function() { $(this).css('background', '#ffffff'); }
        );
    });

Monday, November 8, 2010

Managing distributed transactions without enabling MSDTC...

Is it possible? Short answer is no. Long answer is yes, but only to certain extend. Another stupid attempt to solve problem in a situation where developers are the lowest being in the organisation. In the perfect world where things working as expected, dealing with distributed transaction is a snap.
    ...
    using(TransactionScope scope = new TransactionScope())
    {
        using (SqlConnection conn1 ...)
        {
            ...
        }

        using (OracleConnection conn2 ...)
        {
            ...
        }

        scope.Complete();
    }
    ...
However the nightmare begin when your Server/DB admin give you a big "NO" to MSDTC but the other party insisted for data rollback if anything goes wrong during the process. So what I did was to create my own transaction manager class. Before I begin, I need to have a wrapper class that contain a connection and transaction objects, this is where the begintransaction happen. The class will be manage by the transaction manager. Technically it's just managing a group of local transactions.
    using System;
    using System.Data;
    
    public class EnlistedDBConnection : IDisposable
    {
        private IDbConnection _connection;
        private IDbTransaction _transaction;
        
        public IDbConnection Connection
        {
            get { return _connection; }
        }
        
        public IDbTransaction Transaction
        {
            get { return _transaction; }
        }
        
        public EnlistedDBConnection(IDbConnection connection)
        {
            _connection = connection;
            
            if (_connection.State == ConnectionState.Closed) _connection.Open();
            _transaction = connection.BeginTransaction();
        }
        
        internal void Commit()
        {
            _transaction.Commit();
        }
        
        internal void Rollback()
        {
            _transaction.Rollback();
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (_connection != null && _connection.State == ConnectionState.Open) _connection.Close();
            if (_connection != null) _connection.Dispose();
            if (_transaction != null) _transaction.Dispose();
        }

        #endregion
    }
Code for the transaction manager. Before commiting, I need to ensure all connections are alive, if any of it down, cancel everything. However there's still one worst case scenario that this code couldn't handle, after done with connection checking, while committing suddenly one connection down in the process. It is not possible to rollback the committed transaction. So chances for orphan data are still there.
    using System;
    using System.Data;
    using System.Collections.Generic;
    
    public class BasicTransactionManager : IDisposable
    {
        private bool _isCommited;
        private List<EnlistedDBConnection> _enlistedConnections;
    
        public BasicTransactionManager() : this(new List<EnlistedDBConnection>())
        {
        }
        
        private BasicTransactionManager(List<EnlistedDBConnection> enlistedConnections)
        {
            _enlistedConnections = enlistedConnections; 
        }
        
        public EnlistedDBConnection Enlist(IDbConnection connection)
        {
            EnlistedDBConnection item = new EnlistedDBConnection(connection);
            _enlistedConnections.Add(item);
            
            return item;
        }
        
        public void Complete()
        {
            Commit();
        }
        
        /// 
        /// While in the loop, worst case scenario that this logic couldn't handle is that
        /// if the first transaction committed, then the second one failed, chances for orphan data
        /// to occur are there because we couldn't rollback something that has been commited.
        /// 
        private void Commit()
        {
            // if one of the db connection failed, cancel everything
            if(!VerifyConnection()) throw new Exception("DB connection failed.");
            
            string message = String.Empty;
            foreach (EnlistedDBConnection enlistedConnection in _enlistedConnections)
            {
                try
                {
                    enlistedConnection.Commit();
                }
                catch(Exception ex)
                {
                    message += String.Format("{0}\r\n", ex.Message);
                }
            }
            if(!String.IsNullOrEmpty(message)) throw new Exception(message);
            
            _isCommited = true;
        }
        
        private void Rollback()
        {
            string message = String.Empty;
            foreach (EnlistedDBConnection enlistedConnection in _enlistedConnections)
            {
                if(enlistedConnection.Connection != null && enlistedConnection.Connection.State == ConnectionState.Open)
                {
                    try
                    {
                        enlistedConnection.Rollback();
                    }
                    catch (Exception ex)
                    {
                        message += String.Format("{0}\r\n", ex.Message);
                    }
                }
            }
            if (!String.IsNullOrEmpty(message)) throw new Exception(message);
        }
        
        private bool VerifyConnection()
        {
            bool _allOpened = true;
            
            foreach(EnlistedDBConnection enlistedConnection in _enlistedConnections)
            {
                if(enlistedConnection.Connection == null || enlistedConnection.Connection.State != ConnectionState.Open)
                {
                    _allOpened = false;
                    break;
                }
            }
            
            return _allOpened;
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (!_isCommited) Rollback();
            
            _enlistedConnections.ForEach( delegate(EnlistedDBConnection item) { item.Dispose(); } );
            // _enlistedConnections.ForEach( item => item.Dispose() );
        }

        #endregion
    }
This is how I use it in my business object. EnlistedDBConnection exposed connection and transaction property. That's how I obtain the instance and pass it to Command object.
    using (BasicTransactionManager transaction = new BasicTransactionManager())
    {
        EnlistedDBConnection dbcon1 = transaction.Enlist(/* your db connection object */);
        EnlistedDBConnection dbcon2 = transaction.Enlist(/* your db connection object */);

        ...

        transaction.Complete();
    }
Note:
This solution is not by any mean to be a replacement to MSDTC (not even in your wet dream). However, it is better to have something rather than nothing. I'd rather use this solution instead of executing another command to undo the changes manually which I feel ridiculous.

Saturday, November 6, 2010

JQuery pluggins summary and best practices...

Writing jQuery plugins allows you to make the most out of the library and abstract your most clever and useful functions out into reusable code that can save you time and make your development even more efficient. Here's a brief summary of the post and what to keep in mind when developing your next jQuery plugin:
  • Always wrap your plugin in (function( $ ){ // plugin goes here })( jQuery );
  • Don't redundantly wrap the this keyword in the immediate scope of your plugin's function
  • Unless you're returning an intrinsic value from your plugin, always have your plugin's function return the this keyword to maintain chainability.
  • Rather than requiring a lengthy amount of arguments, pass your plugin settings in an object literal that can be extended over the plugin's defaults.
  • Don't clutter the jQuery.fn object with more than one namespace per plugin.
  • Always namespace your methods, events and data.
  • jQuery.fn is pronounced jQuery effin'

Monday, November 1, 2010

Compress and Decompress text using System.IO.Compression...

I'm lazy today. This code was copied directly from internet for my personal reference.
    using System;
    using System.Text;
    using System.IO;
    using System.IO.Compression;

    public static class GZipStreamUtility
    {
        public static string Compress(string text)
        {
            if (String.IsNullOrEmpty(text)) return String.Empty;

            byte[] buffer = Encoding.UTF8.GetBytes(text);
            MemoryStream ms = new MemoryStream();
            using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
            {
                zip.Write(buffer, 0, buffer.Length);
            }

            ms.Position = 0;
            MemoryStream outStream = new MemoryStream();

            byte[] compressed = new byte[ms.Length];
            ms.Read(compressed, 0, compressed.Length);

            byte[] gzBuffer = new byte[compressed.Length + 4];
            System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
            System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);

            return Convert.ToBase64String(gzBuffer);
        }

        public static string Decompress(string compressedText)
        {
            if (String.IsNullOrEmpty(compressedText)) return String.Empty;

            byte[] gzBuffer = Convert.FromBase64String(compressedText);
            using (MemoryStream ms = new MemoryStream())
            {
                int msgLength = BitConverter.ToInt32(gzBuffer, 0);
                int length = gzBuffer.Length - 4;
                ms.Write(gzBuffer, 4, length);

                byte[] buffer = new byte[msgLength];

                ms.Position = 0;
                using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
                {
                    zip.Read(buffer, 0, buffer.Length);
                }

                return Encoding.UTF8.GetString(buffer);
            }
        }
    }