Wednesday, July 25, 2007

what I did last year?

C code : 13000 lines
Java code : 8000 lines

for the last week...I wrote 4000 lines C++!! and more work are coming.

Wednesday, July 18, 2007

don't abuse OS's cache

I was writing a simple program, open a file, read the data. Each data structure is n bytes.
At first, I read it once a block (n bytes). I think it is fastest, because when I read the first block, OS should cache the whole page ( i.e. 4K) for future use. So when I fetch the next block, it doesn't need to load from hard-disk.
But when I change the reading method, each time reads 4K in to buffer, then separate from buffer, the speed boost up like 10 times.
Why? I think the reason lies in when you ask OS to load data, it will invoke system call, then Interrupt, and the OS copy the data from kernel mode to user mode for your use. This also cost time.

Tuesday, July 17, 2007

direction of computing

Moshe Bar, openMosix founder and project leader, also engage Xen, KVM, has decided to close openMosix, and focus on single machine's computing.

Hmm, I have loved both three technology, was hoping openMosix can turn hundreds of old machine into a super power computer.

But now, hardware development out weight the software. multi-cpu, multi-core has gained more attention. I hope this can give us unlimited computing power.

here is the announce:
link: http://sourceforge.net/forum/forum.php?forum_id=715406

Posted By: bruceknox
Date: 2007-07-15 09:35
Summary: openMosix Project End of Life Announcement

Tel Aviv (July 15, 2007) - openMosix Project Ending

Moshe Bar, openMosix founder and project leader, has announced plans to end the openMosix Project effective March 1, 2008.

The increasing power and availability of low cost multi-core processors is rapidly making single-system image (SSI) Clustering less of a factor in computing. The direction of computing is clear and key developers are moving into newer virtualization approaches and other projects.

openMosix has been a very successful project with tens of thousands of installations. Another measure of this success is found in the many projects that have incorporated openMosix into their own products.

openMosix’ Auto-Discovery innovation paved the way for the Instant SSI Clusters that soon exploded the number of cluster installations. Instant Clusters made installation and setup automatic for the non-computer specialist and for the first time brought significant computing power to many researchers worldwide.

openMosix also broke new ground in Operating Systems theory including important lessons learned in Distributed Shared Memory and other challenging areas. Many individuals have learned Linux kernel development through openMosix which has been used in computing curriculum, laboratories, and research.

openMosix source will remain on SourceForge indefinitely, frozen as of March 1st, 2008. The openMosix website will remain open until March 1st, 2008 and the openMosix-Devel List will close as of December 1, 2007.

Moshe Bar stated that, “I wish to thank all the users and developers who enthusiastically supported openMosix and made the project such a success.”

Project website is http://www.openmosix.org/

openMosix is a Linux kernel extension for single-system image (SSI) clustering that allows building a cluster from ordinary networked computers. Applications benefit without modification specifically for openMosix.

auto generate code using UML

hum, finally feel why drawing UML is helpful. since it can generate code (the dumpy and duplicate part), release programmer's work. And you have a cool drawing and deep thought before coding. :)

ps: I use open source tool dia to draw UML, and it can generate code. or use dia2code.

Sunday, July 15, 2007

automatic test for http interface

Ha~ I wrote a AJAX web page last night, which will run several cases, each post different data to my fcgi program, and check the return value, then output PASS or FAIL. And a simple synchronize for separate running tests.
That make QA life easier.

here is my page:

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

<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<title>login test</title>

</head>



<body>

<script type="text/javascript" language="javascript">

var http_request = false;

var output = null;

var expect = null;

var pass_out = null;

function makePOSTRequest(url, parameters) {

http_request = false;

if (window.XMLHttpRequest) { // Mozilla, Safari,...

http_request = new XMLHttpRequest();

if (http_request.overrideMimeType) {

// set type accordingly to anticipated content type

//http_request.overrideMimeType('text/xml');

http_request.overrideMimeType('text/html');

}

} else if (window.ActiveXObject) { // IE

try {

http_request = new ActiveXObject("Msxml2.XMLHTTP");

} catch (e) {

try {

http_request = new ActiveXObject("Microsoft.XMLHTTP");

} catch (e) {}

}

}

if (!http_request) {

alert('Cannot create XMLHTTP instance');

return false;

}



http_request.onreadystatechange = alertContents;

http_request.open('POST', url, true);

http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

http_request.setRequestHeader("Content-length", parameters.length);

http_request.setRequestHeader("Connection", "close");

http_request.send(parameters);

}



function alertContents() {

if (http_request.readyState == 4) {

if (http_request.status == 200) {

//alert(http_request.responseText);

result = http_request.responseText;



// code for IE

if (window.ActiveXObject)

{

var doc=new ActiveXObject("Microsoft.XMLDOM");

doc.async="false";

doc.loadXML(result);

}

// code for Mozilla, Firefox, Opera, etc.

else

{

var parser=new DOMParser();

var doc=parser.parseFromString(result,"text/xml");

}



var xml=doc.documentElement;

document.getElementById(output).innerHTML = xml.childNodes[1].childNodes[0].nodeValue;

if ( parseInt(document.getElementById(output).innerHTML) == parseInt(expect))

{

document.getElementById(pass_out).innerHTML = "<font color=\"green\">" + "PASS" + " </font>";

}

else

{

document.getElementById(pass_out).innerHTML = "<font color=\"red\">" + "FAIL" + " </font>";



}

} else {

alert('There was a problem with the request.');

}

mutex = 1;

}

}



var mutex = 1;

function get(user, pass, my_output, my_expect_output, my_pass_out) {

if(mutex == 1)

{

mutex = 0;

var poststr = "user=" + encodeURI( document.getElementById(user).value ) +

"&pass=" + encodeURI( document.getElementById(pass).value );

output = my_output;

pass_out = my_pass_out;

expect = document.getElementById(my_expect_output).innerHTML;

makePOSTRequest('/cgi-bin/login.fcgi', poststr);

}

else

{

setTimeout('get(\"'+user+'\",\"'+pass+'\",\"'+my_output+'\",\"'+my_expect_output+'\",\"'+my_pass_out+'\")', 1000);

}

}



function test_all()

{

document.getElementById("button1").click();

document.getElementById("button2").click();

document.getElementById("button3").click();

document.getElementById("button4").click();

document.getElementById("button5").click();

document.getElementById("button6").click();

document.getElementById("button7").click();



}



</script>

<input name="TestALL" type="button" value="TestALL" onclick="javascript:test_all();"/>



<table width="894" border="1">

<tr>

<th width="94" scope="row">TestCase</th>

<th width="174" scope="row">Aim</th>

<th width="174" scope="row">input</th>

<td width="194">expect output </td>

<td width="192">actual output </td>

<td width="10">Run</td>

<td width="10">Pass?</td>

</tr>

<tr>



<th scope="row">1</th>

<th scope="row">correct</th>

<th scope="row">Username

<input name="user" id="user1" type="text" value="abc" />

<br/>

Password

<input name="pass" type="password" id="pass1" value="abc" /></th>

<td><span id="expect1">0</span></td>

<td><span id="output1"></span></td>

<td><input name="button1" type="button" id="button1"

onclick="javascript:get('user1','pass1', 'output1','expect1', 'pass_out1');" value="test" /></td>

<td><span id="pass_out1" ></span></td>



</tr>

<tr>





<th scope="row">2</th>

<th scope="row">mising username </th>

<th scope="row">Username

<input name="user" id="user2" type="text" />

<br/>

Password

<input name="pass" type="password" id="pass2" value="abc" /></th>

<td><span id="expect2">-40001</span></td>

<td><span id="output2"></span></td>

<td><input name="button2" type="button" id="button2"

onclick="javascript:get('user2','pass2', 'output2','expect2', 'pass_out2');" value="test" /></td>

<td><span id="pass_out2" ></span></td>



</tr>

<tr>





<th scope="row">3</th>

<th scope="row">mising password </th>

<th scope="row">Username

<input name="user" id="user3" type="text" value="abc" />

<br/>

Password

<input name="pass" type="password" id="pass3" /></th>

<td><span id="expect3">-40001</span></td>

<td><span id="output3"></span></td>

<td><input name="button3" type="button" id="button3"

onclick="javascript:get('user3','pass3', 'output3','expect3', 'pass_out3');" value="test" /></td>

<td><span id="pass_out3" ></span></td>



</tr>

<tr>





<th scope="row">4</th>

<th scope="row">incorrect username </th>

<th scope="row">Username

<input name="user" id="user4" type="text" value="abcd" />

<br/>

Password

<input name="pass" type="password" id="pass4" value="abc" /></th>

<td><span id="expect4">-40003</span></td>

<td><span id="output4"></span></td>

<td><input name="button4" type="button" id="button4"

onclick="javascript:get('user4','pass4', 'output4','expect4', 'pass_out4');" value="test" /></td>

<td><span id="pass_out4" ></span></td>



</tr>

<tr>





<th scope="row">5</th>

<th scope="row">incorrect password </th>

<th scope="row">Username

<input name="user" id="user5" type="text" value="abc" />

<br/>

Password

<input name="pass" type="password" id="pass5" value="abcd" /></th>

<td><span id="expect5">-40003</span></td>

<td><span id="output5"></span></td>

<td><input name="button5" type="button" id="button5"

onclick="javascript:get('user5','pass5', 'output5','expect5', 'pass_out5');" value="test" /></td>

<td><span id="pass_out5" ></span></td>



</tr>

<tr>





<th scope="row">6</th>

<th scope="row">both incorrect</th>

<th scope="row">Username

<input name="user" id="user6" type="text" value="abcd" />

<br/>

Password

<input name="pass" type="password" id="pass6" value="abcd" /></th>

<td><span id="expect6">-40003</span></td>

<td><span id="output6"></span></td>

<td><input name="button6" type="button" id="button6"

onclick="javascript:get('user6','pass6', 'output6','expect6', 'pass_out6');" value="test" /></td>

<td><span id="pass_out6" ></span></td>



</tr>

<tr>





<th scope="row">7</th>

<th scope="row"><p>Server </p>

<p>internal</p>

<p>error </p></th>

<th scope="row"><p>need to test by hand </p>

<p>Username

<input name="user7" id="user7" type="text" value="abcd" />

<br/>

Password

<input name="pass7" type="password" id="pass7" value="abcd" />

</p></th>

<td><span id="expect7">-40002</span></td>

<td><span id="output7"></span></td>

<td><input name="button7" type="button" id="button7"

onclick="javascript:get('user7','pass7', 'output7','expect7', 'pass_out7');" value="test" /></td>

<td><span id="pass_out7" ></span></td>



</tr>

</table>







</body>

</html>

use rude::cgi in fastCGI

rude::cgi was designed for CGI. when I put it in use for my fastCGI program, I make it a patch.
1) rude::cgi use singleton pattern , which doesn't work under fastCGI, because fcgi need to create new instance each time to parse new request. So I modify rude's constructor and destructor, make it destroy the instance after use.
2)fastCGI replace the stdio.h, and most of its functions. so where rude::cgi uses stdio.h, put #include before #include . that will work.

I am enjoying fast speed of fastcgi, while easy programming with rude::cgi.


ps:I have tried to use qDecoder, also patch a similar modification, but it doesn't work for fcgi (giving a signal 11, SIGSEG ). but it works under cgi mode. I have no idea.