Rindaで遊ぶ
LindaのRuby実装、Rindaを使うことになったのでそのメモ。Rindaすげーよ!
Rindaについては
http://www.druby.org/ilikeruby/d208.htmlをご覧ください。非常に丁寧な解説があります。
TupleSpaceデーモンを作ってみる
いきなりかよ、って感じですが、今回作ろうとしてるシステムでは、どこかに「常時走りっぱなしになってるTupleSpace保持プロセス」が必要だったので…
tsd.rb (TupleSpaceDaemon)を次のようにして書きます。手抜き。
#!/usr/bin/ruby require 'rinda/tuplespace' drb_host = ARGV.shift drb_host ||= "127.0.0.1" drb_port = ARGV.shift drb_port ||= "6456" pid_filepath = ARGV.shift pid_filepath ||= "/usr/local/tsd/pid" pid_file = File.open(pid_filepath, 'w') $druby_listen="#{drb_host}:#{drb_port}" fork{ Process::setsid pid = fork{ STDIN.reopen("/dev/null", "r+") STDOUT.reopen("/dev/null", "w") STDERR.reopen("/dev/null", "w") ts = Rinda::TupleSpace.new DRb.start_service("druby://#{$druby_listen}", ts) DRb.thread.join sleep } pid_file.puts pid pid_file.close }
で、rc.dのデーモンとして登録したいので、次のようなシェルスクリプト tsd.sh を作ります。squidのものをパクってます。
#!/bin/bash # tsd This shell script takes care of starting and stopping # Tuple-Space daemon # # chkconfig: - 90 25 # description: This shell script takes care of starting and stopping \ # Tuple-Space daemon # pidfile: /usr/local/tsd/tsd.pid # config: /usr/local/tsd/tsd.conf . /etc/rc.d/init.d/functions prog="tsd" CONF="/usr/local/tsd/tsd.conf" LTSD="/usr/local/tsd/tsd.rb" PID="/usr/local/tsd/tsd.pid" # import config . $CONF RETVAL=0 start() { # check ltsd is already working if [ -f $PID ] ; then # pid file exists. check the process is working. ps -p `cat $PID` >/dev/null 2>&1 if [ $? = 0 ] ; then # process is still working! echo "ltsd is still working. aborting..." 1>&2 exit 1 fi # pid file is invalid now. rm -f $PID fi echo -n $"Starting $prog: " $LTSD $LISTEN $PORT $PID RETVAL=$? [ $RETVAL -eq 0 ] && echo_success [ $RETVAL -ne 0 ] && echo_failure echo return $RETVAL } stop() { # check the pid file exists if [ ! -f $PID ] ; then # pid file is missing echo "pid file is not found. aborting..." 1>&2 return 3 fi echo -n $"Stopping $prog: " kill `cat $PID` >/dev/null 2>&1 RETVAL=$? [ $RETVAL -eq 0 ] && rm -f $PID [ $RETVAL -eq 0 ] && echo_success [ $RETVAL -ne 0 ] && echo_failure echo return $RETVAL } case "$1" in start) start ;; stop) stop ;; restart) stop start ;; probe) exit 0 ;; *) echo $"Usage: $0 {start|stop|restart}" exit 2 esac exit $?
あとは
# ln -s tsd.sh /etc/rc.d/init.d/tsd # chkconfig --add tsd # service tsd start
で動くはずです。たぶん。
デーモン動作確認
irbでちゃちゃっとやりましょう。
# irb irb(main):001:0> require 'drb' => true irb(main):002:0> ts = DRbObject.new_with_uri('druby://127.0.0.1:6456') => #<DRb::DRbObject:0xb7f16b68 @ref=nil, @uri="druby://127.0.0.1:6456"> irb(main):003:0> ts.write(["take-test",1]) => #<DRb::DRbObject:0xb7bc88f8 @ref=-604674008, @uri="druby://127.0.0.1:6456"> irb(main):004:0> ts.take(["take-test",nil]) => ["take-test", 1] irb(main):005:0> ts.read_all(["take-test",nil]) => [] irb(main):006:0> 1.upto(10){|i| ts.write(["take-test", i]) } => 1 irb(main):007:0> ts.read_all(["take-test",nil]) => [["take-test", 1], ["take-test", 2], ["take-test", 3], ["take-test", 4], ["take-test", 5], ["take-test", 6], ["take-test", 7], ["take-test", 8], ["take-test", 9], ["take-test", 10]] irb(main):008:0> ts.read_all(["take-test",nil]).each{|tuple| puts tuple[1] } 1 2 3 4 5 6 7 8 9 10 => [["take-test", 1], ["take-test", 2], ["take-test", 3], ["take-test", 4], ["take-test", 5], ["take-test", 6], ["take-test", 7], ["take-test", 8], ["take-test", 9], ["take-test", 10]] irb(main):009:0> exit
ね、簡単でしょ?