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
    }
}