2006年 11月 10日

RingServer を繋ぐ

両方の Server 同士でそれぞれタプルを書き込み合うっていうのがたぶん一番簡単な方法かな?

ts    = Rinda::TupleSpace.new
place = Rinda::RingServer.new(ts)

DRb.start_service(uri, ts)

other_ring_server = DRbObject.new_with_uri("druby://other-network")
ts.notify(tuple_match).each do |t|
  other_ring_server.write(t)
end

でもこれだけだと NAT とかの場合にタプルは取得できるのにサービスに接続できないというハメになりそう。
drb/gw.rb を使わないとだめかな? SimpleDelegator を DRbUndumped にしてあげるだけでもいけそうな気がする

Rinda::PeskyRingProvider

class Rinda::PeskyRingProvider < Rinda::RingProvider
	def provide
		entry = nil
		loop do
			begin
				if entry
					# 登録済みタプルを削除する
					entry.renew(0)
				end
				# RingServer を再検索する
				Rinda::RingFinger.finger.lookup_ring_any
				entry = super
			rescue DRb::DRbConnError, RuntimeError => e
				# RingServer が見つからないときのエラーをキャッチ
				entry = nil
			end

			sleep 60
		end
	end
end

AppleScript

スクリプトエディタのライブラリ使うとアプリケーションごとのリファレンス見れるのか……
inspect 相当の命令ってないのかなぁ。{1, 1} を "{1, 1}" にするとか

rubyosa libxml-ruby

http://rubyosa.rubyforge.org/ を入れようと思ったら libxml-ruby が入らなかった。

extconf.rb:64: undefined method `find_header' for main:Object (NoMethodError)

ruby のバージョンが古いせい (1.8.2) っぽい。
しかし新しいバージョン入れるのめんどい(コンパイルはしてあるけど、置き換えるのがいろいろめんどそう……)ので、

sudo gem install libxml-ruby -- --with-xml2-include=/usr/include/libxml2

した。

rubyosa 使って applescript にインターフェイスにアクセスした場合帰ってくる文字コードは Shift_JIS みたいだ。

タイムタグがついた歌詞ファイルを HTTP でとってきて iTunes に同期させるテスト

http://lab.lowreal.net/trac/browser/c/lyric/itunes-timetag.rb

/ART-SCHOOL/EVIL/02-WISH.txt みたいな感じになってるのを HTTP からとってきて表示させてみる。
しかし track position が秒単位でしかとれないのでいまいち。

今日の gem install

2006年 11月 09日

無脳

algorithm-diff で常に直近の数行の文字ごとの diff をとりながら、共通する部分をキーワードDBに登録していく。
ログは全てn-gram 式の全文検索エンジンに突っ込んでいく。

直近の diff から得た共通部分からランダムにトピックワードを選択し、全文検索。出てきた結果の上位数件からランダムに行を抽出し、直近の行と再び diff をとる。その結果のキーワードをキーワードDBから取り出した(どうやって?)ランダムなものに置換する。

Rinda Reload

http://lab.lowreal.net/trac/browser/c/mendoi/autoring

ネットワークまたがった場合のいい方法が浮かばないなぁ。とりあえず chain できるようにしてみた。他に方法あるんだろうか

# 主要 RingServer を uri つきで起動
./ring.rb -u druby://host:4321

でもって違うネットワークでは普通に RingServer をたてて
uri 指定して reload メッセージを別の RingServer の tuplespace に投げるサービスを起動

./ring.rb&
./reload_chain.rb druby://host:4321&

美しくないな。

っていうか上流サーバのあるネットワークで cl.rb 起動されても下流に通知されないからこれじゃだめか。ネットワークが分かれているというより、NAT なのが悪いんだよなぁたぶん。NAT でなければ Finger.new("servername") でいけそうだ
解決法:ネットワーク分けない

mabinogi のギルド

所属ギルドが解散するらしい。残念だなぁ。

ここ最近ログインしてもコミュニケーションサーバーが重くてギルドチャットがまともに通らないことが多い。直後はしばらく繋がらないから発言できないし。キャラクターチェンジ多いとほぼずっとオフライン扱いになってしまう。直して欲しいな、と書こうと思っていたけどもうどうでもいいな。

大してログインもできないくせにこれから他のギルドに所属するのは面倒くさい。今更知らないギルドに入って相手の考えていることを量りながらチャットするなんてモチベーションは生まれてこないし、そんなに時間がとれない。

そろそろネトゲも卒業ですか。

Provider

Provider は RingServer を定期的に再検索するようにしたほうがいいっぽいなぁ。RingServer が落ちてもそれを検知できないから……

RingServer を定期的に再検索する Provider

provider = Rinda::RingProvider.new(:Reload, DRbObject.new(reload), 'Reload')
entry = nil
loop do
	begin
		if entry
			# 登録済みタプルを削除する
			entry.renew(0)
		end
		# RingServer を再検索する
		Rinda::RingFinger.finger.lookup_ring_any
		entry = provider.provide
	rescue DRb::DRbConnError, RuntimeError => e
		# RingServer が見つからないときのエラーをキャッチ
		entry = nil
		puts e.message
	end


	sleep 60
end

なんかいい方法ないかなぁ。これだと Renewer は意味がなくなる。(Renewer はサーバからのリクエストの答えるだけなので、サーバが動いてなければ意味をなさない。)

provide メソッドをオーバライドしてブロックするようにしてもいいかもしれない。

2006年 11月 08日

anond show id

	$X("//ul[@class='footstamps']/li").forEach(function (i) {
		var id = $X("string(./img/@title)", i);
		i.appendChild($N("span", {}, id));
	});

hoe でリリース

なんかよくわからん試行錯誤。
gem install hoe で sow って rake package とかは別にいいとして、rake release がうまくいかないというアレ。rubyforge ライブラリのほうの設定しないとだめっていう話っぽい?

$ rubyforge setup (~/.rubyforge/config.yml が初期化されて開く)

でごたごた書いて group_id, package_id を書いてやると (これ調べるのめんどい) 一応いきそうな幹事にはなる、けど、まだこれだとだめっぽい。なんなんだ

$ rake release VERSION=0.0.5 --trace
-snip-
** Execute release
Logging in
at depth 0 - 18: self signed certificate
Releasing charnames v. 0.0.5 tarball
at depth 0 - 18: self signed certificate
rake aborted!
undefined method `[]' for nil:NilClass
/usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/rubyforge.rb:215:in `add_release'
/usr/lib/ruby/gems/1.8/gems/hoe-1.1.2/lib/hoe.rb:246:in `define_tasks'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:387:in `execute'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:387:in `execute'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:357:in `invoke'
/usr/lib/ruby/1.8/thread.rb:135:in `synchronize'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:350:in `invoke'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:1906:in `run'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:1906:in `run'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/bin/rake:7
/usr/bin/rake:18
exit 1

めんどい。とりあえず手動でリリースしてみた。http://rubyforge.org/frs/?group_id=2552

release_id を html からとってくる処理の部分でこけてる。puts html とかやって見てみるとログインできてないという……
パスワードが単純に間違ってるのかなぁと思って確かめたけど違うようには見えない。cat cookie.dat すると何も書いてない。あやしいなぁ……
めんどいよおお

gem

CPAN は欲しいものがだいたいあるので諦めて、gem をひとつきに一個を目標にして作っていくよ><
名前に迷ったときは CPAN インスパイヤでつけていくことにする。多分一番幸せな方法だ。

gem 化できそうなの

  • safe eval
  • uri からタイトルとかとってくるやつ
  • sakage モールス

オートリロードの設定がめんどいので設定をオートにする試み

オートリロードでリロードが楽になるのはいいんだけど、リロードさせるために設定をしたりとかするのがすっごいめんどく感じるようになってきたので設定もオートでやろうぜって思った。

Rinda::Ring は UDP で検索したり登録したりしてサービス呼び出せるライブラリで、これを使うと一瞬で上のようなことができちゃってオレスゲー感を味わえます。ちょーLL

まず tuplespace を起動する。以下のスクリプトそのまま。このタプルスペースはサービスの情報を統括してる。

require 'rinda/ring'
require 'rinda/tuplespace'

DRb.start_service

ts = Rinda::TupleSpace.new
place = Rinda::RingServer.new(ts)

DRb.thread.join

次に各種リロードサービスを tuplespace に登録するスクリプト。 こいつらはブラウザとともに常駐して、リロード要求をうけつける。これらはもちろん RingServer と同じホストで動いている必要はない。

以下は例

reloadfx.rb

#!/usr/bin/ruby

require 'rinda/ring'
require 'net/telnet'

class Reload
    def reload
        telnet = Net::Telnet.new({
            "Host" => "localhost",
            "Port" => 4242
        })
        telnet.puts("content.location.reload(true)")
        telnet.close
    end
end

reload = Reload.new
DRb.start_service(nil, reload)

provider = Rinda::RingProvider.new(:Reload, DRbObject.new(reload), 'Reload')
provider.provide

DRb.thread.join

reloadsafari.rb

#!/usr/bin/ruby

require 'rinda/ring'
require 'net/telnet'

class Reload
    def reload
        <<-`EOC`
        osascript -e '
        tell application "Safari"
            do JavaScript "location = (location.href);" in document 1
        end tell
        '
        EOC
    end
end

reload = Reload.new
DRb.start_service(nil, reload)

provider = Rinda::RingProvider.new(:Reload, DRbObject.new(reload), 'Reload')
provider.provide

DRb.thread.join

でもって、上記サービスをタプルスペースから検索し、リロードメソッドを呼ぶスクリプト

#!/usr/bin/ruby
# reload.rb
require 'rinda/ring'

DRb.start_service
ts = Rinda::RingFinger.primary

ts.read_all([:name, :Reload, DRbObject, nil]).each do |i|
    begin
        p i[2].reload
    rescue Exception => e
        puts e.message
        puts e.backtrace
    end
end

この reload.rb を呼ぶだけで、何の設定もなしに、ネットワーク内のブラウザをリロードする。

新しくブラウザを起動したら同時にそのブラウザ用の Provider を起動すれば、それも何の設定もなしにリロードしてくれるってわけですよ。やばい!

Rinda::Ring さいこう>< DRb は Ruby の宝><

もうちょっといぢってみる。

rubyforge

毎回プロジェクト登録するのめんどいから、なんか包括的なプロジェクトつくって、それにパッケージ追加していくほうがいいのかなぁ。

パッケージの名前

すごい困る。

gems を使う上で関連づいていなければならない三つ(!)の名前がある

  • require "foo/barbaz" の foo/barbaz
  • Foo::BarBaz.new の Foo::BarBaz
  • gem install foo-barbaz の foo-bar

どういう規則でつけるかが決まってない。上のだと case が保たれてない。

それと CPAN みたいに WebService::Foo::Bar みたいなのを作ろうと思うと、それぞれのライブラリで module WebService を定義してあげないといけない。

begin
  WebService
rescue NameError
  WebService = Module.new
end

begin
  Foo
rescue NameError
  Foo = Module.new
end

とか毎回やるのはアレだしどうするんだろう。

http://wiki.rails2u.com/misc/string_flections
web_service/cgi => WebService::Cgi

module WebService
  module Foo
    class Bar
    end
  end
end

て書けばいいのか。インデントが増えまくり

rule

提供するクラス/モジュール
FooBar::Baz
require の名前
foo_bar/baz
rubyforge プロジェクト名とパッケージ名
foobar-baz

あたりが妥当か

しかし

module Foo
end

class Foo #=> Foo is not a class (TypeError)
end

とかなるから何をクラスにしてなにをモジュールにするのかが問題に……

ttyTube

って誰かが言ってたネタだったっけ……
サイトにアクセスすると誰かの tty が覗けるサービス。

svk

svk のリポジトリ管理サブコマンドを忘れた。help しても対して情報だしてくれない。

svk help intro
svk mirror --list

UserAgent::RandomProxyByCyberSyndrome