noda 0.0.1 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,6 +1,8 @@
1
1
  = noda
2
2
 
3
- Description goes here.
3
+ Noda �̓V���v���ȃW���u�L���[�T�[�o�[�ł�.
4
+
5
+ druby���g�p���āC�}���`�X���b�h�𕪎U�T�[�o�Ŏ������Ă��܂��D
4
6
 
5
7
  == Contributing to noda
6
8
 
@@ -14,6 +16,6 @@ Description goes here.
14
16
 
15
17
  == Copyright
16
18
 
17
- Copyright (c) 2011 takuya. See LICENSE.txt for
19
+ Copyright (c) 2011 takuya_1st. See LICENSE.txt for
18
20
  further details.
19
21
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.5
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created on 2011-5-12.
4
+ # Copyright (c) 2011. All rights reserved.
5
+ #
6
+
7
+ require 'rubygems'
8
+ require 'daemons'
9
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/noda")
10
+ KCODE='s'
11
+ options = {
12
+ :dir_mode => :script,
13
+ :dir => '/var/run',
14
+ :multiple => true,
15
+ :ontop => false,
16
+ :mode => :exec,
17
+ :backtrace => true,
18
+ :monitor => true
19
+ }
20
+ require "socket"
21
+ ip= IPSocket::getaddress(Socket::gethostname)
22
+ STDOUT.puts " job_monitor at http://#{ip}:10080"
23
+ STDOUT.puts " job_server at druby://#{ip}:10001"
24
+ Daemons.run_proc("job_server",options){
25
+ m=Noda::JobMonitor.new("#{ip}","10080","druby://#{ip}:10001")
26
+ m.start_monitor
27
+ s=Noda::JobServer.new("#{ip}", "10001")
28
+ s.start_service
29
+ }
30
+
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created on 2011-5-12.
4
+ # Copyright (c) 2011. All rights reserved.
5
+ #
6
+
7
+ require 'rubygems'
8
+ require 'daemons'
9
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/noda")
10
+ KCODE='s'
11
+ options = {
12
+ :dir_mode => :script,
13
+ :dir => '/var/run',
14
+ :multiple => true,
15
+ :ontop => false,
16
+ :mode => :exec,
17
+ :backtrace => true,
18
+ :monitor => true
19
+ }
20
+ require "socket"
21
+ ip= IPSocket::getaddress(Socket::gethostname)
22
+ STDOUT.puts " connect to job_server at druby://#{ip}:10001"
23
+ Daemons.call(options){
24
+ s=Noda::JobWorker.new("#{ip}", "10001")
25
+ s.start_service
26
+ }
27
+
@@ -0,0 +1,71 @@
1
+
2
+ module Noda
3
+
4
+ class JobMonitor
5
+ require 'webrick'
6
+ require 'drb/drb'
7
+ attr_accessor :job_server, :web_server
8
+ def initialize(addr="localhost",port="10080",job_server="druby://localhost:10001")
9
+ @job_server = DRbObject.new_with_uri(job_server)
10
+ @addr = addr
11
+ @port = port
12
+ self.init_webrick
13
+ end
14
+ def start_monitor
15
+ trap("INT"){ @web_server.shutdown }
16
+ @thread = Thread.new{ @web_server.start}
17
+ end
18
+ def stop_monitor
19
+ @web_server.stop
20
+ end
21
+ def init_webrick
22
+ config = WEBrick::Config::HTTP
23
+ config[:Port] = @port
24
+ config[:BindAddress]=@addr
25
+ config[:AccessLog] = WEBrick::Log.new("/dev/null",1) #���O�v��Ȃ��D
26
+ config[:Logger] = Logger.new("/dev/null") #���O�v��Ȃ��D
27
+ @web_server = WEBrick::HTTPServer.new(config)
28
+ @web_server.mount_proc '/' do |req,res|
29
+ res.content_type="text/plain"
30
+ res.body = "running" if @job_server.alive?
31
+ res.body = "stopped" unless @job_server.alive?
32
+ end
33
+ @web_server.mount_proc '/in_queue' do |req,res|
34
+ res.content_type="text/plain"
35
+ if req.path_info =~ %r'^/(\d+)$' then
36
+ num = $1.to_i
37
+ res.body = @job_server.input._at(num).to_s
38
+ end
39
+ if req.path_info =~ %r'^/$' then
40
+ res.body = @job_server.input.size.to_s
41
+ end
42
+ end
43
+ @web_server.mount_proc '/out_queue' do |req,res|
44
+ res.content_type="text/plain"
45
+ if req.path_info =~ %r'^/(\d+)$' then
46
+ num = $1.to_i
47
+ res.body = @job_server.output._at(num).to_s
48
+ end
49
+ if req.path_info =~ %r'^/$' then
50
+ res.body = @job_server.output.size.to_s
51
+ end
52
+ end
53
+ @web_server.mount_proc '/hash_table' do |req,res|
54
+ res.content_type="text/plain"
55
+ res.body = @job_server.hash_table.size.to_s
56
+ end
57
+ @web_server.mount_proc '/hash_table/keys' do |req,res|
58
+ res.content_type="text/plain"
59
+ res.body = @job_server.hash_table.keys.inspect
60
+ end
61
+ @web_server.mount_proc '/hash_table/fetch' do |req,res|
62
+ res.content_type="text/plain"
63
+ if req.path_info =~ %r'^/([^/]+)$' then
64
+ key = $1.to_s
65
+ res.body = @job_server.hash_table.get(key).to_s
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,39 @@
1
+ module Noda
2
+
3
+ class JobServer
4
+ include DRb::DRbUndumped
5
+ attr_reader :thread, :server
6
+ def initialize( addr='localhost', port='10001',acl=nil,log_file=STDOUT )
7
+ @q_in = RQueue.new()
8
+ @q_out = RQueue.new()
9
+ @hash_table = Table.new()
10
+ @server = DRb.start_service("druby://#{addr}:#{port}",self)
11
+ @thread = @server.thread
12
+ @logger = Logger.new(log_file)
13
+ end
14
+ def stop
15
+ @server.stop_service
16
+ end
17
+ def alive?
18
+ @server.alive?
19
+ end
20
+ def input
21
+ #�T�[�o�[�͕K���C���v�b�g�L���[��Ԃ�
22
+ @q_in
23
+ end
24
+ def output
25
+ @q_out
26
+ end
27
+ def hash_table
28
+ @hash_table
29
+ end
30
+ def start_service
31
+ @thread.join
32
+ end
33
+ def logger
34
+ @logger
35
+ end
36
+ end
37
+
38
+
39
+ end
@@ -0,0 +1,60 @@
1
+ module Noda
2
+
3
+
4
+ class JobWorker
5
+ attr_reader :thread
6
+ attr_accessor :max_retry_connect , :wait_time_to_retry
7
+ def initialize( job_server_addr="localhost",job_server_port="10001" )
8
+ @server_uri = "druby://#{job_server_addr}:#{job_server_port}"
9
+ @max_retry_connect = 30
10
+ @wait_time_to_retry = 2
11
+ require "socket"
12
+ @local_addr = IPSocket::getaddress(Socket::gethostname)
13
+ self.connect
14
+ end
15
+ def connect_job_server
16
+ error_conter = 0
17
+ begin
18
+ @job =DRbObject.new_with_uri(@server_uri)
19
+ @job.hash_table
20
+ @logger = @job.logger
21
+ rescue DRb::DRbConnError => e
22
+ error_conter +=1
23
+ raise e if error_conter > @max_retry_connect
24
+ sleep @wait_time_to_retry
25
+ retry
26
+ end
27
+ end
28
+ def handle_task()
29
+ # @logger.info("self.class@#{@local_addr}#{self.object_id}"){"i try to pop a task."}
30
+ task = @job.input.pop
31
+ # @logger.info("self.class@#{@local_addr}#{self.object_id}"){"i got a task-#{task.name}"}
32
+ # @logger.info("self.class@#{@local_addr}#{self.object_id}"){"i start handling a task-#{task.name}"}
33
+ result = task.do_task(@job.hash_table)
34
+ @job.output.push result
35
+ end
36
+ def init_thread
37
+ @table = @job.hash_table
38
+ @thread= Thread.new{
39
+ loop{
40
+ self.handle_task()
41
+ sleep 0.001
42
+ }
43
+ }
44
+ end
45
+ def connect
46
+ self.connect_job_server
47
+ end
48
+ def start
49
+ self.init_thread
50
+ @thread.join
51
+ end
52
+ def status
53
+ @thread.status if @thread
54
+ end
55
+ def stop
56
+ @thread.kill
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,53 @@
1
+ # -*- utf8 -*-
2
+
3
+ module Noda
4
+ require 'monitor'
5
+ class RQueue
6
+ include DRb::DRbUndumped
7
+ attr_reader :name
8
+ def initialize( max=nil, name=nil )
9
+ @name = name
10
+ @list = []
11
+ @max = nil
12
+ @max = max if max
13
+ self.extend(MonitorMixin)
14
+ @m_empty = self.new_cond
15
+ @m_full = self.new_cond
16
+ end
17
+ def push obj
18
+ self.synchronize{
19
+ @m_full.wait_while{ self.full? } if @max
20
+ @list.push obj
21
+ @m_empty.broadcast
22
+ }
23
+ end
24
+ def pop
25
+ self.synchronize{
26
+ @m_empty.wait_while{ self.empty? }
27
+ obj = @list.shift
28
+ @m_full.broadcast if @max
29
+ obj
30
+ }
31
+ end
32
+ def include?(v) @list.include? v end
33
+ alias exists? include?
34
+ def firsts(n=1) (0...n).map{self.pop} end
35
+ def first() self.pop end
36
+ def size() @list.size end
37
+ def max_size() @max end
38
+ def empty?() @list.empty? end
39
+ def close_to_full?() @list.size >= @max-5 end
40
+ def full?()
41
+ # max=nil �Ȃ�Limitless�B�‚܂薳����
42
+ @list.size >= @max if @max
43
+ end
44
+ def all() self.firsts(self.size) end
45
+ # �P����m�܂ł̒l�����B�O�n�܂�łȂ����Ƃɒ���
46
+ def _at(pos)
47
+ i = pos - 1
48
+ return @list.at(i) if (i) < self.size
49
+ end
50
+ end
51
+
52
+
53
+ end
data/lib/noda/table.rb ADDED
@@ -0,0 +1,54 @@
1
+ #
2
+ module Noda
3
+ #スレッドセーフなHASHテーブルを作ってる
4
+ #内部的にはHashにしている
5
+ #KVSとして使っている
6
+ #TODO::HASHとして動くようにEnumerableを実装したい
7
+ #TODO::DBやファイルに保存する。このクラスAPIでアクセス出来るアダプタを作りたい
8
+ class Table
9
+ include DRb::DRbUndumped
10
+ include Enumerable
11
+ attr_reader :name
12
+ def initialize(name=nil)
13
+ @hash = {}
14
+ @name = name
15
+ self.extend(MonitorMixin)
16
+ @m_lock = self.new_cond
17
+ @saved_keys = []
18
+ end
19
+ def get(key)
20
+ @hash[key][:data]
21
+ end
22
+ def put(key, obj)
23
+ self.synchronize{
24
+ @hash[key] = {:data=>obj,:saved=>false}
25
+ }
26
+ end
27
+ def has_key?(key) @hash.has_key? key end
28
+ alias :exists? :has_key?
29
+ def keys() @hash.keys end
30
+ def size() @hash.size end
31
+ def each
32
+ @hash.each_pair{|k,v| yield( k,v[:data] ) }
33
+ nil
34
+ end
35
+ def saved?(key)
36
+ @hash[key][:saved]
37
+ end
38
+ def update_saved_at(key,status=true)
39
+ self.synchronize{
40
+ @hash[key][:saved]=status
41
+ }
42
+ end
43
+ def each_unsaved_pair
44
+ @hash.each_pair{|k,v| next if v[:saved]; yield( k, v[:data] ) }
45
+ nil
46
+ end
47
+ def has_unsaved_key?
48
+ return true if @hash.find{|k,v| v[:saved]==false}
49
+ return false
50
+ end
51
+ end
52
+
53
+ end
54
+
@@ -0,0 +1,43 @@
1
+ module Noda
2
+
3
+ class TableAutoSaver < JobWorker
4
+ attr_reader :thread
5
+ attr_accessor :max_retry_connect , :wait_time_to_retry
6
+ def initialize( job_server_addr="localhost",job_server_port="10001" )
7
+ super
8
+ @interval = 2
9
+ require 'tmpdir'
10
+ @save_dir = Dir.tmpdir
11
+ end
12
+ def save_dir=(dirname)
13
+ raise ArgumentError, "#{dirname} is not direcotry." unless FileTest.directory? dirname
14
+ @save_dir=dirname
15
+ end
16
+ def save_dir
17
+ @save_dir
18
+ end
19
+ def handle_task()
20
+ sleep @interval
21
+ return unless @table.has_unsaved_key?
22
+ @table.each_unsaved_pair{|k,v|
23
+ self.save(k,v)
24
+ @table.update_saved_at(k,true)
25
+ }
26
+ end
27
+ def save(key,val)
28
+ Dir.chdir(@save_dir){
29
+ open(key.to_s, "w"){|f|
30
+ f.write(Marshal.dump({:key=>key, :data=>val}))
31
+ }
32
+ }
33
+ end
34
+ def interval=(sec)
35
+ @interval=sec
36
+ end
37
+ def interval()
38
+ @interval
39
+ end
40
+ end
41
+
42
+
43
+ end
data/lib/noda/task.rb ADDED
@@ -0,0 +1,21 @@
1
+ module Noda
2
+
3
+ class Task
4
+ #�Q�Ɠn���ɂ������Ƃ��� ���� include ���g��
5
+ # objects-by-reference
6
+ #def by_reference() include DRb::DRbUndumped end
7
+
8
+ #this should be overwrite
9
+ def do_task(hash_table)
10
+ end
11
+ #this should be overwrite
12
+ def name
13
+ return self.object_id unless @name
14
+ return @name if @name
15
+ end
16
+ def name=(str) @name=str end
17
+ end
18
+
19
+
20
+ end
21
+
data/lib/noda.rb CHANGED
@@ -1,15 +1,17 @@
1
1
  require 'rubygems'
2
2
  require 'drb/drb'
3
-
3
+ require 'logger'
4
4
 
5
5
  $:.unshift(File.dirname(__FILE__)) unless
6
6
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
7
7
  require 'noda/rqueue'
8
8
  require 'noda/job_server'
9
+ require 'noda/job_monitor'
9
10
  require 'noda/job_worker'
10
11
  require 'noda/table'
11
12
  require 'noda/task'
12
13
  require 'noda/table'
14
+ require 'noda/table_auto_saver'
13
15
 
14
16
  module Noda
15
17
  #VERSION = '0.0.1'
data/noda.gemspec CHANGED
@@ -5,13 +5,14 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{noda}
8
- s.version = "0.0.1"
8
+ s.version = "0.0.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["takuya"]
12
- s.date = %q{2011-05-18}
12
+ s.date = %q{2011-05-28}
13
13
  s.description = %q{noda is job queue system using druby }
14
14
  s.email = %q{takuya.1st@gmail}
15
+ s.executables = ["noda_job_worker", "noda_job_server"]
15
16
  s.extra_rdoc_files = [
16
17
  "LICENSE.txt",
17
18
  "README.rdoc"
@@ -24,9 +25,26 @@ Gem::Specification.new do |s|
24
25
  "README.rdoc",
25
26
  "Rakefile",
26
27
  "VERSION",
28
+ "bin/noda_job_server",
29
+ "bin/noda_job_worker",
27
30
  "lib/noda.rb",
31
+ "lib/noda/job_monitor.rb",
32
+ "lib/noda/job_server.rb",
33
+ "lib/noda/job_worker.rb",
34
+ "lib/noda/rqueue.rb",
35
+ "lib/noda/table.rb",
36
+ "lib/noda/table_auto_saver.rb",
37
+ "lib/noda/task.rb",
28
38
  "noda.gemspec",
29
- "test/test_noda.rb"
39
+ "test/test_helper.rb",
40
+ "test/test_job_monitor.rb",
41
+ "test/test_job_server.rb",
42
+ "test/test_job_worker.rb",
43
+ "test/test_noda.rb",
44
+ "test/test_rqueue.rb",
45
+ "test/test_table.rb",
46
+ "test/test_table_saver_woker.rb",
47
+ "test/test_task.rb"
30
48
  ]
31
49
  s.homepage = %q{http://github.com/takuya/noda}
32
50
  s.licenses = ["MIT"]
@@ -0,0 +1,14 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'rubygems'
4
+ require 'drb/drb'
5
+ require File.dirname(__FILE__) + '/../lib/noda'
6
+
7
+ require 'noda'
8
+ require 'noda/job_server'
9
+ require 'noda/job_worker'
10
+ require 'noda/job_monitor'
11
+ require 'noda/rqueue'
12
+ require 'noda/table'
13
+ require 'noda/task'
14
+ include Noda
@@ -0,0 +1,63 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ class TestJobMonitor < Test::Unit::TestCase
3
+ #�e�X�g�̓}���`�X���b�h�ōs����̂ŁA�|�[�g�Փ˂���Error�ɂȂ�܂��D
4
+ def test_start_monitor
5
+ #���j�^���N�����邩�ǂ���
6
+ m = JobMonitor.new("localhost","10081")
7
+ t = m.start_monitor
8
+ sleep 0.01
9
+ assert m.web_server.status == :Running
10
+ m.stop_monitor
11
+ sleep 0.01
12
+ assert m.web_server.status == :Shutdown
13
+ end
14
+ def test_monitor_in_queue
15
+ require 'open-uri'
16
+
17
+ m = JobMonitor.new("localhost", "10080")
18
+ t = m.start_monitor
19
+ sleep 0.01
20
+ assert m.web_server.status == :Running
21
+ s = JobServer.new
22
+ s.input.push 1234
23
+ assert open("http://localhost:10080/").read == "running"
24
+ assert open("http://localhost:10080/in_queue/").read == "1"
25
+ s.input.push 1111
26
+ assert open("http://localhost:10080/in_queue/").read == "2"
27
+ assert open("http://localhost:10080/in_queue/1").read == "1234"
28
+ assert open("http://localhost:10080/in_queue/2").read == "1111"
29
+ d = s.input.pop
30
+ assert open("http://localhost:10080/in_queue/").read == "1"
31
+ end
32
+ def test_monitor_out_queue
33
+ require 'open-uri'
34
+
35
+ s = JobServer.new("localhost","100011")
36
+ m = JobMonitor.new("localhost", "10083","druby://localhost:100011")
37
+ t = m.start_monitor
38
+ sleep 0.01
39
+ assert m.web_server.status == :Running
40
+ s.output.push 1234
41
+ assert open("http://localhost:10083/").read == "running"
42
+ assert open("http://localhost:10083/out_queue/").read == "1"
43
+ s.output.push 1111
44
+ assert open("http://localhost:10083/out_queue/").read == "2"
45
+ assert open("http://localhost:10083/out_queue/1").read == "1234"
46
+ assert open("http://localhost:10083/out_queue/2").read == "1111"
47
+ end
48
+ def test_monitor_in_queue
49
+ require 'open-uri'
50
+
51
+ s = JobServer.new("localhost","100012")
52
+ m = JobMonitor.new("localhost", "10084","druby://localhost:100012")
53
+ t = m.start_monitor
54
+ sleep 0.01
55
+ assert m.web_server.status == :Running
56
+ assert open("http://localhost:10084/").read == "running"
57
+ assert open("http://localhost:10084/hash_table/").read == "0"
58
+ s.hash_table.put "1234", "abcdefg"
59
+ assert open("http://localhost:10084/hash_table/").read == "1"
60
+ assert open("http://localhost:10084/hash_table/fetch/1234").read == "abcdefg"
61
+ assert open("http://localhost:10084/hash_table/keys").read == "[\"1234\"]"
62
+ end
63
+ end
@@ -0,0 +1,85 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+
4
+ class TestJobServer < Test::Unit::TestCase
5
+ def test_start_stop_job_server
6
+ #�W���u�}�X�^���N�����邩�ǂ���
7
+ s = JobServer.new
8
+ assert s.alive? == true
9
+ s.stop
10
+ assert s.alive? == false
11
+ end
12
+ def test_job_server_input_queue
13
+ #druby�o�R�Ő������u���b�N����邩�ǂ���
14
+ test_str = "hello world"
15
+ s=JobServer.new
16
+ m = m = DRbObject.new_with_uri('druby://localhost:10001')
17
+ t1 = Thread.new{
18
+ m1 = DRbObject.new_with_uri('druby://localhost:10001')
19
+ q1 = m1.input
20
+ q1.pop
21
+
22
+ }
23
+ #�u���b�N����Ă��邩
24
+ assert t1.status == "sleep"
25
+ m2 = DRbObject.new_with_uri('druby://localhost:10001')
26
+ q2 = m2.input
27
+ q2.push test_str
28
+ #�u���b�N��������ꂩ�ǂ���
29
+ assert t1.status == "run"
30
+ #�T�[�o�[���~
31
+ s.stop
32
+ end
33
+ def test_job_server_output_queue
34
+ #druby�o�R�Ő������u���b�N����邩�ǂ���
35
+ test_str = "hello world"
36
+ s=JobServer.new
37
+ m = m = DRbObject.new_with_uri('druby://localhost:10001')
38
+ t1 = Thread.new{
39
+ m1 = DRbObject.new_with_uri('druby://localhost:10001')
40
+ q1 = m1.output
41
+ q1.pop
42
+
43
+ }
44
+ #�u���b�N����Ă��邩
45
+ assert t1.status == "sleep"
46
+ m2 = DRbObject.new_with_uri('druby://localhost:10001')
47
+ q2 = m2.output
48
+ q2.push test_str
49
+ #�u���b�N��������ꂩ�ǂ���
50
+ assert t1.status == "run"
51
+ #�T�[�o�[���~
52
+ s.stop
53
+ end
54
+ def test_job_server_input_queue_data
55
+ s=JobServer.new
56
+ m = m = DRbObject.new_with_uri('druby://localhost:10001')
57
+ t1 = Thread.new{
58
+ m1 = DRbObject.new_with_uri('druby://localhost:10001')
59
+ q1 = m1.input
60
+ q1.push "hello world"
61
+
62
+ }
63
+ m2 = DRbObject.new_with_uri('druby://localhost:10001')
64
+ q2 = m2.input
65
+ ret = q2.pop
66
+ assert ret == "hello world"
67
+ s.stop
68
+ end
69
+ def test_job_server_output_queue_data
70
+ s=JobServer.new
71
+ m = m = DRbObject.new_with_uri('druby://localhost:10001')
72
+ t1 = Thread.new{
73
+ m1 = DRbObject.new_with_uri('druby://localhost:10001')
74
+ q1 = m1.output
75
+ q1.push "hello world"
76
+
77
+ }
78
+ m2 = DRbObject.new_with_uri('druby://localhost:10001')
79
+ q2 = m2.output
80
+ ret = q2.pop
81
+ assert ret == "hello world"
82
+ s.stop
83
+ end
84
+ end
85
+
@@ -0,0 +1,55 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ class TestJobWoker < Test::Unit::TestCase
3
+
4
+
5
+ def test_init_job_woker
6
+ worker = JobWorker.new
7
+ assert worker
8
+ end
9
+ #test task
10
+ class MyTask
11
+ def do_task(hash)
12
+ return "test_task_end"
13
+ end
14
+ end
15
+ def test_start_stop
16
+ s =JobServer.new
17
+ w = JobWorker.new
18
+ t = Thread.new{
19
+ w.start
20
+ }
21
+ s.input.push MyTask.new
22
+ ret = s.output.pop
23
+ assert ret == "test_task_end"
24
+ s.stop
25
+ w.stop
26
+ assert w.status == false #�X���b�h�I���ł����H
27
+ end
28
+ def test_do_task
29
+ s=JobServer.new
30
+ worker = JobWorker.new
31
+ s.input.push MyTask.new
32
+ worker.handle_task
33
+ ret = s.output.pop
34
+ assert ret == "test_task_end"
35
+ s.stop
36
+ end
37
+ class MyTask2
38
+ def do_task(hash)
39
+ hash.put "MyTask", "foooo"
40
+ return "test_task_end"
41
+ end
42
+ end
43
+ def test_task_write_hash_table
44
+ #�W���u�T�[�o�[�̋��L�̈�ɏ������߂邩�ǂ���
45
+ s=JobServer.new
46
+ worker = JobWorker.new
47
+ s.input.push MyTask2.new
48
+ worker.handle_task
49
+ ret = s.output.pop
50
+ assert ret == "test_task_end"
51
+ v = s.hash_table.get "MyTask"
52
+ assert v == "foooo"
53
+ s.stop
54
+ end
55
+ end
@@ -0,0 +1,51 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestRQueue < Test::Unit::TestCase
4
+ def setup
5
+ @q = RQueue.new
6
+ end
7
+ def test_RQueue_init
8
+ q = RQueue.new
9
+ assert q.empty?
10
+ end
11
+ def test_RQueue_init_with_RQueue_max_size
12
+ max = 10
13
+ q = RQueue.new max
14
+ assert q.empty? && q.max_size==max
15
+ end
16
+ def test_RQueue_mutex_push
17
+ max = 100
18
+ q = RQueue.new max
19
+ th1 = Thread.new{
20
+ loop{
21
+ q.push 1
22
+ }
23
+ }
24
+ th2 = Thread.new{
25
+ loop{
26
+ q.push 1
27
+ }
28
+ }
29
+ sleep 0.1
30
+ assert th1.status == "sleep" && th2.status == "sleep" && q.full?
31
+ end
32
+ def test_RQueue_mutex_pop
33
+ max = 10
34
+ q = RQueue.new max
35
+ max.times{ q.push 1 }
36
+ th1 = Thread.new{
37
+ loop{
38
+ q.pop
39
+ }
40
+ }
41
+ th2 = Thread.new{
42
+ loop{
43
+ q.pop
44
+ }
45
+ }
46
+ while not q.empty? do
47
+ sleep 0.1
48
+ end
49
+ assert th1.status == "sleep" && th2.status == "sleep" && q.empty?
50
+ end
51
+ end
@@ -0,0 +1,50 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestPageList < Test::Unit::TestCase
4
+ def test_table_put
5
+ list = Table.new
6
+ key,value = "test", "valuevalue"
7
+ list.put key,value
8
+ assert list.get(key) == value
9
+ end
10
+ def test_table_size
11
+ list = Table.new
12
+ assert list.size == 0
13
+ key,value = "test", "valuevalue"
14
+ list.put key,value
15
+ assert list.size == 1
16
+ end
17
+ def test_table_exists
18
+ list = Table.new
19
+ key,value = "test", "valuevalue"
20
+ list.put key,value
21
+ assert list.exists? key
22
+ end
23
+ def test_table_each
24
+ list = Table.new
25
+ data = { "a"=> "aa","b"=>"bv", "c"=> "cc", "d"=> "dd" }
26
+ data.each{|k,v| list.put k,v }
27
+ data.each{|k,v| assert list.get(k) == v }
28
+ list.each{|k,v| assert data[k] == v }
29
+ end
30
+ def test_save_table_data
31
+ list = Table.new
32
+ key,value = "test", "valuevalue"
33
+ list.put key,value
34
+ assert list.saved?(key) == false
35
+ list.update_saved_at(key)
36
+ assert list.saved?(key) == true
37
+ end
38
+ def test_table_each_unsaved_pair
39
+ list = Table.new
40
+ data = { "a"=> "aa","b"=>"bb", "c"=> "cc", "d"=> "dd" }
41
+ data.each{|k,v| list.put k,v }
42
+ list.put( "abc","123")
43
+ list.update_saved_at("abc")
44
+ assert list.saved?("abc")
45
+ a={}
46
+ list.each_unsaved_pair{|k,v| a[k]=v }
47
+ assert a.sort == data.sort
48
+ end
49
+
50
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ Thread.abort_on_exception=true
3
+
4
+ class TestTableSaverWorker < Test::Unit::TestCase
5
+ def test_table_saver_initialize
6
+ s = JobServer.new("localhost","10001")
7
+ saver = TableAutoSaver.new
8
+ saver.interval = 12
9
+ assert saver.interval == 12
10
+ end
11
+ def test_table_saver_save_dir
12
+ s = JobServer.new("localhost","10002")
13
+ saver = TableAutoSaver.new("localhost","10002")
14
+ begin
15
+ saver.save_dir = Dir.tmpdir + "a"
16
+ rescue => e
17
+ assert e.to_s =~ %r"is not direcotry."
18
+ end
19
+ d = Dir.mktmpdir("table_saver_")
20
+ saver.save_dir = d
21
+ assert saver.save_dir == d
22
+ Dir.rmdir d
23
+ assert FileTest.exists? d == false
24
+ end
25
+ def test_table_saver_save_dir
26
+ s = JobServer.new("localhost","10003")
27
+ saver = TableAutoSaver.new("localhost","10003")
28
+ t1 = saver.init_thread
29
+ t2 = Thread.new{
30
+ s.hash_table.put("aaaa",1234)
31
+ s.hash_table.put("baaa",1234)
32
+ s.hash_table.put("caaa",1234)
33
+ s.hash_table.put("daaa",1234)
34
+ s.hash_table.put("eaaa",1234)
35
+ while(s.hash_table.has_unsaved_key? )
36
+ sleep 0.001
37
+ end
38
+ }
39
+
40
+ t2.join
41
+
42
+ assert s.hash_table.has_unsaved_key? == false
43
+
44
+ end
45
+
46
+ end
data/test/test_task.rb ADDED
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestPageList < Test::Unit::TestCase
4
+ def test_task_name
5
+ t = Task.new
6
+ assert t.name == t.object_id
7
+ t.name = "No.001"
8
+ assert t.name == "No.001"
9
+ end
10
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: noda
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - takuya
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-18 00:00:00 +09:00
18
+ date: 2011-05-28 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -80,8 +80,9 @@ dependencies:
80
80
  version_requirements: *id004
81
81
  description: "noda is job queue system using druby "
82
82
  email: takuya.1st@gmail
83
- executables: []
84
-
83
+ executables:
84
+ - noda_job_worker
85
+ - noda_job_server
85
86
  extensions: []
86
87
 
87
88
  extra_rdoc_files:
@@ -95,9 +96,26 @@ files:
95
96
  - README.rdoc
96
97
  - Rakefile
97
98
  - VERSION
99
+ - bin/noda_job_server
100
+ - bin/noda_job_worker
98
101
  - lib/noda.rb
102
+ - lib/noda/job_monitor.rb
103
+ - lib/noda/job_server.rb
104
+ - lib/noda/job_worker.rb
105
+ - lib/noda/rqueue.rb
106
+ - lib/noda/table.rb
107
+ - lib/noda/table_auto_saver.rb
108
+ - lib/noda/task.rb
99
109
  - noda.gemspec
110
+ - test/test_helper.rb
111
+ - test/test_job_monitor.rb
112
+ - test/test_job_server.rb
113
+ - test/test_job_worker.rb
100
114
  - test/test_noda.rb
115
+ - test/test_rqueue.rb
116
+ - test/test_table.rb
117
+ - test/test_table_saver_woker.rb
118
+ - test/test_task.rb
101
119
  has_rdoc: true
102
120
  homepage: http://github.com/takuya/noda
103
121
  licenses: