mbedのプログラムを自動でmbedのUSBドライブにコピーする
mbedで遊んでいます。
jsdo.itやwonderfl.netではブラウザ上でJavaScript,ActionScript3を書いて
webサイトやFlashコンテンツを書き出すことのできる開発環境なのに対して、
mbed.orgはブラウザ上でC++を書いてmbedボード用のプログラムバイナリを書き出せる開発環境です。
さらにmbedボードはusbでつなぐとusbドライブに見えるので、mbed.orgからダウンロードしたバイナリをusbドライブにコピーして、ハードウェアリセットボタンを押すとマイコンにプログラムをロードできます。
画期的!
しかもprintfするとusbを通して /dev/tty.usbmodem* に流れてくるのでprintfデバッグが超簡単!
ところが、
ブラウザ上のエディタからコンパイル、バイナリのダウンロードは Ctrl+d ってキーボードショートカットがあるものの、
usbドライブにコピペしつつ古いバイナリは消す、という作業がめんどくさすぎたので
* Downloadsディレクトリを監視
* Remote_LPC1768.binのようなファイルが追加されたら
* /Volumes/MBEDにコピーしつつ
* 古いバイナリを削除
* growlに通知
ということをしてくれるスクリプトを書きました。
手作業でリセットボタンを押すのはとりあえず今はしょうがないかなあ
Happy MBED hacking!
iOS5の絵文字とガラケースマホ両対応サービスでどうmysqlに保存するか
iOS5から絵文字キーボードで入力した絵文字がUnicode6になったということで、
絵文字キーボードで絵文字を入力するとどんなコードになるのか、ダンプしてみました。
この記事の最後にのっけておきます。
さて
* MySQL5.5以上じゃないと4バイトのutf8は保存できない
* iPhoneで入力した絵文字をガラケーで表示したい
という時に、どうするのがよいのでしょう?
MySQL5.5でないMySQLに何を保存するか、というところで考えるとよいのだろうか
案1)
DBには Encode::JP::Emoji の x-utf8-e4u-mixed を保存する場合
全部の入力 -> decode(’x-utf8-e4u-mixed’, $input) -> mysql(mysql_enable_utf8=>1)
出力時に encode(’x-utf8-e4u-’. docomo/kddiweb/softbank3g)
案2)
DBには HTTP::MobileAgent::Plugin::Charset を使い、 $mobile_agent->encoding->decode したものを保存
ただし入力にUnicode6絵文字が含まれる場合には
$input =~ s!(\p{InEmojiUnicode})!_unicode6_emoji_to_softbank3g($1)!eg;
_unicode6_emoji_to_softbank3g の中身は:
decode(’x-utf8-e4u-unicode’) -> encode(’x-utf8-e4u-softbank3g’) -> decode(’utf8′) -> mysql(mysql_enable_utf8=>1)
出力時には $mobile_agent->encoding->encode して出す
今までDBには案2の感じでデータがたまってるって歴史的な背景があり、
案2でいきたいが。
iOS5の全絵文字を案2の_unicode6_emoji_to_softbank3gにかけてみると、
国旗の絵文字がいくつか変換できない(参照: https://gist.github.com/1300581 )
さてどうしよう。
参考
Encode::JP::Emojiをつかってみて思ったこと
Encode::JP::Emoji の携帯絵文字コード変換マッピングまとめ
how twitter @anywhere works
ということでOAuth2のImplicitGrant方式(または古いドラフトではUserAgent方式)ってのはどうなってるのか実例を見ようと、twitterの@anywhereのJSのソース(http://platform.twitter.com/anywhere.js)を読んでみた。
JSがminifyされてるので JsDecoder で読みやすくしたり
ChromeのDeveloper ToolsでどんなURLにアクセスしてるのか見てさらに掘り進んでいったり。
blog.twitter.comに@anywhereがはいってるのでそこで確認してみた。
@Twitter にマウスオーバーするとオーバーレイが出て「フォローする」ってボタンがある
それを押すとポップアップが開き、oauth2の、Clientを認証するか?って聞くダイアログが出るっぽいURL(https://oauth.twitter.com/2/authorize?oauth_callback_url=…略)だが、まずはTwitterにログインするためのTwitterID(またはメアド)とパスワードが聞かれるフォームが表示される、ただしsubmitボタンが「連携する」になってる
「連携する」を押すと、リダイレクトされ、#以降に何やら入っているURLがちらっと表示された後に、ポップアップが閉じる
何事もなかったかのようだが、もう一度 @Twitter にマウスオーバーすると、「フォローしている」と表示される
ここでおもむろにConsoleで
localStorage.twttr_anywhere
とうつと、なにやらtokenがあるようだ。
localStorage.twttr_anywhere_expiry
というのもあって、2時間の有効期限を表して自分で無効化したりするのかな
@Twitterをフォローするリクエストは、これを使って行なわれたようだ。iframe使ったクロスドメインかな
Chrome Developer ToolsのNetworkタブに履歴が残っていたのでそれを再現すると、こんな感じ。
OAuth2のaccess_tokenのような権力をもつtokenだがAuthorizationヘッダが必要な何かみたい。
ということで、JSのみでaccess_tokenとってきたらlocalStorageにいれておいてあって、
それをフォローしたりするリクエストで使っていることがわかりました。
localStorageは
User agents must raise a SECURITY_ERR exception whenever any of the members of a Storage object originally returned by the localStorage attribute are accessed by scripts whose effective script origin is not the same as the origin of the Document of the Window object on which […]
yokohama.pm #7行ってきた
今日来てた人たちのモジュールやコードを使わせていただいているなー、
っていろんな人の顔を見ながら思った!
発表資料
yokohama.pm slide ナカマップのなにか
最後の方のコードはいろいろおかしいので参考になさらないほうがよいでしょう。
でもSocket.IOはクライアント側すごく短くかけてドメイン超えれるし魅力的だなー
なんとかしたい
なんとかしようと思ったときに、
Authorization Code方式(またはImplicit Grant方式)でaccess_token取得した後に、
そのaccess_tokenをSocket.IOのJavaScriptクライアントに渡せるとよいが、どういう経路で安全に渡すことができるんだろう。
Twitterの@anywhereのドキュメントには、
PLAIN TEXT
CODE:
The higher the anywhere.js file is on the page, the sooner it can process the access token.
ってある。
OAuth2のImplicit Grant方式では
Authorization Serverからリダイレクトされてきた時にaccess_tokenが#フラグメント以降に入ってるんだけど
それを他のJavaScriptコードとかから読み取られる前(最初のscriptタグ)にanywhere.jsがあれば
安全ってことなのかな?
上の方にanywhere.js置いてね、って書いてあるけど
スクリプト設置した人が下の方においたら、htmlの上から設置場所までの間にxssでなんか仕込めたらTwitterのaccess_tokenとられちゃうんだよね?
access_tokenの有効期限が短いってことだけどそれでいいのかな?
で@anywhere使ってTwitter認証してリダイレクトされてきたらTwitterにログイン状態で
@anywhereの貼ってあるページ上で誰かをフォローできる、ってことは
access_tokenなのか同様の力を持つものがブラウザにCookieなりlocalStorageなりで保存されてるってこと?
CSRF対策用のトークンみたいなワンタイムな感じなのかな?
わからないことが多すぎる><
anywhere.js を読んでみよう
Math::Random::MT benchmark
randのばらつき方が均等になる、という理由でMath::Random::MTが使われているようです。(身近で
macにXS版を入れようとすると
In file included from _mt.c:1:
mt.h:17: error: expected specifier-qualifier-list before ‘uint32_t’
mt.h:21: error: expected ‘)’ before ‘seed’
mt.h:22: error: expected ‘)’ before ‘*’ token
_mt.c:17: error: expected declaration specifiers or ‘...’ before ‘uint32_t’
_mt.c: In function ‘mt_init_seed’:
_mt.c:20: error: ‘uint32_t’ undeclared (first use in this function)
_mt.c:20: error: (Each undeclared identifier is reported only once
_mt.c:20: error: for each function it appears in.)
_mt.c:20: [...]
iTunesの重複曲を削除する - perl
家のPCのWindowsを入れなおすついでに家のiTunesとmacbookのiTunesの中身を同期しようと思い、何も考えずにiTunesのホームネットワークに追加して曲をコピペしたら大量に重複曲ができていっこいっこ手で削除するなんてめんどくさくてできない場合の話。
iTunesには「重複する項目を表示」って機能はあるのに重複してる曲を削除する、っていう便利機能は無い。
ただし、同じアーティスト名、同じアルバム名(つまり同じディレクトリ)の同名曲は、
ファイル名の末尾に数字をつけてincrementしていく、ってルールでコピーしてきたファイルを置くようだ。
そこで、perlで重複曲を削除してみる
% perl remove-duplicate.pl /Users/mash/Music/iTunes/iTunes\ Media/Music/
って実行すると重複してるっぽい曲だけ消してくれる
その後、実体が無いけど曲のリストがあるiTunesを開き、上から順に →カーソルキー を押しっぱなしにしたりすると
のようにびっくりマークがつくので、表示項目に「追加日」を追加して、
びっくりマークを目印に、複数選択しながら消していくとまあ許容できるめんどくささになった
Term::Prompt がなんか楽しくて意味もなく "really?" とか聞くちょっとしたスクリプトを書く今日このごろ
PS. iTunes Music Library.xml をいっしょに編集したりすればもっと簡単なのかもしれない
WWW::Mechanize::Firefoxで簡単スクリーンショット
WWW::Mechanize::Firefox-すごいな
mozreplと組み合わせてこんなコードで簡単にスクリーンショットがとれる
perl mechanize-firefox.pl "yahoo.co.jp" yahoo.png
とかってやってとれたスクリーンショットはこんな
write error: filehandle isn't open at /path/to/MozRepl/Client.pm line 186
とかって出たらFirefoxのmozreplが立ち上がってない。
maximum input buffer length exceeded: 1048576 bytes at /path/to/MozRepl/Client.pm line 186
とかって出たらmozreplとperlスクリプトのtelnetのバッファが足りないようなのでgistにあるbufsizeを大きめにとる
PS: 開いてるFirefoxでとったのでMacBookProの解像度を活かしてサイズは(1899 x 1607)になってるのは自慢です
DBICでcreate_relatedをoverrideする
DBICを使っています。
User has_many Histories
っていう関係のテーブルUserとHistoryがあった時に、
Userの行それぞれに対して、最新のHistoryをUserの行の中にキャッシュしておくと便利なときがあります。
そんな時に、$user->add_to_histories ってやった時に $userもupdateしたい、という話です。
PLAIN TEXT
PERL:
CREATE TABLE user (id unsigned not null auto_increment, **中略**, history unsigned not null);
CREATE TABLE history (id unsigned not null auto_increment, user unsigned not null, **中略**, created_date datetime not null);
UserのRowクラスは
PLAIN TEXT
PERL:
package Schema::Row::User;
中略
__PACKAGE__->has_many( histories => 'Schema::Row::History', 'user' );
HistoryのRowクラスは
PLAIN TEXT
PERL:
package Schema::Row::History;
中略
__PACKAGE__->belongs_to( user => 'Schema::Row::User' );
UserのRowクラスに追加されるadd_to_$relを使って
PLAIN TEXT
PERL:
$user->add_to_histories({ action => 'marriage' }); [...]
[perl]32bit/64bitでメモリ使用量違うけど
同じperlのコードを、2台の違うサーバで動かした時に、やたらメモリ量が違うなぁと。
サーバ1: 50MBくらい
サーバ2: 200MBくらい
なんでだろと調べる
サーバ1で
PLAIN TEXT
CODE:
perl -V
Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
Platform:
osname=linux, osvers=2.6.26-1-686, archname=i486-linux-gnu-thread-multi
...
use64bitint=undef, use64bitall=undef, uselongdouble=undef
...
Compiler:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O2 -g',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include'
ccversion='', gccversion='4.3.2', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, [...]
IO::AIOお試し
AnyEvent/Coro期がわたしにもやってきましたよ。
ファイル書き込みを非同期でやりたいのでIO::AIO試してみました。
Coro::AIO使えばcallback形式ではなく綺麗に書けるようだけれどとりあえずIO::AIOの書き方で。
結果は、↓とかってなるから非同期的な感じだなぁっていうのはわかるんですが、
AnyEventの $cv->send , $cv->recv をとっぱらっても同じように動く。
なぜ?
Event loop integrationっていうのはそれが無い状態に対して、何してくれるの?
PLAIN TEXT
CODE:
perl try/anyevent_aio.pl
[pre] at try/anyevent_aio.pl line 5.
[aft] at try/anyevent_aio.pl line 13.
[opened]0
[opened]1
[opened]2
[opened]3
[opened]4
[opened]5
[opened]6
[opened]7
[opened]8
[opened]9
[wrote]0
[wrote]1
[wrote]2
[wrote]4
[wrote]6
[wrote]3
[wrote]7
[wrote]5
[wrote]8
[closed]9:0
[closed]8:1
[closed]7:2
[closed]6:4
[closed]5:6
[closed]4:3
[closed]3:7
[closed]2:5
[wrote]9
[closed]1:8
[closed]0:9
Hoppyいいよ
Hoppyいい
シリコンバレー行った時に参加した Flash Game Summit とかでも、FITC Toronto 2009でも、マルチプレーヤーFlash熱そうだったので自分の周りではきてる。
汎用的なXMLSocketサーバを書いた
POEとか使ったシングルプロセスシングルスレッドのデーモンでデータベース扱う時はどうするのがいいんだろう?
裏にDB扱うためだけにhttpサーバ置いてデーモンからはそれに非同期でhttpリクエストするという方法がある。
ということでまずはauthを非同期にしてみました。
http://github.com/mash/Hoppy/tree/master
$c->handlerってtcp周りのイベントのハンドラってことでいいのかな。
PLAIN TEXT
PERL:
$c->regist_service(
auth => 'MyApp::Auth',
);
ってやると $c->handler->{auth} に入るのは気のせいかと思いたかったので
s/handler/service/ してみました。めっちゃコアっぽいけどまぁいいか。
ごめんねColinちゃん。
yokohama.pm 4回目行ってきた&DI
いいまとめはこちら
http://d.hatena.ne.jp/hiratara/20090417/1239946298
DIがよくわからなかったなぁ
Bread::Boardの感じだと結局コンストラクタに引数与えるのを書き方かえるだけに見えるけど
外部のxmlファイルに記述したくない、って牧さんは言ってたけど、
フォーマットがxmlかどうかは別として、javaをちょいちょい使ってる時の認識では、
別ファイルであることがDIの本質なんじゃないのかなぁと思っていた。
javaはコンパイルの必要な言語で、
xmlを変えてもリコンパイルが必要無い、
ってメリットがjavaではある
使うときにオブジェクトを渡して、使う側ではインターフェースしか使ってない、
こういうのもDIっていうかな
これをいい感じに書けるのがBread::Boardなのかな
PLAIN TEXT
PERL:
package A;
use Moose;
has cache => ( isa => 'Cache::Cache', is => 'rw', required => 1, default => sub { new Cache::FileCache } );
sub fetch_something {
my ($self, $key) = @_;
my $ret = $self->cache->get($key);
if ( ! defined($ret) ) {
$ret = fetch($key);
$self->cache->set( $key, [...]
preventing cache stampedes
webサイトとかで、重いSQLを使ったページを快適に表示するために、重いSQLの結果をキャッシュするためにmemcachedとかをよく使います。
キャッシュの有効期限が切れた後に、大量のリクエストに対応して大量の重いSQLが走ると困るので、どうしよう。
これをthundering herd 問題といったり、cache stampede, database stampedeというそうです。
キャッシュ切れた後にががっとくるやつ、です。
A. キャッシュの有効期限が切れる
B. SQL発行
C. SQLの結果を受け取る
D. キャッシュにつっこむ
A-D.の間に大量のリクエストが来ると、重いSQLが走るので困ります。
Kazuhookuさんが書いています。
キャッシュシステムの Thundering Herd 問題
対策としては、以下の2種類の手段があります。
* バックエンドへの同一リクエストを束ねるような仕組みを実装する
* エクスパイヤ以前の残存時間が一定以下となった段階で、キャッシュエントリのアップデートを開始する
昨日memcachedの勉強をしている時のFAQの資料にもいろいろ書いてあったのですが、
いくつか対策方法があるようです。
How to prevent clobbering updates, stampeding requests
The easiest answer is to avoid the problem. Don't set caches to expire, and update them via cron, or as data is updated. This does not eliminate [...]
Catalyst::Plugin::DumpRequired
fastcgi(Catalyst,perl)+lighttpdでよくウェブアプリをつくるのですが
Copy on Writeの恩恵を受け、メモリを節約するために、
fastcgiの親プロセスで網羅的にperlモジュールを読み込んでおき、
子プロセスの親プロセスとで共有するメモリを増やしたくなります。
子プロセスでどんなモジュールをrequireしてるのか?
がわかればMyApp.pmでuseしておくことで親プロセスで読み込めます。
それをわかりやすくするためのCatalystプラグインを作りました。
MyApp.pmで
PLAIN TEXT
PERL:
__PACKAGE__->setup(do {
my @plugins;
push @plugins, 'StackTrace', 'DumpRequired' if $ENV{CATALYST_DEBUG};
@plugins;
});
とかするといいと思います。
いろんなパスを通るようにrequest投げると $c->log->debug にrequireしたモジュールが出てきます。
以下参考にさせていただきました。
mod_perlで親プロセスとのCopy on Writeな共有メモリを増やす方法
Template-Plugin-AddTimeというのをつくった
codereposに置きました
Template::Plugin::AddTime - TT filter plugin to add file modified time
# 正直あまり自信はないのですが
jsとかcssとか、あまり変化しないのでブラウザにしっかりキャッシュしてほしいけど、
ファイルを更新した時には再読み込みしてほしいって時に、
expiresヘッダをつけないと、ブラウザの実装によってリクエストが来たり来なかったりして
cssを更新したのに読み込まないクライアントは表示が崩れたりします。
なのでexpiresヘッダをつけてしっかりブラウザにキャッシュして欲しいって時に、
ファイルの更新時刻をくっつけたりバージョン番号をくっつけたりすることがあります。
これはファイルの更新時刻をくっつけるためのTT Filterプラグインです。
こんなふうに使います。
# or with a base path
[% USE AddTime('tmpl/static') -%]
[% '/js/prototype\.js' | addtime -%]
# adds modified time of tmpl/static/js/prototype\.js
/js/prototype\.js\?1231163490
こうしておいて、lighttpdの設定で
expire.url = (
"/js/" => "access 1 years",
)
とかってすれば
Expires: Fri, 01 Jan 2010 00:42:29 GMT
Cache-Control: max-age=31104000
こんなヘッダがくっついてくる。
svnでソース管理してる時には [...]