Thursday, December 12, 2013

Analyzing the simplest Wayland Clinet test

Wayland is a replacement of X System.
This document is based on current Wayland 1.3 documentation & its source code.



The simplest testcase is weston-simple-touch. This source code
is http://cgit.freedesktop.org/wayland/weston/tree/clients/simple-touch.c

Analysis on Client code only

Main function is very simple. Setup by calling touch_create(). and looping by wl_display_dispatch().


int
main(int argc, char **argv)
{
 struct touch *touch;
 int ret = 0;

 touch = touch_create(600, 500);

 while (ret != -1)
  ret = wl_display_dispatch(touch->display);

 return 0;
}

Initialization & Structures

At first we set up wl_display & wl_registry.

display
 - display context. Similar concept of XDisplay in X System.

registry
 - generated from display. global registry object : bind an object to the display

static struct touch *
touch_create(int width, int height)
{
 struct touch *touch;

 touch = malloc(sizeof *touch);
 if (touch == NULL) {
  fprintf(stderr, "out of memory\n");
  exit(1);
 }
 touch->display = wl_display_connect(NULL);
 assert(touch->display);

 touch->has_argb = 0;
 touch->registry = wl_display_get_registry(touch->display);
 wl_registry_add_listener(touch->registry, &registry_listener, touch);
 wl_display_dispatch(touch->display);
 wl_display_roundtrip(touch->display);

 if (!touch->has_argb) {
  fprintf(stderr, "WL_SHM_FORMAT_ARGB32 not available\n");
  exit(1);
 }
...

Objects which can be bound to registry are:

  • wl_compositor
  • wl_subcompositor
  • screenshooter
  • text_cursor_position
  • wl_text_input_manager
  • wl_shm
  • wl_output
  • wl_drm
  • wl_seat
  • wl_input_method
  • wl_shell
  • desktop_shell
  • screensaver
  • wl_input_panel
  • workspace_manager
  • ...
Some ones have wl_ prefix, others don't. But I do not know why exactly yet. I suppose wl_ mean wayland spec, and no prefix means supplemental add on.

And we can extract more specific objects from registry-bound objects.

In this example, we use the following objects only.

wl_compositor
        -> wl_surface       //<- surface

wl_shell
        -> wl_shell_surface

wl_shm
        -> wl_shm_pool
                -> wl_buffer    //<- graphics buffer for surface

wl_seat
        -> wl_touch            //<- touch
   


static void
handle_global(void *data, struct wl_registry *registry,
       uint32_t name, const char *interface, uint32_t version)
{
 struct touch *touch = data;

 if (strcmp(interface, "wl_compositor") == 0) {
  touch->compositor =
   wl_registry_bind(registry, name,
      &wl_compositor_interface, 1);
 } else if (strcmp(interface, "wl_shell") == 0) {
  touch->shell =
   wl_registry_bind(registry, name,
      &wl_shell_interface, 1);
 } else if (strcmp(interface, "wl_shm") == 0) {
  touch->shm = wl_registry_bind(registry, name,
           &wl_shm_interface, 1);
  wl_shm_add_listener(touch->shm, &shm_listener, touch);
 } else if (strcmp(interface, "wl_seat") == 0) {
  touch->seat = wl_registry_bind(registry, name,
            &wl_seat_interface, 1);
  wl_seat_add_listener(touch->seat, &seat_listener, touch);
 }
}

Touch object

To get wl_touch, add touch listener on wl_seat(http://fossies.org/dox/wayland-1.3.0/structwl__seat__interface.html). wl_seat is group of input devices.
static void
seat_handle_capabilities(void *data, struct wl_seat *seat,
    enum wl_seat_capability caps)
{
 struct touch *touch = data;

 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !touch->wl_touch) {
  touch->wl_touch = wl_seat_get_touch(seat);
  wl_touch_set_user_data(touch->wl_touch, touch);
  wl_touch_add_listener(touch->wl_touch, &touch_listener, touch);
 } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && touch->wl_touch) {
  wl_touch_destroy(touch->wl_touch);
  touch->wl_touch = NULL;
 }
}

static const struct wl_seat_listener seat_listener = {
 seat_handle_capabilities,
};

After getting wl_touch in wl_seat_listener, finally we can control touch event using wl_touch, wl_touch_listener. It is so a long way.

touch_down()/up()/move() seem clear. But I don't understand touch_handle_frame()/cancel() yet.

touch_paint() is just a drawing function that contains surface update routine such as wl_surface_attach(), wl_surface_damage(), wl_surface_commit(). touch->data is user memory address, which is explained in the next section.


static void
touch_paint(struct touch *touch, int32_t x, int32_t y, int32_t id)
{
 uint32_t *p, c;
 static const uint32_t colors[] = {
  0xffff0000,
  0xffffff00,
  0xff0000ff,
  0xffff00ff,
  0xff00ff00,
  0xff00ffff,
 };

 if (id < (int32_t) ARRAY_LENGTH(colors))
  c = colors[id];
 else
  c = 0xffffffff;

 if (x < 2 || x >= touch->width - 2 ||
     y < 2 || y >= touch->height - 2)
  return;

 p = (uint32_t *) touch->data + (x - 2) + (y - 2) * touch->width;
 p[2] = c;
 p += touch->width;
 p[1] = c;
 p[2] = c;
 p[3] = c;
 p += touch->width;
 p[0] = c;
 p[1] = c;
 p[2] = c;
 p[3] = c;
 p[4] = c;
 p += touch->width;
 p[1] = c;
 p[2] = c;
 p[3] = c;
 p += touch->width;
 p[2] = c;

 wl_surface_attach(touch->surface, touch->buffer, 0, 0);
 wl_surface_damage(touch->surface, x - 2, y - 2, 5, 5);
 /* todo: We could queue up more damage before committing, if there
  * are more input events to handle.
  */
 wl_surface_commit(touch->surface);
}

static void
touch_handle_down(void *data, struct wl_touch *wl_touch,
    uint32_t serial, uint32_t time, struct wl_surface *surface,
    int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
{
 struct touch *touch = data;
 float x = wl_fixed_to_double(x_w);
 float y = wl_fixed_to_double(y_w);

 touch_paint(touch, x, y, id);
}

static void
touch_handle_up(void *data, struct wl_touch *wl_touch,
  uint32_t serial, uint32_t time, int32_t id)
{
}

static void
touch_handle_motion(void *data, struct wl_touch *wl_touch,
      uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
{
 struct touch *touch = data;
 float x = wl_fixed_to_double(x_w);
 float y = wl_fixed_to_double(y_w);

 touch_paint(touch, x, y, id);
}

static void
touch_handle_frame(void *data, struct wl_touch *wl_touch)
{
}

static void
touch_handle_cancel(void *data, struct wl_touch *wl_touch)
{
}

static const struct wl_touch_listener touch_listener = {
 touch_handle_down,
 touch_handle_up,
 touch_handle_motion,
 touch_handle_frame,
 touch_handle_cancel,
};

Surface & Graphics buffer object

The following code is the rest of the touch_create() function, which set up the wl_surface, wl_shell_surface and attach a graphics buffer on wl_surface.

At first, we create wl_surface, and wl_buffer, which is pointing real memory array. And then just link this two objects by wl_surface_attach(). Finally we create damage and commit all state.

static struct touch *

 touch->width = width;
 touch->height = height;
 touch->surface = wl_compositor_create_surface(touch->compositor);
 touch->shell_surface = wl_shell_get_shell_surface(touch->shell,
         touch->surface);
 create_shm_buffer(touch);

 if (touch->shell_surface) {
  wl_shell_surface_add_listener(touch->shell_surface,
           &shell_surface_listener, touch);
  wl_shell_surface_set_toplevel(touch->shell_surface);
 }

 wl_surface_set_user_data(touch->surface, touch);
 wl_shell_surface_set_title(touch->shell_surface, "simple-touch");

 memset(touch->data, 64, width * height * 4);
 wl_surface_attach(touch->surface, touch->buffer, 0, 0);
 wl_surface_damage(touch->surface, 0, 0, width, height);
 wl_surface_commit(touch->surface);

 return touch;
}
At first we create a file with input size, and then extract user address by mmap. This user address is for direct-pixel manipulating in touch_paint(). And we need to wl_buffer which is interpreted by Wayland system. wl_shm_pool means a memory chunk. wl_buffer represents more specific graphics buffer with width, height, stride, pixel format. I was confused with close(fd) right after creating wl_buffer ( call wl_shm_pool_create_buffer() ), but APUE 3rd edition said
... Closing the file descriptor used when we mapped the region does not unmap the region. ...
And other web page also said (http://pubs.opengroup.org/onlinepubs/009695399/functions/mmap.html)
The mmap() function shall add an extra reference to the file associated with the file descriptor fildes which is not removed by a subsequent close() on that file descriptor. This reference shall be removed when there are no more mappings to the file.

shm_format() callback function in wl_shm_listener is just for checking whether the format of ARGB8888 is available or not on compositor.

static void
create_shm_buffer(struct touch *touch)
{
 struct wl_shm_pool *pool;
 int fd, size, stride;

 stride = touch->width * 4;
 size = stride * touch->height;

 fd = os_create_anonymous_file(size);
 if (fd < 0) {
  fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
   size);
  exit(1);
 }

 touch->data =
  mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 if (touch->data == MAP_FAILED) {
  fprintf(stderr, "mmap failed: %m\n");
  close(fd);
  exit(1);
 }

 pool = wl_shm_create_pool(touch->shm, fd, size);
 touch->buffer =
  wl_shm_pool_create_buffer(pool, 0,
       touch->width, touch->height, stride,
       WL_SHM_FORMAT_ARGB8888);
 wl_shm_pool_destroy(pool);

 close(fd);
}

static void
shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{
 struct touch *touch = data;

 if (format == WL_SHM_FORMAT_ARGB8888)
  touch->has_argb = 1;
}

struct wl_shm_listener shm_listener = {
 shm_format
};

Interaction with the server (weston)

One of the important information shared between client & server is fd (file descriptor). Wayland uses domain-socket IPC to transfer it. I do not dive deep inside. Reference is source code of "Sending a file descriptor over a UNIX domain socket" in APUE 3rd Edition

Here I just check the interaction point: which functions or call-stacks perform that IPC.
In the client, wl_display_dispatch() and other "dispatch" functions such as wl_display_roundtrip().

<send>
sendmsg ()
wl_connection_flush () at connection.c:286
wl_display_dispatch_queue () at wayland-client.c:1201
wl_display_dispatch () at wayland-client.c:1290
<receive>
recvmsg ()
wl_os_recvmsg_cloexec () at wayland-os.c:123
wl_connection_read () at connection.c:327
read_events () at wayland-client.c:964
wl_display_dispatch_queue () at wayland-client.c:1220
wl_display_dispatch () at wayland-client.c:1290

In the server(weston compositor)

<send>
sendmsg ()
wl_connection_flush () at connection.c:286
wl_display_flush_clients () at wayland-server.c:880
wl_display_run () at wayland-server.c:868
main () at compositor.c:3377
<receive>
recvmsg ()
wl_os_recvmsg_cloexec () at wayland-os.c:123
wl_connection_read () at connection.c:327
wl_client_connection_data () at wayland-server.c:261
wl_event_source_fd_dispatch () at event-loop.c:86
wl_event_loop_dispatch () at event-loop.c:421
wl_display_run () at wayland-server.c:869
main () at compositor.c:3377

Now go to the source code. There is a pattern in Wayland code.







  • If wl_OBJ_FUNC() exists in the client, there is OBJ_FUNC() in the server.
  • if wl_OBJ_listener and its callback FUNC() exists, there is wl_OBJ_send_FUNC() in the server.


  • Clients' wl_OBJ_FUNC()s and a server's wl_OJB_send_FUNC()s just post the event/request on it's queue, not do IPC directly. IPC happens when calling wl_display_dispatch() in the clients and calling wl_connection_flush()/read() in the server.

    Touch object

    If the client calls wl_display_registry(), server will receive the message and run display_registry()

    wayland/src/wayland-server.c
    display_get_registry(struct wl_client *client,
           struct wl_resource *resource, uint32_t id)
    {
     struct wl_display *display = resource->data;
     struct wl_resource *registry_resource;
     struct wl_global *global;
    
     registry_resource =
      wl_resource_create(client, &wl_registry_interface, 1, id);
     if (registry_resource == NULL) {
      wl_client_post_no_memory(client);
      return;
     }
    
     wl_resource_set_implementation(registry_resource,
               &registry_interface,
               display, unbind_resource);
    
     wl_list_insert(&display->registry_resource_list,
             &registry_resource->link);
    
     wl_list_for_each(global, &display->global_list, link)
      wl_resource_post_event(registry_resource,
               WL_REGISTRY_GLOBAL,
               global->name,
               global->interface->name,
               global->version);
    }
    
    If call wl_registry_bind(registry, name/*seat_name*/, &wl_seat_interface, 1), registry_bind() -> bind_seat() is called in the server. And this function set up seat_get_touch() as get_touch() callback. In line 1481, wl_seat_send_capabilities() wake-up client wl_seat_listener's callback capabilities( seat_handle_capabilities() in this example).

    wayland/src/wayland-server.c
    static const struct wl_seat_interface seat_interface = {
     seat_get_pointer,
     seat_get_keyboard,
     seat_get_touch,
    };
    
    static void
    bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
    {
     struct weston_seat *seat = data;
     struct wl_resource *resource;
     enum wl_seat_capability caps = 0;
    
     resource = wl_resource_create(client,
              &wl_seat_interface, MIN(version, 3), id);
     wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
     wl_resource_set_implementation(resource, &seat_interface, data,
               unbind_resource);
    
     if (seat->pointer)
      caps |= WL_SEAT_CAPABILITY_POINTER;
     if (seat->keyboard)
      caps |= WL_SEAT_CAPABILITY_KEYBOARD;
     if (seat->touch)
      caps |= WL_SEAT_CAPABILITY_TOUCH;
    
     wl_seat_send_capabilities(resource, caps);
     if (version >= 2)
      wl_seat_send_name(resource, seat->seat_name);
    }
    
    And then in seat_handle_capabilities(), we call wl_seat_get_touch(seat), seat_get_touch() is called.

    wayland/src/wayland-server.c
    static void
    seat_get_touch(struct wl_client *client, struct wl_resource *resource,
            uint32_t id)
    {
     struct weston_seat *seat = wl_resource_get_user_data(resource);
     struct wl_resource *cr;
    
     if (!seat->touch)
      return;
    
            cr = wl_resource_create(client, &wl_touch_interface,
        wl_resource_get_version(resource), id);
     if (cr == NULL) {
      wl_client_post_no_memory(client);
      return;
     }
    
     if (seat->touch->focus &&
         wl_resource_get_client(seat->touch->focus->resource) == client) {
      wl_list_insert(&seat->touch->resource_list,
              wl_resource_get_link(cr));
     } else {
      wl_list_insert(&seat->touch->focus_resource_list,
              wl_resource_get_link(cr));
     }
     wl_resource_set_implementation(cr, &touch_interface,
               seat, unbind_resource);
    }
    
    Which actions do wake up wl_touch_listener's callback? In the case of touch down event, wl_touch_send_down() by default_grab_touch_down() wake up wl_touch_listener's down() callback.
    wayland/src/wayland-server-protocol.h
    static inline void
    wl_touch_send_down(struct wl_resource *resource_, uint32_t serial, uint32_t time, struct wl_resource *surface, int32_t id, wl_fixed_t x, wl_fixed_t y)
    {
     wl_resource_post_event(resource_, WL_TOUCH_DOWN, serial, time, surface, id, x, y);
    }
    

    The server's related callstack is as follows, dafault_grab_touch_down() is registered as input device handler's callback
    default_grab_touch_down () at input.c:172
    notify_touch () at input.c:1069
    evdev_flush_motion () at evdev.c:265
    evdev_process_events () at evdev.c:365
    evdev_device_data () at evdev.c:396
    wl_event_source_fd_dispatch () at event-loop.c:86
    wl_event_loop_dispatch () at event-loop.c:421
    weston_compositor_read_input () at compositor.c:1349
    wl_event_source_fd_dispatch () at event-loop.c:86
    wl_event_loop_dispatch () at event-loop.c:421
    wl_display_run () at wayland-server.c:869
    main () at compositor.c:3377


    Surface and graphics buffer object

    This sequence is same as the case of touch object

    wl_registry_bind(registry, name, &wl_shm_interface, 1); -> bind_shm();
    shm_format()(wl_shm_listener's format() callback) <- wl_shm_send_format(resource, WL_SHM_FORMAT_ARGB8888); 
    wl_shm_create_pool(...); -> shm_create_pool(...);
    wl_shm_pool_create_buffer(...); -> shm_pool_create_buffer(...);

    Here I check shm_create_pool(). This function extract graphics buffer from given fd. I don't know why Wayland distinguish wl_shm_pool & wl_shm_buffer yet.


    wayland/src/wayland-server.c
    static void
    shm_create_pool(struct wl_client *client, struct wl_resource *resource,
      uint32_t id, int fd, int32_t size)
    {
     struct wl_shm_pool *pool;
    
     pool = malloc(sizeof *pool);
     if (pool == NULL) {
      wl_client_post_no_memory(client);
      goto err_close;
     }
    
     if (size <= 0) {
      wl_resource_post_error(resource,
               WL_SHM_ERROR_INVALID_STRIDE,
               "invalid size (%d)", size);
      goto err_free;
     }
    
     pool->refcount = 1;
     pool->size = size;
     pool->data = mmap(NULL, size,
         PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     if (pool->data == MAP_FAILED) {
      wl_resource_post_error(resource,
               WL_SHM_ERROR_INVALID_FD,
               "failed mmap fd %d", fd);
      goto err_free;
     }
     close(fd);
    
     pool->resource =
      wl_resource_create(client, &wl_shm_pool_interface, 1, id);
     if (!pool->resource) {
      wl_client_post_no_memory(client);
      munmap(pool->data, pool->size);
      free(pool);
      return;
     }
    
     wl_resource_set_implementation(pool->resource,
               &shm_pool_interface,
               pool, destroy_pool);
    
     return;
    
    err_close:
     close(fd);
    err_free:
     free(pool);
    }
    

    Compositor-related functions such as wl_surface_attach(...) are a bit different. The counter part of the client functions are located in weston/src/compositor.c, not in wayland/src/wayland-server.c. I think that compositor related things such like surface handling are not fixed as wayland protocol, depend on compositor implementation.

    wl_registry_bind(registry, name, &wl_compositor_interface, 1) -> compositor_bind(...)
    wl_compositor_create_surface(...) -> compositor_create_surface(...)
    wl_surface_attach(...) -> surface_attach(...)
    wl_surface_damage(...) -> surface_damage(...)



    Additionally I will check wl_surface_frame(). This is used in weston/clients/simple-egl.c and simple-shm.c. The return-type of wl_surface_frame() is struct wl_callback, not wl_frame or wl_surface_frame something. wl_callback is callback object. Its listener has only one callback function, done(). It seems a generic type of objects receiving event from the server for expanding features.

    wl_surface_frame() -> surface_frame()
    wl_callback_listener's done() callback <- wl_callback_send_done(cb->resource, msc)


     window->callback = wl_surface_frame(window->surface);
     wl_callback_add_listener(window->callback, &frame_listener, window);
    
    

    The server's related callstack is as fallows. After page flip is done, weston broadcast frame done event to all clients.

    wl_resource_post_event () at wayland-server.c:148
    wl_callback_send_done () at wayland-server-protocol.h:202
    weston_output_repaint () at compositor.c:1334
    weston_output_finish_frame () at compositor.c:1364
    page_flip_handler () at compositor-drm.c:719
    drmHandleEvent ()

    Another example using wl_callback is wl_display_sync()

    wl_resource_post_event () at wayland-server.c:148
    wl_callback_send_done () at wayland-server-protocol.h:202
    display_sync () at wayland-server.c:650




    Tuesday, November 26, 2013

    Nexus 4 Rooting from source code


    Intro

    There are so many documents dealing with rooting Android devices. But most of webpages describe it using binaries already pre-built by Hacker groups. It is not enough for rookies who want to build their own binaries from source code, kernel to user level. This manual is written for them.

    Before Rooting we need to prepare to restore original release binaries. We can get full binary images and vendor specific driver binaries for custom build from here: https://developers.google.com/android/


    Android web pages(http://source.android.com/index.html) already contain all information. I just added comments dedicated to Nexus 4 and re-arrange their order.

    Sunday, November 24, 2013

    Install java6 jdk from oracle binary instead of using "apt-get install sun-java6-jdk"


    For Android platform development, we need java6.
    But the guide is outdated. "sun-java6-jdk" is deprecated! ;-(

    We have to find another way.


    First of all, we need oracle java6 jdk binary.

    The url is Oracle download page. You need your account on oracle.com for downloading it.
    http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase6-419409.html#jdk-6u45-oth-JPR




    tmax@tmax3:~/work/android$ chmod +x jdk-6u45-linux-x64.bin
    tmax@tmax3:~/work/android$ ./jdk-6u45-linux-x64.bin
    Unpacking...
    Checksumming...
    Extracting...
    UnZipSFX 5.50 of 17 February 2002, by Info-ZIP (Zip-Bugs@lists.wku.edu).
    replace jdk1.6.0_45/db/bin/ij? [y]es, [n]o, [A]ll, [N]one, [r]ename: A
      inflating: jdk1.6.0_45/db/bin/ij
      inflating: jdk1.6.0_45/db/bin/NetworkServerControl
      inflating: jdk1.6.0_45/db/bin/setNetworkClientCP.bat
      inflating: jdk1.6.0_45/db/bin/setEmbeddedCP.bat
      inflating: jdk1.6.0_45/db/bin/stopNetworkServer.bat
    ...

    I set up my  environment by following (https://help.ubuntu.com/community/Java#Oracle_.28Sun.29_Java_6
     ). But I failed. Compiling failed with the error message below.
    host Java: jsilver (out/host/common/obj/JAVA_LIBRARIES/jsilver_intermediates/classes)
    Note: external/jsilver/src/org/clearsilver/FactoryLoader.java uses unchecked or unsafe operations.
    Note: Recompile with -Xlint:unchecked for details.
    jar: internal error:
    java.io.FileNotFoundException: -C (No such file or directory)
       at gnu.java.nio.channels.FileChannelImpl.open(libgcj.so.12)
       at gnu.java.nio.channels.FileChannelImpl.<init>(libgcj.so.12)
       at gnu.java.nio.channels.FileChannelImpl.create(libgcj.so.12)
       at java.io.FileInputStream.<init>(libgcj.so.12)
       at gnu.classpath.tools.jar.Creator.writeFile(libgcj-tools.so.12)
       at gnu.classpath.tools.jar.Creator.writeCommandLineEntries(libgcj-tools.so.12)
       at gnu.classpath.tools.jar.Creator.writeCommandLineEntries(libgcj-tools.so.12)
       at gnu.classpath.tools.jar.Updater.run(libgcj-tools.so.12)
       at gnu.classpath.tools.jar.Main.run(libgcj-tools.so.12)
       at gnu.classpath.tools.jar.Main.main(libgcj-tools.so.12)
    make: *** [out/host/common/obj/JAVA_LIBRARIES/jsilver_intermediates/javalib.jar] Error 1
    make: *** Deleting file `out/host/common/obj/JAVA_LIBRARIES/jsilver_intermediates/javalib.jar'

    The guide use "update-alternatives" utility for manual setup ("manual" means not-using-apt-get). It looks fancy. But something is wrong: conflict with pre-installed gcj java(GNU Compiler for Java). I could not fix it up. No idea about "update-alternatives".

    So I just followed ( http://www.arndaleboard.org/wiki/index.php/O_WiKi#Installing_the_JDK). I set PATH=$JAVA_HOME/bin:$PATH in .bashrc. The site gave good resource.


    Wednesday, November 13, 2013

    Disk data backup using dd

    Yesterday I saw the message pop-up "Hard driver failure blah blah ~". "Smart Data" utility said that replace my hard drive immediately.

    Main reason is "reallocated sector count warning". increasing Bad sector.

    There are so many posting about this issue





    Most of posting recommend that I should replace my hard disk immediately. Only few postings say the warning can be handled by recent system, so I can use my disk longer before more crucial waning occurs. But they also recommend data backup.

    So I decided to replace my HDD. Because I'm not busy, I thought that I did it relaxedly.


    My colleague recommended to use "dd"(disk dump") This tool clones a HDD as a block device, so I don't need to re-install OS.

    I accepted his advice. I insert a new HDD and old one with same bland & same size but different versions.  And I type the following command

    dd if=/dev/sdb of=/dev/sda

    I regretted my decision. Because dd is not gui tool, there is no fancy display, so I could not check current status.

    I asked the colleague How long it will take. He don't know it!!! He just knew about that, did not have used it.
    I'm upset. What I could do was just watching "dd"'s CPU occupation info using "top". It was steadily 30%. I tried to search for information of the performance of "dd" command on the webs. but I found nothing.

    It took 28800 seconds, almost 8 hours for cloning 1 TB !!!!!

    I didn't do any thing yesterday!!!

    One of my friend recommends to use "bs=1m" option for "dd". And another colleague recommends a specialized hardware cloning HDD called "clone1". It's chip and fast and can be used as a external HDD adapter.


    Saturday, October 26, 2013

    Documentary film about AYRTON SENNA

    I saw a documentary film describing Ayrton Senna's dramatic life.

    His passion touched me. I am about to cry at the climax.
    He only concentrated on his driving, not money, politics.

    Some bloggers felt uncomfortable since they did not agree with "FACTs" which is described in the film. They said that all mentions and interviews are based on the side of the main character, Senna. Alain Prost, another great driver in his ages, was shown as a political antagonist who used dirty means for winning. That is not fair.

    Nevertheless I swear this film will make most of men moved, who are struggling in our real world. Anyone cannot deny his strong eagerness to be the best F1 driver.

    And plus,
    If stay with the ending title, we will admire his warm humanity shown even in the track.

    The following link is the film, which is from BRAZIL but the link has no sub caption. I saw it on a Korean pay web-site providing VOD.
    http://www.youtube.com/watch?v=uBmNov-2SPA




    Saturday, October 12, 2013

    Regular Expressions

    Now I'm reading http://www.regular-expressions.info/tutorial.html for making simple log analyzer using python.

    I was confused with special characters, which are used in VIM & other applications.

    I started to use regular expressions searching for strings in VIM editor, so I got used to the regular expression of VIM. In VIM's regular expressions, if I want to find "+", I have to type just "+". But in python I use "\+" instead of "+" because "+" is registered as a special character(meta-character). (http://docs.python.org/2/library/re.html?highlight=split#re.split)
    In VIM "\+" is a meta-character. It is opposite to python.

    Special characters are 12: "\, ^, $, ., |, ?, *, +, (, ), [, {, "


    Monday, September 30, 2013

    Crossing Han River

    When i was a child crossing a bridge is a mission impossible. Han River is one of grand rivers in the world. The distance between both sides is almost 1.5km as I know. It was hard that children walk across. But now it becomes a piece of cake. Just walking and walking will bring me to the opposite site.