Diets Don't Work

Something interesting I read during lunch hour today. Book author, Bob Schwartz, in his book, Diets Don't Work,  proposes four simple rules to stay naturally thin.

1. Eat only when hungry.
Don't eat when you're emotional (bored, sad, happy, and etc.) Eat when you're feeling hungry. You will know when your stomach starts to growl. But instead, we eat (mostly junk food) when we are doing some other activities (movies, web surfing, or chit-chatting). Have your ever notice we sometimes have the urge to chew on something even though we're not hungry ?

2. Eat exactly what your body wants.
If you're craving for certain food, go take it but do not take this rule literally. This does not means we can eat fast food or soft drink for every meal. See rule 4.

3. Eat each bite consciously.
Be mindful, deliberately focus on the eating. Be aware of the food that goes into your mouth, the smell, colours, texture, or taste. Stop any other activities. No computer, television, or conversation with other people. Can you remember your last meal ? Can you describe it (the taste, colour, texture) ? What are the ingredients ? If you can't remember, then you're not paying attention.

4. Stop when your body has had enough.  
Moderation is the key here. Follow rule 3 and stop when you're satisfied. If you are worry about wasting food, take a smaller portion, like half cup of cooked rice.

In summary, the general rule is be conscious of what you put into your mouth and learn to enjoy your food. By the way, these rules are applicable to money as well.

Raspberry Pi Setup - Part 2

Continue with my journey of setting this machine up. Since I misplaced my Edimax EW-7811UN wifi adapter, which will work seamlessly without any compilation, I had to buy another one. However, I can't find the exact brand and model and I ended up with TP-LINK TL-WN725N, which according to wiki [2], will work out of the box using the build-in USB port. However, you will need to upgrade the kernel from 3.2.x to 3.6.x.

1. First let's find out the current kernel version.
$ uname -a
Linux raspberrypi 3.2.27+ #250 PREEMPT Thu Oct 18 19:03:02 BST 2012 armv6l GNU/Linux

2. Yesterday, I made a mistake by not expanding the rootfs. Hence, firmware upgrade failed due to lack of disk space. To fix that, run the initial configuration tool when we first boot up the image.
$ sudo raspi-config

Select expand_rootfs option to expand root partition (/) to use up all the remaining space in the SD card (mine is 16GB). Save the settings and reboot. New filesystem layout as follows:
$ df -h
Filesystem           Size   Used Avail   Use% Mounted on
rootfs               15G    1.8G   13G    13% /
/dev/root            15G    1.8G   13G    13% /
devtmpfs             93M       0   93M     0% /dev
tmpfs                19M    232K   19M     2% /run
tmpfs                5.0M      0  5.0M     0% /run/lock
tmpfs                37M       0   37M     0% /run/shm
/dev/mmcblk0p1       56M     17M   40M    30% /boot
tmpfs                7M       0    37M     0% /tmp

3. Update the Raspberry Pi's firmware using Hexxeh's rpi-updater tool.
$ sudo apt-get install git-core ca-certificates
$ sudo wget -O /usr/bin/rpi-update
$ cd /usr/bin
$ sudo chmod +x /usr/bin/rpi-update
$ sudo ./rpi-update

Let's check the kernel version again. And yes, we have upgraded to kernel 3.6.X.
$ uname -a
Linux raspberrypi 3.6.11+ #362 PREEMPT Tue Jan 22 14:52:21 GMT 2013 armv6l GNU/Linux

4. Type these commands to verify that the Wifi adapter is working.
$ lsusb | grep 8188
Bus 001 Device 004: ID 0bda:8176 Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter

$ lsmod | grep 8192
8192cu   489381  0

$ iwconfig wlan0

5. I am lazy to configure Wifi in the console, let's try using GUI way. You can read console config method here. However, I lost my mouse and have to resort to remote GUI using VNC. Following the instruction in the wiki.

In the Raspberry machine, to setup a VNC server.
$ sudo apt-get install tightvncserver
$ tightvncserver # set password
$ vncserver :0 -geometry 1920x1080 -depth 24

6. In my Ubuntu machine, install the VNC client viewer and connect to the server. See sceenshot.
$ sudo apt-get install xtightvncviewer
$ xtightvncviewer

7. In the VNC viewer, double-click the WiFi Config -> Scan -> Select Connection -> Right Click to add -> Type password.

8. Reboot the machine
$ sudo reboot

Different WHOIS Protocols

Comparison of the description of the WHOIS protocol (getting domain name or IP information) between RFC 812, RFC 954, and RFC 3912. RFC 3912 is the latest version replacing RFC 954 which in turn replacing RFC 812. I prefer the writing style of RFC 954, simple and direct.

a) RFC 812

Connect to the service host (SRI-NIC)
      TCP: service port 43 decimal
      NCP: ICP to socket 43 decimal, establishing two 8-bit connections

Send a single "command line", ending with .

Receive information in response to the command line.  The server closes its connections as soon as the output is finished.

b) RFC 954.

Connect to the SRI-NIC service host at TCP service port 43 (decimal).

Send a single "command line", ending with (ASCII CR and LF).

Receive information in response to the command line.  The server closes its connection as soon as the output is finished.

c) RFC 3912
"A WHOIS server listens on TCP port 43 for requests from WHOIS clients.  The WHOIS client makes a text request to the WHOIS server, then the WHOIS server replies with text content.  All requests are terminated with ASCII CR and then ASCII LF.  The response might contain more than one line of text, so the presence of ASCII CR or ASCII LF characters does not indicate the end of the response.  The WHOIS server closes its connection as soon as the output is finished. The closed TCP connection is the indication to the client that the response has been received."
Some hands-on exercises using whois and telnet program. We're connection to because we want to find the root domain name server against the Root Zone Database.

a) whois command
$ whois -h com | less

b) telnet command. Press enter after you've type the domain extension. You can type any domain name as well.
$ telnet 43
Connected to
Escape character is '^]'.

Opening Text Steam in PHP

I'm glad I read the documentation on fread() method. Now I understand why this method behaves in such way.

The old way (before PHP 5) of handling remote (non file) data stream. What and why is 8192 ? That is the length in byte of the chunk size, which by default is 8192 bytes.
$handle = fopen("", "rb");
$contents = '';
while (!feof($handle)) {
  $contents .= fread($handle, 8192);

The new way (from PHP 5 onwards) without the need to specific chunk size.
$handle = fopen("", "rb");
$contents = stream_get_contents($handle);

Raspberry Pi Setup and Installation

Few months ago, I bought a Raspberry Pi computer from element14, the electronic distributor shop. Although I had watched some You Tube videos of the computer, still very surprised with this business-card sized machine. Went to bought some extra parts (SD card, power supply, and HDMI cable) before configuration. Installation steps are based on the Embedded Linux Wiki with my own comments.

0. Download the image file from official site. Do the checksum verification so that the downloaded file is not corrupted.
$ sha1sum

1. Uncompress the file.
$ unzip 
inflating: 2012-12-16-wheezy-raspbian.img

2. Put in the SD card and use the disk free (df) command to find the device name. Our device name is NOT /dev/mmcblk0p1, that is the first partition, hence p1. The actual device name is /dev/mmcblk0.
$ df -h
Filesystem             Size  Used Avail Use% Mounted on
/dev/mmcblk0p1         15G   32K   15G  1%    /media/kianmeng/3265-3765

3. Unmount the device before we can write the image to the SD card.
$ umount /dev/mmcblk0

4. According to the wiki, there are two command line ways to write the image, namely using disk dump (dd) or enhanced disk dump (dcfldd). I had tried both ways and prefer disk dump (dd) program as you can see more information shown below. Image writing roughly took 646 seconds which is around 10 minutes.

4a. Using enhanced disk dump (dcfldd)
$ sudo apt-get install dcfldd
$ sudo dcfldd bs=4M if=2012-12-16-wheezy-raspbian.img of=/dev/mmcblk0
256 blocks (1024Mb) written.
462+1 records in
462+1 records out

4b. Using plain old disk dump (dd)
$ sudo dd bs=4M if=2012-12-16-wheezy-raspbian.img of=/dev/mmcblk0                                                                   
462+1 records in
462+1 records out
1939865600 bytes (1.9 GB) copied, 646.172 s, 3.0 MB/s

5. Make sure everything is written to the SD card.
$ sudo sync

6. To view the file system layout of the image, we will install the graphical partition editor. You can use this program to create the new /data partition to utilize the free space in the card.
$ sudo apt-get install gparted
$ sudo gparted /dev/mmcblk0

7. We will follow command line method to create a extra /data partition.
$ sudo apt-get install parted
$ sudo parted /dev/mmcblk0
GNU Parted 2.3
Using /dev/mmcblk0
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) unit chs                                                         
(parted) print                                                            
Model: SD SU16G (sd/mmc)
Disk /dev/mmcblk0: 1936,229,20
Sector size (logical/physical): 512B/512B
BIOS cylinder,head,sector geometry: 1936,255,63.  Each cylinder is 8225kB.
Partition Table: msdos

Number  Start     End         Type     File system  Flags
 1      0,130,2   7,165,29    primary  fat16        lba
 2      7,165,30  235,214,42  primary  ext4

7a. Contrary to the wiki instruction, we will not round up the chs (cylinders, head, sector) addressing.
(parted) mkpart primary 235,214,43 1936,229,20
(parted) print                                                            
Model: SD SU16G (sd/mmc)
Disk /dev/mmcblk0: 1936,229,20
Sector size (logical/physical): 512B/512B
BIOS cylinder,head,sector geometry: 1936,255,63.  Each cylinder is 8225kB.
Partition Table: msdos

Number  Start       End          Type     File system  Flags
 1      0,130,2     7,165,29     primary  fat16        lba
 2      7,165,30    235,214,42   primary  ext4
 3      235,214,43  1936,229,20  primary

7b. Rounding of chs value will cause incorrectly partition alignment. See example below.
(parted) mkpart primary 236,0,0 1936,229,20                               
Warning: The resulting partition is not properly aligned for best performance.

8. Quit parted program, format and label the partition. See the partition layout after this step using gparted program.
$ sudo mkfs.ext4 /dev/mmcblk0p3
$ sudo e2label /dev/mmcblk0p3 data

9. To make sure we can automount the /data partition in the SD card, add this line to the file system table (/etc/fstab) file.
$ vi /etc/fstab
/dev/mmcblk0p3  /media/pi  ext4  defaults   1   2

10. Mount the new partition and see the content. You should obtain below result.
$ sudo mkdir /media/pi
$ sudo mount /media/pi
$ cd /media/pi
$ ls

Resolutions for Programmer - Part 2

Follow up on yesterday post on Matthew Might's 12 resolutions for programmer. Continue with item 7 - 12.

7. Focus on security.
Imagine you've lost your laptop. What are your contingency plan? For a start, certain passwords are stored using a password manager, I am using pass, a command line password manager. Second, use two steps authentication and verification for any web applications that support it, example is Gmail. Third, clear your browser cache and history and use Incognito mode when necessary. Slowly switch to key-based SSH login when necessary, I need to start doing this.

8. Back up your data.
DVD disc is plan A. External hard disc is plan B. Cloud storage is plan C. Is time to start clean up all these stuff and slowly move everything to cloud storage. Still thinking which cloud storage provider to use. I don't mind paying. Full list of comparison of different cloud storage.

9. Learn more theory.
Definitely algorithm and data structure. I believe SICP book with cover the fundamental part.

10. Engage the arts and humanities.
Typography and book design. Increase my understanding and appreciation of good book design. These should be a good start.

11. Learn new software.
Write some custome Gimp plugins to put my newly-learned Python knowledge to good use. Always wanted to do this. Also can learn some Scheme along the way as well.

12. Complete a personal project.
I was hoping one small project for each month. Maybe a small PHP or Python library.

In summary, dump all your ideas out and try to implement them and have fun.

Resolutions for Programmer - Part 1

It's almost the end of January 2013. No resolutions set yet ? Why not read +Matthew Might's 12 resolutions for programmer for some inspirations ? If I were following his resolutions, how would I do it differently? I will start with the first 6 resolutions and continue the subsequent 6 in next post.

1. Go analog.
Definitely cooking. Gordon Ramsay's Scrambled Eggs and Jacques P├ępin's omelette are two egg-related dishes I really like to master. I've tried and failed miserably. Trust me, is not as simple as it seems. Cooking is always a good weekend activity.

2. Stay healthy.
I had fought hard and recovered (almost 95%) from Repetitive strain injuries (RSIs), nervous injuries due to repetitive typing (for my case). But the current obstacle is become more healthy. Doing maintenance programming and sitting all day will harm your body somehow. Bought a Pedometer, start monitoring my daily walking steps.

3. Embrace the uncomfortable.
Switch to CamelCase from underscore-based style. I fscking hate CamelCase. Enough said.

4. Learn a new programming language.
Scheme functional programming language and finish the Structure and Interpretation of Computer Programs (SICP). Unfortunately, I can only start this by June due to other pressing commitments. Will continue learning Python as well but is learning by doing small projects.

5. Automate.
The only thing I can think of is to put every important events, birthday, and life milestones into Google calendar.

6. Learn more mathematics.
Read one book on statistics. Relearn statistics.

You're Your Code?

Via Hacker News. Excellent career advice for young people, applicable for middle age software developer as well. Some thoughts on the article related to a career as a developer.

You're your job or you're are your code. After prolonged exposure to a certain programming language or development environment and tools, it will slowly dictate your  your taste, opinions, and personality. Hence, most developers turned out to be quite opinionated, egoistic, and so full of themselves. Examples are editor choices, coding style, and programming languages.

Look at the career path of developer older than you. Do met a few older developer or used to be a developer. Either they start their own companies, promoted to project manager or software architect, or totally switch their career fields. Not a favourable future for those who still enjoy coding on day-to-day basis. Although they may work on mundane CRUD application or what I always love to name it, a glorify Excel sheet.

The Missing apple-touch-icon-precomposed.png

And I thought I had fixed the 404 missing apple-touch-icon-precompose.png file issue few week ago but yet today the issue still haven't resolved. It seems that the image files must located at the document root of the web server.

Meaning that if you put your image file outside the document root like below
-- assets/
   -- img/
      -- apple-touch-icon-precomposed.png

You need to redirect them using mod_rewrite to the actual path. In you .htaccess, add these lines.

    RewriteEngine On
    RewriteRule ^apple-touch-icon-precomposed\.png$ assets/img/apple-touch-icon-precomposed.png [L]

When I checked my .htaccess file, I noticed I did the same for favicon.ico as well and it never cross my mind to do the same for this !

Redis : New Member to the Server Stack

Interesting article on the size and the technologies behind big porn sites. While some may not agree, porn industry do accelerate Internet advancement. To best of my knowledge, how I visualize the software stacks behind these sites.
[browser] --- [cdn | memcached] --- [haproxy | varnish] --- [nginx] --- [redis]

It seems that Redis, the key-valued storage engine has slowly replaces MySQL as the de facto primary data storage engine. Contrast to what the article said, Redis was not used to store and serve videos. Instead, it should be used for storing metadata. Which is consistency with the typical use cases for Redis.

One of the server stack you should look into in 2013. What's the next step ? Let's get it install in Ubuntu 12.10.
$ sudo apt-get install redis-server
$ redis-cli

For further reading, I will recommend you to read Ken Nejima's thought on Redis. Note that the article was written in 2010 but it is the best writing on Redis I read so far.

On PHP Future Direction

"The vision has been the same for years. A general purpose scripting language with a focus on web development."
-- Rasmus, creator of PHP Language
To begin with, PHP was never really a general purpose scripting language but a templating language. Or precisely, a web development Domain-specific language (DSL). Do you know, compare to other popular scripting languages (Python, Ruby, or Perl), this language needs a configuration file to work. And yet, I have been using PHP for the past 8+ years and it never occurs to me? Ouch ! Furthermore, it only excels as a complementary component of the LAMP-stack.

The recent disagreement in php internal shown that there are two camps in the list, the PHP way (procedural with some OO) and Java-esque (more OO features influenced by JAVA). I belong to the former camp. I feel that most recent implemented features (e.g. namespacing and trait) are cater only for framework developers rather than mere web developer like us.

Rather than trying to implement yet another complex feature like annotation, why not:

a) Support multi-threading in PHP instead of using pcntl_fork

b) Since we already have a good enough model (PDO) and default view (PHP itself), what's lacking right now is a good controller or router in the core. Something like http_route("get", "/hello/%s", ...), inspired by Silex. Hence, making PHP itself a micro-framework. This sure will render most PHP frameworks out there obsolete.

c) Official centralize library repository like Perl's CPAN or Ruby's gems in the core. Yes, I know we have PEAR and now Composer.

Enough rambling for today. For further reading, read the excellent discussion at Hacker News and r/PHP.

It was one of that fscking day

It was one of that fscking day. The dreadful day where we programmer hate it the most, the day you were completely stuck, and can't seem to fix the bug. You tried suspending the script at different breakpoints, and no, not working. Frustrated, went for a walk, ate an ice-cream, read a book, and fixed some other bugs just to clear the head. Tried again, different approach, but still, nothing bloody works.

"Just one more try"

You told yourself before you start packing and left for home. Your last attempt, no more. Your mind already set to write down the next morning to do item in your journal. Suddenly, you noticed there this this line of code,

$new_name = "a" . $name;

"Why you want to prepend the letter a ?"
"Let's remove that and try again."

Whoala! After enduring frustration for the whole day and 1 hour 56 minutes spent working on it, the bug was finally fixed ! Bloody hell ! This is fscking stupid ! What was I thinking? Come to think of it, is Karma. After I caused my boss to fix my stupid "new feature" yesterday.

Yes, it was one of that fscking day.

Senior Engineer?

John Allspaw, author of the books Web Operations: Keeping the Data on Time and The Art of Capacity Planning: Scaling Web Resources, wrote and excellent post on being a senior engineer. By his definition, a senior engineer should be a "mature" engineer. Mature not only in the mastery of technical skill but also personal characteristics as well. In summary, don't be an arsehole, be empathy, share your knowledge, and grow together with your peer.

Sounds very optimistic, right? Unfortunately, we do work in a chaotic technical environment. Sometimes you will work with stackholders who just want to watch the world burn. Ok. I better stop right now, otherwise this will turn into endless ranting.

Back to the post. There is this part about trade-off and the important of working code is better than elegant code. Being a maintenance programmer in most of my career life and all the technical debts inherited, I have to say, although reluctantly, this approach works. Nobody cares much how you do it, they just want you to automagically solve their problem, if possible, within time and cost. These days, instead of striving for elegant code (my self-righteous, over-designed and bullshit view of clever code), I will try to get it done fast and almost right. Yes, almost right (simple and sufficient enough).

Am I a senior engineer? Yes, in term of age. Mature engineer? Not yet, there is room for improvement and is a long journey. The first step towards this goal is be useful and be helpful.

Password Hashing Function in PHP 5.5

As I mentioned before, one of the most welcoming new feature in PHP 5.5 is the new password hashing API. The API consists of four helper functions wrapped over the hard to use crypt function. Due to several password leaking incidents and most PHP developers still stick with plain MD5 or SHA512 hashing, there is a need for simple and stronger default password hashing API.

Imagine you have a existing user table with schema as shown below. The password field (pass) is a MD5 hashed field
- username varchar(255)
- password char(32)

First, to migrate from MD5 to BCRYPT hashing, we need to alter the password column to CHAR(60) BINARY or BINARY(60) if you're using MySQL. Why BINARY ? Space and speed reasons.

Second, rewrite your validation function so when user login to the system, if the record still using the old hashing method, validate it and update it using new hashing algorithm. Sample simplified code as follow:
function validate_login($username, $password)
    $password = get_user_password($username);
    if ( password_need_rehash($password, PASSWORD_BCRYPT) )
        $valid = old_validate_login($username, $password);
        if ( ! $valid ) return FALSE;
            password_hash($password, PASSWORD_BCRYPT);
    return password_hash($password, PASSWORD_BCRYPT) === $password;

How about those PHP version < 5.5 ? No worry, there exists a compatibility version which offers the similar functionality.

Source Code Visualization Using Gource

Found this visualization tool, Gource, while surfing. Decided to try it out on the project I have been working on for the past year. Installation and generation instruction as follow for Ubuntu 12.10.

1. Install the necessary softwares. FFmpeg, the video encoder, is needed to generate the video.
$ sudo apt-get install gource ffmpeg

2. Before we can visualize anything, we must generated the log file. If you're not sure the log command for your version control software, just use the --log-command flag as shown. I am using Subversion for this example.
$ gource --log-command svn
svn log -r 1:HEAD --xml --verbose --quiet

3. Go into your project folder and generate the log file.
$ svn log -r 1:HEAD --xml --verbose --quiet > project.xml

4. Visualize the log file and be amazed
$ gource project.xml

5. By default, Gource will show everything. However, sometimes we need customize the visual output to hide certain sensitive information and adjust the screen resolution. Play with the settings to get the best visual output. Customization very much dependent on the size of the log file and the number of developers. This process can increase disk I/O rate, you may experience some slowness.
$ time gource --camera-mode track --seconds-per-day 0.25 --hide date,dirnames,files,filenames,usernames -640x360 project.xml -o gource.ppm

real    2m6.712s
user    0m40.415s
sys     0m47.443s

Two important notes on reducing the file size. First, I compressed 4 days log into one day using the (--seconds-per-day 0.25) flag. Second, Gource core dumped on me when I tried using resolution of 426x240, the lowest resolution suggested by YouTube to maintain 16:9 aspect ratio. Hence, I have to switched back to 640x360.

6. In step 5, we have generated an uncompressed sequence of screenshot in PPM format (gource.ppm). Now we are going to encode the PPM file to create the video to be uploaded later to YouTube. Following the encoding instruction,
$ time ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i gource.ppm -vcodec libx264 -preset ultrafast -threads 4 -bf 0 gource.mp4

real    1m11.968s
user    0m20.273s
sys     0m33.950s

7. Upload the video to YouTube. See video above. By the way, the blue user icon is me.