지금까지 쭉 써오면서...주로 혼자만 쓰다보니;;; merge기능은 잘 안썼었다.
(branch를 쓰긴했지만, 그냥 테스트용도로 잠시 쓰고 버렸을뿐;;)
이번에 쓰려고 하니 잘 모르는부분이 많아서 검색 후 좋은 내용을 발견.

그래서 링크걸어둔다.

http://bchavez.bitarmory.com/archive/2008/06/03/quothow-toquot-svn-merge-with-tortoisesvn.aspx
유일하게 하는 게임이 WoW이고...길드는 알레리아 섭 SLRCLUB 에서 활동중이다.
사람도 제법 많아지고 그래서...10인 레이드는 길드에서 자체 소화하는데, 템 분배가 문제.
아무래도, 템파밍이 완료 된 사람은 '길드니까' 이래저래 불려다니거나 하는 입장이고, 템먹고 싶은 사람은 '길드니까' 공짜로 쉽게 갈수있는 장점이 있다. 아무래도 전자의 경우엔 피해를 본다?라는 느낌이 든다. 무료봉사라는 거지. 이를 해결할 방법은?

1. 정식공대처럼 포인트제로 계산.
-> 포인트 관리 누가할꺼냔? -.-;;

2. 저득정액주팟
-> 풀어서 말하면...적게 템을 먹은 사람이 우선권을 지니고, 같은 레벨의 사람이면 주사위를 굴려 높은 사람이 먹으며, 먹을때 일정 골드를 내어서 무득인 사람들이 나눠가진다.

그랬는데...좀 2번은 길팟이니까 별로라고 하는 사람들이 많아서...epgp라는 길드레이드 지원 애드온을 깔게되었다.

여기까지가 epgp라는걸 쓰게 된 배경 헥헥;;

여튼 본 얘기는...여기부터. ㅎㅎㅎ 테스트 하다보니...한글지원이 제대로 안되는거다 두둥!!! 왠 한문으로 깨지기도 하고... 그래서? 일단 버그가 있다고 리포팅했으나, 솔직히 한글을 쓰지도 않는 녀석들인데 디버그 포인트도 못찾는게 당연지사. 어쩔수없이...디버깅을 내가 시작했다 -ㅁ-;;;

그래서 찾아보니...unicode 변환하는 부분에서 문제가 있었다. 비트연산이 좀 잘못되어있었던것. 여튼...덕택에 한글과 중국어가 잘 지원되도록 fix되었다. ㅎㅎㅎ epgp라는 애드온 자체의 문제는 아니고, 얘네들이 쓰는 라이브러리가 있는데 (AceLib라고...꽤 유명한거 같은데) 거기서 문제가 있었던것. 내가 올렸던 이슈는 http://code.google.com/p/epgp/issues/detail?id=378 여기서 확인 가능하다 ^^;

왠지 오픈소스(뭐...걍 유저들이 만들어가는거니까 맞지?ㅎㅎ)에 기여한거 같아서 뿌듯하기도 하고~~ 덕분에 내 소중한 일요일의 3~4시간이 날아가버렸지만 -ㅁ-;;;
commit을 잘못했을 경우에 대처법. (tortoise SVN)

Subversion doesn’t offer this capability directly, but you can achieve the same results using the merge command. So if you accidently check in some code that you want to then effectively remove from the tree, you can.

svn merge usage has three forms (run svn help merge for the full details) but the one I prefer looks like this:

svn merge -r<from>:<to> <repository> <working directory>

In the wild that translates to something like this (from within your checked-out trunk):

svn merge -r1455:1454 https://prime/svn/client/tfg/aurora2/trunk .

Follow this up with a check in:

svn ci -m "Rolled back to r1454"

Note that it doesn’t remove the broken revision (in the above case, r1455) from the repository. Instead you’ll get a new revision (r1456) which is identical to 1454. It’s still possible though for the broken version to be checked out if you specifies r1455.



요렇게 하면 된다넹~~~
(링크 : http://lambie.org/2008/05/23/rolling-back-your-subversion-repository-to-a-previous-good-revision/)
뭐...사실 좋은 툴들 많지만. 그냥 Windows에서 자체 제공하는것으로 체크하는 방법.

#include <stdlib.h>             // STEP 1
#include <crtdbg.h>             // STEP 2

int main()
{
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
   
    int * p = (int *)malloc(sizeof(int) * 10);
    _CrtDumpMemoryLeaks( );
}

요렇게 종료전에 CrtDumpMemoryLeaks 호출하면 memory leak이 있을경우 알려준다.
(위에서는 STDOUT으로 설정했으니까 콘솔창에 보여진다)
요즘 WoW 게임에서...공격대장 이라는 걸 가끔 해보고있다.

WoW를 모르는분들을 위해서 설명드리자면...일반 인스턴스던젼은 5명에서 팀이 되어서 하는거고, 레이드는 파티단위로 몇파티를 모아서 간다. 즉 10인 레이드라고 하면 2개의 파티(= 10명)인거고, 25인 레이드는 5파티로 가는거다. WoW초창기에는 40인 레이드도 있었으니...정말 많은 인원이었을 거다.

알레리아 서버에서 SLRCLUB 길드에 속해있는데, 사제-_-;면서 왜 공대장을 하고있는진 모르겠지만...(보통 힐러인 사제는 공대장을 잘 하지않고, 메인탱커인 전사가 한다. 아무래도 탱커가 공격대(=레이드)리딩을 하기때문에 그렇다.) 아 생각났다. 우리길드의 맨탱(메인탱커를 줄여서 이렇게 표현한다)이 마이크가 없다 -_-;;;;;;;;;

뭐 여튼...우여곡절 끝에 다들 한번 해보자! 해서...길드 레이드를 첨 가게되고, 내가 공대장을 맡게되고...그러다보니 계속 공대장이 필요할땐 그냥 내가 하고있다. (왜 다 그렇지않은가. 첨하긴 어렵지만, 한번해보고나면 할만한거...^^) 근데 공대장 요게 좀 묘하다. 실세계에서의 팀장과 비슷한 역할이랄까?

보통 게임에서 공대장은 일단 필요한 클래스들을 모집한다. 모집할때 아무렇게나 모집하지않는다. 탱커,힐러,딜러가 어떻게 배분되어야하는지, 시너지를 얻으려면 클래스 구성을 어떻게 할것인지. 모으는데 너무 오래걸린다? 그럼 시너지를 포기하고서라도 아무렇게나 모아도 목적 달성이 가능한 팟인지 알아야한다. (공대원들의 스펙이 좋으면 시너지가 없어도 충분할테니까...)

자 팀원이 모였다. 보통, 특정 네임드 잡을때는 정석적인 공략법이 있다. 일단 그건 가이드라인으로 볼 수 있다. 하지만 언제나 변수는 있기마련 ^^;; 누군가가 다른 의견을 제시한다.

'이거 이렇게 하더니까 훨 좋던데요?'

끙...저게 좋을까? 진짜? 생각해보고 판단한다. 공대원에 대한 신뢰가 있거나, 충분히 좋은 의견이라고 생각되면 해본다. 아니라면 그냥 가이드라인을 따른다(or 내맘대로 한다). 잘 잡았으면 성공!!!
근데 못잡았다??!?!?!? 그럼 일단 전 공대원들의 시간을 10분 이상 날려먹는다. (재정비하는데 제법 시간 걸린다..) 그럴경우 공대장이 잘해야된다. 전원 스펙의 부족이라면 한두번 더 해보고 접어야한다. 더이상은 그냥 시간낭비일뿐이니까...
그게 아니고 전술적 문제였다면, 수정해보고, 공대원들의 의견을 들어보고, 수행한다. (보통의 경우에는...이렇게 된다 ^^;; 스펙의 문제는 보통 모을때 어느정도 파악이 되기때문에...) 그리고 충분히 잡을 수 있다는 화이팅도 한다.


상위의 과정과 실제 현실과의 다른점은 뭘까? 음....글쎄. 리더일 경우 월급이 많다는것 정도? ^^;;;
뭐 ctypes 매뉴얼에 잘 나와있긴한데...
왠만한 winapi들은 python win32 expansion에 들어있다. 그런데 가끔은 없는것도 있단말이지.
그럴경우는 kernel32.dll에 있는 함수를 직접 호출해줘야한다.
하는 방법은 매우 간단하다.
(FindFirstVolume이라는 winapi 호출을 한다고 가정한다)

from ctypes import *
winapifunc = windll.kernel32.FindFirstVolumeA

그리고는 winapifunc 함수호출. 끝.
-ㅁ-;; 좀 허전하지? ㅎㅎ 여기서 반드시 주의할점. 대부분의 windows api들은 A,W로 끝나는 ANSI, Unicode 버젼이 따로 존재한다. 즉, 실제 함수명과 MSDN에 나오는 함수명은 다른것. 실제 함수명을 보고싶다...면 DLL export 가 어떻게 되어있는지 살펴보면 좋다.

http://www.nirsoft.net/utils/dll_export_viewer.html

여기 가보면 해당 유틸리티를 다운받을수 있다. 이건 꼭 kernel32.dll뿐만 아니라 다른 dll들에도 적용되므로 (다른점이라면 LoadLibrary 호출이 한줄 더 들어가는정도?) 참고하자~~~
문서로 남겨뒀다가 복사해둔다.

1 Apache 설치 (2.2.3)
    yum install httpd
2 python 확인 (2.4.3)
    yum install python
3 setuptools 설치 (EasyInstall)
    python ./ez_setup.py
4 Genshi 설치
    easy_install Genshi (잘 되지않을경우 -U 옵션 붙여서 실행)
5 python-sqlite 설치 (1.1.7)
    yum install python-sqlite
6 subversion Binary 설치
    Summer 에서 패키지한 1.5.1버젼 rpm들을 받아서 설치
(
    or
    -이 방식으로는 mod_dav_svn이 컴파일되지않는다-
    subversion 소스설치 (apache와 연동시키지않는다 - 세팅할게 많으므로)
        # 소스 다운로드 (1.4.6) - dep도 같이 다운로드.
        # cd subversion-1.4.6/neon
        # ./configure --enable-shared
        # ./make
        # ./make install
        # ./cd ..
        # ./configure
        # ./make
        # ./make install
        # ./make swig-py
        # ./make install-swig-py
        # subversion 소스 디렉토리에서 make swig-py && make install-swig-py로 Python 바인딩을 설치하고,
        다음 명령으로 python 경로에 등록해준다.
        $ echo [subversion설치경로]/lib/svn-python >
            [python 설치경로]/lib/python2.x/site-packages/subversion.pth
        - thanks to http://pragprog.tistory.com/tag/Subversion
)
7 mod_python 설치
    1 yum install mod_python
8 Install Trac
    1 홈페이지에서 Trac을 다운로드 (0.11.1)
    2 압축풀기
    3 python ./setup.py install
9 trac 디렉토리 초기화 후 tracd 를 실행해서 trac자체는 제대로 동작하는지 확인한다.


기본설정은 끝. 실제 환경을 만들어 보자 (apache+trac 연동)

1 mod_python이 동작하는지 확인
    1 /etc/httpd/conf/httpd.conf에
        <Location /mpinfo>
           SetHandler mod_python
           PythonInterpreter main_interpreter
           PythonHandler mod_python.testhandler
        </Location>
      추가 후 웹페이지 확인. (http://trac/mpinfo)
    2 추가한 부분 삭제.
2 .htpasswd 생성
    1  htpasswd 명령어로 사용자 생성 및 추가
3 httpd.conf 추가
    <Location /trac>
            SetHandler mod_python
            PythonInterpreter main_interpreter
            PythonHandler trac.web.modpython_frontend
            PythonOption TracEnvParentDir /data/trac
            PythonOption TracUriRoot /trac
            PythonOption PYTHON_EGG_CACHE /tmp
    </Location>   
    <LocationMatch "/trac/[^/]+/login">
            AuthType Basic
            AuthName "Type your ID, Password"
            AuthUserFile /data/trac/.htpasswd
            Require valid-user
    </LocationMatch>




=====================================================================
                    프로젝트 생성하기
=====================================================================
1 root로 접속
2 trac-admin [프로젝트 trac path] initenv
3 각종 파라미터 입력
4 svnadmin create [프로젝트 svn path]
5 폴더 권한변경 => [/]# chown -R apache.apache [프로젝트 trac path]
6 폴더 권한변경 => [/]# chown -R apache.apache [프로젝트 svn path]

요즘 python을 개인적으로 관심있게 보고있는데...한가지 의문이 생겼더랜다.

'스크립트 언어지만, 실제 .py 코드가 동작하는것은 이미 쓰여진 코드. 그러면 runtime에 코드를 동적으로 생성해서 실행하는것이 가능할까?'

자세히는 보지않아서 정확한 구현을 어떻게 하는지는 기억이 나지는 않지만, C/C++쪽에서도 실시간으로 op code를 만들 수 있다. 비단 C/C++뿐만 아니라 .NET 환경하에서도 가능하다. (예전 windows들도 상당히 즐겨썼다고 한다. asm을 만들어서 끼워넣는 방법. Beautiful code 라는 책에서 살펴볼 수 있다)
그렇다면 python은??

일단 함수,클래스 들의 호출은 kldp에 문의해서 알아봤다 ㅎㅎ (링크)

__dict__ 를 사용하면 될꺼같은데요.
만약 인터프레터에서 나가고 싶으면 exit() 을 처도 되지만,
__buitlins__.__dict__["exit"]() 을 처도 나가집니다. ㅎㅎ.
다른 예로...

>>> class Foo:
... def bar(self):
... print "Hello, world"
...
>>> a = Foo()
>>> a.bar()
Hello, world
>>> Foo.__dict__
{'__module__': '__main__', 'bar': , '__doc__': None}
>>> Foo.bar(a)
Hello, world
>>> Foo.__dict__['bar'](a)
Hello, world
>>>

이 코드에선 a.bar(), Foo.bar(a), 와 Foo.__dict__['bar'](a) 가 다 같은 뜻을 가집니다 ㅎㅎ. 만약 문자열을 가지고 함수를 부르고 싶으면 __dict__['문자열'] 을 해버리면 되겟군요.

오호라...역시 되는구나.
그렇다면 조금 다른 활용을 살펴보도록 하자. 보통 OOP에서의 동적 함수 호출이라고 하면 C++로 표현해서 다음과 같은걸 의미한다.

class Base
{    virtual void foo() = 0; };

class Derived_1
{    virtual void foo() { 어쩌구; } };

class Derived_2
{    virtual void foo() { 저쩌구; } };

그리고는 실제 호출시에는 Base의 포인터만을 이용해서 호출하는 방식. 이방식의 문제점이라면...Factory Pattern을 쓴다고 했을때, type별로 매칭되는 뭔가를 따로 만들어줘야 한다는거지. id라고나 할까? id가 1이면 Derived_1을 생성해주고, 2이면 Derived_2를 생성해주고.

자 예제 코드 --->>
Base * FactoryMethod(int class_id)
{
    if (1 == id)
        return new Derived_1();
    else if (2 == id)
        return new Derived_2();
    else
        return NULL;
}

요런식으로 된다. 그런데...그냥 따로 id 받지않고 클래스 명을 받을수도 있지않을까? 또 코드로 말하자면 --->>
Base * FactoryMethod(const string class_name)
{    return new class_name(); }

이렇게 말이다. 좀 어이없을수도...;; C/C++에선 쉽지않을꺼다. (가능할까? 흠...잘 모르겠네...;;) 그런데 python은 저게 된다 -_-;;;; 컴파일을 인터프리터로 할 수 있기때문에 가능하다. 아래의 코드.

-------------------------------------------------------------
import codeop

class T1:
    def Eval(self, val):
        print val

class T2:
    def Eval(self, val):
        print 2 * val

tmpcodeobj = codeop.compile_command('obj = T1()')
eval(tmpcodeobj)
obj.Eval(10)
-------------------------------------------------------------

위의 코드에서 'obj=T2()' 이렇게 문자열을 바꾸면 T2:Eval() 이 호출된다. ^^;
스크립트 언어의 위대함이랄까...;;;
Memory allcation에 대해서 공부하다가 요청하는 숫자에 적합한 2의배수 값을 찾아주는게 필요해서 한번 간단히 짜봤다.

// 처음 1이 나오는 MSB 위치를 리턴 : 0-31
unsigned int SearchMSB(unsigned int n)
{
    unsigned int i;
    for (i=0; i<32; i++) {
        if (0x80000000 == (n & 0x80000000))
            break;
        n <<= 1;       
    }
    return i;
}

unsigned int FindFitSize(unsigned int n)
{
    unsigned int msb = SearchMSB(n);
    unsigned int tmp = SearchMSB((1 << (31-msb)) - 1 + n);
    return 1 << (31-tmp);
}

int _tmain(int argc, _TCHAR* argv[])
{
    while(1)
    {
        int n;
        printf("input number : ");
        scanf("%d",&n);
        printf("fit size : %u\n\n", FindFitSize(n));
    }
    return 0;
}

여기서 SearchMSB의 경우는 거의 모든 CPU에서 한사이클짜리 단일 asm으로 제공되어진다. (linux의 O(1) 스케쥴링 알고리즘이 그걸 이용함. - 물론 코드 분석한건 아니고 주워들은 얘기 ㅎㅎㅎ - TI DSP에도 _lmbd 라는 명령어로 존재한다.)

FindFitSize의 결과는 64를 넣으면 딱 맞으니까 64를 리턴하고,  65를 넣으면 128을 리턴하는 것. 또 나중에 생각하기 귀찮아서 생각난김에 플밍하고 기록해둠~ ^^;;
이쪽 세계도 심오하구나...하고 절실히 느끼는중 ^^;;
크누스 형님이 제창하신 buddy-system (2의 배수로만 메모리 할당해주는것 - 33바이트를 요구하면 64바이트를 65KB를 요구하면 128KB를... 구현이 쉽다는게 장점) 에서 요즘은 slab allocator로 넘어가는게 대세인것 같다.

이런 링크도 참고해보고 -> http://monac.egloos.com/1246303
slab allocator 관련된 논문들도 보고있는데....어려웠던 부분은,
좀 더 하위레벨 얘기가 나오면 GG상황이었던것. 예를들어, 하드웨어 캐쉬 미스를 줄이기 위해 이런걸 썼다 라고 하는데...'웅?? 이뭥뮈?;;' 이러고 있으니 ㅋㅋㅋ SDR interleaving 얘기도 나오고... 그래도 이리저리 찾아보니 슬슬 알아가는 재미가 있다 ㅎㅎㅎ

다 알게되면 좀 정리 해야할듯...

+ Recent posts