문제를 푸는 것자체는 그다지 어렵지 않았으나, 멋있게 풀어보려고, 오늘 출근길 지하철에서 타블렛에 좀 끄적였다. W by H 행렬이라 보고, top left에서, 시계방향, 반시계방향 Spiral Array를 출력해주는 것을 만들었다. (물론 요즘은 erlang에 심취해있으므로, 구현언어는 당연히 erlang이다.)
요지는 조건 검사 같은 것을 하는 것이아니라, 수열을 사용한다. 즉, 동일한 상태 이동의 반복 회수가 수열이다. 연속된 transition의 개수를 구하는 함수를 f(x)라 하면,
f(x) = f(x - 2) - 1
x가 2보다 크면 무조건 성립이고, x = 1, 2 일때의 값은 clockwise, counterclockwise에 따라 W 또는 H로 조금 달라지기는 하지만 중요한 요점은 수열을 이용해 계산으로 구한다는것이다. 자세한 건 코드 참조!
2008-08-18 : 거의 동일한 방법으로 푼 사람이 이미 있었다. 맨앞에 몇개와 끝부분의 erlang 버전만 확인하고서 획기적인 방법이라고 좋아라하고 있었다니.... Orz. 그래도 high order function을 사용해서 functional에 걸맞는 멋진 프로그램이라고 나 자신에게 조금은 구차한(?) 최면을 거는 중이다.
unit test - makefile에서... make file에 다음과 같은 부분을 추가한 후에, make test 하면 간편하게 명령행에서 unit test를 수행할 수있다. (makefile 뼈대는 Programming Erlang을 기초로 했다.)
...... MODS = doc str_util db i18n tiny_scan ......
test: compile test_subdirs rm -rf Mnesia.nonode@nohost # removes previous mneisa db (optional). @for m in ${MODS};\ do \ echo "testing $$m";\ ${ERL} -noshell -pz "subdir1" -pz "subdir2" -s $$m test -s init stop;\ done
test_subdirs: cd subdir1; make test cd subdir2; make test
unit test, coverage test - 개발중 REPL(distel 또는 erl prompt) 에서... REPL을 사용해서 (멋지게) 코딩-테스트를 반복중이라면, 다음과 같은 모듈을 하나 디렉토리에 넣어서 test:unit() 또는 test:cover() 를 실행시켜서 unit test 및 coverage test를 시시때때로 수행해 볼 수 있다.
%%%------------------------------------------------------------------- %%% File : test.erl %%% Author : manywaypark <manywaypark@gmail.com> %%% Description : some test codes. %%% %%% Created : 11 Aug 2008 by manywaypark <manywaypark@gmail.com> %%%------------------------------------------------------------------- -module(test).
83> foo:save_xml("/tmp/foo.xml", Root). ** exception exit: {badarg,[{io,format, [<0.3348.0>,"~s~n", [[60,63,120,109,108,32,118,101,114,115,105, 111,110,61,34,49,46,48,34|...]]]}, {erl_eval,do_apply,5}, {shell,exprs,6}, {shell,eval_exprs,6}, {shell,eval_loop,3}]} in function io:o_request/2
이거 분명히 예전에 공부할 때 예제가 동작하는 것을 확인한 함수였는데.... binary로 써보기로했다.
84> Export=xmerl:export_simple([Root], xmerl_xml). ........ 85> file:write_file("/tmp/1.xml", list_to_binary(lists:flatten(Export))). ** exception error: bad argument in function list_to_binary/1 called as list_to_binary([60,63,120,109,108,32,118,101,114,115,105, 111,110,61,34,49,46,48,34,63,62,60,111,108, 100,114,103,112|...])
한글이 포함되어 안되는 것으로 짐작이 갔다.
99> list_to_binary([0, 1, 2]). <<0,1,2>> 100> list_to_binary([0, 1, 2, 255]). <<0,1,2,255>> 101> list_to_binary([0, 1, 2, 255, 256]). ** exception error: bad argument in function list_to_binary/1 called as list_to_binary([0,1,2,255,256])
결론은 list_to_binary가 255를 넘어가는 non-ascii를 제대로 처리하지 못해서였다.
esolr를 사용하려고 좀 만지작 거리다가, 버그를 하나 발견해서, 리포팅했다. 설명에 나온 기본 세팅으로 하면 잘 되는 것처럼 보이지만, select_url과 search_url 두개의 key가 Option을 설정할 때와 읽어올 때 혼동되게 되어있어서, solr의 URL을 정해주면 제대로 동작하지 않는 버그였다. 딸리는 영어지만 원작자의 페이지에 댓글을 달아두었다. ^^;
jetty에 동일한 war를 context path를 달리해서 여러 instance를 띄우는 방법에 관해 간략히 설명한다. 비교적 복잡한 solr를 예로 들겠다.
jetty 설치 jetty는 debian package를 다운로드 받아서 깔면 별 문제없이 잘 실행된다. (ftp://ftp.mortbay.org/pub/) 현재 안정 버전중 최신인 jetty-6.1.11를 받았다.
동일 war 여러 instance 설정 동일한 war를 다른 context path 및 설정으로 실행시키고 싶었다. solr로 예를 들자면, 몇개의 설정이 다른 solr가 떠서 url에 따라 다른 분야의 검색에 관한 서비스(인덱싱, 검색 질의 등)를 제공하는 것이다. solr wiki에 관련 설명이 나오는데 좀 모호한 부분이 있어서 한번 정리해 보았다.
중복 deploy 방지 (disable WebAppDeployer): /etc/jetty6/contexts 쪽의 설정만 사용하게 하기위해서 /etc/jetty6/jetty.xml에서 다음 부분을 삭제하거나, 주석처리한다.
<!-- Active JNDI so we can specify "solr/home" --> <Array id="plusConfig" type="java.lang.String"> <Item>org.mortbay.jetty.webapp.WebInfConfiguration</Item> <Item>org.mortbay.jetty.plus.webapp.EnvConfiguration</Item> <Item>org.mortbay.jetty.plus.webapp.Configuration</Item> <Item>org.mortbay.jetty.webapp.JettyWebXmlConfiguration</Item> <!-- <Item>org.mortbay.jetty.webapp.TagLibConfiguration</Item> --> </Array> <Set name="ConfigurationClasses"><Ref id="plusConfig"/></Set>
<!-- Adding <New class="org.mortbay.jetty.plus.naming.EnvEntry"> --> <!-- here sets a GLOBAL jndi value. Arg! --> <!-- So we specify "solr/home" in the overrideDescriptor instead --> </Configure>
<!-- This web.xml format file is applied to the people webapp AFTER it has been configured by the default descriptor and the WEB-INF/web.xml descriptor -->
<!-- NOTE: If Solr looked at something like this: --> <!-- NOTE: getServletContext().getInitParameter("solr.home"); --> <!-- NOTE: we could do the following w/o mucking with JNDI --> <!-- <context-param> <param-name>solr.home</param-name> <param-value>fixme-some-path</param-value> </context-param> -->
</web-app>
위의 두 파일은 인물 검색용 이라고 가정하자. 위의 파일에서 파일명과 파일 내용에 나오는 people을 book으로 바꾸어서
저장하면, 이제 http://localhost:8080/pepple/admin,
http://localhost:8080/book/admin 두개의 독립된 solr를 하나의 servlet engine -
jetty -에서 실행시키고 있는 것이다.
두 context path에서 실행은 되는데 아마도 에러가 날것이다. solr 관련 설정이 없어서 인데, "solr/home"으로 지정한 디렉토리에, solr의 example에 있는 solr 디렉토리 내의 파일들을 다 복사해주면 된다. 즉 위의 설명대로 파일 및 디렉토리를 구성했다면,
# JETTY_HOME은 보통 /usr/share/jetty6 이다. $ cp -R /path/to/solr/example/solr/* $JETTY_HOME/people/ $ cp -R /path/to/solr/example/solr/* $JETTY_HOME/book/
그래도 에러날 것이다. 이제 정말 마지막 설정하나, $JETTY_HOME/(people|book)/conf/solrconfig.xml 에서 <dataDir>${solr.data.dir:./solr/data}</dataDir>로 되어 있는 부분을
집에서 좀 볼일이 있어서 회사 서버로 접속을 했다가 Ubuntu 서버들을 간만에 upgrade하려했더니 업데이트 서버에서 파일이 없다는 식의 에러가 나면서 안됐다. 살펴보니 edgy였다. http://(kr|us).archive.ubuntu.com/ubuntu/dists/ 에 직접 브라우저로 들어가서 살펴보니 egdy는 아예 디렉토리도 없다. Orz. 가만히 생각해보니 모든 서버를 Dapper (LTS)로 했다가, 한놈만 갑자기 죽는 현상이 있어서 egdy로 올렸던 것이 떠올랐다.
표준적인(?) 방법으로, /etc/apt/sources.list에서 edgy를 몽땅 feisty로 바꾸고
W: mdadm: unchecked configuration file: /etc/mdadm/mdadm.conf W: mdadm: please read /usr/share/doc/mdadm/README.upgrading-2.5.3.gz . W: mdadm: no arrays defined in configuration file. W: mdadm: falling back to emergency procedure in initramfs.
'이거 잘못되면 주말에 회사 나가게 생겼구나. 3T짜리 레이드가 인식이 안될 수도 있겠다'
구글링을 해서 자료를 찾고, reboot을 하는 중에 계속 ping을 날리는데 ping이 "Destination Host Unreachable"에서 "64 bytes from boxname (xxx.xxx.xxx.xxx)"으로 바뀔때 어찌나 기쁘던지...
해결법(google and copy and paste):
sudo apt-get remove mdadm sudo apt-get install sysv-rc-conf sudo sysv-rc-conf # Press space to "uncheck" each item on the mdadm and mdadm-radi lines) sudo apt-get remove grub sudo apt-get install grub sudo update-grub sudo dpkg --configure -a