Wednesday, December 29, 2010

A trip, book, random code and additional non-sense

On a 24 hr train trip from Halifax to Toronto I enjoyed some reading from Clean Code: A Handbook of Agile Software Craftsmanship most interesting chapter so far is Object and Data Structures.

Some random coding here

Integer partition:


void gen(int lead,int postfix,int number,int *arr,int index,int originalNumber){
if(postfix<1)
return;
do{
int i=index;
arr[i++] = number - postfix;
arr[i] = postfix;
int j = 0;
int sum =0;
for(j=0;j<=index+1;j++){
cout << arr[j] << " ";
sum += arr[j];
}
cout << endl;
counter++;
gen(lead,postfix-1,postfix,arr,index+1,originalNumber-1);
lead++;
postfix = originalNumber - lead;

}while(lead < originalNumber);
}


which I thought is an awful implementation so I stole a python implementation as below


## {{{ http://code.activestate.com/recipes/218332/ (r1)
import sys
def partitions(n):
# base case of recursion: zero is the sum of the empty list
if n == 0:
yield []
return

# modify partitions of n-1 to form partitions of n
for p in partitions(n-1):
yield [1] + p
if p and (len(p) < 2 or p[1] > p[0]):
## print ["DEBUG: "] +  p
yield [p[0] + 1] + p[1:]
## end of http://code.activestate.com/recipes/218332/ }}}
print "Enter a number (0 to quit): "
n = int(sys.stdin.readline())
while n>0:
counter = 0
for p in partitions(n):
print p
counter = counter + 1
print "There were " + str(counter) + " unqiue partitions"
print "Enter a number (0 to quit): "
n = int(sys.stdin.readline())


the equivalent C# implementation is


public static IEnumerable<List<int>> intpart(int n)
 {
   if (n < 0)
                yield return null;
            if (n == 0)
                yield return new List<int>();
            foreach (List<int> list in intpart(n - 1))
            {
                if (list == null) break;
                var temp = new List<int>();
                temp.Add(1);
                temp.AddRange(list);
                yield return temp;

                if (list.Count > 0 && (list.Count < 2 || list[1] > list[0]))
                {
                    var newList = new List<int>();
                    newList.Add(list[0] + 1);
                    newList.AddRange(list.GetRange(1, list.Count - 1));
                    yield return newList;
                }
            }
  }


and playing with python and generating permutations


def ListPermutations(prefix,original):
    if original == "":
        print prefix
    else:
        index = 0
        length  = len(original)
        while index < length:
            if index < length-1 and original[index]==original[index+1]:
                index = index + 1
                continue
            newprefix = prefix + original[index]
            neworiginal = original[0:index]+original[index+1:]
            index = index + 1
            ListPermutations(newprefix,neworiginal)
          
##
and now java


public static void generate(int []array){
        while(array[0]
        {
            int sum = 0;
            int n = array.length;
            int stopIndex = -1;          
            for(int i:array){
                sum+= i;
                stopIndex++;              
                if(sum>=n){
                    System.out.print( ((sum-n)>0?(sum-n):i) );                  
                    break;
                }
                System.out.print(i + " ");
            }
            sum = 0;
            counter++;
            System.out.println();                                  
            int startIndex = 1;          
            for(int i=stopIndex-1;i>=startIndex;i--)
            {
                if(array[i]
                {
                    array[i]++;
                    for(int j=i+1;j
                        array[j]=1;
                    generate(array);
                   
                }
            }
            array[0]++;
            for(int i=1;i
            {
                array[i]=1;
            }
        }
    }

as for the additional non-sense, seize your moment for you may not get a second chance and enjoy http://www.youtube.com/watch?v=g9hMLnmeNm4  awfully nice sound and words

Monday, December 27, 2010

DEBUG.exe no more

this is old stuff. debug.exe let you write assembly instructions in DOS and execute them. i was told it will no longer be on windows operating systems i think the 64 bit versions.

here is some code to print A-Z with spaces between.

a
MOV AH,02
MOV DL,41
CMP DL,5B
JE 0114
INT 21
MOV DH,DL
MOV DL,20
INT 21
MOV DL,DH
ADD DL,01
JMP 0104
RET

g
q

Wednesday, December 15, 2010

Add Page Breaks Conditionally

Sometimes after developing a report you may have a requirement to conditionally add a page break after or before each logical portion of the report. Some users may need to see all of the logical units in consecutive pages and some prefer to see each logical unit in its own page.

Here is a simple trick to conditionally add the page break. Two simple steps:


  • Put your data control(s) that you'd like to conditionally paginate within a list control.










  • Edit the Detail Group of the list control and set the Group Expression to a condition a statement that uses a parameter or some other flag to determine whether to group the list based on a variable or a constant. Here is an example: =Iif(Parameters!PageBreak.Value, Fields!ProductID.Value,"")
  • Make sure you check the "Add page break at end" in the Grouping and Sorting Properties dialog box of the enclosing list dialog; see screen shot below.



Hope this helps.

Monday, December 13, 2010

Catastrophic Computer Bugs

Some seemingly minor software bugs that had catastrophic impact (or nearly so).

http://www.pcpro.co.uk/features/363580/when-computers-go-wrong/2

I do remember the awful blackout in the fall of 2003 and it's amazing to know that it was caused by a race condition bug in a nearly 4 million lines of C code.

Monday, December 6, 2010

HTTP 401.1 When Visiting an IIS-hosted Site from the Hosting Server

This is tested on Windows 2003 sp2. The conditions:

The Problem:

  • You create a web site on IIS 6 and give the website a host header value, say, somewebapp
  • You create a dns entry of type A pointing to the IP address of the machine hosting the IIS server that's hosting your application
  • You try to visit the web app on the hosting server using the host header value somewebapp and you're prompted to enter a username and password and after entering a valid username & password, you're greeted with HTTP 401.1 Access is Denied error message. Note that if you visit the same app using the same alias from other machines, there is no problem. 
This issue did not bother me until I found out the search function on the SharePoint 3.0 server is not working. It turned out that these two issues are related. The search service on SharePoint does not work because the indexing services cannot crawl the site(s) if both the site and the indexing service are hosted on the same server. Basically, the indexing service receives the same 401.1 error you receive when visiting your apps. You may also notice that numerous warning events are logged on your windows server that's hosting the SharePoint service. These events are under 'Gatherer' category and some look like
The start address <sts3://...> cannot be crawled 
Context: Application 'Search index file on the search server', Catalog 'Search'
Details:
Access is denied.
 The Solution:


 To fix this Microsoft recommends disabling loopback check as detailed here http://support.microsoft.com/kb/896861 

The interesting thing is that if you go back to your DNS record and delete the Host A type record you created for your app and replace it with a CNAME record pointing to the name of the server and not the IP address, the problem disappears after some time after the DNS changes take effect. I tested this with some IIS apps but I did not test in isolation in the case of the SharePoint service to say for sure that changing from Host A to CNAME fixes the problem.

 


Tuesday, November 30, 2010

ContextSwitchDeadlock Exception

This ran into this strange exception which I haven't seen before.

The CLR has been unable to transition from COM context 0x33c5458 to COM context 0x33c55c8 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.
More on this exception and how to disable it from being thrown can be found here http://msdn.microsoft.com/en-us/library/ms172233(v=VS.90).aspx  and here http://blogs.microsoft.co.il/blogs/adlaim/archive/2007/08/06/The-CLR-has-been-unable-to-transition-from-COM-context.aspx

In my case, I believe the conditions that led to this exception to be thrown were caused by a call to a web service that was taking too (long > 60) seconds to either return or timeout.

Monday, November 1, 2010

Consuming Reporting Services 2005 Web Service

Reporting Service 2005 Web Service is a very useful API that lets do many tasks programmatically  such as rendering reports, uploading them, creating folders, setting properties etc.

In here I will try to show a brief tutorial on how to write a simple client that uses the SSRS 2005 Web Services. I assume you're using VS2008. The main point of this post is that when working Reporting Services 2005, you have to add a Web Service reference and NOT a Service reference. Doing so will alleviate you from having to apply the work-around shown here http://alsaydi.blogspot.com/2009/01/using-report-services-2005-web-service.html 

-- Create your project and start adding the references to the Reporting Services Web Services (ReportExecution and ReportService)
  1. Right click on your project References and select Add Service Reference the following dialg box show come up:


Now hold on. Click on Advanced because what we're trying to add is a Web Service Reference and not a Service Reference. Clicking on advanced gets you the below


Now for compatibility's sake, you have to click on "Add Web Reference ..." button  to get the below dialog box


and in the above dialog, you can now enter the URL for asmx file normally something like

http://ReportingServices_ServerName_Here/ReportServer/ReportService2005.asmx


The service you just added in the above steps will enable your project to call the Web Service to do things such as managing folder, listing reports, setting properties etc. To be able to render reports you need to add the Reporting Service Execution reference which you can do by repeating the above steps but use the URL below instead
 http://ReportingServices_ServerName_Here/ReportServer/ReportExecution2005.asmx

Now your project should be able to use the generated proxy classes to make calls against the reporting services Web Service API. There are some classes that have the same name in ReportingServices namespace and in the ReportingExecution for this reason you'll have to fully qualify your classes when you instantiate; otherwise you get "class name is ambiguous reference between ReportService2005 and ReportExecution2005". Sample code below will illustrate


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ReportingServicesClient.ReportExecution2005;
using ReportingServicesClient.ReportService2005 ;
using System.Web.Services.Protocols;
namespace ReportingServicesClient
{
    
    public class RS2005Client
    {
        private ReportingService2005 rs = null;
        private ReportExecutionService rsExec = null;
        private readonly string htmlformat = "HTML4.0";
        private readonly string excelformat = "EXCEL";
        private readonly string xmlformat = "XML";
        public RS2005Client()
        {
            rs = new ReportingService2005();
            rsExec = new ReportExecutionService();
            rs.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            rsExec.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            
        }
        public byte[] RenderReport(string path,ReportFormat frmt)
        {
            string format = null;
            switch (frmt)
            {
                case ReportFormat.HTML:
                    format = htmlformat;
                    break;
                case ReportFormat.Excel:
                    format = excelformat;
                    break;
                case ReportFormat.XML :
                    format = xmlformat;
                    break;
                default:
                    throw new Exception("RenderReport: invalid format supplied");
                    break;
            }
            return RenderReport(path, format);
        }
        private byte[] RenderReport(string path,string format)
        {
            byte[] result = null;
            string reportPath = path;// "/Cosmetic Tracking/Events";
            string historyID = null;
            string devInfo = @"False";
            #region parameters
            // Prepare report parameter.
            /*ParameterValue[] parameters = new ParameterValue[3];
            parameters[0] = new ParameterValue();
            parameters[0].Name = "EmpID";
            parameters[0].Value = "288";
            parameters[1] = new ParameterValue();
            parameters[1].Name = "ReportMonth";
            parameters[1].Value = "6"; // June
            parameters[2] = new ParameterValue();
            parameters[2].Name = "ReportYear";
            parameters[2].Value = "2004";*/
            #endregion                        
            string encoding;
            string mimeType;
            string extension;
            ReportExecution2005.Warning[] warnings = null;
            ReportExecution2005.ParameterValue[] reportHistoryParameters = new ReportExecution2005.ParameterValue[1];
            string[] streamIDs = null;
            ExecutionInfo execInfo = new ExecutionInfo();


            ExecutionHeader execHeader = new ExecutionHeader();
            rsExec.ExecutionHeaderValue = execHeader;
            execInfo = rsExec.LoadReport(reportPath, historyID);

            //rs.SetExecutionParameters(parameters, "en-us"); 
            try
            {
                //rsExec.SetExecutionParameters(reportHistoryParameters,"US-en");                
                result = rsExec.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
                            
            }
            catch (SoapException e)
            {
                throw e;                
            }
            return result;
        }
    }

    public enum ReportFormat
    {
        HTML
        ,Excel
        ,XML
    }
}

Thursday, October 7, 2010

Restoring Windows XP Files on Windows 7 Home Premium

A few days ago I bought a new computer with Windows 7 Home Premium pre-installed. After the initial setup, I tried to restore my backup from my old Windows XP system. The file was a BKF file. When I looked for the backup and restore program to read the BKF file and restore things, I found out that the file cannot read BKF. I cannot believe this! What the heck ? This is absolute non-sense!

The trick (you have to have a trick to read your OWN files on Windows 7 even though you paid $$$ for ....) anyways the trick is to copy ntbackup.exe program from another machine:

The files you'll need to copy are

ntbackup.chm
ntbackup.exe
ntbackup.hlp
ntmsapi.dll
vssapi.dll

the chm and hlp are nice to have and I don't think they are required.

copy anywhere on your new system and just start ntbackup.exe you may get a warning saying that the program cannot connect to the Removable Storage service which you can ignore and proceed to read your BKF files.

What were they thinking?

Wednesday, September 22, 2010

back to c

re-visiting C so in a couple of nights during Ramadan while waiting for suhur. I played with the anti-prime seq problem. The problem: in a sequence of integers [n,m] where 1<=n,m<=1000, determine whether the sum of each sub-sequence of length k where 2<=k<=10 is a composite integer. I started recursively but it turned out a simple while loop will do.


/**
 12 Ramadan 1431
 08/22/2010
 ***/
#include 
#include 
#include 
#include 
int init_array(int array[],int n,int m,int d);
int find_anti_prime_sequence(int array[],int i,int candidate_to_not_use,int n,int m,int d,int length);
int find_next_solution(int array[],int index,int used,int n,int m,int d,int length);
int is_anti_prime(int array[],int from,int to,int d);
int is_prime(int n);
void dump_array(const char * arrayname,int * array, int length); 
//int * numbers_ptr = NULL;
int main (int argc, const char * argv[]) {
    int i = 0;
 int n = 1;
 int m = 1000;
 int d = 10;
 int length = m - n  + 1;
 int result = 0;
 int * array = NULL;
 int temp = 0;
 //printf("enter n, m and d (0 0 0 to quit:)");
 scanf("%d%d%d",&n, &m, &d);
 while (n>0) {
  length = m - n +1;
  result = 0;
  array = (int *) malloc(sizeof(int)*length);
  temp = n;
  for (i=0; i< length; i++) {
   array[i] = temp++;
  }
  for (i=0; i< length; i++) {
   array[i] = 0;
  }
  array[0] = n;
  result = find_anti_prime_sequence(array, 0, 0, n, m, d, length);
  if (result) {
   fprintf(stdout,"%d", array[0]);
   for (i=1; i< length; i++) {
     fprintf(stdout,",%d" , array[i]);
    }
    fprintf(stdout,"\n");
   }
  else{
   fprintf(stdout,"No anti-prime sequence exists.\n");
  }  
  fflush(stdout);
  fflush(stderr);  
  free(array);
  n = 0;m=0;d=0;
  //printf("enter n, m and d (0 0 0 to quit): ");
  scanf("%d%d%d",&n, &m, &d); 
 }
    return 0;
}
int init_array(int array[],int n,int m,int d)
{
 int i=0;
 int candidate = 0;
 array[0] = n;
 
 for (i=1; i 0) {
   array[i] = candidate;
  }
  else {
   return 1;/* break or return ? we probably should and try all values of n for the first case ?*/
  }
  
 }
 return 1;
}
/***
 * This is the recursive backtracking algorithm and the iterative one too.
 *
 *******/
int find_anti_prime_sequence(int array[],int i,int candidate_to_not_use,int n,int m,int d,int length)
{
 int candidate = 0;
 if (i<0) {
  return 0;
 }
 if (i>=length-1 /* && candidate_to_not_use == 0 */) {
  return 1;
 }
 //dump_array("main array", array, i);
 //candidate = find_next_solution(array, i, candidate_to_not_use, n, m, d,length);
 while(1)
 {
  if(i<0)
   return 0;
  if(i>= length - 1)
   return 1;
  candidate = find_next_solution(array, i, candidate_to_not_use, n, m, d,length);
  if(candidate >0)
  {
   array[++i] = candidate;
   candidate_to_not_use=0;
  }
  else
  {
   
   if(i==0 && array[i] < m)
   {
    array[i]++;
    candidate_to_not_use =0;    
   }
   else
   {
    candidate_to_not_use = array[i];
    i--;
   }
  }  
 }
 /*if (candidate > 0) {
  array[i+1]=candidate;
  return find_anti_prime_sequence(array,i+1,0,n,m,d,length);
  }
  else
  {
  if (i ==0 ) {
  if (array[i] < m) {
  array[i]++;
  return find_anti_prime_sequence(array,i,0,n,m,d,length);
  }
  }
  return find_anti_prime_sequence(array,i-1,array[i],n,m,d,length);
  }*/
}
int find_next_solution(int array[],int index,int used,int n,int m,int d,int length)
{
 int candidate = 0;
 int i =0; 
 int from = 0;
 int to = index + 1;
 if (index + 1 < d) {
  from = 0;
 }
 else {
  from = index - d + 2;
 }
 if (to >= length) {
  to = length -1;
 }
 if(used > 0){
  n=used+1;
 }
 while (n<=m) {
  for (i=0; i < = index; i++) {
   if (array[i]==n /* || n <= used */) {
    break;
   }
  } 
  if (i>index)
  {
   array[to]=n;
   // dump_array("array: ", array, length);
   // fprintf(stderr, " -- %d %d\n",from  , to); 
   if (is_anti_prime(array, from, to,d)) {
    candidate = n;
    break;
   }
  }
  n++;
 }
 return candidate;
}
int is_anti_prime(int array[],int from,int to,int d)
{
 int is_seq_prime = 0;
 int current_d= 2;
 int i = 0;
 int j = 0;
 int sum = 0;
 while (current_d < = d) {
  for (i=from; i < to; i++) {
   int limit = i+current_d-1;
   if (limit > to) {
    limit = to;
   }
   for (j=i; j < = limit; j++) {
    sum += array[j];
   }
   is_seq_prime =  is_prime(sum);
   if(is_seq_prime)
   {
    break;
   }
   sum = 0;
   
  }
  if (is_seq_prime) {
   break;
  }
  current_d++;
 }
 return !is_seq_prime;
}

int is_prime(int n)
{
 int i = 3;
 int square_root = 0;
 if (n%2 == 0) {
  return 0;
 }
 square_root = sqrt(n);
 i = 3;
 for (i; i < = square_root; i++) {
  if (n%i == 0) {
   return 0;
  }
 }
 return 1;
}
void dump_array(const char * arrayname , int * array,int length)
{
 int i =0;
 fprintf(stderr, "dum_array %s: ",arrayname);
 for (i=0; i < length; i++) {
  fprintf(stderr, "%d " , array[i]);
 }
 //fprintf(stderr, "\n");
}


Wednesday, September 15, 2010

XulRunner Firefox Add-on is not Mozilla XulRunner

Recently we found a firefox instance with a strange add-on XulRunner which hijacked firefox traffic when the user went to google. This is different from XulRunner Mozilla runtime program for more on the latter see https://developer.mozilla.org/en/XULRunner

The strange add-on would make http connection and exchange data with  google.ad.sgdoubleclick.net  as someone here https://support.mozilla.com/en-US/questions/749007 said. And I believe it was also responsible for exchanging data with a server here hosted-by.leaseweb.com

Here is a document from Mozilla on how to uninstall an add-on http://kb.mozillazine.org/Extensions_Uninstall 

Tuesday, August 31, 2010

Cheer up

This is one of the stories that cheer one up

http://money.cnn.com/2010/08/23/technology/sal_khan_academy.fortune/index.htm

Khan Academy is awesome http://www.khanacademy.org/  without tutorials on math, physics finance etc.

Thursday, July 29, 2010

Back to Basics: C Basic Types and Their Representation in Memory

Great lectures Stanford put online http://www.youtube.com/watch?v=jTSvthW34GU 
The linked lecture explains very nicely two's complement are 15:00. Other great lectures in this series called Programming Paradigm.

Something I liked is that the lecturer explained why two's complement system is used to represent negative numbers. In short basically it makes basic operation like addition and subtraction really easy for hardware and thus fast. Examples are given in the lecture to illustrate.
see near the end of the lecture where representing floating-point numbers is discussed.
#include 
int main()
{
 int i = 37;
 float f = * (float *) &i;

 printf("%f\n",f);

 return 0;
}
You'll see why the code above does not print what one thinks it might print it first glance. By dereferencing a float point cast from the address of i, we're causing f to have the same pattern of 37 when interpreted as int but not the value 37.




Wednesday, July 28, 2010

Open . == Start .

If you're used to Windows command shell cmd.exe, you probably execute start . to start explorer with current directory; very nice saves a few seconds from the tedious navigation by hand.

In Mac OS X, the same thing can be done with open . or open /some/directory. Very handy.

Some variations of the open command

open . -g  : opens finder in the background

open -e filename : open filename with textedit { -t for default text editor and using -a you can specify application }

open filename : will open with default app

obviously the man pages have much more ...

Thursday, July 22, 2010

Why my Cache´/ ODBC query is awfully slow?

It's not supposed to be this slow. The query is simple, optimized, performs great in different environment /severs or it just does not make it can be this slow. We're talking about an hour to hour.5 of execution time. It just does not make sense; it was working fine a while back. What's changed?

Suddenly you visit a tab in ODBC Data Source Administrator dialog box that you rarely (maybe) check. The tracing tab. Yes the tracing tab. Tracing was active. Some drivers like Cache odbc driver gives its own logging/tracing; that can slow queries. Because the query itself; its result and statistics about it and its transmission over the network are logged to file. Sometimes every row retrieved is analyzed and logged. This surly slows down your query. You use to debug issues. you if forgotten active, it can be a hidden cause of why queries take too long to come back with results.

Something happened to me a long time ago but wanted to record it here. Sometimes a problem seems daunting, sophisticated etc but the fix is awfully simple.

Thursday, July 8, 2010

JavaScript Performance

Playing with client-side filtering. If we have a table with a number of rows, the goal is to allow a user type some text and if particular columns contain the typed text they will be left shown and the rest will be hidden (css display:none).



COL1COL2COL3
Value 1 to filter Value2 to filterValue3

First Attempt


We can have thousands of rows in a table. So iterate over all rows. for each row get its cells and then use indexOf on the cell innerText property to see if the string being searched for is in the table.

function FilterTable(tableName, text){
 var table = document.getElementById(tableName);
 var trs = table.getElementsByTagName('tr');
 var tds = [];
 if (text == '') {
 
  var tds = [];
  for (var i = 0; i < trs.length; i++) {
   trs[0].style.display = '';
  }
 }
 else {
  for (var i = 1; i < trs.length; i++) {
   trs[i].style.display = none;
   tds = trs[i].getElementsByTagName(td);
   index = tds[0].innerText.indexOf(text) + tds[1].innerText.indexOf(text);
   if (index > -1) {
    trs[i].style.display = '';
   }
  }
 }
}

I was only filtering by first and second column so I did not really iterate over every column.
The interesting thing is that this approach has a terrible terrible performance on large number of rows > 2500. The surprising thing is that even though performance is generally awful; it's even worse in Chrome than in IE8!!


Second Attempt


Playing with the above code, I noticed that the most expensive operation was actually not the indexOf call (although I didn't really use the chrome/ie8 profiler to verify this). The most expensive operation is accessing the DOM and changing properties. Namely this:
trs[i].style.display = 'none';

So in my second attempt I made some important changes:
  • in the search loop I instead saved the indices of the table rows whose cells contain the text for which the code is filtering the table. I saved those indices to an array. Later in the code I iterated quickly over the rows and set them all to hidden and one more pass over of the RowsToBeShown array and set those rows only to be visible.

  • The second change: instead of calling indexOf on two cells, I concatenated (at the server side) the contents of both cells and put them in the title property of the first cell. Now I have to call indexOf just once.

  • Another change is that I use jquery this time to select the cells to be filtered. I set the class name of the those cell to "FilterTarget".


function NewFilterTable(tableName,text)
{
  text = trim(text.toUpperCase());
     var table = document.getElementById(tableName);
     var tds = [];
     var none = 'none';
     var showthese = [];

     var j = 0;
     var td = 'td';
     var index = -1;
     if (text == '') {
         var trs = table.getElementsByTagName('tr');
         for (var i = 1; i < trs.length; i++) {
             trs[i].style.display = '';
         }
     }
     else {
         tds = $(".FilterTarget");         
         for (var i = 0; i < tds.length ; i++) {
             if (
             tds[i].title.indexOf(text) > -1 ) {
                 showthese.push(i);
             }
         }
     }
     for (var i = 0; i < tds.length; i++) {
         tds[i].parentNode.parentNode.style.display = none;
     }
     for (var i = 0; i < showthese.length; i++) {
         tds[showthese[i]].parentNode.parentNode.style.display = '';
     }
     return true;
}
Although I am still iterating twice over the tds array, moving the DOM accessing code out of the search helped performance big time. Withe first approach, Chrome would choke when the filter function is called and give the user a choice to stop executing the JavaScript code. IE does take very long time relatively speaking to run through the filtering code. With the seconds approach and with the same number of rows in the table, both IE8 and Chrome take about 3-5 seconds to run the function.
I am sure that are better ways/well-tested libraries that will do the filter much better but it's rather interesting what moving things around can do to performance. I will see what jQuery API can do here and also jQrid plugin for jQuery is awesome by the way for showing tables and doing an amazing number of things http://www.trirand.com/blog/
here the trim function


function trim(text) {
     return text.replace(/^\s+|\s+$/, '');
 }



I changed some variable names and minor things while typing up this post, so there might some js errors

Saturday, July 3, 2010

css dropdown menu

just a very simple css styling with a bit of javascript code to create a drop down list with one just one level of nesting for now. will put here for reference
<script type="text/javascript">
function countdown (num) {
alert('testing ...');
        for (var i = 0; i <= num; i += 1) {
           // setTimeout(function(){doAlerts(num,i)} , i * 1000);
         setTimeout('doAlerts('+num+','+i+');' , i * 1000);

}
}
//
function doAlerts(num,i)
{
 alert(num - i);
}
    //countdown(5);
var g_display = 'block';
function toggleSubMenu(sender)
{
 var display = sender.getElementsByTagName('ul')[0].style.display;
//alert(display);
 if(display != null && display != '')
{
  g_display = display ;
  sender.getElementsByTagName('ul')[0].style.display = '';
}
else
{
  sender.getElementsByTagName('ul')[0].style.display =  g_display;
}
}
</script>
<style type="text/css">
.menu
{
}
.menu > li
{
 float:left;
 margin-right:1px;
 padding: 0px 5px 0px 5px;
 list-style-type:none;
 border: solid 1px #c4c4c4;
 background-color:#c1c1c1;
 width:120px;
}
.menu > li:hover
{
 /* background-color : blue; */
}
ul
{
 padding: 0px 5px 0px 5px;
 list-style-type:none;
 border: solid 1px #c4c4c4;
}
ul li ul
{
 display:none;
 padding: 0px 0px 0px 0px;
 list-style-type:none;
 border: solid 1px #c4c4c4;
}
ul li ul li
{
 display:block;
}
ul li ul li:hover
{
 background-color:#549ade;
}
</style>
 <input onclick="countdown(5);" type="button" value="Do It" />


<ul class="menu">
<li onmouseout="toggleSubMenu(this);" onmouseover="toggleSubMenu(this);">
        Thing 1
        
<ul>
<li>Subthing A</li>
<li>Subthing B</li>
<li>Subthing C</li>
</ul>
</li>
<li onmouseout="toggleSubMenu(this);" onmouseover="toggleSubMenu(this);">
        Thing 2
        
<ul>
<li>Subthing D</li>
<li>Subthing E</li>
<li>Subthing F</li>
</ul>
</li>
<li onmouseout="toggleSubMenu(this);" onmouseover="toggleSubMenu(this);">
        Thing 3
        
<ul>
<li>Subthing G</li>
<li>Subthing H</li>
<li>Subthing I</li>
</ul>
</li>
</ul>

Wednesday, June 30, 2010

We are What We Choose: Jeff Bezos to Princeton Class of 2010

I enjoyed reading Jeff Bezos' (Amazon CEO) remarks delivered to Princeton class 2010.
Some valuable advice and interesting stories.

http://www.princeton.edu/main/news/archive/S27/52/51O99/index.xml

An excerpt from the remarks:
Tomorrow, in a very real sense, your life -- the life you author from scratch on your own -- begins.

How will you use your gifts? What choices will you make?
Will inertia be your guide, or will you follow your passions?
Will you follow dogma, or will you be original?
Will you choose a life of ease, or a life of service and adventure?
Will you wilt under criticism, or will you follow your convictions?
Will you bluff it out when you're wrong, or will you apologize?
Will you guard your heart against rejection, or will you act when you fall in love?
Will you play it safe, or will you be a little bit swashbuckling?
When it's tough, will you give up, or will you be relentless?
Will you be a cynic, or will you be a builder?
Will you be clever at the expense of others, or will you be kind?

Monday, June 28, 2010

How Some Things are Done in Facebook: Operations at Facebook

via slashdot: an amazing talk on several aspects of operations at fb. include infrastructure, configuration management, code deployment, monitoring etc.

A few things I took from the talk:
  • over 300 TB of data live in RAM served out of memcached

  • HipHop for code transformation from PHP to C++
    CFengine for configuration management

  • BitTorrent for code deployment {several 100s megabytes of code deployed to 10s of 1000s of machines to facebook.com }

  • Ganglia for monitoring

  • On-Demand tools: used for things like on-demand fix a mistake that escaped engineers in testing/deployments stages. Facebook used to use DSH but they outgrew it so FB built their own tool. Don't know if they made open source yet, the lecturer said he could not talk too much about it. ????? it allows making changes very quickly.


  • Facebook pushes code at least once a day and weekly pushes out new features not necessarily turning them on.

  • Normal software development structure Software engineers -> QAs -> operations. Facebook gets rid of the middle layer and delegate its tasks to first layer.

  • Facebook is loose on change management but very heavy on logging


  • very interesting talk. link here

    Also notice youtube new feature. still in beta but amazing { transcribe audio and translate sub-titles.}



    very cool.

    Wednesday, June 23, 2010

    Google between Auto-Complete and Searches History

    Ever used google's search textbox found in the bottom of its results page? It's actually a bit different than the upper search textbox. A long time ago google introduced auto-complete first in home page and next in the results page. But lately I noticed that in the results page the upper textbox auto-completes and the bottom one auto-completes from your search history. I think it's very cool; this way you have both options.

    Also the other neat thing is that Google's auto-complete feature is location-aware. So if you type something, Google will auto-complete for you based on top searches and trends originating in your locality first and if there is not it goes globally. also neat.

    Write but Can't Read

    an author of many books (Howard Engel)  found himself one morning unable to read but yet he was/is able to write. Wrote even two more books according to

    http://www.npr.org/templates/story/story.php?storyId=127745750

    Friday, April 30, 2010

    Steve Jobs on Flash and the iX Platform

    http://www.apple.com/hotnews/thoughts-on-flash/

    New open standards created in the mobile era, such as HTML5, will win on mobile devices (and PCs too). Perhaps Adobe should focus more on creating great HTML5 tools for the future, and less on criticizing Apple for leaving the past behind.


    It's very interesting and I don't mind seeing less of Flash and more HTML5.

    Monday, April 12, 2010

    Tableless

    I just wanted to post this html code here for my future reference.  This document was originally auto-generated to show some images. The tool generated table tags and used rowspan and colspan in ways that caused most browsers to show gaps between certain images.

    I converted the code to use ol tag and with some css styling (using float and display properties) the images lined up perfectly on standards compliant browsers (chrome, firefox) .

    For IE7 and below I used conditional commenting to raise up some of the images.

    Note that when using a layout like the one shown below and when the browser's window is resized, the images will move to fit new window's size. To prevent images relocation, I set the display property of the ol tag to table so it will behave like a table. However IE6 and I think IE7 does not respect this property so I added an actual table around the ol tag.


    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <style type="text/css">
      body
      {
      margin:0px;
      padding:0px;
      }
      table
      {
      margin:0px;
      padding:0px;
      }
      img
      {
      display:block;
      margin:0px;
      padding:0px;
      background-color:#75b044;
      }
      ol
      {
      list-style-position: outside;
      list-style-type:none;
      margin:0px;
      padding:0px;
      display:table;
      }
      li
      {
      margin:0px;
      padding:0px;
      
      
      }
      .li1
      {
      float:left;
      margin-top:0px;
      }
      .li2
      {
      float:left;
      margin-top:-1px;
      }
      .moveleft
      {
      margin-left:-1px;
      }
    </style>
    </head>
    <body>
      <!--[if lte IE 7]>
          <style>
     .li1
     {
     margin-top:-4px;
     }
     .li2
     {
     margin-top:-20px !important;
     }
     </style>
          <![endif]-->
      
      <table cellpadding="0" cellspacing="0"><tr><td> 
    <!-- added table to prevent images from re-locating-->
    <!-- when window is re-sized in IE6 because it does not -->
    <!-- respect display:table css property -->
     <ol>
       <li>
         <img  id="banner"  alt="" src="" />
         </li>
       <li class="li1">
         <img  id="leftRowSpan1" alt="" src="" />
         </li >
       <li class="li1">
         <img  id="leftRowSpan2" alt="" src="" />
         </li>
       <li class="li1">
         <img id="rightRowSpan1"  alt="" src="" />
         <img id="rightRowSpan2"  alt="" src="" />
         </li>
       <li style="clear:both;"  > </li>
       
       <!-- third row -->
       <li class="li2 ieli2">
         <img id="leftRowSpan3" alt="" src="" />
       </li>
       <li class="li2 ieli2">
         <img id="leftRowSpan4" alt="" src="" />
         </li>
       <!-- third row right images -->
       <li class="li2 ieli2 moveleft">
         <img id="rightRowSpan3" alt="" src="" />
         <img id="rightRowSpan4" alt="" src="" />
       </li>
       <li style="clear:both;"></li>
       <li class="li2 ieli2">
         <img id="leftColSpan1" alt="" src="" />
         </li>
       <li class="li2 moveleft">
         <img id="rightColSpan2" alt="" src="" />
       </li>
       <li style="clear:both;"></li>
       <li class="li2 ieli2">       
         <img alt="" src=""/>
         </li>
       <li class="li2 ieli2 moveleft">
         <img alt="" src="" />        
       </li>
       <li style="clear:both;">
          <img id="footer" alt="" src=""/>        
          </li>
            </ol>
     </td></tr></table>
    </body>
    </html>
    
    
    

    Wednesday, April 7, 2010

    Keyboardless Future

    We will see more and more touch-enabled computing devices. But will touchscreens be the norm and keyboards the exceptions.

    http://www.readwriteweb.com/archives/farewell_keyboard_generation_i_will_grow_up_on_touchscreens.php

    Wednesday, March 17, 2010

    Phone BSoD

    as you can in image, my phone showing "the blue screen of death" there are some debugging information mot_nvim_glue.c and the line number too. some other debugging info are given too. It turned out that motorola was sending emails with these debugging information from my phone directly to there servers.