Your wish is my command

It’s a long journey

Nginx가 꽤 괜찮은가 본데?

RubyOnRails를 해볼 일이 생겼습니다. 기회가 없어서 하지않았던 건데.. 어쩌다보니 이것도 돌아보게 되었네요.

여기저기 문서를 뒤지다보다 보니 nginx에 대한 언급이 되고있고 특히 nginx에 대해서 눈에 띄는건 성능이 굉장이 좋다는 군요. 홈페이지 about에 소개된 FastFail.FM, WordPress.com의 예를 둘러보니 시도해볼까? 하는 생각이 듭니다.

Apache를 현재 무리없이 쓰고있지만, 어느 순간부턴 느낌이 너무 복잡해졌다고나할까? 하여간 그런 느낌이 들고, 요즘은 웹 서버에서는 연결받고 Application server로 바로 넘기는 일 밖에 안하나 이런 일에 충실한 웹 서버면 충분 하겠지요.

시간나면 해봐야죠. ㅋㅋ

ListView의 SubItem에 ProgressBar 그리기

TListView에 ProgressBar를 표현하는 것을 간단하게 생각하면 TProgressBar를 생성하고 SubItem위치에 표시하면 됩니다. 그리고 컬럼이 사이즈가 조절될 때 (HeaderTracking) 적당하게 위치 조절해주면 됩니다. 간단하게 심플하게 생각하면 그렇지요.

근데 그냥 OnDrawSubItem 이벤트에서 Themes을 이용해서 그려주면 어떨까? 하고 해 봤는데, 생각보다 간단합니다.

procedure TThemeForm.ListView1CustomDrawSubItem(Sender: TCustomListView;
  Item: TListItem; SubItem: Integer; State: TCustomDrawState;
  var DefaultDraw: Boolean);
var
  Element: TThemedElementDetails;
  R: TRect;
  Progress: 1..100;
begin
  if ((Sender as TListView).ViewStyle = vsReport) and (SubItem = 3) then
  begin
    R := Item.SubItemRect(SubItem, drBounds);
    Inc(R.Left);
    if Sender.GridLines then Dec(R.Bottom);

    Element := ThemeServices.GetElementDetails(tpBar);
    ThemeServices.DrawElement(Sender.Canvas.Handle, Element, R);

    Element := ThemeServices.GetElementDetails(tpChunk);
    InflateRect(R, -4, -3);
    Progress := 30;
    R.Right := R.Left + MulDiv(Progress, R.Right - R.Left, 100);
    ThemeServices.DrawElement(Sender.Canvas.Handle, Element, R);

    DefaultDraw := False;
  end;
end;

SubItemRect 함수는 다음과 같습니다.

function TListItemHelper.SubItemRect(SubItemIndex: Integer; Code: TDisplayCode): TRect;
const
  Codes: array[TDisplayCode] of Longint = (LVIR_BOUNDS, LVIR_ICON, LVIR_LABEL, LVIR_SELECTBOUNDS);
begin
  ListView_GetSubItemRect(ListView.Handle, Index, SubItemIndex, Codes[Code], @Result);
end;

자 잘나옵니까?

Msbuild를 이용해서 컴파일할때 Map 정보넣기..

JclDebug Expert를 이용해서 실행파일에다가 map파일 정보를 넣는건 쉽습니다. 그냥 메뉴에서 선택해주면 알아서 하니깐요.

하지만 우리 프로젝트에서는 msbuild를 이용해서 빌드를 하는데, 이걸로하면 JclDebug Expoert가 동작하지 않아서 map파일이 들어가지 않습니다. 흠..

이걸 어떻게 하나고 뒤져보니 Jcl에 이미 프로그램이 들어가있습니다. 하지만 소스만 들어가 있이니 컴파일해서 적용하면 되겠지요.

  1. msbuild MyProg.dproj /t:build /p:Configuration=Release /p:DCC_Define=RELEASE /p:DCC_MapFile=3 빌드할때 맵파일을 생성합니다.
  2. MakeJclDebug -E MyProg.map 컴파일이 끈나면 map파일을 압축해서 프로그램 바이너리에 집어넣습니다.

이렇게 하고 JclDebug에서 제공하는 ExceptionDialog가 실행되면 자동으로 바이너리의 map파일을 이용해서 StackTrace를 출력해줍니다.

마우스 휠메시지를 포커스가 있는 컨트럴이 아닌 마우스가 위치한 컨트럴로 보내기

{
  마우스 휠을 움직이면 포커스가 있는 컨트럴에 WM_MOUSEWHEEL이 가는데, 다른
  Application을 보면 마우스 포인터가 위치한 컨트럴에서 반응을 하는 경우가 있다.

  이 유닛을 포함하면 WM_MOUSEWHEEL 메시지가 마우스 커서가 있는 컨트럴로 간다.
  따라서 마우스 클릭을 하여 포커스를 이동할 필요가 없다.
}
unit WMMouseWheelUnderCursor;

interface

implementation

uses
  Windows, Forms, Classes, AppEvnts, Messages, Controls;

type
  TWMMouseWheelMessageUnderCursor = class(TApplicationEvents)
  private
    procedure OnMessageHandler(var Msg: tagMSG; var Handled: Boolean);

  public
    constructor Create(AOwner: TComponent); override;
end;

{ TWMMouseWheelMessageUnderCursor }

constructor TWMMouseWheelMessageUnderCursor.Create(AOwner: TComponent);
begin
  inherited;

  OnMessage := OnMessageHandler;
end;

procedure TWMMouseWheelMessageUnderCursor.OnMessageHandler(var Msg: tagMSG;
  var Handled: Boolean);
var
  Pt: TPoint;
  Control: TWinControl;
 begin
  if Msg.message = WM_MOUSEWHEEL then
  begin
    Pt.X := Word(Msg.lParam);
    Pt.Y := HiWord(Msg.lParam);
    Control := FindVCLWindow(Pt);
    if not Assigned(Control) then
      Handled := True
    else if Control.Handle <> Msg.hwnd then
    begin
      Handled := True;
      SendMessage(Control.Handle, WM_MOUSEWHEEL, Msg.wParam, Msg.lParam);
    end;
  end;
end;

initialization
  TWMMouseWheelMessageUnderCursor.Create(Application);
end.

Indy로 Form Submit하기 삽질

  • TIdMultipartFormDataStream를 이용하면 될 것 같아서 열심히 했다.
  • 근데 UTF8 인코딩이 필요하다. AddFormField로 추가하면 될 것 같았다. AddObject도 안된다.
  • TIdMultipartFormDataStream는 유니코드를 전혀 지원하지 않는다.
  • 그냥 TStrings로 했다. 잘된다.. ㅡㅜ

Drupal에서 삽질

  • WebForms에서 만들 폼에다가 넣는 중이있다.
  • 잘 넣는데 가끔 폼에 적은 내용이 전달이 되지 않는다. 흠… 한참 삽질하다 다시 보니 WebForms의 필드 타입이 textfield인 곳에 여러줄 넣으면 안된다. 아마 여러줄에 이상한 문자가 있었나?.. 하여간 가끔안되다가 되다가.
  • 여러줄 필요한 곳의 타입을 textarea로 변경하니 잘 된다.

Gettext가 업데이트 되었다.

gettext가 0.18로 업데이트 되었다.

이놈은 항상 무섭다. 엄청나게 많은 ports들이 의존성을 갇고 있기 때문에(portmaster -r gettext로 보면, 직간접적으로 X11이 돌아가는 시스템은 147개, X11이 안돌아가는 놈은 90개) 함부로 업데이트 했다가는 날리가 난다. 그런데 쩝.. 업데이트 된 줄도 모르고 다른거 업데이트 하다가 의존성 때문에 업데이트가 되고 말았다. 이런 실수 실수…

어쩔수 없이 gettext가 업데이트 된 상황을 반영해야한다.

portmaster -w -r gettext

하다가 기존의 라이브러리 참조하는에러가 나서 임시로 라이브러리를 기존 것으로 symbolic 걸어놓고 다시 gettext 업데이트 하고 있다.

조심하자…

추가

  1. portmaster 2.32버전으로 올라가면서 -w옵션이 추가되었는데, 공유 라이브러리는 백업을 하고 업그레이드를 하기 때문에 위처럼 symbolic link를 거는 삽질을 안해도 된다.
  2. portmaster 걸때 시간도 같이 측정했으면 재밌었을 텐데… 그냥 하고 있으므로 무시…

Delphi 2009 부터는 Exception에 StackTrace가 있는데?

StackTrace를 확인하기 위해서 JclDebug를 사용하고 있었는데(2007 버전부터), 혹시나하고 StackOverflow에서 찾아봤더니 Delphi 2009 버전부터는 Exception에 StackTrace 정보가 들어가 있다.

시간날 때 공부해야겠군요.

추가: 좀 봤는데, 실제로 StackTrace를 보여주는 게 아니라 그를 위한 Framework입니다. 그냥 JclDebug로 하세용.

Bugzilla 데이터베이스를 MySQL에서 PostgreSQL로 이전하기

그냥 contrib/bzdbcopy.pl을 사용하면 된다. 그냥하면 안되고 파일 열어서 데이터베이스 연결 속성을 좀 바꿔주면 된다.

그리고 Custom Field를 만들었다면 그건 여기서 처리 못한다. 그럴땐 간단한 스크립트 만들어 돌리면 된다.

import MySQLdb
import psycopg2

mysql_bugs_conn = MySQLdb.connect(user='**\**', db='****', passwd='****')
pgsql_bugs_conn = psycopg2.connect('dbname=**\** user=****')

mysql_cursor = mysql_bugs_conn.cursor()
pgsql_cursor = pgsql_bugs_conn.cursor()

mysql_cursor.execute("SELECT bug_id, cf_testcase FROM bugs WHERE cf_testcase is not null")
for bug_id, cf_testcase in mysql_cursor.fetchall():
pgsql_cursor.execute("UPDATE bugs SET cf_testcase = %s WHERE bug_id = %s", (cf_testcase, bug_id))
pgsql_bugs_conn.commit()

그런데 이걸 왜 했냐고? MoinMoin에서 Bugzilla 데이터를 보여주는 Macro를 사용하는데 이게 가끔은 ????게 나온다. 뭐 인코딩 문제인데… MySQL이 문젠가 하고 그냥 바꿔봤다. 근데 잘 된다. 어짜피 MySQL보단 PostgreSQL을 더 선호하니 그냥 해버렸다. ^^;

추가: PostgreSQL로 이전하고 pgpool로 connection pool을 돌렸다. ㅋㅋ