iPhone マルチスレッドを1つだけにする

最近iPhoneの記事が多いですが・・・。

iPhoneアプリが起動時にサブプロセスを起動させて、何かと重たい処理はそっちにお願いみたいなことはよくやりたいと思いますが、単純に起動時にサブプロセスを作っていると、アクティブ、非アクティブと変更しているといつの間にか複数プロセスがごろごろ。

原因は生成するタイミングにあった訳ですが。
・アクティブ時にログイン認証を行う
・ログイン認証が終わったタイミングで生成

要するにアクティブになったタイミングで次々とプロセスを生成していました。

そこで生成する箇所で既に生成済みの場合はプロセスを生成しないようにしました。
念のため、同期処理の宣言を入れてます。


@synchronized(self) {
        if (!_existsDaemon) {
            _existsDaemon = YES;
            // サブスレッドを作成する
            [NSThread detachNewThreadSelector:@selector(_startDaemon) toTarget:self withObject:nil];
        }
    }

iPhone ツールバーを均等に配置する

ツールバーにボタンなどを単純に追加すると、左寄せになってしまう。





UIToolbar* toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 480-44, 320, 44)];
 UIBarButtonItem* prevButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRewind target:self action:@selector(clickPrev)];
    UIBarButtonItem* nextButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFastForward target:self action:@selector(clickNext)];
    UIBarButtonItem* space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [toolBar setItems:[NSArray arrayWithObjects:space, prevButton, space, nextButton, space, nil]];



それを均等にする方法




間にUIBarButtonSystemItemFlexibleSpaceを入れるだけ。


UIToolbar* toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 480-44, 320, 44)];
    UIBarButtonItem* prevButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRewind target:self action:@selector(clickPrev)];
    UIBarButtonItem* nextButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFastForward target:self action:@selector(clickNext)];
    UIBarButtonItem* space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [toolBar setItems:[NSArray arrayWithObjects:space, prevButton, space, nextButton, space, nil]];

iPhone 複数画像スライド、拡大縮小させる

完成系のイメージはiPhoneのアルバム。

複数画像がある状態で、
1.フリック動作で次の画像、前の画像がみれる
2.2本の指で拡大縮小ができる
3.(できれば)ステータスバーやツールバーが自動的に消える

を作りたいなーと思い、いろいろ調べながら試行錯誤した内容を書きます。

1.フリック動作で次の画像、前の画像がみれる

これはUIScrollViewのプロパティーを設定する。
pagingEnabled ページング
showsHorizontalScrollIndicator 横スクロールバー
showsVerticalScrollIndicator 縦スクロールバー
scrollsToTop ステータスバーをタップしたときにTOPに戻る(今回は横ページ遷移のため特にいらない)

各ページのx座標をずらしてaddSubviewすればOK
1ページ目 CGRextMake(0, 0, 320, 480);
2ページ目 CGRextMake(320, 0, 320, 480);
3ページ目 CGRextMake(640, 0, 320, 480);
のような感じで。


UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    scrollView.pagingEnabled = YES;
    scrollView.showsHorizontalScrollIndicator = NO;// 横スクロールバー非表示
    scrollView.showsVerticalScrollIndicator = NO; // 縦スクロールバー非表示
    scrollView.scrollsToTop = NO; // ステータスバーのタップによるトップ移動禁止

    NSArray* imageNames = [NSArray arrayWithObjects:@"image2.jpeg", @"image1.jpeg", @"image3.jpeg", nil];
    int imageNum = [imageNames count];
    for (int i=0; i < imageNum; i++) {
        UIImage* image = [UIImage imageNamed:[imageNames objectAtIndex:i]];
        UIImageView* imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
        CGSize size = CGSizeMake(MIN(image.size.width, 320), MIN(image.size.height, 480));
        imageView.frame = CGRectMake(320*i + (320 - size.width) / 2, 0 + (480 - size.height) / 2, size.width, size.height);
        [scrollView addSubview:imageView];
    }
    [scrollView setContentSize:CGSizeMake(320*imageNum, 480)];
    [self.view addSubview:scrollView];

iPhone SHA1、SHA256の生成

iPhoneでSHA1、SHA256の生成方法。
調べてもあまり出てこないので、ちょっとあっているのか不安ですが、簡単な文字列の比較では問題ない感じでした。


+(NSString*) sha1ForStr:(NSString *)str {
 const char *c = [str UTF8String];
    unsigned char result[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1(c, strlen(c), result);
    NSMutableString* strs = [NSMutableString string];
    for (int i=0; i < CC_SHA1_DIGEST_LENGTH; i++) {
        [strs appendFormat:@"%02x", result[i]];
    }
    return strs;
}

+(NSString*) sha256ForStr:(NSString *)str {
 const char *c = [str UTF8String];
    unsigned char result[CC_SHA256_DIGEST_LENGTH];
    CC_SHA256(c, strlen(c), result);
    NSMutableString* strs = [NSMutableString string];
    for (int i=0; i < CC_SHA256_DIGEST_LENGTH; i++) {
        [strs appendFormat:@"%02x", result[i]];
    }
    return strs;
}

ちなみにperlでは
perl -MDigest::SHA -e 'print Digest::SHA::sha1_hex("aaa"), "\n"'
perl -MDigest::SHA -e 'print Digest::SHA::sha256_hex("aaa"), "\n"'
です。

iPhone文字列のサイズを取得

テキストフィールドは高さ固定ですが、UITextViewは高さを調整できます。
そして、動的に高さを変更する場合、高さを取得するためのAPIが存在します。

UIStringDrawing.hに定義があります。

//単一行
- (CGSize)sizeWithFont:(UIFont *)font; // Uses UILineBreakModeWordWrap
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode;

//複数行
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size; // Uses UILineBreakModeWordWrap
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode; // UITextAlignment is not needed to determine size

サンプルコード
UITextView* textView = [[[UITextView alloc] init] autorelease];
    [textView setText:@"sample"];

 // ピクセル
 CGSize textSize = [textView.text sizeWithFont:textView.font
        constrainedToSize:CGSizeMake(320, 1000)
         lineBreakMode:UILineBreakModeCharacterWrap];
    NSLog(@"textSize font:%@ w:%f h:%f", textView.font, textSize.width, textSize.height);
    // textSize font: font-family: "Helvetica"; font-weight: normal; font-style: normal; font-size: 12px w:39.000000 h:15.000000

ちなみに2行文のテキストを指定すると
[textView setText:@"sample\n2nd line"];
...
//w:43.000000 h:30.000000

iPhone開発 ARC forbids explicit message send of ‘retain’の解決方法

Xcode4.2で、「ARC forbids explicit message send of ‘retain’」のエラーが。

ひとまず解決方法

1.プロジェクトファイルを選択
2.Bullid Settingsを選択
3.Allを選択して、検索フィールドにAutomaticを指定
4.Apple LLVM compiler 3.0 - Language内のObjective-C Automatic Refarence CountingをYesに変更

iPhone 子プロセスではNSURLConnectionののタイムアウトが検知できない?

タイムアウトが検知できないというか、delegateが何も通知されてきません。

実装は至ってシンプル

-(void)click:(UIButton*)button
{
    // サブスレッドを作成する
    [NSThread detachNewThreadSelector:@selector(doProcess) toTarget:self withObject:nil];
//    [self doProcess];
}

- (void)doProcess {
    // ここから追加
    NSURL *url = [NSURL URLWithString:@"http://localhost:5000/"];
    NSURLRequest *req=[NSURLRequest requestWithURL:url];
    NSURLConnection *conn=[[NSURLConnection alloc] 
                                    initWithRequest:req delegate:self];
    if (conn) {
        NSLog(@"start loading");
        receivedData = [[NSMutableData data] retain];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    NSLog(@"receive response");
    [receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    NSLog(@"receive data");
    [receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
    NSLog(@"%@", [[NSString alloc]initWithData:receivedData encoding:NSUTF8StringEncoding]);
}

サブプロセスからだと、ログは以下のものしかでません
2011-11-29 01:13:04.444 Sample01[98789:13003] start loading

もちろんサブプロセスではなく、メインスレッドであれば正しく動作します。
2011-11-29 01:23:50.675 Sample01[98997:f803] start loading
2011-11-29 01:23:51.182 Sample01[98997:f803] receive response
2011-11-29 01:23:51.183 Sample01[98997:f803] receive data
2011-11-29 01:23:51.183 Sample01[98997:f803] Succeeded! Received 1446 bytes of data

そもそもサブプロセスなんだから非同期の通信じゃなくてもよくて、
NSURL *theURL = [NSURL URLWithString:@"http://localhost:5000/"];
    NSURLRequest *req=[NSURLRequest requestWithURL:theURL];
 NSMutableData*      data;
    NSHTTPURLResponse*  resp;
    NSError*            err = nil; 
    data = [NSMutableData dataWithData:[NSURLConnection sendSynchronousRequest:req returningResponse:&resp error:&err]];

    NSLog(@"Succeeded! Received %d bytes of data",[data length]);
    NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);

これで正しく取得できました。

UITableViewCellの背景色の指定

UITableViewCellの背景色は
tableView: cellForRowAtIndexPath:
ではなく、
tableView:willDisplayCell:forRowAtIndexPath:
じゃないと効かない。

ただし、UITableViewCellのcontentViewにaddSubviewした場合は、
上記の方法でもselectionStyleは正しく背景色が指定できない。
※今は解決されているかも(Xcode4.2)

上記の問題があったので、
UITableViewCellのサブクラスを作成して、
-(void)layoutSubviews {
    self.backgroundColor = [UIColor redColor];
}
とすれば全体に背景色を指定できる。

iPhone特定の条件でデバックを行う

Xcode4.2において、ブレークポイントを設定して、特定の条件のみ処理を止めたいときの設定

サンプルコード

いつも通りブレークポイントを設定します。
その後右クリックで「Edit Breakpoint」を選択します。
 Conditionに「i==50」と設定すれば、iの値が50の時だけBreakpointを有効にできます

設定項目
  • Condition
    • 数式を指定
  • Ignore
    • 指定した回数はスルーする (2を指定すると3回目に止まる)
  • Action
    • 以下の詳細な動作を登録できる。デフォルトは何もしないで止まるだけ
      • ActionScript
      • Capture OpenGL Frame
      • Debugger Command
      • Log message 
        • %B メソッド名、%H カウントなど指定可能
      • Shell Command
      • Sound
  • Option
    • 一時停止しないで次に進む

SSHで公開鍵方式でパスワードなしでログインする

クライアントPCで秘密鍵、公開鍵を作成します

$ ssh-keygen -t rsa
※パスワードを2回入れます
そして~/.ssh/id_rsa と ~/.ssh/id_rsa.pub が作成されます

それをサーバ側にscpしてサーバ側の.ssh/authorized_keysに追加します。
scp ~/.ssh/id_rsa.pub [アカウント]@[ホスト名]
ssh [アカウント]@[ホスト名] cat id_rsa.pub >> .ssh/authorized_keys

ポートスキャンをコマンドで行う

macのutilitiesにポートスキャンを行うコマンドがあるみたい。

/Applications/Utilities/Network\ Utility.app/Contents/Resources/stroke

使い方はそのまんまですね。


$  /Applications/Utilities/Network\ Utility.app/Contents/Resources/stroke -h
stroke address startPort endPort

アドレス、開始Port番号、終了Port番号って所でしょうか。

iPhone KVCで値が変更したら通知を受ける

iPhone開発において、ある値が変更されたら通知を受ける仕組みがある。
例えばネットワークに接続中かどうかのフラグがあり、それが変更するたびに、インジケータをまわす、止めるを制御したいなどなど

  • NetWorkManagerクラス
NetWorkManager.h
@property (nonatomic, readonly, getter=isNetworkAccessing) BOOL networkAccessing;

NetWorkManager.m

- (BOOL)isNetworkAccessing {
return [_requests count] = 0;
}

- (void) requestXXX {
NSRequest* reqeust;
// 省略
[self willChangeValueForKey:@"netWorkAccesing"];
[_requests addObject:request];
[self didChangeValueForKey:@"netWorkAccesing"];
}

  • ObserverReciveSampleクラス
ObserverReciveSample.m
- (id)init{
// 省略

// キー値監視の登録
_netWorkManager = [[[NetWorkManager* alloc] init];
[netWorkManager addObserver:self forKeyPath:@"networkAccessing" options:0 context:NULL];
}

- (void)observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void*)context {
// networkAccessingキーの場合
if ([keyPath isEqualToString:@"networkAccessing"]) {
// ネットワークアクティビティを更新する
[UIApplication sharedApplication].networkActivityIndicatorVisible = _netWorkManager.networkAccessing;
}
}

今回は明示的にwillChangeValueForKeyやdidChangeValueForKeyをしていますが、それを指定しない場合、以下のように監視する方法もあるみたいです。
※上記の場合だと、パラメータが存在しなくても動作します。



+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key {
if ([key isEqualToString:@"networkAccessing"]) {
return YES;
}
return [super automaticallyNotifiesObserversForKey:key];
}





サーバが重たいと感じたら

WEB+DBPressの内容を自分なりに理解するためのメモ


1.ロードアベレージを確認
$ uptime
13:13 up 3 days, 2:18, 2 users, load averages: 3.35 3.18 2.27

(ロードアベレージが低い)
netstat -i

続きは今度

~/.ssh/configを設定してみる

~/.ssh/configにいろいろ設定すると、ssh hostnameが楽になる。

今の環境はssh dev_host_01の名前解決ができない。

$vim ~/.ssh/config
Host dev_host_01
HostName XXX.XXX.XXX.XXX

これで、IPを入力しなくてもなんとかなると。

そして他にもUserなど指定したりもできるみたい。
Host dev_host_01
HostName XXX.XXX.XXX.XXX
User user_name

Perlの正規表現で記号を削除

別に正規表現でなくても良いのだが、文字列から記号を削除したい場合に、どのようなアプローチがあるのか、検討してみた。

便利そうなUnicodeのブロックを使ってみる
¥p{Latin}で数字となるが、
ローマ数字なども含んでいるので使えない

sub nomalize {
my $str = shift;
$str =~ s/[^0-90-9a-zA-Za-zA-Z\p{Han}\p{Katakana}\p{Hiragana}]//g;
return $str;
}

[File::Basename]を調べる

use strict;
use warnings;

use File::Basename;

use Test::More;

my $path = 't/file/dir/sample.t';
subtest 'fileparse' => sub {
my ($filename, $directory, $suffix) = fileparse($path);
is $filename => 'sample.t', 'filename';
is $directory => 't/file/dir/', 'directory';
is $suffix => undef, 'suffix';
};

subtest 'fileparse suffixes' => sub {
my ($filename, $directory, $suffix) = fileparse($path, qw/.t/);
is $filename => 'sample', 'filename';
is $directory => 't/file/dir/', 'directory';
is $suffix => '.t', 'suffix';
};

subtest 'basename' => sub {
my $filename = basename($path);
is $filename => 'sample.t', 'filename';
};

subtest 'basename suffix' => sub {
my $filename = basename($path, qw/.t/);
is $filename => 'sample', 'filename';
};

subtest 'fileparse suffiexs2' => sub {
my $prefix_name = join '', (fileparse($path, qw/.t/))[1,0];
is $prefix_name => 't/file/dir/sample';
};

done_testing;

patchコマンド

svnやgitを使ってると、特に意識することはないけど、
仕組みというか概念というか、とりあえず使ってみた。



diff -u 1.pl 2.pl
--- 1.pl 2011-06-29 23:49:54.000000000 +0900
+++ 2.pl 2011-06-29 23:50:10.000000000 +0900
@@ -1,3 +1,3 @@
1
-2
+22
3
diff -c 1.txt 2.txt
*** 1.pl 2011-06-29 23:49:54.000000000 +0900
--- 2.pl 2011-06-29 23:50:10.000000000 +0900
***************
*** 1,3 ****
1
! 2
3
--- 1,3 ----
1
! 22
3
-uを付けるとunified 出力形式を用いる。
-cを付けるとcontext 出力形式を用いる。

まぁどちらでもよいけど、-uを選択。

それをsample.patchとして保存。

基本的な使い方
patch <sample.patch

オプション
-b : バックアップ -B だとプレフィックスを指定できる
-R : パッチは新旧のファイルが反転しているとみなす。
--dry-run : パ ッチを当てたときの結果を表示
-f : 問い合わせ無しの実行
-i [pach file] : パッチをファイルから読み込む - を指定すると標準入力(デフォルト)
-p[num] : 適用するパスのプレフィックスを[num]個削除する
--verbose : 詳細情報表示

ファイルの圧縮/解凍

今更な感じだけど、覚えていないので、メモ程度に記述

tar zcvf 圧縮後のファイル名 対象ファイル...
tar zxvf 圧縮ファイル

詳細も調べたいけど今ではない。

異なるサーバ間のファイルをマージする

開発環境が複数あると、マージなんかが大変になるわけで、比較的簡単にやりたい。
出来ればGUIでやりたいのだが、WindowsのWinMergeみたいな便利なものがなく、
ひとまず p4Mergeでチャレンジ

1.まずマウントしてローカルファイルのアクセスをできるように
mount -w -t smbfs //user:pass@dev1/path /mnt/dev1/path/
mount -w -t smbfs //user:pass@dev2/path /mnt/dev2/path/

2.p4mergeを呼び出す
p4merge ベースファイル 左側のファイル 右側のファイル マージ結果ファイル
p4merge /mnt/dev1/hrk_ys/lib/Foo.pm /mnt/dev1/hrk_ys/lib/Foo.pm /mnt/dev2/hrk_ys/lib/Foo.pm /mnt/dev2/hrk_ys/lib/Foo.pm

ベースファイルはsvn HEADとかから取得するといんだろうなー。

※Automatorを使うと便利 テキスト入力から取得してコマンドを作るみたいな
※dev_host1 dev_host2 lib/Foo.pm => p4merge ...

ひとまずこれでGUIでなんとか出来る。

Perlのeachには気をつけろ

perlのeachではまったので、メモを。

$ perl -v
This is perl, v5.8.5 built for i386-linux-thread-multi

サンプルソース
use strict;
use Data::Dumper;

use Test::More;

my $hash = +{ a => 1 };
#note explain $hash;
Data::Dumper->new( [$hash] )->Sortkeys(1)->Dump;
ok each %{ $hash };


結果
not ok 1

ちなみに、Sortkeys(0)をすると、okとなります。
同様にnote explain $hashでもnot okになります。
explain は内部的にData::Dumperを呼んでいるため。

そして、何が原因か探ろうとおもったのですが、
中身がData::Dumper::Dumpex(実物はxs)なので断念。

たぶん、eachでつかうitaratorがリセットされてないだけだと思いますが。。

こんな感じです。

use strict;

use Test::More;

my $hash = +{ a => 1 };
#note explain $hash;
#Data::Dumper->new( [$hash] )->Sortkeys(1)->Dump;
while (my $k = each %{ $hash } ) {
last
}
ok each %{ $hash };


ついついexplainしたくなりますが、気をつけます。

Perlをもっと詳しく知りたいけど日本語じゃないとだめって人へ

タイトル => 自分のことでして。。

素敵なサイトを発見したので、メモ的な感じでココに残しておく

http://perldoc.jp/

みなさん本当に感謝しています。

SVNコマンドリファレンス

特定のリビジョンの差分を確認
{{{
# svn diff -c 144180 --summarize .
M lib/Foo.pm

以下と同じ
# svn diff -r 144180:144181 --summarize .
}}}

Mac isoファイルをCDに書きこむ

[アプリケーション] => [ユーティリティ] => [ディスクユーティリティ.app]を開く

左上にある「ディスクを作成」をクリックして書き込みたいファイルを選ぶ。
らくちん♪

Cometの調査

OSのイベントライブラリー
- libevent
- epoll
- kqueue
- select
- poll

Cometサーバー
- ErlyComet Erlang

レスポンスヘッダ
- Transfer-Encoding:chunked
- Connection: close
facebook ? Connection: keep-alive

Cometを使っているサービス
- Meebo(http://www.meedo.com)

Cometサーバ比較
- Comet Maturity Guide (http://cometdaily.com/maturity.html)

Perlで実装しているサーバ
- perl comet server Meteor

Facebook
- Erlang スクリプト言語
- Yaws httpサーバ

Google Talk
- XMPP

vimのエンコーディング(encoding, fileencoding, termencoding)

Vim+Screenの設定でいろいろ苦労したので、ちょっと書いておく

vimrc
set fileencodings=utf8,euc-jp,iso-2022-jp,sjis

そして、いままでは、
:set encoding
とかやってたけど、
set enc
set fenc
set tenc
とかできるみたい。

またファイルを開くときに文字コードを指定する方法
vim "+e ++enc=euc-jp file_to_path"

詳しくは後日調べる。

perlでHTTPアクセス

perlからhttpアクセスで外の世界に行くよ

use LWP::UserAgent;

my $response = LWP::UserAgent->new->get('http://hoge.com/foo/var');

MacVimをコマンドから起動

MacVimをコマンドから起動する方法
mvim

なぜそんなことをするかというと、PATHがうまく設定されないから…。

以上。

javascriptの備忘録

文字列が含まれているかのチェック

var url = "http://foo.com/path/to/index.html";
if (url.search(/?/) < 0) {
url += "?var=1";
} else {
url += "&var=1;
}



Mobile Safari用(HTML5)

var elements =
document.querySelector(
"form.search > input [type='text']");

Reederのショートカット

マウスはつかったらダメっておばあちゃんがいってたので、ショートカットを調べました。

表示の操作

  • Command + 1: ★
  • Command + 2: 未読
  • Command + 3: すべて

アイテム/フォルダの移動

  • K: 前のフィード
  • J: 後のフィード
  • Shift+K: ブラウザのまま前のフィード
  • Shift+J: ブラウザのまま次のフィード
  • Shift+P: 前のフォルダへ移動
  • Shift+N: 次のフォルダへ移動

perl例外のあれこれ(warn, die, carp, croak)

perlにおいて例外を発生するやり方は、普通、warnとかdieとかですが、コール元の情報が表示されないため、例外が発生して事が分かっても、どのように呼ばれて例外が発生したのか分かりづらい事が多々あります。(たぶん)

そんなこんなで、より解析しやすいcarp/croakをちょっと調べてみした。

test_warn();
sub test_warn {
warn 'warn_message';
}
# warn_message at exception.pl line 13.

test_die();
sub test_die {
die 'die_message';
}
# die_message at exception.pl line 18.

use Carp;
test_carp();
sub test_carp {
carp 'carp_message';
}
#carp_message at exception.pl line 23
# main::test_carp() called at exception.pl line 21

use Carp;
test_croak();
sub test_croak {
croak 'croak_message';
}
# croak_message at exception.pl line 28
# main::test_croak() called at exception.pl line 26


といったように、呼び出し元の情報まで表示してくれます。

port fowardの設定

地震の影響で、自宅作業社が多くなり、エンジニアはssh + port fowardで繋げられうようになりました。

もちろん自分はなんのことかわからないので、調べまくりの実験しまくりの手探りでなんとか解決しました。

踏み台サーバ      : ssh_host01
社内プロキシサーバ: proxy_host01:8080
メールサーバ : mail_pop_01:110
送信サーバ : mail_smtp_01:25
IRC : irc_host_01:6778


開いてるポートを使うため60000移行を使うことに。

webサーバ    localhost:8080  => proxy_host01:8080 に接続
メールサーバ localhost:60110 => mail_pop_01:110 に接続
送信サーバ localhost:60025 => mail_smtp_01:25 に接続
IRC localhost:60001 => irc_host_01:6778 に接続


上記のような転送をやってもらうための設定
ssh ssh_host01 ¥
-L 8080:proxy_host01:8080 ¥
-L 60110:mail_pop_01:110 ¥
-L 60025:mail_smtp_01:25 ¥
-L 60001:irc_host_01:6778


こちらを起動して、それぞれの接続先を変更すれば完成

ちなみにportの最大値は65535なので、ircのportは60001を使ってます
あと、ホスト名がわからない場合は、IPアドレスで設定しないとつながらないよ。

Mac Excelショートカットの設定/確認

Mac用のExcelでは何かとショートカットが違います。
「ツール」=>「ショートカットのユーザ設定...」で確認の変更ができる。

よく使うもの





'control' + 'u'セルの編集
'option' + '→'
'option' + '-'
シート切り替え
'control' + 'shift' + '+'
'control' + 'shift' + '-'
ズームイン/ズームアウト(個人設定)
'option' + 'command' + 'enter'セル内の改行

AnyEventを使ってみる

AnyEventをつかってみる
本当に初歩的なところなので、今後いい感じに追加していきます。

use strict;
use warnings;

use AnyEvent::Impl::Perl;
use AnyEvent;

print "start\n";
my $cv = AnyEvent->condvar;
my $io; $io = AnyEvent->io(
fh => \*STDIN, # 標準入力
poll => 'r', # 読み取り専用?
cb => sub {
print "cb start\n";
chomp(my $input = );
undef $io;
$cv->send($input); # send(....)を実行すると、recvの戻り値が入る
},
);

print "recv wait\n";
if (defined(my $input = $cv->recv)) { # sendの引数が戻り値として受け取れる
print "got: [$input]\n";
}
print "end\n";


ひとまず実行
perl sample.pl
start
recv wait
・・・ここで待たされる。
hogehoge[Enter] <= 入力する
cb start
got: [hogehoge]
end


ポイントはrecvを呼び出すと、sendの引数を取得するために、待ちます。




次はAnyEvent->timer

use strict;
use warnings;

use AnyEvent::Impl::Perl;
use AnyEvent;

print "start\n";
my $cv = AnyEvent->condvar;
my $timer; $timer = AnyEvent->timer(
after => 3, # 3秒後に
interval => 1, # 1秒間隔
cb => sub {
print "cb start\n";
$cv->send;
},
);

print "wait\n";
$cv->recv; # 待機

print "end\n";


実行

perl any_event_timer.pl
start
wait
(3秒後)
end


after: 指定した時間後に実行
interval: 1秒間隔
ただし繰り返し処理させる場合、別のAnyEvent->condvar;でsleepする必要あり?

jQuery Timersの使い方

jQuery Timersを使用して1秒置きに処理を実行したい場合などなど

繰り返し処理
$( 対象オブジェクト ).everyTime( ミリ秒数 , '関数名'(省略可) , 関数命令 );


繰り返し停止処理
$( 対象オブジェクト ).stopTime( '関数名' , 関数命令(省略可) );


一回のみ時限処理
$( 対象オブジェクト ).oneTime( ミリ秒数 , '関数名'(省略可) , 関数命令 );

perlスライス

perlのスライスってわかりづらいよね。

use strict;
use warnings;

use Test::More;

my %hash = ( key1 => 'val1', key2 => 'val2' );

# スライス
my ( $a, $b ) = @hash{qw/key1 key2/};
is $a, 'val1', 'val1';
is $b, 'val2', 'val2';

# keysを使っても取れるが、順番はランダム
my ( $a1, $b1 ) = @hash{ keys %hash };
is_deeply + { $a1 => 1, $b1 => 1 }, +{ 'val1' => 1, 'val2' => 1 }, "keys";

# ハッシュリファレンスでも使えます
my $hash = +{ key1 => 'val1', key2 => 'val2' };
my ( $a2, $b2 ) = @$hash{qw/key1 key2/};
is $a2, 'val1', 'hash ref val1';
is $b2, 'val2', 'hash ref val2';

# マージにも使えますね
my $hash1 = +{ key1 => 'val1', key2 => 'val2' };
my $hash2 = +{ key3 => 'val3', key4 => 'val4' };
my $ret = +{
key1 => 'val1',
key2 => 'val2',
key3 => 'val3',
key4 => 'val4',
};

@$hash2{ keys %$hash1 } = @$hash1{ keys %$hash1 };
is_deeply $hash2, $ret, 'merge';

# 単純なマージならこれでもできます
my $hash3 = +{ %$hash2, %$hash1 };
is_deeply $hash3, $ret, 'merge2';

done_testing;

vimのシンタックスハイライト

vimを使ってテンプレートエンジンを編集するときに、
色が出ないよーってことでいろいろ設定してみました。

ここからファイル(tt2.tar.gz)をダウンロード
http://www.vim.org/scripts/script.php?script_id=830

~/.vim/syntax/を作る(なければ)

ダウンロードしたファイル(tt2.vim,tt2html.vim)をコピーする

シンタックスハイライトを設定する
au BufNewFile,BufRead *.mt setf tt2html

mysqldumpでバックアップ

mysqldumpを使ってmysqlのバックアップをとる

ただピンポイントでやりたい場合、既にあるSQLにちょっと追加したい場合など、
lvやlessでコピペしたい

mysqldump -uroot data-base-name

いろいろなperlを持っているPCの実行

scriptの先頭に#!/usr/bin/perl ってかかれてるのに(shebang 行というらしい)、
実際にはperlbrewでいれたperl~/perl5/...にあるやつを使いたい。

#!/usr/bin/env perl


これで大丈夫。

perlで同じようなメソッドを楽に定義する

同じような処理をする似たようなメソッドはfor文使って楽しちゃいましょう。

例えば、
sub debug {
my ($self, @args) = @_;
$self->log->debug(@args);
}
sub info {
my ($self, @args) = @_;
$self->log->info(@args);
}
sub warn {
my ($self, @args) = @_;
$self->log->warn(@args);
}


こんなやつはこんな感じでやっつけちゃいましょ。

for my $name (qw/debug info warn/) {
no strict 'refs';
*{$name} = sub {
my ($self, @args) = @_;
$self->log->$name(@atgs);
}
}

DBIモジュール

DBIモジュールに付いて調べる


1レコードづつ取得する


selectrow_array => 配列


my @ret = $dbh->selectrow_array(
'select user_id, reg_date, nickname from user_data');
is_deeply \@ret, [ 10001, 1297573789, 'はるく' ];


selectrow_arrayref => 配列リファレンス

my $ret = $dbh->selectrow_arrayref(
'select user_id, reg_date, nickname from user_data');
is_deeply $ret, [ 10001, 1297573789, 'はるく' ];


selectrow_arrayref => ハッシュリファレンス

my $ret = $dbh->selectrow_arrayref(
'select user_id, reg_date, nickname from user_data');
is_deeply $ret, +{ user_id => 10001, reg_date => 1297573789, nickname => 'はるく' };


複数レコード取得

selectall_arrayref => 配列リファレンス

my $ret = $dbh->selectall_arrayref('select user_id, reg_date, nickname from user_data');
is_deeply $ret, [[10001, 1234567, 'はるく'], [10002, 1234567, 'ひかり']];



selectall_arrayref (Slice[]) => 配列リファレンス

my $ret = $dbh->selectall_arrayref('select user_id, reg_date, nickname from user_data', +{ Slice => []});
is_deeply $ret, [[10001, 1234567, 'はるく'], [10002, 1234567, 'ひかり']];


selectall_arrayref (Slice+{}) => ハッシュリファレンス

my $ret = $dbh->selectall_arrayref('select user_id, reg_date, nickname from user_data', +{ Slice => +{}});
is_deeply $ret, [ +{ user_id => 10001, reg_date => 1234567, nickname => 'はるく'}, ... ];


selectall_arrayref (Columns) => ハッシュリファレンス

my $ret = $dbh->selectall_arrayref('select user_id, reg_date, nickname from user_data', +{ Columns +{}});
is_deeply $ret, [ +{ user_id => 10001, reg_date => 1234567, nickname => 'はるく'}, ... ];


selectall_hashref => ハッシュリファレンス

my $ret = $dbh->selectall_hashref($sql, 1); # user_idでも一緒
is_deeply $ret => +{
10001 => +{ user_id => 10001, reg_date => 12345, nickname="はるく"},
10002 => +{ user_id => 10002, reg_date => 12346, nickname="ひかり"},
}



my $ret = $dbh->selectall_hashref($sql, [1, 2]); # qw/user_id reg_date/でも一緒
is_deeply $ret => +{
10001 => +{ 12345 => +{ user_id => 10001, reg_date => 12345, nickname="はるく"} },
10002 => +{ 12346 => +{ user_id => 10002, reg_date => 12346, nickname="ひかり"} },
}

vimをより良くするよ

インストールしているもの。

コマンド
Ctrl-w + カーソルのある画面を一行分大きくする
Ctrl-w + カーソルのある画面を一行分小さくする
Ctrl-w > カーソルのある画面を右にー列大きくする
Ctrl-w < カーソルのある画像を左に一列大きくする
Ctrl-w = 画面のサイズを同じにする

プラグイン

補完機能
acp.vim




オートクローズ
autoclose.vim

自動で'"(などを入力shしたときに閉じてくれる



ツリー型ファイルエクスプローラ
opsplorer.vim




タグ
taglist.vim

タグリストを表示

Google Map APIメモ

表示したマップの緯度経度を取得


var myOptions = {
zoom: 14,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

var latlngBounds = map.getBounds();
// 中央
latlngBounds.getCenter();
// 北東端
latlngBounds.getNorthEast();
// 南西端
latlngBounds.getSouthWest();

geohashの調査

位置情報のgeohashについての調査

ある地点(DeNA本社)の位置を基準に周囲の情報を取る場合、
geohashをつかってやろうとすると、

139.689949864418, 35.6832269343074 => xn76fxzjgg85feqxv9h8t


ここまではよいが、geohash特有の先頭x文字だけ使って範囲を絞っていくと、
よく考えればそうだけど、左下範囲が選択されることになる。

xn76fxzjgg 地図上に現れる
http://aligach.net/geohash/geohash_visualizer2.html#xn76fxzjgg,19,500,400

xn76fxz 右側に拡大
http://aligach.net/geohash/geohash_visualizer2.html#xn76fxz,18,500,400

xn76fx 大きく左側に拡大
http://aligach.net/geohash/geohash_visualizer2.html#xn76fx,15,500,400

xn76fx 大きく左側に拡大
http://aligach.net/geohash/geohash_visualizer2.html#xn76fx,15,500,400

これぐらいでいいか

jQuery Mobileをつかう

リンクでページ遷移をする場合、基本ajaxで行ってるみたい。

直接遷移して欲しい時はaタグの場合
rel="external"

を付ける

formタグの場合は
data-ajax="false"

をつける


<a href="/hoge" rel="external">りんく</a>
....
<form action="/hoge" action="post" data-ajax="false">
<input type="submit" value="GO">
</form>


すべてを無効にする場合

1.config.jsを作成

$(document).bind("mobileinit", function(){
$.mobile.ajaxLinksEnabled = false; // Ajax を使用したページ遷移を無効にする
$.mobile.ajaxFormsEnabled = false; // Ajax を使用したフォーム遷移を無効にする
});


2.jqueryの読み込みを見込ませる。
読み込ませる順番も大事 jquery.js => config.js => jquery.mobile.js
<script type="text/javascript" src="/static/js/jquery.1.5.0.min.js"></script>
<script type="text/javascript" src="/static/js/config.js"></script>
<script type="text/javascript" src="/static/js/jquery.mobile-1.0a3.min.js"></script>

google blogの投稿フォーマット

コード引用


<pre style="background: none repeat scroll 0pt 0pt rgb(247, 247, 247); border: 1px solid rgb(215, 215, 215); margin: 1em 1.75em; overflow: auto; padding: 0.25em;">
ココにコードを書く
</pre>


use strict;
use warnings;

sub hoge {
my $args = shift;
}

1;


エスケープ
「&」----&amp;
「>」----&gt;
「<」----&lt;
「"」----&quot:

gitの設定

~/.gitconfigの設定。
このままコピペで大丈夫。

[user]
name = ******
email = ******
[color]
ui = auto
[alias]
co = checkout
st = status
di = diff
br = branch
ci = "commit -a"
[core]
pager = lv -c

iPhoneをMacに接続したときにiPhotoを起動させない

自宅に充電器がないので、充電だけしたいのに、いつもよけいなiPhotoが起動してしまう。

そこで、えいっと消したいんだがiPhotoの設定には見つからず。
じつは「イメージキャプチャ」というものが絡んでいました。

iPhoneを接続した状態で、
「アップリケーション」=>「イメージキャプチャ.app」
を起動すると、左下に「このiPhoneを接続時に開くアプ...」となっているところを「割り当てなし」に選択すると、接続しただけでは表示されません。

べつに変な写真が入ってるわけじゃないからね。

perltidyをインストールしてみた

インストールはいたって簡単

$ cpanm install Perl::Tidy


そうすると、perltidyがインストールされる。

$ which perltidy
/usr/local/bin/perltidy


あとはそれを使い綺麗にしてもらう。

perltidy old_sample.pl -o old_sample.pl


エディターなんかに登録すると、らくちん
~/.vimrcに

map ,ptv :'<,'>! perltidy
map ,pt :%! perltidy

を追加して、
,ptvを入力すると選択している箇所が、
,ptを入力すると、ファイル全体を綺麗にしてくれます。

ついでに~/.perltidyrcも公開

-l=78 # Max line width is 78 cols
-i=4 # Indent level is 4 cols
-ci=4 # Continuation indent is 4 cols
#-b # backup
#-st # Output to STDOUT
-se # Errors to STDERR
-vt=0 # vertical tightness
-cti=0 # Closing Token Placement
-pt=1 # Medium parenthesis tightness
-bt=1 # Medium brace tightness
-sbt=1 # Medium square brace tightness
-bbt=1 # Medium block brace tightness
-nsfs # No space before semicolons
-nolq # Don't outdent long quoted strings
-bbvt=1
-bar
-ce
-nsbl
#-sot
#-lp
# Break before all operators
# -nibc コメントが先頭にくる
# -olc
# -isbc
-wbb="% + - * / x != == >= <= =~ !~ < > | & >= < = **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x="

.bashrcを大公開

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

export PS1="[\u@\h \w]\\$ "
PROMPT_COMMAND='echo -ne "\033]0;$(whoami)@$(hostname):$(pwd)\007"'

# svn
export SVN_EDITOR="vim"
alias svn_diff="svn diff --diff-cmd svn-diff"

# git
source ~/.git-completion.bash

# command
alias exec_vim="/Applications/MacVim.app/Contents/MacOS/MacVim &"

.screenrcを大公開

escape ^Z^Z

bind a title
bind ^u encoding utf8
bind ^j encoding sjis
bind ^e encoding euc-jp

# バッファーサイズ
defscrollback 100000
# vim,lessを閉じたときに画面を元に戻す(on) 戻さない(off)
altscreen off

autodetach on

caption always "%{=r dd} %-w%{=d dd}%n %t%{-}%+w %= %{=r dd}"

screen -t "localhost"

shell bash

term xterm-256color
termcapinfo xterm 'is=^[r^[m^[2J^[H^[?7h^[?1;4;6l'

Mac OSXにhomebrewでmysqlをインストール

どうもrootのパスワードが設定できなくて、2回ぐらいuninstallしましたが、
テーブル定義?(/usr/local/var/mysql/)がのこっていたので、うまくいかず、
まっさらな状態にするとインストールできました

$ brew uninstall mysql
$ rm -r /usr/local/var/mysql

インストール
$ brew install mysql


==> Downloading http://mysql.mirrors.pair.com/Downloads/MySQL-5.1/mysql-5.1.54.tar.gz
[省略]
==> Caveats
Set up databases with:
unset TMPDIR
mysql_install_db

If this is your first install, automatically load on login with:
cp /usr/local/Cellar/mysql/5.1.54/com.mysql.mysqld.plist ~/Library/LaunchAgents
launchctl load -w ~/Library/LaunchAgents/com.mysql.mysqld.plist

If this is an upgrade and you already have the com.mysql.mysqld.plist loaded:
launchctl unload -w ~/Library/LaunchAgents/com.mysql.mysqld.plist
cp /usr/local/Cellar/mysql/5.1.54/com.mysql.mysqld.plist ~/Library/LaunchAgents
launchctl load -w ~/Library/LaunchAgents/com.mysql.mysqld.plist

Note on upgrading:
We overwrite any existing com.mysql.mysqld.plist in ~/Library/LaunchAgents
if we are upgrading because previous versions of this brew created the
plist with a version specific program argument.

Or start manually with:
mysql.server start
==> Summary
/usr/local/Cellar/mysql/5.1.54: 220 files, 45M, built in 8.2 minutes


ひとまずインストール完了

上記のコマンドをそのままやっても良いが、
自動的に起動してほしくないので、
セットアップのみ実行

$ mysql_install_db
$ mysql.server start
$ /usr/local/Cellar/mysql/5.1.54/bin/mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!


In order to log into MySQL to secure it, we'll need the current
password for the root user. If you've just installed MySQL, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.

[ルートのパスワード設定しますか?]
Set root password? [Y/n] Y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
... Success!


By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.

[ルート以外のユーザは削除する?]
Remove anonymous users? [Y/n] n
... skipping.

Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess at the root password from the network.

[リモートからルートのログインする?]
Disallow root login remotely? [Y/n] Y
... Success!

By default, MySQL comes with a database named 'test' that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.

[テスト用のデータベースは削除する?]
Remove test database and access to it? [Y/n] n
... skipping.

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

[今すぐ設定を反映させる?]
Reload privilege tables now? [Y/n] Y
... Success!

Cleaning up...



All done! If you've completed all of the above steps, your MySQL
installation should now be secure.

Thanks for using MySQL!

Mac OSX 起動時に実行するアプリケーションの設定方法

Windowsで言うとこのスタートアップ

システム環境設定

アカウント

ログイン項目

"+"を押して追加

memcached の中身を見る

memcachedに接続する方法

$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.

statでいろいろな情報を表示(よくわからない・・・。)

$ stat
STAT pid 7692
STAT uptime 19177
STAT time 1297328806
STAT version 1.2.6
STAT pointer_size 32
STAT rusage_user 0.017997
STAT rusage_system 0.058991
STAT curr_items 83
STAT total_items 163
STAT bytes 21606
STAT curr_connections 5
STAT total_connections 500
STAT connection_structures 9
STAT cmd_get 406
STAT cmd_set 163
STAT get_hits 234
STAT get_misses 172
STAT evictions 0
STAT bytes_read 46646
STAT bytes_written 23103
STAT limit_maxbytes 67108864
STAT threads 4
END

コマンド形式は
[]\r\n

取得は
# get hoge
VALUE hoge 0 3
var

設定は
# set hoge 0 5 3
# var
STORED

ちなみに、こっちでも表示することが可能

$ memcached-tool localhost dump

FireMobileSimulatorを楽に使う方法

vimperator
https://github.com/zentooo/rc/blob/master/.vimperator/plugin/fms_switcher.js


FireGestures
* fire mobile simulator OFF
firemobilesimulator.core.resetDevice();
* ある端末を設定(リストの順番)
firemobilesimulator.core.setDevice(1);

DataStoreの辛いところ

# DataStoreの限界 FacebookやインスタグラムのようなSNSで、投稿、公開範囲、お気に入りなどの機能をDataStoreで実現しようとするとどうしても辛くなる。 ## DataStoreで実現可能? - users - id - feeds - i...