Put your message here! Contact me for more information
 
 







 

Archive for December, 2006


 

Slashdot today (Dec 28, 2006) has a link to an article on WSJ about a conversation between 2 venture capitalists. One of them is claiming Web 2.0 is another bubble and the other one claims the otherwise. My take on it: Web 2.0 is NOT another bubble like what happened during the dot-com boom and burst. Why? It’s not general public money that are pumped into the web 2.0 ecosystem like what happened 7 years ago with web 1.0. Base on that fact alone, I can safely back my claim.

To a lot of people who are monitoring and following the news on web2.0, it may seems like a bubble is forming. A classic example: we saw that Youtube got bought with $1.65 bln. How on earth a FREE video sharing site with NO real business plan besides selling ads inventory, e.g. eye-sights, is worth that much? It’s hard to believe. Another speculative number from the WSJ article: Facebook is valued at $500. Sure, whatever. I have to admit that I used facebook once in a while to keep in touch with friends, maybe writing on their walls some b-day notes. The truth is when thefacebook.com’s version for Lake Forest College was available, some of my friends assumed that I had built the site. Because not long before that, I had built www.247lfc.com, an online classified-ads for the college and got some reputations ’round campus — not enough to impress the freshman chicks (I just finished by Sophormore year at the time) but enough to raise a few eyebrows of the faculty and cause dis-comforts to the monopoly on-campus e-follet bookstore. Anyway, to me, fundamentally, facebook is more like a week-end project of a student. Slapping a guesstimate value-tag of anything above a few million dollars is already a hard-to-believe thing, not to mention the ridiculous number of $500 million.

However, these 2 examples above and many not-mentioned cases is not a sign of a forming bubble. They are merely examples of over-valued IT products, which happens to be the expensive merchandise deep-pocket companies like Google, MS, Viacom, etc. want to possess. Women like jewelry and nice accessories. Rich women like expensive handbags and sparkling diamonds. Similarly big companies like to have controversial, widely-known products. If they don’t have anything to brag about, they will buy a product with a premium. But that’s about it about this web 2.0 bubble.

There are a few profound reasons why the wave of Web 2.0 companies is not a bubble.

1. There are not enough big companies out there to cause a massive injection of public cash into the market.
If we look around, we can only name a few really successful companies. It’s true that for every one of those successful companies, there are 10 more of the copy-cats. This is because the nature of Web 2.0 companies: very low barrier to entry. Begin with a javascript framework, slapping on some stripy, shiny, cheerful designs and we have a web 2.0 product or service. However, at the end of the day, the general public generally stays unmoved. People don’t even know about the existence of those companies, not to mention about investing in those companies. I don’t hear anyone mentions alot about IPOs these days, besides the flopped IPO of Vonage last year, and Vonage is not even considered a web 2.0 company.

2. The invested money are by Venture capitalists only, not by general public.
What made the dot-com boom was not the VCs. Yes, VCs commands lots of money, but it was the general public’s interests on the companies at the time that caused the massive injection of cash into the internet. Usually VC’s funding are cost-prohibitive to the general public — I don’t think any VC would accept a small investment of $20,000 from this random old man on the street to so that the guy can participate in the VC’s game. VC’s get funding from rich or uber rich guys because it’s all about the risk/reward ratio: the rich can take more risks so they can play the higher reward game with more money at stakes. The general public are less fortunate, we loose a few thousand dollars in stocks and we will show a disgusting face when someone mentions that company’s name again. The Risk/Reward ratio is of ordinary people are so low that we can’t invest in anything other than ourselves (e.g. paying for college). Since there are not enough IPO’s going around, and people still have the scar of the last burn from the dot-com explosion, the general public are safe from web 2.0 this time. Without the money of the mass, there won’t be any bubble at all.

With that said, where are we heading in the near future? I can see that we will have some consolidations among the copy-cats. Some of the grass will die, or weeded out because the lack of nutritions due to the absence of a real business plan. In stead of seeing 20, or 30 YouTube clones, we will see 2, or at most 3. In stead of seeing 50 Myspace clones, we will hear about 3, or 4, or less.

The overall trend will be the localization of popular services to a per-country basis. Even though MySpace is big in the States, Bebo is leading in Europe, or in South Korea or China, there are major local brands that leave MySpace in the distant trail. Take Ebay: they were just reported to begin waving the white flag, giving up China’s market. So localization is the big trend in the coming year. Successful services or products are ported and modified to work better with the local people. And most of the time, Western companies are very slow in terms of internationalizing or localizing their products and services. Hence, they are likely not able to compete with local companies offering the same or copy-cat products.

Also, I would expect to see more sophisticated Web 2.0 services, instead of the cut-and-paste mashed up services that have mushroomed for the past 2 years. Take the new Yahoo Mail beta as an example: the free webmail serivce behaves more and more like a desktop application with sophisticated features that even a few years ago very few people would imagine. Together with the maturing Javascript frameworks (Dojo, YUI, Google Toolkit, etc.), more soup-ed up applications can be built. A consequence of this fact is building up a web 2.0 application is not a trivial or easy task like what we have seen and experienced: building a working, functional web 2.0 application will require serious planings, engineering of infrastructure, and software design. Such things requires skill and efforts, and they are the results of serious investment in terms of time, money, and human resource. Effectively we will see larger micro-ISV (independent software vendor) putting out applications, instead of a one-man-team or two-man-team like before.

In brief, what currently happens with the Web 2.0 lanscape is low barrier-to entry of AJAX technology leads to the proliferation of new web 2.0 applications. Financial-wise, I don’t see a bubble at all. If there is, then it’s just the beginning, not the end. For me, I’ll hope on the web2.0 wagon and enjoy the ride. It’s too much of a good opportunity to miss out. The thing is, are you ready when the time comes?

view comments
 


I was working on some javascript stuff for a project and ran into this problem with setInterval(): for IE 6, calling setInterval() to an object’s method results in the wrong scope. In the object’s method, the alfamous **this** keyword now refers to **window**, instead of the conventional “this” as in “**this object**”. So let me give you some more details on this and a free, amazingly simple solution to this head-ache.

**SPOILER:**\\ the solution uses eval(). if you are allergic to eval(), don’t take my advice.\\ **END SPOILER**

===== The code =====
Let’s look at some code and we’ll have a little discusssion. Here’s the psuedo-code for a fictional TimeTicker object, which is supposed to automatically update a “clock” on the screen every second.


/* A. Constructor */
function TimeTicker()
{
/* A.1 - populate internal variable here, like hour, minute, second, etc. */
...

/* A.2 - now we set the timer to periodically update the time value every 999 miliseconds */
this.timer = setInterval( this.updateTime, 999 );
}

/* B. This function is to update the time value somewhere on the screen */
TimeTicker.prototype.updateTime = function ()
{
/* B.1 - compute new value */
...
this.hour = new_hour_value;
this.minute = new_minute_value;
this.second = new_second_value;
...

/* B.2 - now update the screen */
...
}

===== The problem =====
The above psuedo code will sadly **FAIL** in both IE and FF (not because it’s only psuedo-code!), as the ‘’setInterval()” invocation has **totally changed the scope** of the polled function. First of all, let’s look at ”**A.2**” from above. Calling ”this” within the ‘’setInterval()” will change the reference of ”this” to some other object (which I think is ”this” now refers to ”window”.) Hence calling ‘’setInterval( this.updateTime, 999 )” fails in both Firefox and IE 6, as it means that the ‘’setInterval()” will poll the ”window.updateTime()” function every 999 ms. That’s not what we want, and ”window” object could care less about our ”updateTime()” since we suddenly found ourselves in the wrong scope.

===== The Firefox’s Solution =====
For firefox, the fix is a small rewrite of how we would call the polled-function, updateTime(). The setInterval() function in Firefox is improved and we can now pass an extra parameter to it, and that’s exactly what we will do. We pass in the current object’s reference as ”this” to the a proxy function, which in turn makes a call to the updateTime(). I found this solution through [[http://www.klevo.sk/javascript/javascripts-settimeout-and-how-to-use-it-with-your-methods/|Klevo’s blog]], a web developer from Slovakia.

We will have to rewrite ”**A.2**” as follows:


/* A.2 */
this.timer = setInterval ( function( that ) { that.updateTime(); }, 999, this );

What we just did is we create a proxy function, whose only parameter is ”that”, a pointer to another object. Within this proxy function, we can make invoke all of “that”’s methods! Basically we migrate the scope of ”this” as a reference to the current ”TimerTicker” object into the polled proxy function via a pass-by-reference ”that” parameter. Notice the extra 3rd parameter of ‘’setInterval()”: we are passing ”this”, in this case, a reference to the current ”TimeTicker” object, as the only parameter of the newly created proxy function. Since now ”that” is equivalent to ”this”, we can call all methods of TimeTicker object! Beautiful!

===== The Internet Explorer’s Problem =====
While setInterval() in Firefox provide us a way to pass in extra parameters, IE’s version of ‘’setInterval()” is less flexible (and it also did drive me nuts!) Anyway, let’s talk about the mechanism of IE’s ‘’setInterval()”. According to [[http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/setinterval.asp|MSDN’s manual on setInterval()]], the syntax of setInterval() is

”iTimerID” = ”window”.**setInterval(** ”vCode”, ”iMilliSeconds” [, sLanguage])

with ”vCode” is either a reference pointer or a “string that indicates the code to be executed when the specified interval has elapsed”. Since there’s no way we can pass an extra parameter to the polled-function, we cannot pass ”this” as a 3rd parameter of setInterval() as what we just did for Firefox.

If we rewrite the code as this.timer = setInterval ( this.updateTime(), 999);then 2 things are gonna happen: first,” this.updateTime()” is executed right away. It’s equivalent to a direct call to the ”updateTime()” function of the current object, ”TimeTicker”. As we are still in the scope of the current function, hence, ”this” refers to the current ”TimeTicker” object. Secondly, after the 999ms has elapsed, ‘’setInterval()”" will invoke ”this.updateTime()”, and now ”this” refers to ”window” as we are now out of the scope of the ”TimeTicker” object. And of course, ”window.updateTime()” is wrong. So what you see is that your script will work the first time (when this.updateTime() is executed in the correct scope), and then everything fails (when this.updateTime() is excuted by setInterval() in the wrong scope).

And If we write this.timer = setInterval ( this.updateTime, 999);(Notice the missing parenthesis). This will also fails as when this.updateTime is invoked, we are already in the wrong scope, the scope of ”window” object!

On the other hand, if we writethis.timer = setInterval ("this.updateTime()", 999);we are still in the wrong scope when setInterval() invoke the updateTime() method. ”this” still refers to ”window” when the updateTime() function is executed. Notice that we can include the parenthesis “( )” (and potentially other pass-by-value parameters since the method is refered to as a string and it’s not executed right away, but only when being invoiked by ‘’setInterval()”). However, we can’t pass a pointer to the current object in a string!

We’d like to pass a pass-by-reference pointer object to point to the current ”TimeTicker” object but no matter what we do, we cannot seem to do so. But be hold! Our salvation comes from the use of a glorifying global variable, and of course, a dash of ”eval()”, just enough to tame Internet Explorer.

===== The Internet Explorer’s Solution =====
I’d like to include the code for IE here, just read over and we will discuss later.


/* C. global scope object */
var globalScope = new Array();

/* A. Constructor */
function TimeTicker()
{
/* A.0 - An extra unique identifier for the current object */
this.uniqueId = some_text_or_numers;

/* A.1 - populate internal variable here, like hour, minute, second, etc. */
...

/* A.3 - setInterval Fix */
/* A.3.1 - for IE */
if( document.all )
{
/* A.3.1.1 - make a reference to the current object and saved in the global scope array
* to use later to correct the scope.
*/
globalScope[ this.uniqueId ] = this;
setInterval( 'ieIntervalHandler("' + this.uniqueId + '","updateTime")', 999 );
}
else
{
/* A.3.2 - Mozilla */
this.timer = setInterval ( function( that ) { that.updateTime(); }, 999, this );
}
}

And we add an extra function, ”ieIntervalHandler( **id**, **strFunc** )” to the script.

/* D. - Special IE setInterval handler function with scope corrected */
function ieIntervalHandler( id, strFunc )
{
/* D.1 - correct the scope then make the call */
var scope = globalScope[id];
eval( "scope." + strFunc + "()" );
}

All set? Here comes the explanations: First of all, we added a global associative array named globalScope (”**C**”). This associative array is used to store reference to a particle object based on that object’s unique identifier. Confused? Not a problem, just keep on reading.

Let’s read A.0, this is where we set the unique identifier for this ”TimeTicker” object. For this technique to work, each object **must** have a **unique identifier** since the unique identifier is used as the **key** of the global associative array.

Look at ”**A.3.1**”. Here we do a little browser-intelligence. If the browser doesn’t know ”document.all”, which is IE-specific, we use the improved version of ‘’setInterval()” as mentioned in the above Firefox’s solution section. If the browser is indeed IE, at ”**A.3.1.1**”, we store the reference to this ”TimeTicker” object as an element in the globalScope associative array. Then we cheerfully and confidently ‘’setInterval()” the ”ieIntervalHandler()” function (see ”**D.1**”). We do a pass-by-value the unique ID of the current ”TimeTicker” object as the first parameter of ”ieIntervalHandler()”, and ”updateTime” as the name of the method of the same ”TimeTicker” object.

Look at ”**D.1**”. Here we have a 2-line function. First, we get the reference to the particular TimeTicker object, which we already stored in the globalScope associative array back in ”**A.3.1.1**”. Since we are now in the scope of ieIntervalHandler(), our ‘’scope” variable is pointing to the ”TimeTicker” object. With the correct reference to the correct object, now we can make the call to the correct method with a quick, painless ”eval()”eval( "scope." + strFunc + "()" );

What did we just do? We use a global array to store the references so that later on we can get to the right object, even when ieIntervalHandler is invoked by ‘’setInterval()” and the scope now is all over the place — we could care less! Hence we now can solve the wrong scope issue within IE. And guess what, now we can have any object to poll a method of itself! How awesome is that?

===== Memory Issue =====
Since we need to keep polling a function, we need to be careful of not creating more and more objects or functions that the garbage collect will never be able to purge because of a hidden reference somewhere. If you do create a lot of objects that do self-polling using this global associative array technique, when destroying the object, you will probably have to set the element of the globalScope to ”**null**” also, so that there is no further reference to the destroyed object. Also, in ”**A.3.2**”, we do create a new function everytime we’d like to run the timer, this may be a potential memory leaking point on Firefox.

I’d like to leave the quest of battling memory-leak monster to somebody else, but just remeber to watch out for potential weak point where memory leak can happen, especially when your page will be opened for a prolonged preriod of time.

===== Keywords spam =====
This setInterval() and the scope problem is a pretty abstract and hard to describe problem. I just include some potential search keywords here so that other people can by chance find this page. Call it keyword spam, call it shameless-self advertising, I could care less, but if somebody find this helpful, then I call it success :)

setInterval scope loosing, setTimeout, this setInterval wrong scope, javascript setInterval scope, global associative array scope correction, object oriented setInterval, self polling, this polling scope error, internet explorer setInterval fail, firefox setInterval fail, setInterval object.

===== Final remarks =====
Thank you for reading! I hope this helps. And I’d like to wish you a …

Merry Christmas and Happy New Year!

4:13AM, Dec 23, 2006.

view comments
 

SpamFor the past few days I’ve been experiencing very high volume of spam comments. It’s about 500 per day, more or less — at least for the last 4 days! I wonder why there is a sudden jump in the volume of spam comments. Askimet told me that it has caught more than 10,000 comments since I started this blog in March 2006. I guess it’s because my blog has some page-rank (it was 4, then 3 untill now after 1and1 suspended my account) so spammers are attracted like moths and the lightsource.

If you wonder, most of the comments are about pornography, buying drugs online, gambling. Suddenly I feel like I’m a P.i.m.p. (remember that 50 cents song?) who constantly needs to purchase cheap drugs while playing pokers with other people. Oh wait, and those spammers they know that I suffer impotency too since they keep offering me cheap cialis or viagra. Humh, thanks but no thanks.

Askimet’s been wonderful. It stopped most spam comments and once in a while do I receive an entry that got through. The entries that Askimet misses are usually too short or the words used are random enough to fool the pattern matching engine. In the future, I may find (or write) an add-on to the commenting system to do some captcha and stop those spammers from eating my lunch.

Oh…sigh… people …people…

view comments
 

One of my little ColdFusion projects is to allow users to download a dynamically generated word document, whose contents are fetched from the database. Luckily, to open a file in word is pretty simple: just rename it into .doc and Word will open it. Especially, for HTML content, I can just force the user to download the HTML page and have him/her save it with a .doc extension and be done with it.

In my case, I didn’t want to write the dynamic content to a file and force the download via the Header of “Content-Disposition: attachment”. What I did was capturing all output into a file, then craft the HTTP header using the cfhead tag to force the inline download. Let me show you real quick how to do this, it may save you some time messing around with ColdFusion.

===== The script =====







…. output your database result here …





#content#

===== Explanation =====
Let’s go over the A, B, C, D in the above code snippet.

* **A**: Since we don’t want ColdFusion to randomly send the contents (and of course, the header too, which will mess up the force download) to the client’s browser, we explicitly tell ColdFusion to only flush out the content contained within the cfoutput tag.
* **B**: Here you can do all of your data access, such as running retrieval queries, etc. It’s the R in the CRUD, **C**reate, **R**etrieve, **U**pdate, **D**elete
* **C**: We capture all output produced by cfoutput into a variable, which allows us to do filtering or word replacment later on.
* **D**: Now we craft the header to force the download. We explicitly say that this is a word document, so if the user has Word installed, s/he will have the option to open the file with Word directly.Here is the heart of the solution. Since we don’t have a file to read the contents from but a whole bunch of HTML contained in a variable, we set the Content-Disposition to inline and specify the name of the file that the user is about to download. You can set the file to be .doc if you’d like the downloaded file to be associated with Word.We provide some description to the downloaded file.#content#And now we can just flush out the content to the browser. That wasn’t too bad, was it? When the user accesses the CFML script, s/he will be prompted to download the file to the local computer. Nice!

===== Further Readings =====
No good tutorials are without a reference section, so here is the list of interested articles that I find useful
* [[http://livedocs.macromedia.com/coldfusion/7/htmldocs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=ColdFusion_Documentation&file=00000232.htm|Macromedia manual on Cfheader]]
* [[http://us2.php.net/readfile|PHP manual on readfile()]] and [[http://us2.php.net/header|PHP manual on header()]] - The 2 articles are particularly helpful to see how the header can be sent to the browser. Eventhough we used ColdFusion in this short tutorial, the same technique can also be applied to PHP.
* [[http://www.ietf.org/rfc/rfc2183.txt| RFC2183]] - The EITF Request for Changes technical details on header messages. I did use this as the starting point. When in doubt, look for RFC documents as they are is always the definitive (and most correct) guide.

view comments
 

For the past few days I’ve been working on the cluster project again, after a month of suspension. Finally today I was able to configure a (almost) working load balancer with 3 web servers (1 is the loadbalancer itself, and 2 other dedicated web servers, web01 and web02). I’m in the process of writing down the scripts which I will follow later on to do the screencast. At this stage, what I have is half of the whole picture of a web cluster:

  • Failover loadbalancer server pair, running Heartbeat and ldirectord
  • A small cluster of 3 load-balanced web servers, using weighted round robin
  • A pair of Nameserver to provide name-lookup service for the entire cluster, no more “ping 10.10.10.10.101.101.10.12“!

What is missing is the loadbalanced MySQL cluster. I have been able to get a cluster of 3 MySQL boxes working, but now I’d like to add the ipvsadm and ldirectord to provide load-balancing feature so that the cluster can be scaled up easier.

I am pretty proud of myself for learning all of these amazing technologies within a relatively short period of time. Especially for the DNS, I have learned so much about the networking aspect of a network of computer. The two books, “DNS & BIND” and “BIND Cookbook”, both by O’Reilly, are amazing reference source. I particularly like the “DNS & BIND” book for its in depth coverage on the concept of how nameservers work. Without that fundamental knowledge, it’s hard to build such a working cluster with growing demands.

Here is the revised virtual Linux cluster diagram. So slowly but surely my cluster project is reaching its destination: a complete virtualized web cluster running on VMWare. And once this is done, I think I begin to learn how to develop cluster-ready applications.

Revised HA Cluster

view comments