Titanium MobileのiOSモジュールを書くときのメモ

Titanium MobileのiOSモジュールを書くときにProxyクラスでのメソッドの引数との取り方

-(id)encodeURIComponent:(id)args
{
	id arg = [args objectAtIndex:0];
	NSString *unencodedString = [TiUtils stringValue:arg];
}

辞書(jsオブジェクトの取り方)

-(void)showContacts:(id)args
{
ENSURE_SINGLE_ARG(args, NSDictionary)
animated = [TiUtils boolValue:@"animated" properties:args def:YES];
}

Titanium MobileでiOSモジュールを書くときにはまった

とりあえず公式ドキュメント通りにhello worldでも試してみるかでいきなりつまづいた。
公式ドキュメント

公式ドキュメントにはiOSモジュールプロジェクト作成後にビルドしたzipファイルを

cp com.test-iphone-0.1.zip /Library/Application\ Support/Titanium/

しろと書いてあるが、ここに配置してTitaniumSDKからLaunchしても

/Library/Application Support/Titanium/modules/iphone/com.test/0.1

にはデプロイされずTitanium Mobileのログにも

[ERROR] Script Error = Couldn't find module: com.test.

シミュレータ画面には

Application Error Couldn't find module: com.test

出る。


苦手な英語でぐぐってみたがそれっぽい情報は見当たらず、みんなしれっとモジュール開発をしている
え!?俺の環境おかしい!?


と思いつつ、2日ぐらい途方にくれてたところ

こちらのブログを発見。
「com.armarkerti-iphone-0.1.zipを、サンプル動作用に作成したプロジェクトのディレクトリにコピーして下さい。」とあったので「え!?うそ!?」と思ってTitanium Mobileのプロジェクト直下に配置したところ、、、
無事にrequireできてサンプルのiOSモジュールの動作を確認。。。。


俺の英語の読解に誤りがなければモジュールの配置場所がいつかのバージョンからか

/Library/Application\ Support/Titanium/
↓
プロジェクトホーム直下

に変更されていたようだ。

ちなみにzipが展開されるディレクトリも

/Library/Application Support/Titanium/modules/iphone/com.test/0.1
↓
プロジェクト直下/modules/iphone/com.test/0.1

になっていた。

落ち着いて考えると複数プロジェクト開発するんだからこの変更は当たり前っちゃー当たり前なんだけど、、、
Titanium Mobileの開発スピードにドキュメント作成が追いついていないってこの前のデブサミでも増井さんが言っていましたが、その影響をもろに受けました、、、、
※リンク先からダウンロードできるPDF(Module_Developers_Guide_iOS-1.pdf)の末尾にRevision Historyが8/18/2010(Initial release)となっているので多分Titanium mobileが1.4ぐらいの時のものから更新されてないのだろうか、、、、


でもそれっぽい変更点はリリースノートに見当たらないんだけどなぁ。。。
やっぱ俺の英語の理解がおかしいのかな、、、

CとJavaで書いてみた

C言語のお勉強がてらに「珠玉のプログラミング」に載っていた「渡された配列の中で和が最大になる部分配列を探索する」アルゴリズムを実装してみました。


例えば配列{31, -41, 59, 26, -53, 58, 97, -93, -23, 84}が渡された場合は、{59, 26, -53, 58, 97}の合計187が最大値となるので、この部分配列を抜き出すのが正解となります。


一応javaでも書いてみたのですが、10000の長さのint配列をランダム生成して実行してみると
java:100秒ぐらい
C :500秒ぐらい


Cのほうが早いと思ってんですが、なんかコンパイルオプションとかあるのかな。
それとも俺のCの書き方が悪いんだろうか、、、、、


もうちょっと調べてみる
以下コードです

Cで書いた場合

#include <stdio.h>
#include <time.h>
#include <sys/time.h>

double gettimeofday_sec()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec + (double)tv.tv_usec*1e-6;
}

long runsort(int intsort[], int intsort_len)
{
        long max = 0;
        long sumtemp = 0;
	printf("intsort_len=%d\n", intsort_len); 
        int i;
        int j;
        int k;
        for(i = 0; i < intsort_len; i++) {
                for(j = i; j < intsort_len; j++) {
                        if(j == i) {
                                continue;
                        }
			sumtemp = 0;
                        for(k = i; k <= j; k++) {
                                sumtemp += intsort[k];
                        }
			/* printf("sumtemp=%d\n", sumtemp); */
                        max = max < sumtemp ? sumtemp : max;
			/* printf("max=%d\n", max); */

                }
                if(i % 100 == 0) {
                        printf("%d\n", i);
                }
        }
        return max;
}


int main (void)
{
	int array1[10000];
	int array1_len = sizeof(array1) / sizeof(array1[0]);
	printf("length=%d\n", array1_len);
	int i;
	double t1,t2;
	srand((unsigned)time(NULL));

	for(i = 0; i < array1_len; i++) {
		array1[i] = (int)rand() % 60000 - 30000;
		/* printf("random=%d\n", array1[i]); */
	}

	printf("start sorting....\n");
	t1 = gettimeofday_sec();
        long result = runsort(array1, array1_len);
	t2 = gettimeofday_sec();

        printf("result=%d, time=%10.30f\n", result, t2-t1);
	return 0;
}

Javaで書いた場合


import java.util.Random;

/**
 * Hello world!
 *
 */
public class App2 
{
    public static void main( String[] args )
    {
//    	int[] target = {31, -41, 59, 26, -53, 58, 97, -93, -23, 84}; //187
    	int[] target = new int[10000];
    	for(int i = 0; i < target.length; i++) {
    		Random r = new Random();
    		target[i] = r.nextInt();
    	}
    	App2 app = new App2();
    	long starttime = System.currentTimeMillis();
    	long result = app.sort(target);
    	System.out.println(result + ":" + (System.currentTimeMillis() - starttime) + "ms");

    }
   
    //配列中の最大の二つの要素を足した数を返す
    private long sort(int[] intsort) {
    	long max = 0;
    	for(int i = 0; i < intsort.length; i++) {
    		for(int j = i; j < intsort.length; j++) {
    			if(j == i) {
    				continue;
    			}
    			long sumtemp = 0;
    			for(int k = i; k <= j; k++) {
    				sumtemp += intsort[k];
    			}
    			max = max < sumtemp ? sumtemp : max;
    		}
    	if(i % 100 == 0) {
    		System.out.println(i);
    	}
    	}
    	return max;
    }
}

自宅のcuda環境を2.3から3.2にアップグレードすべくcudaまわりをキレイに再インストールすることにした。
その時の備忘録。


cudatoolkit_3.2.16_linux_64_rhel5.5.run
devdriver_3.2_linux_64_260.19.21.run
gpucomputingsdk_3.2.16_linux.run
をそれぞれインストール。
インストール方法については
http://developer.nvidia.com/object/cuda_3_2_downloads.html#Linux
Linux Getting Started Guide(PDF)に詳しく書かれているのでそのとおりに作業してすんなり。
(2.3の時はここらへんのドキュメントをしっかり読んでなかったのでえらい苦労した、、、)

~/NVIDIA_GPU_Computing_SDK/CにcdしてmakeしてdeviceQueryなどが実行できることを確認。



コンパイル時の設定
適当にコードを書いてnvccコンパイルしようとすると

cutil.h: そのようなファイルやディレクトリはありません

が出る。


自分のコードの中で#include でcutilというヘッダーファイルを読み込んでいるが、このパスが見当たらないエラーということらしい。
ファイル自体は~/NVIDIA_GPU_Computing_SDK/C/common/inc/cutil.h
にあるので、以前は/usr/includeとかにコピーしていたが、どうやら/usr/local/cuda/bin/nvcc.profileにコンパイル時の環境変数を書けるらしい。

TOP = $(_HERE_)/..
HOME = /home/hogehoge/NVIDIA_GPU_Computing_SDK
LD_LIBRARY_PATH += $(TOP)/lib:$(TOP)/extools/lib:
PATH += $(TOP)/open64/bin:$(_HERE_):

INCLUDES += "-I$(TOP)/include" "-I$(TOP)/include/cudart" $(_SPACE_) "-I$(HOME)/C/common/inc"

LIBRARIES =+ $(_SPACE_) "-L$(HOME)/C/lib" "-L$(TOP)/lib$(_TARGET_SIZE_)" -lcudart

CUDAFE_FLAGS +=
OPENCC_FLAGS +=
PTXAS_FLAGS +=

と書いておいた。
赤字が追加した設定。
cudaまわりのincludeする必要があるディレクトリをINCLUDESに追記して、必要なライブラリをLIBRARIESに追記している。




その後再度コンパイルをしたが、

nvcc -o keisan keisan.cu
/tmp/tmpxft_000078bb_00000000-13_keisan.o: In function `main':
tmpxft_000078bb_00000000-1_keisan.cudafe1.cpp:(.text+0x1735): undefined reference to `cutGetCmdLineArgumenti'
tmpxft_000078bb_00000000-1_keisan.cudafe1.cpp:(.text+0x17ec): undefined reference to `cutCheckCmdLineFlag'
collect2: ld はステータス 1 で終了しました

が出る。

cutilというライブラリをコンパイル時は指定しないといけないので、
nvcc -o ./keisan keisan.cu -lcutil
とするが

/usr/bin/ld: cannot find -lcutil
collect2: ld はステータス 1 で終了しました

でエラーになる。

落ち付いて先ほどnvcc.profileで指定した$(HOME)/C/libの中を見るとlibcutil_x86_64.aという名前になっているので
nvcc -o ./keisan keisan.cu -lcutil_x86_64
と指定したらコンパイル成功。
名前が変わっている理由はよくわからん。



参考
CUDAで最新のTOOLKITを使用するとCUTILライブラリがリンクできない問題
http://d.hatena.ne.jp/den8/20101026/1288101236
[GPGPU][CUDA]パスで難航CommentsAdd Star
http://d.hatena.ne.jp/ryamada22/20091009/1255083882

Linux(CentOS5.5)でMacのTimeMachine機能を利用する

家サーバをソフトウェアRAID化したので、MacからTimeMachineを使ってバックアップできるように設定する。
http://hatx.blog.so-net.ne.jp/2008-02-13
ここによるとnetatalkがtmというオプションでTime Machine対応を宣言するようになったらしい。

今までは色々と設定とかを工夫したり、ごにょごにょしたりしていたのが簡単に設定できるようになったみたい。
実際に
http://www.argv.org/~chome/blog/noisefactory/2009/09/linux-boxtime-machine.html
の通りに設定したらすんなり設定できた。

便利すなー

CentOS5.5でソフトウェアRAID + 監視

わが家には検証のPCサーバ(CentOS5.5 + Corei3 + mem4G)と子供の写真などデータロストしては困るデータ用に製品(Buffalo LinkStation LS-Q1.0TL/1D)がある。

このリンクステーションは去年(2009年)の7月頃に購入しているが、今月の引越で見事にぶっ壊れた。


マニュアルを見る限り赤ランプが7回点滅なので、HDDが認識されてないエラーみたいだが、他のHDDに差し替えたり、他の増設ベイに挿し直しても直らないので、思い切って捨てた。
※そもそも読み込み書き込みが予想以上に遅くて正直使い物にならない。
今まではお金を出して買った嫁への手前、データ冗長化のためだけに我慢して使っていた。


なので、この際検証PCを家庭内重要データ保管用NASとしても運用する事に決めた。


必要な要件は
・RAID1以上で冗長化されている
・ディスク障害が起きた時に通知される
が必須。


今回はついでにハードウェアを含めたシステム状態のトレンド監視も要件として入れた。


まずはRAID1構築。
CentOSインストール時のソフトウェアRAID構築はなんどかやったことはあるが、後からRAID設定するのは今回が初めて。
CentOSでソフトウェアRAIDの構築を参考して作業したところ問題なく完了。
すげー簡単に設定できるんだな、、、


次に障害検知してからの通知。
linuxソフトウェアRAIDで使うmdadmには監視デーモンとして稼働させるスクリプトであるmdmonitorも用意されているようなのでそれを使う。
設定を書く必要があるので設定ファイル"/etc/mdadm.conf"を作成するを参考に設定ファイルを作成。


mdmonitorデーモンを起動し、片方のHDDの電源を抜いてテストするもメールが飛ばない、、、
postfixを起動していなかったため、起動。


でもメール飛ばない。


よくわからんが多くのISPでは25番ポートへの接続はブロックしていることが多いらしい。
なので、ISPから提供されているsmtpサーバ経由でメールをrelayしないと送れないことが多いみたい。
ISP経由は微妙なので(今後変えるかもしれないし)、gmailsmtpを使わせてもらうことにする。


設定は
Postfixで、GMAIL経由でメールを送る(OP25B対策)
Relaying Postfix SMTP via smtp.gmail.comを参照して設定。
問題なく通知されるようになった。


あとはトレンド監視。
使い慣れているmuninを使って監視する。
ただ、今回はハード監視も入れてみたいのでlm_sensorsを調べる。
こことか調べて設定してみるも最後の設定用の文字列が出力されない。
そしてリブートしてからsensors実行してもやはり「No sensors Found」になる。
lm_sensorsのドキュメントを見るとH55チップセットは対応してないっぽい。


あきらめてsmartctlを利用したHDD温度監視で我慢することにした。


とりあえずこれで最低限のNASの運用はいけるのかな。
しばらく様子を見よう。