2008/10/20

dtrace를 이용한 프로세스의 화일(fd)당 write 패턴 분석

간혹 프로세스가 작동하는 것을 보면 프로세스가 오픈한 화일들에 대한 읽기/쓰기 패턴이 궁금할때가 있어집니다. 
예를 들면, 평소에 문제가 없었는데, DB로부터 데이타를 읽어와서 화면에 출력하는 어떤 경우 화면에 출력이 느려지는 경우가 있습니다.

이런 환경에서 이 프로세스가 오픈한 화일들을 대상으로 어떻게 작동하는 지를 볼 수 있다면 매우 편리할 것입니다.

솔라리스에서는 pfiles라는 유틸리티나 mdb를 이용하여 프로세스가 오픈한 화일들을 볼 수가 있습니다. 다음은, 이메일 클라이언트로 유명한 썬더버드라는 툴이 어떤 화일들을 오픈했는 지 확인하는 방법입니다.

#pfiles 1180
bhkim@vaio-bhkim:~/Desktop$ pfiles 1180  > /tmp/thunderbird.1180.pfiles
bhkim@vaio-bhkim:~/Desktop$ cat /tmp/thunderbird.1180.pfiles
1180:    /usr/lib/thunderbird/thunderbird-bin
  Current rlimit: 512 file descriptors
   0: S_IFCHR mode:0666 dev:301,0 ino:6815752 uid:0 gid:3 rdev:13,2
      O_RDONLY|O_LARGEFILE
      /devices/pseudo/mm@0:null
   1: S_IFIFO mode:0000 dev:299,0 ino:182 uid:0 gid:50 size:0
      O_RDWR
   2: S_IFIFO mode:0000 dev:299,0 ino:182 uid:0 gid:50 size:0
      O_RDWR
   3: S_IFDOOR mode:0444 dev:311,0 ino:42 uid:0 gid:0 size:0
      O_RDONLY|O_LARGEFILE FD_CLOEXEC  door to nscd[1156]
      /var/run/name_service_door
   4: S_IFSOCK mode:0666 dev:310,0 ino:50338 uid:0 gid:0 size:0
      O_RDWR|O_NONBLOCK FD_CLOEXEC
    SOCK_STREAM
    SO_SNDBUF(16384),SO_RCVBUF(5120)
    sockname: AF_UNIX
    peername: AF_UNIX /tmp/.X11-unix/X0
   5: S_IFIFO mode:0000 dev:299,0 ino:671 uid:101 gid:10 size:0
      O_RDWR
   6: S_IFIFO mode:0000 dev:299,0 ino:671 uid:101 gid:10 size:0
      O_RDWR
   7: S_IFREG mode:0644 dev:182,65544 ino:18136 uid:101 gid:10 size:0
      O_WRONLY|O_CREAT|O_TRUNC
      /export/home/bhkim/.thunderbird/5x1njpem.default/.parentlock
   8: S_IFIFO mode:0000 dev:299,0 ino:672 uid:101 gid:10 size:0
      O_RDWR|O_NONBLOCK
   9: S_IFIFO mode:0000 dev:299,0 ino:672 uid:101 gid:10 size:0
      O_RDWR|O_NONBLOCK
  10: S_IFIFO mode:0000 dev:299,0 ino:673 uid:101 gid:10 size:0
      O_RDWR|O_NONBLOCK
  11: S_IFIFO mode:0000 dev:299,0 ino:673 uid:101 gid:10 size:0
      O_RDWR|O_NONBLOCK
  12: S_IFREG mode:0644 dev:182,65544 ino:18139 uid:101 gid:10 size:140912
      O_RDWR
      /export/home/bhkim/.thunderbird/5x1njpem.default/abook.mab
  13: S_IFREG mode:0644 dev:182,65538 ino:37521 uid:0 gid:2 size:851050
      O_RDONLY|O_LARGEFILE
      /usr/lib/thunderbird/chrome/classic.jar
  14: S_IFREG mode:0644 dev:182,65538 ino:37527 uid:0 gid:2 size:837452
      O_RDONLY|O_LARGEFILE
      /usr/lib/thunderbird/chrome/en-US.jar
  15: S_IFSOCK mode:0666 dev:310,0 ino:31861 uid:0 gid:0 size:0
      O_RDWR FD_CLOEXEC
    SOCK_STREAM
    SO_SNDBUF(16384),SO_RCVBUF(5120)
    sockname: AF_UNIX
    peername: AF_UNIX /tmp/.iiim-bhkim/:0.0
  16: S_IFIFO mode:0000 dev:299,0 ino:674 uid:101 gid:10 size:0
      O_RDWR
  17: S_IFIFO mode:0000 dev:299,0 ino:674 uid:101 gid:10 size:0
      O_RDWR
  18: S_IFIFO mode:0000 dev:299,0 ino:675 uid:101 gid:10 size:0
      O_RDWR
  19: S_IFIFO mode:0000 dev:299,0 ino:675 uid:101 gid:10 size:0
      O_RDWR|O_NONBLOCK
  20: S_IFCHR mode:0644 dev:301,0 ino:78118918 uid:0 gid:3 rdev:149,1
      O_RDONLY
      /devices/pseudo/random@0:urandom
  21: S_IFSOCK mode:0666 dev:310,0 ino:33534 uid:0 gid:0 size:0
      O_RDWR|O_NONBLOCK FD_CLOEXEC
    SOCK_STREAM
    SO_SNDBUF(16384),SO_RCVBUF(5120)
    sockname: AF_UNIX
    peername: AF_UNIX /var/tmp/orbit-bhkim/linc-292-0-48e4789fdb523
  22: S_IFSOCK mode:0666 dev:310,0 ino:38996 uid:0 gid:0 size:0
      O_RDWR|O_NONBLOCK FD_CLOEXEC
    SOCK_STREAM
    SO_REUSEADDR,SO_SNDBUF(49152),SO_RCVBUF(49152)
    sockname: AF_INET 127.0.0.1  port: 41233
  23: S_IFSOCK mode:0666 dev:310,0 ino:31860 uid:0 gid:0 size:0
      O_RDWR|O_NONBLOCK FD_CLOEXEC
    SOCK_STREAM
    SO_REUSEADDR,SO_SNDBUF(16384),SO_RCVBUF(5120)
    sockname: AF_UNIX /var/tmp/orbit-bhkim/linc-49c-0-48e474737f48b
  24: S_IFSOCK mode:0666 dev:310,0 ino:31858 uid:0 gid:0 size:0
      O_RDWR|O_NONBLOCK FD_CLOEXEC
    SOCK_STREAM
    SO_REUSEADDR,SO_SNDBUF(16384),SO_RCVBUF(5120)
    sockname: AF_UNIX /var/tmp/orbit-bhkim/linc-49c-0-48e474737f48b
    peername: AF_UNIX
  25: S_IFREG mode:0644 dev:182,65538 ino:180840 uid:0 gid:2 size:1916121
      O_RDONLY|O_LARGEFILE
      /usr/lib/thunderbird/chrome/toolkit.jar
  26: S_IFREG mode:0755 dev:182,65538 ino:180947 uid:0 gid:2 size:790881
      O_RDONLY|O_LARGEFILE
      /usr/lib/thunderbird/chrome/ko.jar
  27: S_IFREG mode:0644 dev:182,65544 ino:70397 uid:101 gid:10 size:2400716
      O_RDONLY|O_LARGEFILE
      /export/home/bhkim/.thunderbird/5x1njpem.default/XUL.mfasl
  28: S_IFREG mode:0400 dev:182,65544 ino:18228 uid:101 gid:10 size:74694
      O_RDONLY|O_LARGEFILE
      /export/home/bhkim/.thunderbird/5x1njpem.default/extensions/{C0CB8BA3-6C1B-47e8-A6AB-1FAB889562D9}/chrome/quicknote.jar
  29: S_IFREG mode:0644 dev:182,65538 ino:180837 uid:0 gid:2 size:2712048
      O_RDONLY|O_LARGEFILE
      /usr/lib/thunderbird/chrome/messenger.jar
  30: S_IFREG mode:0644 dev:182,65544 ino:18131 uid:101 gid:10 size:32825
      O_RDWR
      /export/home/bhkim/.thunderbird/5x1njpem.default/panacea.dat
  31: S_IFIFO mode:0000 dev:299,0 ino:681 uid:101 gid:10 size:0
      O_RDWR|O_NONBLOCK
  32: S_IFREG mode:0644 dev:182,65544 ino:18143 uid:101 gid:10 size:1617
      O_RDWR
      /export/home/bhkim/.thunderbird/5x1njpem.default/ImapMail/mail-apac.sun.com/%EB%B0%9B%EC%9D%80%20%ED%8E%B8%EC%A7%80%ED%95%A7926b93e.msf
  33: S_IFREG mode:0644 dev:182,65544 ino:29639 uid:101 gid:10 size:1508
      O_RDWR|O_CREAT|O_TRUNC
      /export/home/bhkim/.thunderbird/5x1njpem.default/ImapMail/mail-apac.sun.com/%EB%B0%9B%EC%9D%80%20%ED%8E%B8%EC%A7%80%ED%95%A36b3cbd8.msf
  34: S_IFREG mode:0644 dev:182,65544 ino:38481 uid:101 gid:10 size:1965
      O_RDWR
      /export/home/bhkim/.thunderbird/5x1njpem.default/ImapMail/mail-apac.sun.com/%EB%B0%9B%EC%9D%80%20%ED%8E%B8%EC%A7%80%ED%95%A9ecefa66.msf
  35: S_IFIFO mode:0000 dev:299,0 ino:681 uid:101 gid:10 size:0
      O_RDWR|O_NONBLOCK
  36: S_IFREG mode:0600 dev:182,65544 ino:18120 uid:101 gid:10 size:98304
      O_RDWR FD_CLOEXEC
      /export/home/bhkim/.thunderbird/5x1njpem.default/cert8.db
  37: S_IFREG mode:0600 dev:182,65544 ino:18129 uid:101 gid:10 size:32768
      O_RDWR FD_CLOEXEC
      /export/home/bhkim/.thunderbird/5x1njpem.default/key3.db
  38: S_IFREG mode:0644 dev:182,65544 ino:18186 uid:101 gid:10 size:3554267
      O_RDWR
      /export/home/bhkim/.thunderbird/5x1njpem.default/ImapMail/mail-apac.sun.com/INBOX.msf
  39: S_IFSOCK mode:0666 dev:310,0 ino:25977 uid:0 gid:0 size:0
      O_RDWR|O_NONBLOCK
    SOCK_STREAM
    SO_SNDBUF(49152),SO_RCVBUF(49640)
    sockname: AF_INET 129.158.2.81  port: 36053
    peername: AF_INET 192.18.19.180  port: 993
  41: S_IFREG mode:0644 dev:182,65538 ino:180836 uid:0 gid:2 size:1575881
      O_RDONLY|O_LARGEFILE
      /usr/lib/thunderbird/chrome/comm.jar
  42: S_IFREG mode:0644 dev:182,65544 ino:117215 uid:101 gid:10 size:169599
      O_RDWR
      /export/home/bhkim/.thunderbird/5x1njpem.default/ImapMail/mail-apac.sun.com/Trash.msf
  43: S_IFREG mode:0644 dev:182,65544 ino:18126 uid:101 gid:10 size:0
      O_RDWR|O_CREAT|O_LARGEFILE
      /export/home/bhkim/.thunderbird/5x1njpem.default/urlclassifier2.sqlite
  44: S_IFREG mode:0644 dev:182,65544 ino:18126 uid:101 gid:10 size:0
      O_RDWR|O_CREAT|O_LARGEFILE
      /export/home/bhkim/.thunderbird/5x1njpem.default/urlclassifier2.sqlite
  45: S_IFSOCK mode:0666 dev:310,0 ino:61169 uid:0 gid:0 size:0
      O_RDWR|O_NONBLOCK FD_CLOEXEC
    SOCK_STREAM
    SO_SNDBUF(16384),SO_RCVBUF(5120)
    sockname: AF_UNIX
    peername: AF_UNIX /tmp/dbus-6tM2grR7lu
  46: S_IFREG mode:0644 dev:182,65544 ino:64775 uid:101 gid:10 size:375842
      O_RDWR
      /export/home/bhkim/.thunderbird/5x1njpem.default/ImapMail/imap.gmail.com/INBOX.msf
  47: S_IFSOCK mode:0666 dev:310,0 ino:25978 uid:0 gid:0 size:0
      O_RDWR|O_NONBLOCK
    SOCK_STREAM
    SO_SNDBUF(49152),SO_RCVBUF(49680)
    sockname: AF_INET 129.158.2.81  port: 54161
    peername: AF_INET 209.85.135.109  port: 993
  48: S_IFREG mode:0644 dev:182,65544 ino:65840 uid:101 gid:10 size:65031
      O_RDWR
      /export/home/bhkim/.thunderbird/5x1njpem.default/ImapMail/imap.gmail.com/Trash.msf
  49: S_IFSOCK mode:0666 dev:310,0 ino:13077 uid:0 gid:0 size:0
      O_RDWR
    SOCK_STREAM
    SO_SNDBUF(16384),SO_RCVBUF(5120)
    sockname: AF_UNIX
    peername: AF_UNIX /tmp/fam-bhkim/fam-
  50: S_IFREG mode:0644 dev:182,65544 ino:18130 uid:101 gid:10 size:238135
      O_RDWR
      /export/home/bhkim/.thunderbird/5x1njpem.default/history.mab
  51: S_IFREG mode:0644 dev:182,65544 ino:18176 uid:101 gid:10 size:813104
      O_RDWR
      /export/home/bhkim/.thunderbird/5x1njpem.default/ImapMail/mail-apac.sun.com/Sent-1.msf


많은 화일들을 오픈하는 군요.

일단 이정보를 확보한 상태에서, 다음과 같이  dtrace를 실행볼 수 있겠습니다.
#dtrace -q -n 'syscall::write:entry/pid==1180/{self->trace=timestamp;fd=arg0;}' -n 'syscall::write:return/self->trace/{delta=timestamp-self->trace;@[fd]=avg(delta/1000);printf("transfer size : %d[%d], response time:%d us\n",arg0,fd,delta/1000);self->trace=0;}'

예쁘게 스크립트용으로 정리를 해본다면,

#/usr/bin/dtrace

#option D quiet
syscall::write:entry
/pid==1180/
{
    self->trace=timestamp;
    fd=arg0;
}

syscall::write:return
/self->trace/
{
   delta=timestamp-self->trace;
   printf("transfer
size : %d[%d], response time:%d
us\n",arg0,fd,delta/1000);
   @[fd]=avg(delta/1000);
   self->trace=0;
}

뭐 이쯤 되지 않겠나 싶습니다.  출력을 위해서 세련되게 포맷팅은 하지 않았습니다.
아무런 작동을 하지 않고 있을때  출력은 대개 이렇군요.

transfer size : 1[9], response time:8 us
transfer size : 1[11], response time:6 us
transfer size : 1[9], response time:8 us
transfer size : 1[9], response time:8 us
transfer size : 44[4], response time:8 us
transfer size : 1[9], response time:8 us
transfer size : 1[9], response time:8 us
transfer size : 1[9], response time:8 us
^C
transfer size : 1[9], response time:7 us

               11                6
                9                7
                4                8

printf에서 첫번째 아규먼트는 write()한 크기이고, 두번째는 대상 fd 번호이고, 세번째는 write() 호출에 대한 turnaround time입니다. 따라서, 위 출력의 앞부분에서

transfer size : 44[4], response time:8 us
은 4번 fd에서 44바이트 쓰기를 했는데, 8 microsecond 걸렸다는 얘기로 보면 되겠죠.

위 출력의 최종부분은 각 fd에 대한 평균 turnaround time을 출력하는 부분입니다.
11번 fd에서 평균 6us, 9번 fd에서 7us, 4번 fd에서 8us 정도가 걸렸군요.

이 글 맨앞에 언급한 pfiles를 이용하여 각 fd가 어떤 화일인가를 측정해본다면 매우 가시적인 결과를 얻을 수 있습니다.
fd[4]   AF_UNIX /tmp/.X11-unix/X0 ; 음. X11도에 화면 출력을 위한 fd이군요.
fd[9]
S_IFIFO mode:0000 dev:299,0 ino:672 uid:101 gid:10 size:0 ; IFIFO는 내부 통신용이겠죠.
fd[11]
S_IFIFO mode:0000 dev:299,0 ino:673 uid:101 gid:10 size:0 ; 역시 내부 통신용이네요.

첨부 화일을 하나 다운받고 있는 와중에 dtrace를 떠봤습니다.
...
transfer size : 1[35], response time:2 us
transfer size : 1[35], response time:2 us
transfer size : 4096[54], response time:27 us
transfer size : 73[54], response time:31 us
transfer size : 1[9], response time:4 us
transfer size : 1[9], response time:4 us
transfer size : 1[9], response time:3 us
transfer size : 1[9], response time:3 us
transfer size : 1[9], response time:2 us
transfer size : 1[9], response time:3 us
transfer size : 1[11], response time:4 us
transfer size : 1[9], response time:2 us
transfer size : 4096[53], response time:48 us
transfer size : 4096[53], response time:36 us
transfer size : 4096[53], response time:35 us
transfer size : 4096[53], response time:38 us
transfer size : 4096[53], response time:37 us
transfer size : 4096[53], response time:39 us
transfer size : 1536[53], response time:40 us
transfer size : 1[9], response time:3 us
transfer size : 1[9], response time:2 us
transfer size : 1[9], response time:2 us
...
               11                2
               35                2
                9                3
                6                4
                4                5
               49               11
               39               21
               54               25
               53               28
위와 같은 정보가 나오네요. 53번 54번 fd가 나왔는데, 위에 화일에는 없는 fd이므로 첨부화일을 다운받으면서 만들어진 새 fd라고 보여집니다. 이럴때는 open을 새롭게 감시해서 어떤 화일이 새로 오픈 되었는지도 알 수 있겠죠.

위의 결과에서 각 fd가 write한 총합과 평균 응답시간을 합해서 출력을 하려면 다음과 같이 할 수 있습니다.
dtrace를 살짝 바꿔봅니다.

#dtrace -q -n 'syscall::write:entry/pid==1180/{self->trace=timestamp;fd=arg0;}' -n 'syscall::write:return/self->trace/{delta=timestamp-self->trace;@w[fd]=sum(arg0);@l[fd]=avg(delta/1000);printf("transfer size : %d[%d], response time:%d us\n",arg0,fd,delta/1000);self->trace=0;}' -n 'END{printa(@w,@l);}'

...(생략)
transfer size : 4096[53], response time:39 us
transfer size : 4096[53], response time:11 us
transfer size : 4096[53], response time:10 us
transfer size : 4096[53], response time:10 us
transfer size : 4096[53], response time:10 us
transfer size : 4096[53], response time:10 us
transfer size : 4096[53], response time:10 us
transfer size : 4096[53], response time:10 us
transfer size : 2079[53], response time:9 us
transfer size : 120[4], response time:11 us
transfer size : 8[4], response time:3 us
...(중략)


                6                2                4
               30               40            72036
               49               46               11
               38               73            73137
               35              346                2
                9              406                3
               11              533                2
               39              859               17
               54            14925               24
               53           461993               23
                4          1199979                5

4번 fd에서 가장 많은 쓰기를 하네요. 화면에 출력하기 바쁘단 얘기죠. 그렇지만, 매 쓰기당 평균 응답시간은 5us입니다. 그다지 느리지 않네요. 반면, 그위에 새로이 나타난 53,54번 fd는 쓰기의 양은 덜하지만 평균 쓰기 응답시간이 23us,24us입니다. 첨부 화일의 fd인데, 역시 disk(화일 시스템)이 느리다는 것을 의미합니다. 53번 화일은 총 460K 바이트정도 썼으며, 매 쓰기당 23us 걸렸네요. 갑자기 전부 몇번 write를 했는지 쓰기하는 총 걸린 시간이 얼마인지를 알 수 있으면 더 좋겠다는 생각이 드는 군요.

dtrace를 조금더 바꿔봅니다. 그리고 이번에는 '지운편지함'을 액세스 해봤습니다.

#dtrace -q -n 'syscall::write:entry/pid==1180/{self->trace=timestamp;fd=arg0;}' -n 'syscall::write:return/self->trace/{delta=timestamp-self->trace;@c[fd]=count();@w[fd]=sum(arg0);@t[fd]=sum(delta/1000); @l[fd]=avg(delta/1000);printf("transfer size : %d[%d], response time:%d us\n",arg0,fd,delta/1000);self->trace=0;}' -n 'END{printa(@c,@w,@t,@l);}'

transfer size : 216[4], response time:5 us
transfer size : 212[4], response time:4 us
transfer size : 112[4], response time:6 us
transfer size : 172[4], response time:6 us
transfer size : 6420[4], response time:11 us
transfer size : 1[9], response time:7 us
^C
               fd       total # of writes total size of write total elapsed  average tt
               30                5              813               78               15
               42                5            29654            52081            10416
               53               12              869              198               16
               35               77             5946              222                2
               11              141              187              334                2
                9              313              313             1022                3
                4             3025          1133659            15468                5

fd 42번의 값이 눈에 확띄는군요. 총 쓰기 시간이 52ms이고, 총 write 호출 회수는 5번, 각 호출당 응답시간은 10ms이네요.
42번이 뭘까요 ?
  42: /export/home/bhkim/.thunderbird/5x1njpem.default/ImapMail/mail-apac.sun.com/Trash.msf

아하, 지운 편지함의 메일박스 화일이군요.
결론적으로 본다면, 이 메일박스를 좀 더 빠른 디렉토리에 두면 시간은 아주 빨라지겠군요.

오픈소스 라이센스 관련한 판결문입니다.

최근 미국에서 있었던 오픈 소스 라이센스 관련 판결문입니다.

요약 : 오픈소스는 자유 다운, 편집, 재배포가 가능하나, 적용 및 재배포시 반드시 사용한 오픈소스의 원천을 언급해야 한다는 오픈소스 라이센스를 지키지 않는 경우, 오픈 소스 라이센스에 위배될 수 있다라는 판결입니다.

따라서, 오픈소스를 이용해서 모듈을 만드는 경우에는 누구의 어떤 오픈소스를 사용했는 지에 대한 언급(라이센스 화일)을 반드시 하란 얘기겠죠.

번역입니다.
오픈소스 소프트웨어 사용에도 지켜야 할 조건은 있다.

오픈소스 소프트웨어의 특징은 라이센스 사용자(Licensee)들이 오픈소스 소프트웨어의 소스 코드를 무상으로 제공받을 수 있고, 이를 자유롭게 검사, 편집, 개선, 배포할 수 있다는 점이다. 오픈소스 소프트웨어의 이러한 개방적인 성격으로 인하여 많은 사람들이 오픈소스 소프트웨어의 사용에는 어떠한 조건이나 의무도 지켜야 할 필요가 없다는 잘못된 믿음을 갖게 된 것 같다.  오픈소스 소프트웨어에 관한 (국내 Dutch) 판례법상 입장은 아직 명쾌하게 정의되지 않고 있었지만, 최근에 미국의 한 법원에서 흥미로운 판결이 내려졌다. 즉, 2008년 8월 13일, 미국 연방 순회법원 항소심에서 오픈소스 소프트웨어를 다룬 Jacobsen v. Katzer 사건(No. 2008-1001)과 관련하여 법원은 오픈소스 라이센스 계약서의 조건을 위반하는 행위를 하는 경우 저작권 침해로 인정될 수 있다는 취지의 판결을 내린 것이다.

1심 재판에서의 사건 개요:
1심 재판에서 원고인 Robert Jacobsen는 소송절차를 밟아, 피고인 Matthew Katzer(개인)와 Kamind Associates Inc.(회사)를 상대로 권리보호를 위한 가처분 결정을 청구하는 소송을 제기하였다. 이 소송은 원고가 오픈소스 라이센스의 변형인 Artistic License의 조건에 따라 출시한 모형 기관차 컨트롤 용 소프트웨어 패키지인 Java Model Railroad Interface (JMRI)라는 오픈소스 소프트웨어를 피고들이 침해하였다는 원고측의 주장에서 비롯되었다. Artistic License 계약 조건에 의하면 일반 대중들은 누구든지 이 프로그래밍 코드를 별도의 라이센스 비용을 지급하지 않고 무상으로 사용할 수 있다고 규정되어 있다. 피고들은 모형 기차 및 기타 취미용 응용장치들을 위한 상업용 소프트웨어를 설계하여 문제의 JMRI 소스 코드의 일부를 자신들의 상업용 소프트웨어 개발시 사용하고 포함시켰으면서 그 소스 코드는 제외하였고, 소스 코드의 원천도 밝히지 않았다.  이에 따라 원고인 Jacobsen은 피고들이 오픈소스 라이센스의 계약조건을 위반하였다고 주장하면서 소송을 제기하게 된 것이다.

1심 재판 과정에서, 원고의 상기 주장은 받아들여지지 않았고, 법원은 Artistic License 계약조건에 포함된 의무만이 계약상의 규정으로 간주될 수 있으며, 피고들의 의무위반 행위는 오로지 계약상 의무의 불이행을 구성할 뿐이라는 취지의 판결을 내렸었다. 1심 법원의 주장에 의하면, 오픈소스 라이센스 계약 조건은 그 내용이 너무 광범위하고  애매모호하여서 이를 위반하는 것이 계약상의 의무 위반에 추가하여 저작권까지 위반한다고 보기 어렵다는 것이다. 이에 원고인 Jacobsen측은 이 판결에 대한 불복하여 연방 순회법원 항소심에 항소하게 이르렀다.

연방 항소심 절차:
1심 법원에서와는 달리 연방 순회법원 항소심에서는 원고측의 주장을 인정하여 피고들이 원고의 오픈소스 소프트웨어를 위에 기재한 바와 같이 사용한 것은 계약 위반에 해당할 뿐만 아니라 저작권 침해로도 인정된다는 취지의 판결을 내렸다. 연방 순회법원 항소심은 원고인 Jacobsen측이 사용하고 있는 라이센스 조건의 내용에 의하면 그 프로그래밍 코드를 사용하는 사용자들이 지켜야 할 제반 조건들을 포함하고 판단함으로써 이러한 판결을 뒷받침하고 있다.  이는 곧 원고의 라이센스 조건은 계약상의 합의를 구성할 뿐만 아니라 Artistic License 조건은 완벽한 저작권 라이센스를 구성하며, 이러한 라이센스 조건을 위반하는 것은 이와 관련된 저작권을 침해한 것임을 내포하고 있다는 것과 다름없다. 해당 소스코드를 포함하지 않고 그 소스코드의 원천을 밝히지 않은 채 오픈소스 소프트웨어를 배포함으로써, 피고들은 원고인 Jacobsen의  저작권까지 침해한 것이라는 판결이 내려진 것이다.

결론
연방순회법원 항소심에서의 이번 판결은 해당 소스코드를 포함하지 않고 그 소스코드의 원천을 밝히지 않은 채 오픈소스 소프트웨어를 배포하는 것은 불법적이라는 판정을 내린 것이다. 이 점에서 이번 판결은 오픈소스 라이센스에 대한 법률적인 위치에 관한 중요한 확인이라는 점에서 그 의미가 크다고 하겠다. 이와 같이 라이센스 조건을 위반하게 되면 계약 조건을 위반하게 됨은 물론 경우에 따라 그 저변에 존재하고 있는 저작권의 침해로도 간주될 수 있다는 점에서 비넌 판결은 오픈소스 소프트웨어에 관한 저작권 보호의 중요한 획을 구성할 판결이라고 볼 수 있을 것이다. 결국 저작권 법에 따라, 저작권을 위반하는 경우에 저작권자는 침해자로부터 손해배상을 받을 수 있음을 물론이고, 해당 소프트웨어의 무단 배포를 금지하는 법원의 결정을 받아 낼 수 있게 된 것이다. 이는 오픈소스 소프트웨어에 대한 저작권의 효율적인 보호에 커다란 기여를 하게 될 것임에 틀림없다. 따라서, 이번 판결은 모든 오픈소스 커뮤니티 전체에게는 매우 중요하고도 고무적인 일이 아닐 수 없다.


원문
The Use of Open Source Software is Bound by Conditions Too

Characteristics of open source software are that the source code is freely available and that the licensee may inspect, use, improve, supplement and distribute the source code. Exactly the open character of open source software results in the belief that the use of open source software is not bound by any rules or conditions at all. Although the status of open source software has not been crystallized in (Dutch) case law yet, recently an interesting judgment was rendered in the United States. The Court of Appeals for the Federal Circuit ruled on 13 August 2008 in the /Jacobsen v. Katzer/ case, No. 2008-1001, that acting in violation of an open source license agreement may be considered to be a copyright infringement.

Proceedings in the First Instance:
In the first instance, the claimant Robert Jacobsen instituted preliminary relief proceedings against the defendants Matthew Katzer and Kamind Associates, Inc. The basis for this claim was an alleged infringement of Jacobsen's copyrights to the Java Model Railroad Interface (JMRI), a software package for model trains controllers that is made available by Jacobsen under the 'Artistic License', an open source license variant. Under the conditions of the Artistic License, the public may use the programming code without paying a license fee. The defendants design commercial software for model trains and other hobby applications, and have incorporated parts of the JMRI into their commercial software without including the source code and a reference to the source. Jacobsen has argued that the defendants have thus acted in violation with the applicable open source license conditions.

In the first instance, Jacobsen's claim was denied and the Court ruled that the obligations as included in the Artistic License were only to be considered contractual provisions, and that their violation would therefore only constitute a breach of contract. In the Court's opinion, the open source license was described too broadly and too vaguely to be able to constitute a copyright infringement in addition to the breach of contract. Jacobsen has appealed against this judgment to the Court of Appeals for the Federal Circuit.

The Appeal Proceedings:
As opposed to the Court, the Court of Appeals for the Federal Circuit has ruled that the use of the defendants does qualify as an infringement of the copyrights of Jacobsen in addition to the breach of contract. The Court of Appeals for the Federal Circuit has substantiated this judgment by ruling that the text of the licenses, as used by Jacobsen, does actually impose conditions of use on the users of the programming code. This implies that there were not only contractual agreements, but that the Artistic License constitutes a full copyright license, and that violation of the license conditions implies an infringement of the copyrights involved. By distributing the open source software without including the source code and without a reference to the source, the defendants have infringed Jacobsen's copyrights.

Conclusion:
The Court of Appeals for the Federal Circuit has ruled that the distribution of open source software without including the source code and without a reference to the source is unlawful. Thus this judgment constitutes an important confirmation of the legal status of open source licenses. By ruling that a violation of the license conditions entails that in addition to a breach of contract there is also an infringement of the underlying copyright, this judgment constitutes an important hold for the protection of copyrights to open source software. After all, under copyright law, if there is infringement, it is not only possible to obtain damages from the infringing party, but also to obtain a ban on dissemination. It is exactly this extra protection that can contribute to an effective protection of copyrights to open source software. Thus this judgment constitutes an important boost for the entire open source community.


하둡 분산 화일 시스템 개요

멀티스레드 머신에서의 자바 애플리케이션 튜닝

CoolThreads - CMT Tuning and Resources - Applications: Java Servers
CMT라고 불리우는 하드웨어 기반의 멀티스레드 서버에서의 자바 튜닝 방법을 다룬 링크입니다.
주요 제품별 보편적인 튜닝 기법을 제공합니다. apache/tomcat의 경우에는  IBM의 websphere와 가장 비슷하지
않나 생각이 됩니다. WebSphere를 위해서 제공하는 TCP option은 다른 경우에도 공통 적용해도 상당한 효과가 있습니다.