noda 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,8 +1,14 @@
1
1
  = noda
2
2
 
3
- Noda �̓V���v���ȃW���u�L���[�T�[�o�[�ł�.
3
+ Noda is simple Job Queue server
4
+
5
+ Noda はシンプルなジョブキューサーバーです.
6
+
7
+
8
+ drubyを使用して,マルチスレッドを分散サーバで実現しています.
9
+
10
+ Noda uses druby that make easy to multi threading via network.
4
11
 
5
- druby���g�p���āC�}���`�X���b�h�𕪎U�T�[�o�Ŏ������Ă��܂��D
6
12
 
7
13
  == Contributing to noda
8
14
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.13
1
+ 0.0.14
@@ -1,8 +1,13 @@
1
1
 
2
2
  module Noda
3
- #=�T�v
4
- # �W���u��Ԃ��Ď�����WEB�T�[�o�[�ł��B
5
- # DRB�ɐڑ����āC�L���[�c���C���L�n�b�V���e�[�u���A�L���[�̒��g�����邱�Ƃ��o���܂��D
3
+ #=概要
4
+ # ジョブ状態を監視するWEBサーバーです。
5
+ # DRBに接続して,キュー残数,共有ハッシュテーブル、キューの中身を見ることが出来ます.
6
+ # == 使い方
7
+ # m=Noda::JobMonitor.new("#{ip}","10080","druby://#{ip}:10001")
8
+ # m.start_monitor
9
+ # ==コマンドで起動
10
+ # $ noda_job_server start
6
11
 
7
12
  class JobMonitor
8
13
  require 'webrick'
@@ -21,12 +26,13 @@ class JobMonitor
21
26
  def stop_monitor
22
27
  @web_server.stop
23
28
  end
29
+ # 内部で使うWEBRickをインスタンス化してマウントします.
24
30
  def init_webrick
25
31
  config = WEBrick::Config::HTTP
26
32
  config[:Port] = @port
27
33
  config[:BindAddress]=@addr
28
- config[:AccessLog] = WEBrick::Log.new("/dev/null",1) #���O�v��Ȃ��D
29
- config[:Logger] = Logger.new("/dev/null") #���O�v��Ȃ��D
34
+ config[:AccessLog] = WEBrick::Log.new("/dev/null",1) #ログ要らない.
35
+ config[:Logger] = Logger.new("/dev/null") #ログ要らない.
30
36
  @web_server = WEBrick::HTTPServer.new(config)
31
37
  @web_server.mount_proc '/' do |req,res|
32
38
  res.content_type="text/plain"
@@ -1,5 +1,34 @@
1
1
  module Noda
2
2
 
3
+ # ==�W���u�T�[�o��\���N���X.
4
+ # ===�W���u�T�[�o�[
5
+ # +�W���u�T�[�o�[
6
+ # ++�|�[�g+�A�h���X
7
+ # ++�C���v�b�g�E�L���[
8
+ # ++�A�E�g�v�b�g�E�L���[
9
+ # ++�n�b�V���e�[�u��
10
+ # �ō\�������
11
+ # == �W���u�T�[�o�[�̋N��
12
+ # noda_job_server start
13
+ # == �W���u�T�[�o�[�Ƀ^�X�N��o�^
14
+ # require 'drb'
15
+ # sever = DRbObject.new_with_uri('druby://localhost:10001')
16
+ # # �^�X�N�N���X��`���T�[�o�[�ɕۑ����ċ��L����
17
+ # str = %Q'
18
+ # class Noda::MyTask
19
+ # def do_task(table)
20
+ # table.put @name, "#{Process.pid} : #{Time.now}"
21
+ # return "#{@name} in #{Process.pid} : #{Time.now}"
22
+ # end
23
+ # def initialize(name) @name end
24
+ # end
25
+ # '
26
+ # eval(str)
27
+ # server.add_task_class( task.class.to_s, str)
28
+ # # �o�^
29
+ # task = Noda::MyTask.new("test")
30
+ # server.input.push task
31
+ #
3
32
  class JobServer
4
33
  include DRb::DRbUndumped
5
34
  attr_reader :thread, :server
@@ -18,28 +47,40 @@ class JobServer
18
47
  def alive?
19
48
  @server.alive?
20
49
  end
50
+ # input queue.
51
+ # +return Noda::RQueue
21
52
  def input
22
53
  #�T�[�o�[�͕K���C���v�b�g�L���[��Ԃ�
23
54
  @q_in
24
55
  end
56
+ # output . Noda::RQueue
57
+ # +return Noda::RQueue
25
58
  def output
26
59
  @q_out
27
60
  end
61
+ # �^�X�N�Ԃŋ��L����n�b�V���e�[�u�� Noda::Table
62
+ # +return Noda::Table
28
63
  def hash_table
29
64
  @hash_table
30
65
  end
31
66
  def start_service
32
67
  @thread.join
33
68
  end
69
+ # �W���u�̃��K�[���w�肷��D
34
70
  def logger
35
71
  @logger
36
72
  end
73
+ # �^�X�N�̃N���X��`�B���[�J�[�ɃN���X��`�𑗐M����B
74
+ #
75
+ #
37
76
  def add_task_class(class_name, source_code)
38
77
  @task_class_source_list[class_name] = source_code
39
78
  end
79
+ # �^�X�N�̃N���X��`�����o���D
40
80
  def task_class(class_name)
41
81
  @task_class_source_list[class_name]
42
82
  end
83
+ # �o�^�����N���X��`�ꗗ�����o���D
43
84
  def task_class_source_list
44
85
  @task_class_source_list
45
86
  end
data/lib/noda/rqueue.rb CHANGED
@@ -2,13 +2,20 @@
2
2
 
3
3
  module Noda
4
4
  require 'monitor'
5
- # �W���u�̃L���[����
6
- # �L���[�̓X���b�h�Z�[�t�ɏ����Ă���
7
- #
5
+ # ジョブのキュー実装
6
+ # キューはスレッドセーフに書いている
7
+ #
8
+ # キューから値を取り出すと、キューには残らない。
9
+ # ==使用法
10
+ # require 'noda'
11
+ # server =Noda::JobServer.new
12
+ # q = server.input #<= Jobサーバーが持ってる
13
+ # q.push Noda::MyTask.new("hogehgoe")
8
14
  #
9
15
  class RQueue
10
16
  include DRb::DRbUndumped
11
17
  attr_reader :name
18
+ #
12
19
  def initialize( max=nil, name=nil )
13
20
  @name = name
14
21
  @list = []
@@ -18,6 +25,9 @@ class RQueue
18
25
  @m_empty = self.new_cond
19
26
  @m_full = self.new_cond
20
27
  end
28
+ # キュー末尾にオブジェクトを追加。
29
+ #
30
+ # キュー満杯時は実行スレッドをWaitさせます。
21
31
  def push obj
22
32
  self.synchronize{
23
33
  @m_full.wait_while{ self.full? } if @max
@@ -25,6 +35,9 @@ class RQueue
25
35
  @m_empty.broadcast
26
36
  }
27
37
  end
38
+ # キュー先頭からオブジェクトを取り出す.
39
+ #
40
+ # キュー空なら実行スレッドをWaitさせる.
28
41
  def pop
29
42
  self.synchronize{
30
43
  @m_empty.wait_while{ self.empty? }
@@ -33,20 +46,30 @@ class RQueue
33
46
  obj
34
47
  }
35
48
  end
49
+ # 実験用メソッド・使わない.
36
50
  def include?(v) @list.include? v end
37
51
  alias exists? include?
52
+ # キューの先頭N個を取り出す.
38
53
  def firsts(n=1) (0...n).map{self.pop} end
54
+ # キューの先頭1個を取り出す. pop の別名
39
55
  def first() self.pop end
56
+ # キューのサイズを取得
40
57
  def size() @list.size end
58
+ # キュー格納可能数
41
59
  def max_size() @max end
60
+ # キューに値があるか
42
61
  def empty?() @list.empty? end
62
+ # キュー満杯が近いときにTrueを返す.
43
63
  def close_to_full?() @list.size >= @max-5 end
64
+ # キューが満杯かどうか
44
65
  def full?()
45
- # max=nil �Ȃ�Limitless�B�‚܂薳����
66
+ # max=nil ならLimitless。つまり無限大
46
67
  @list.size >= @max if @max
47
68
  end
69
+ # キューの値全てを取り出す.
48
70
  def all() self.firsts(self.size) end
49
- # �P����m�܂ł̒l�����B�O�n�܂�łȂ����Ƃɒ���
71
+ # キューの先頭N番目の値を調べる.チェック用。
72
+ # - pos 1からNまでの値を取る。先頭は1 で指定する.0始まりでないことに注意
50
73
  def _at(pos)
51
74
  i = pos - 1
52
75
  return @list.at(i) if (i) < self.size
data/lib/noda/table.rb CHANGED
@@ -1,10 +1,21 @@
1
1
  #
2
2
  module Noda
3
- #スレッドセーフなHASHテーブルを作ってる
4
- #内部的にはHashにしている
5
- #KVSとして使っている
6
- #TODO::HASHとして動くようにEnumerableを実装したい
7
- #TODO::DBやファイルに保存する。このクラスAPIでアクセス出来るアダプタを作りたい
3
+ # スレッドセーフなHASHテーブルを作ってる
4
+ #
5
+ # ジョブの共有ストレージ.
6
+ # 内部的にはHashにしている
7
+ #
8
+ # KVSとして使う事を想定
9
+ #
10
+ # require 'noda'
11
+ # server =Noda::JobServer.new
12
+ # table = server.hash_table #<= 自分でインスタンス化しない.Jobサーバーから使う
13
+ # table.put "key, "value"
14
+ # タスクから使う場合。
15
+ # do_task(hash_table)
16
+ # v = hash_table.get "key"
17
+ # hash_table.put "key", "value2" # =>更新
18
+ # end
8
19
  class Table
9
20
  include DRb::DRbUndumped
10
21
  include Enumerable
@@ -16,34 +27,60 @@ class Table
16
27
  @m_lock = self.new_cond
17
28
  @saved_keys = []
18
29
  end
30
+ # キー対応した値を取り出す
19
31
  def get(key)
20
32
  @hash[key][:data]
21
33
  end
34
+ # キーを名前に値を保存する.
22
35
  def put(key, obj)
23
36
  self.synchronize{
24
37
  @hash[key] = {:data=>obj,:saved=>false}
25
38
  }
26
39
  end
40
+ # キーがテーブルに存在するか
27
41
  def has_key?(key) @hash.has_key? key end
42
+ # alias to has_key
28
43
  alias :exists? :has_key?
44
+ # キーを全部取得
29
45
  def keys() @hash.keys end
46
+ # テーブルの値の数
30
47
  def size() @hash.size end
48
+ # Enumerable 用。
49
+ #
50
+ # drb 経由で呼び出す時は、参照渡しになるので注意
31
51
  def each
32
52
  @hash.each_pair{|k,v| yield( k,v[:data] ) }
33
53
  nil
34
54
  end
55
+
56
+ # テーブルの値はDump済みかどうか
57
+ #
58
+ # 永続ストレージに書き出すときに
59
+ # このフラグを使って処理をする
35
60
  def saved?(key)
36
61
  @hash[key][:saved]
37
62
  end
63
+ # テーブルの値の保存状態を更新する.
64
+ #
65
+ # 永続ストレージに書き出すときに
66
+ # このフラグを使って処理をする
38
67
  def update_saved_at(key,status=true)
39
68
  self.synchronize{
40
69
  @hash[key][:saved]=status
41
70
  }
42
71
  end
72
+ # テーブルの未保存の値をすべて取り出す.」
73
+ #
74
+ # 永続ストレージに書き出すときに
75
+ # このメソッドを使って処理が出来る
43
76
  def each_unsaved_pair
44
77
  @hash.each_pair{|k,v| next if v[:saved]; yield( k, v[:data] ) }
45
78
  nil
46
79
  end
80
+ # 未保存の値があるか
81
+ #
82
+ # 永続ストレージに書き出すときに
83
+ # このフラグを使って処理をする
47
84
  def has_unsaved_key?
48
85
  return true if @hash.find{|k,v| v[:saved]==false}
49
86
  return false
@@ -1,4 +1,24 @@
1
1
  module Noda
2
+ # ==�W���u�e�[�u���̎����ۑ�
3
+ # �W���u���[�J�[�̃e�X�g����.
4
+ # �^�X�N�����s�������[�J�[
5
+ # �W���u�T�[�o�[�̃e�[�u���ɂ��܂����f�[�^���t�@�C���Ƀ_���v���Ă����܂��D
6
+ # s = JobServer.new("localhost","10013")
7
+ # saver = TableAutoSaver.new("localhost","10013")
8
+ # t1 = saver.init_thread
9
+ # t2 = Thread.new{
10
+ # s.hash_table.put("aaaa",1234)# =>�ۑ������
11
+ # s.hash_table.put("baaa",1234)# =>�ۑ������
12
+ # s.hash_table.put("caaa",1234)# =>�ۑ������
13
+ # s.hash_table.put("daaa",1234)# =>�ۑ������
14
+ # s.hash_table.put("eaaa",1234)# =>�ۑ������
15
+ # while(s.hash_table.has_unsaved_key? )
16
+ # sleep 0.001
17
+ # end
18
+ # }
19
+ #
20
+ # t2.join
21
+
2
22
 
3
23
  class TableAutoSaver < JobWorker
4
24
  attr_reader :thread
data/lib/noda/task.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  module Noda
2
+ #ジョブに登録するタスクのサンプル
3
+ #こんな感じでクラスを作って下さい
2
4
 
3
- class Task
5
+ # タスククラス名は必ずNoda名前空間の下につけます
6
+ class Noda::Task
4
7
  #this should be overwrite
5
8
  def do_task(hash_table)
6
9
  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: 5
4
+ hash: 3
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 13
10
- version: 0.0.13
9
+ - 14
10
+ version: 0.0.14
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-06-03 00:00:00 +09:00
18
+ date: 2011-06-04 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -106,7 +106,6 @@ files:
106
106
  - lib/noda/table.rb
107
107
  - lib/noda/table_auto_saver.rb
108
108
  - lib/noda/task.rb
109
- - noda.gemspec
110
109
  - test/test_helper.rb
111
110
  - test/test_job_monitor.rb
112
111
  - test/test_job_server.rb
data/noda.gemspec DELETED
@@ -1,76 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{noda}
8
- s.version = "0.0.13"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["takuya"]
12
- s.date = %q{2011-06-03}
13
- s.description = %q{noda is job queue system using druby }
14
- s.email = %q{takuya.1st@gmail}
15
- s.executables = ["noda_job_worker", "noda_job_server"]
16
- s.extra_rdoc_files = [
17
- "LICENSE.txt",
18
- "README.rdoc"
19
- ]
20
- s.files = [
21
- ".document",
22
- "Gemfile",
23
- "Gemfile.lock",
24
- "LICENSE.txt",
25
- "README.rdoc",
26
- "Rakefile",
27
- "VERSION",
28
- "bin/noda_job_server",
29
- "bin/noda_job_worker",
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",
38
- "noda.gemspec",
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"
48
- ]
49
- s.homepage = %q{http://github.com/takuya/noda}
50
- s.licenses = ["MIT"]
51
- s.require_paths = ["lib"]
52
- s.rubygems_version = %q{1.5.0}
53
- s.summary = %q{noda is job queue system}
54
-
55
- if s.respond_to? :specification_version then
56
- s.specification_version = 3
57
-
58
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
59
- s.add_development_dependency(%q<shoulda>, [">= 0"])
60
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
61
- s.add_development_dependency(%q<jeweler>, ["~> 1.6.0"])
62
- s.add_development_dependency(%q<rcov>, [">= 0"])
63
- else
64
- s.add_dependency(%q<shoulda>, [">= 0"])
65
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
66
- s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
67
- s.add_dependency(%q<rcov>, [">= 0"])
68
- end
69
- else
70
- s.add_dependency(%q<shoulda>, [">= 0"])
71
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
72
- s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
73
- s.add_dependency(%q<rcov>, [">= 0"])
74
- end
75
- end
76
-