Mental shelter

When one is not capable of standing the elements, one seeks shelter. This is a natural instinct that has facilitated our survival ever since we were weaklings. But, for one to arrive at an oasis, one must first grow capable of leaving the shelter and stand the elements. Such instinct extends to the mental aspect of our capability. There are small things that cater to ones mental comfort: Be it a game, be it a show, be it a sport, be it a habit, be it an article, or be it an addiction. They are all small compare to our goals that set on by our will. However, mental weakness leads to incapability of leaving such shelters.

Remote system upgrade (with grub and bmc-watchdog)

IPMI is a very very powerful tool for system administrators, especially those telecommuting ones. It’s serial over LAN (SOL) support eliminates the need to personally sit in front of a server to do any pre-network operations, including reconfiguring the BIOS settings. However, it does require (A) an additional IP address to access the IPMI network interface from the Internet; or, when no additional IP can be allocated, (B) the access to a second server on the same LAN (not necessarily with administrator privilege). When either (A) or (B) is available, you can theoretically do anything remotely including fresh installation of an operation system (starting, for example, with a network boot and/or a remote drive).

Unfortunately, one of my recent situation allowed neither (A) nor (B). So, the first installation had no option but to be done by on-site personnel. But, once a networked system was up and running with a working grub boot manager, I could remotely install a new system on an unused (or a large enough swap) partition and test it out with the “boot once” support of grub. On a Debian based system with grub-2, this involves

  • changing the value of “GRUB_DEFAULT” in /etc/default/grub to “saved”,
  • running “update-grub”,
  • editing /boot/grub/grub.cfg to make an entry for the new system (if it was not discovered correctly by grub-probe),
  • running “grub-reboot” for the entry, and
  • rebooting the machine.

However, in most cases, you are bound to make some mistakes in the new system and fail to recover network contact to the server until an on-site person can hit the reset button of the machine for you.

Lucky for me, the BMC of the IPMI on the server did have a working watchdog timer. Therefore, I could setup the timer with enough time and start it before rebooting the machine. That way, if the new system worked, I could login to the server through the Internet and stopped the timer. But, if the new system got stuck, the watchdog would do a hard reset on the machine after the time ran out and returned to the original working system… no more waiting for on-site personnel. The actual command I used to setup the timer is bmc-watchdog from freeipmi:

  • bmc-watchdog -s -u 4 -p 0 -a 1 -F -P -L -S -O -i 900

One can consult the man page for the meaning of these options. Simply, this sets up 15 minutes on the timer for a hard reset, which can be checked with

  • bmc-watchdog -g

started with

  • bmc-watchdog -r

and stopped with

  • bmc-watchdog -y

(While, theoretically, one can achieve the same result with ipmitool, it did not work for me on the specific system.)

Portable library for C++ GUI programming

It has been for a few occasions that I find my self wanting to port my GUI programs (most of which were written with gtkmm) to other platforms for the enjoyment of my friends. However, while most GUI toolkits claim to be portable to all platforms (Linux, Windows, and Mac), they generally require installation of multiple shared libraries by the users.

This is a major show stopper for most of my friends and is sufficient to kill any interest in them on the first mention. Therefore, the only viable mean is for me to make and send them statically-linked, monolithic executables that they can happily click on to start the shows. (They generally don’t mind waiting a few minutes to download a bloated binary, as long as it remains a single step.)

My recent survey of the GUI library landscape brought my attention to GLUT. While it still requires installation on Windows, I can easily find static versions of FreeGLUT library for MingW that can be used to cross-compile, on Linux, statically-linked executables that can run independently on Windows. Furthermore, the GLUT framework, which, according to this, “is installed with every install of Mac OS X”.

However, GLUT library only provides facilities for managing windows and handling user inputs. It is by no means a GUI toolkit and you will have to draw all user-interactive elements by yourself (in OpenGL). I do find a GUI library, GLUI, that is built on and should be as portable as GLUT. However, after porting a couple programs to GLUI, I failed to find it enjoyable for me to break up the C++-elegant logic of gtkmm and redo my work in a less polished API.

What follows is the birth of gltk, it is an implementation of the gtkmm API on GLUT. I actually started with adding the libsigc++‘s signal-slot API to GLUI since the original callback mechanism only supported single static callback function and I needed more flexibility to port my programs. But, the hack soon proliferated into the entire source tree, and I decided it would be much more enjoyable for me to start something entirely from scratch.

After a somewhat persisting part-time effort that lasted more than a month, I have just made the first release of the library. It’s usable for a simple application that only needs some buttons, checkboxes, sliders, single line text labels or entries to control calculations. For myself, this represent over 80% of the applications that I would have considered porting. I am feeling pretty happy about it and I hope some others will also find it useful.

Project Homepage: http://gltk.ccdw.org/

Permutation

The following spaghetti prints all permutations of a string (“abcd”). I wrote it as an example to show the benefit of structured programming in my class.

#include <iostream>
using namespace std;
int main()
{
        char c[] = "abcd\n";
        int size = sizeof(c) - 2;
        int n[size + 1];
        n[size] = 1;
        int idx = size;
        char t;
new_round:
        for (int i = 0; i < idx; i ++) n[i] = i + 1;
        cout << c;
start_shift:
        idx = 0;
        t = c[0];
shift_next:
        if (n[idx]) goto shift_done;
        idx ++;
        c[0] = c[idx];
        c[idx] = t;
        t = c[0];
        goto shift_next;
shift_done:
        n[idx] --;
        if (idx == size) return 0;
        if (n[idx] == 0) goto start_shift;
        goto new_round;
}

The structured version is as follows:

#include <iostream>
using namespace std;
int main()
{
        char c[] = "abcd\n";
        int size = sizeof(c) - 2;
        int n[size + 1];
        n[size] = 1;
        int idx = size;
        char t;
        do {
                if (n[idx]) {
                        for (int i = 0; i < idx; i ++) n[i] = i + 1;
                        cout << c;
                }
                idx = 0;
                t = c[0];
                while (n[idx] == 0) {
                        idx ++;
                        c[0] = c[idx];
                        c[idx] = t;
                        t = c[0];
                }
                n[idx] --;
        } while (idx < size);
        return 0;
}

The idea is to rotate a string by n times, where n is the length of the string. While, before each rotation, rotate the n-1 substring at the front n-1 times. And while, before each rotation, rotate the n-2 substring at the front n-2 times. And so on… We can see that this is more elegantly done recursively:

#include <iostream>
using namespace std;
char c[] = "abcd\n";
int size = sizeof(c) - 2;
void rotate(int l)
{
        char ch = c[l - 1];
        for (int i = l - 1; i; i --) c[i] = c[i - 1];
        c[0] = ch;
}
void perm(int l)
{
        if (l == 1) cout << c;
        else for (int i = 0; i < l; i ++) {
                perm(l - 1);
                rotate(l);
        }
}
int main()
{
        perm(size);
        return 0;
}

The above thinking counts on the string to have all distinct chars. When this isn’t the case, a different approach is to consider the lexical order of the permutations. From a given permutation, we simply need to figure out the next in the lexical order until the order is “maximized”. It turns out that this is in the C++ STL. My reimplementation is as follows:

#include <iostream>
using namespace std;
void swap(char & a, char & b)
{
        char c = a;
        a = b;
        b = c;
}
// increase the order of string
bool incr(char * str, size_t len)
{
        size_t i = 1;
        while (i < len && str[i - 1] >= str[i]) i ++;
        if (i == len) return false; // no kink
        // found a kink
        size_t j = i - 1;
        while (j > 0 && str[j - 1] < str[i]) j --; // size kink
        swap(str[i], str[j]); // shave kink
        // reverse rest
        for (i --, j = 0; j < i; i --, j ++) swap(str[i], str[j]);
        return true;
}
int main()
{
        char c[] = "aabbc\n";
        int size = sizeof(c) - 2;
        do cout << c; while (incr(c, size));
}

亡羊補牢

小時讀到這個成語總會有點納悶:這是在笑人家,為時以晚嗎?羊都沒了,補牢有何助益呢?還是只丟了一部分的羊,所以還須要補牢來守住牢中尚有的羊?看看古文《戰國.楚策》中的用法:

莊辛謂楚襄王曰:『君王左州侯、右夏侯,輦從鄢陵君與壽陵君;專淫逸侈靡,不顧國政,郢都必危矣。』襄王曰:『先生老悖乎?將以為楚國祅祥乎?』莊辛曰:『臣誠見其必然者也,非敢以為國祅祥也。君王卒幸四子者不衰,楚國必亡矣。臣請辟於趙,淹留以觀之。』

莊辛去之趙,留五月,秦果舉鄢、郢、巫、上蔡、陳之地,襄王流揜於城陽。於是使人發騶,徵莊辛於趙。莊辛曰:『諾。』莊辛至,襄王曰:『寡人不能用先生之言,今事至於此,為之奈何?』莊辛對曰:『臣聞鄙語曰:「見兔而顧犬,未為晚也;亡羊而補牢,未為遲也。」臣聞昔湯、武以百里昌,桀、紂以天下亡。今楚國雖小,絕長續短,猶以數千里,豈特百里哉?』

『王獨不見夫蜻蛉乎?六足四翼,飛翔乎天地之間,俛啄蚊虻而食之,仰承甘露而飲之,自以為無患,與人無爭也。不知夫五尺童子,方將調鈆膠絲,加己乎四仞之上,而下為螻蟻食也。』

『蜻蛉其小者也,黃雀因是以。俯噣白粒,仰棲茂樹,鼓翅奮翼,自以為無患,與人無爭也。不知夫公子王孫,左挾彈,右攝丸,將加己乎十仞之上,以其類為招。晝游乎茂樹,夕調乎酸鹹,倏忽之間,墜於公子之手。』

『夫雀其小者也,黃鵠因是以。游於江海,淹乎大沼,府噣鱔鯉,仰嚙蔆衡,奮其六翮,而凌清風,飄搖乎高翔,自以為無患,與人無爭也。不知夫射者,方將脩其碆盧,治其繒繳,將加己乎百仞之上。彼礛磻,引微繳,折清風而抎矣。故晝游乎江河,夕調乎鼎鼐。』

『夫黃鵠其小者也,蔡聖侯之事因是以。南游乎高陂,北陵乎巫山,飲茹谿流,食湘波之魚,左抱幼妾,右擁嬖女,與之馳騁乎高蔡之中,而不以國家為事。不知夫子發方受命乎宣王,繫己以朱絲而見之也。』

『蔡聖侯之事其小者也,君王之事因是以。左州侯,右夏侯,輩從鄢陵君與壽陵君,飯封祿之粟,而戴方府之金,與之馳騁乎雲夢之中,而不以天下國家為事。不知夫穰侯方受命乎秦王,填黽塞之內,而投己乎黽塞之外。』

襄王聞之,顏色變作,身體戰慄。於是乃以執珪而授之為陽陵君,與淮北之地也。

這裡,莊辛應該是要告訴襄王:事情尚有補救的餘地。

不過再想一想:羊不見了,為什麼不去找羊而先補牢。這應該是告戒人要先從源頭阻斷禍根,才能避免事情的再惡化。牢補好了,尋羊才有助益。這個道理很簡單,但看看社會上:尋羊的多,補牢的少。(如此事倍而工半,並不是道理難,而是有它人性上的原因。)

簡單的成語,可以用來告戒人;可以用來安慰人;也可以用來提供處理問題的方法。

Building driver for AverMedia A827 on Linux kernel 2.6.38

Vendor: AVerMedia
Product: AVerTV Hybrid Volar HX
Model: A827

This is a Analog+DVB-T USB TV receiver with official support for Linux up until 2009-11-26. The latest driver can be downloaded from the product page above.

The “Normal” automatic process of installing the driver fails for 2.6.38 kernel. Using the “Expert” process to extract the driver source code to a selected location allows one to compile the driver manually and track down the problems. First, the function calls for mutex initialization are gone and should be replaced with those of semaphore initialization. Second, the Teletext support is also gone and should be eliminated from the driver source code. These fixes are summarized in this patch.

However, compiling the driver with “make” results in the WARNINGs that the symbols “param_array_get” and “param_array_set” are undefined. This is due a prebuilt object file, “aver/osdep_dvb.o_shipped”, that was built with an older version of kernel. Building this file requires some internal header files from kernel source tree that are not normally available in, e.g., linux-headers or kernel-headers packages. Provided that the kernel source tree for building the running kernel is installed/available in the system, the shipped object file can be removed. After this, the “make” command can complete without incidence. Installing the drivers (“averusbh826d.ko”  “h826d.ko”) to the module directory, e.g., “/lib/modules/2.6.38/kernel/drivers/media/dvb/dvb-usb” and updating the module dependency with “depmod -a”, the adapter seems to work normally afterwards.

Addiction is the lost of ability to move on

Life is a tour of the world. You come without any preconception and build up a mind of yourself. You travel through time and space, through different stages of growth and experience. And when the time comes for you to leave, you leave with nothing but your mind. Just like for any tour, moving on is just as important as moving in. If you can not, the tour will still end wherever you are.

中醫的運作原理

從粗淺的了解與張明強的說明,我有如此的想法:

以一個物理系統來看人體,人體的各種狀態對映到系統各種的簡正模式(normal modes)。健康態一般應該是系統的主要模式(principle mode),而不同的病態則是其他的非主要模式。中醫的運作在於引入不同的作用來引導系統從非主要模式回到主要模式。而西醫的做法是將人體看成一個機器,不同的病是由在不同位置上所發生的故障造成:只要將故障排除修復,機器即可回復正常運作。