wakame 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/History.txt +20 -0
  2. data/README.rdoc +63 -0
  3. data/Rakefile +86 -0
  4. data/VERSION +1 -0
  5. data/app_generators/wakame/templates/README +0 -0
  6. data/app_generators/wakame/templates/Rakefile +18 -0
  7. data/app_generators/wakame/templates/bin/wakame-agent +9 -0
  8. data/app_generators/wakame/templates/bin/wakame-master +9 -0
  9. data/app_generators/wakame/templates/bin/wakameadm +9 -0
  10. data/app_generators/wakame/templates/cluster/resources/apache_app/apache_app.rb +54 -0
  11. data/app_generators/wakame/templates/cluster/resources/apache_app/conf/apache2.conf +46 -0
  12. data/app_generators/wakame/templates/cluster/resources/apache_app/conf/envvars-app +7 -0
  13. data/app_generators/wakame/templates/cluster/resources/apache_app/conf/sites-app.conf +23 -0
  14. data/app_generators/wakame/templates/cluster/resources/apache_app/conf/system-app.conf +67 -0
  15. data/app_generators/wakame/templates/cluster/resources/apache_app/init.d/apache2-app +192 -0
  16. data/app_generators/wakame/templates/cluster/resources/apache_lb/apache_lb.rb +56 -0
  17. data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/apache2.conf +46 -0
  18. data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/envvars-lb +6 -0
  19. data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/sites-lb.conf +54 -0
  20. data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/system-lb.conf +75 -0
  21. data/app_generators/wakame/templates/cluster/resources/apache_lb/init.d/apache2-lb +192 -0
  22. data/app_generators/wakame/templates/cluster/resources/apache_www/apache_www.rb +50 -0
  23. data/app_generators/wakame/templates/cluster/resources/apache_www/conf/apache2.conf +47 -0
  24. data/app_generators/wakame/templates/cluster/resources/apache_www/conf/envvars-www +7 -0
  25. data/app_generators/wakame/templates/cluster/resources/apache_www/conf/sites-www.conf +23 -0
  26. data/app_generators/wakame/templates/cluster/resources/apache_www/conf/system-www.conf +63 -0
  27. data/app_generators/wakame/templates/cluster/resources/apache_www/init.d/apache2-www +192 -0
  28. data/app_generators/wakame/templates/cluster/resources/ec2_elastic_ip/ec2_elastic_ip.rb +39 -0
  29. data/app_generators/wakame/templates/cluster/resources/mysql_master/conf/my.cnf +154 -0
  30. data/app_generators/wakame/templates/cluster/resources/mysql_master/init.d/mysql +185 -0
  31. data/app_generators/wakame/templates/cluster/resources/mysql_master/mysql_master.rb +174 -0
  32. data/app_generators/wakame/templates/config/boot.rb +85 -0
  33. data/app_generators/wakame/templates/config/cluster.rb +64 -0
  34. data/app_generators/wakame/templates/config/environments/common.rb +0 -0
  35. data/app_generators/wakame/templates/config/environments/ec2.rb +3 -0
  36. data/app_generators/wakame/templates/config/environments/stand_alone.rb +0 -0
  37. data/app_generators/wakame/templates/config/init.d/wakame-agent +72 -0
  38. data/app_generators/wakame/templates/config/init.d/wakame-master +73 -0
  39. data/app_generators/wakame/wakame_generator.rb +124 -0
  40. data/bin/wakame +18 -0
  41. data/contrib/imagesetup.sh +77 -0
  42. data/lib/ext/eventmachine.rb +86 -0
  43. data/lib/ext/shellwords.rb +172 -0
  44. data/lib/ext/uri.rb +15 -0
  45. data/lib/wakame/action.rb +156 -0
  46. data/lib/wakame/actions/destroy_instances.rb +39 -0
  47. data/lib/wakame/actions/launch_cluster.rb +31 -0
  48. data/lib/wakame/actions/migrate_service.rb +65 -0
  49. data/lib/wakame/actions/propagate_instances.rb +95 -0
  50. data/lib/wakame/actions/reload_service.rb +21 -0
  51. data/lib/wakame/actions/scaleout_when_high_load.rb +44 -0
  52. data/lib/wakame/actions/shutdown_cluster.rb +22 -0
  53. data/lib/wakame/actions/shutdown_vm.rb +19 -0
  54. data/lib/wakame/actions/start_service.rb +64 -0
  55. data/lib/wakame/actions/stop_service.rb +49 -0
  56. data/lib/wakame/actions/util.rb +71 -0
  57. data/lib/wakame/actor/daemon.rb +37 -0
  58. data/lib/wakame/actor/service_monitor.rb +21 -0
  59. data/lib/wakame/actor/system.rb +46 -0
  60. data/lib/wakame/actor.rb +33 -0
  61. data/lib/wakame/agent.rb +226 -0
  62. data/lib/wakame/amqp_client.rb +219 -0
  63. data/lib/wakame/command/action_status.rb +62 -0
  64. data/lib/wakame/command/actor.rb +23 -0
  65. data/lib/wakame/command/clone_service.rb +12 -0
  66. data/lib/wakame/command/launch_cluster.rb +15 -0
  67. data/lib/wakame/command/migrate_service.rb +21 -0
  68. data/lib/wakame/command/propagate_service.rb +24 -0
  69. data/lib/wakame/command/shutdown_cluster.rb +15 -0
  70. data/lib/wakame/command/status.rb +81 -0
  71. data/lib/wakame/command.rb +31 -0
  72. data/lib/wakame/command_queue.rb +44 -0
  73. data/lib/wakame/configuration.rb +93 -0
  74. data/lib/wakame/daemonize.rb +96 -0
  75. data/lib/wakame/event.rb +232 -0
  76. data/lib/wakame/event_dispatcher.rb +154 -0
  77. data/lib/wakame/graph.rb +79 -0
  78. data/lib/wakame/initializer.rb +162 -0
  79. data/lib/wakame/instance_counter.rb +78 -0
  80. data/lib/wakame/logger.rb +12 -0
  81. data/lib/wakame/manager/commands.rb +134 -0
  82. data/lib/wakame/master.rb +369 -0
  83. data/lib/wakame/monitor/agent.rb +50 -0
  84. data/lib/wakame/monitor/service.rb +183 -0
  85. data/lib/wakame/monitor.rb +69 -0
  86. data/lib/wakame/packets.rb +160 -0
  87. data/lib/wakame/queue_declare.rb +14 -0
  88. data/lib/wakame/rule.rb +116 -0
  89. data/lib/wakame/rule_engine.rb +202 -0
  90. data/lib/wakame/runner/administrator_command.rb +112 -0
  91. data/lib/wakame/runner/agent.rb +81 -0
  92. data/lib/wakame/runner/master.rb +93 -0
  93. data/lib/wakame/scheduler.rb +251 -0
  94. data/lib/wakame/service.rb +914 -0
  95. data/lib/wakame/template.rb +189 -0
  96. data/lib/wakame/trigger.rb +66 -0
  97. data/lib/wakame/triggers/instance_count_update.rb +45 -0
  98. data/lib/wakame/triggers/load_history.rb +107 -0
  99. data/lib/wakame/triggers/maintain_ssh_known_hosts.rb +43 -0
  100. data/lib/wakame/triggers/process_command.rb +34 -0
  101. data/lib/wakame/triggers/shutdown_unused_vm.rb +16 -0
  102. data/lib/wakame/util.rb +569 -0
  103. data/lib/wakame/vm_manipulator.rb +186 -0
  104. data/lib/wakame.rb +59 -0
  105. data/tasks/ec2.rake +127 -0
  106. data/tests/cluster.json +3 -0
  107. data/tests/conf/a +1 -0
  108. data/tests/conf/b +1 -0
  109. data/tests/conf/c +1 -0
  110. data/tests/setup_agent.rb +39 -0
  111. data/tests/setup_master.rb +28 -0
  112. data/tests/test_actor.rb +54 -0
  113. data/tests/test_agent.rb +218 -0
  114. data/tests/test_amqp_client.rb +94 -0
  115. data/tests/test_graph.rb +36 -0
  116. data/tests/test_master.rb +167 -0
  117. data/tests/test_monitor.rb +47 -0
  118. data/tests/test_rule_engine.rb +127 -0
  119. data/tests/test_scheduler.rb +123 -0
  120. data/tests/test_service.rb +60 -0
  121. data/tests/test_template.rb +67 -0
  122. data/tests/test_uri_amqp.rb +19 -0
  123. data/tests/test_util.rb +71 -0
  124. data/wakame_generators/resource/resource_generator.rb +54 -0
  125. data/wakame_generators/resource/templates/apache_app/apache_app.rb +60 -0
  126. data/wakame_generators/resource/templates/apache_app/conf/apache2.conf +46 -0
  127. data/wakame_generators/resource/templates/apache_app/conf/envvars-app +7 -0
  128. data/wakame_generators/resource/templates/apache_app/conf/sites-app.conf +23 -0
  129. data/wakame_generators/resource/templates/apache_app/conf/system-app.conf +67 -0
  130. data/wakame_generators/resource/templates/apache_app/init.d/apache2-app +192 -0
  131. data/wakame_generators/resource/templates/apache_lb/apache_lb.rb +67 -0
  132. data/wakame_generators/resource/templates/apache_lb/conf/apache2.conf +46 -0
  133. data/wakame_generators/resource/templates/apache_lb/conf/envvars-lb +6 -0
  134. data/wakame_generators/resource/templates/apache_lb/conf/sites-lb.conf +54 -0
  135. data/wakame_generators/resource/templates/apache_lb/conf/system-lb.conf +75 -0
  136. data/wakame_generators/resource/templates/apache_lb/init.d/apache2-lb +192 -0
  137. data/wakame_generators/resource/templates/apache_www/apache_www.rb +56 -0
  138. data/wakame_generators/resource/templates/apache_www/conf/apache2.conf +47 -0
  139. data/wakame_generators/resource/templates/apache_www/conf/envvars-www +7 -0
  140. data/wakame_generators/resource/templates/apache_www/conf/sites-www.conf +23 -0
  141. data/wakame_generators/resource/templates/apache_www/conf/system-www.conf +63 -0
  142. data/wakame_generators/resource/templates/apache_www/init.d/apache2-www +192 -0
  143. data/wakame_generators/resource/templates/ec2_elastic_ip/ec2_elastic_ip.rb +39 -0
  144. data/wakame_generators/resource/templates/mysql_master/conf/my.cnf +154 -0
  145. data/wakame_generators/resource/templates/mysql_master/init.d/mysql +185 -0
  146. data/wakame_generators/resource/templates/mysql_master/mysql_master.rb +119 -0
  147. metadata +289 -0
@@ -0,0 +1,31 @@
1
+
2
+ module Wakame
3
+ module Command
4
+ class CommandArgumentError < StandardError; end
5
+
6
+ def self.included(klass)
7
+ klass.class_eval {
8
+ class << self
9
+ def command_name
10
+ @command_name ||= Util.snake_case(self.to_s.split('::').last)
11
+ end
12
+
13
+ def command_name=(name)
14
+ @command_name=name
15
+ end
16
+ end
17
+ }
18
+ end
19
+
20
+
21
+ def parse(args)
22
+ end
23
+
24
+ def run(rule)
25
+ end
26
+
27
+ def print_result
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,44 @@
1
+
2
+ require 'drb/drb'
3
+ require 'thread'
4
+
5
+ module Wakame
6
+ class CommandQueue
7
+ attr_reader :master
8
+
9
+ def initialize(master)
10
+ @master = master
11
+ @queue = Queue.new
12
+ @result_queue = Queue.new
13
+
14
+ DRb.start_service(Wakame.config.drb_command_server_uri, self)
15
+ #@drb_server = DRb.start_drbserver(Wakame.config.drb_command_server_uri, self)
16
+ end
17
+
18
+ def shutdown
19
+ DRb.stop_service()
20
+ #@drb_server.stop_service()
21
+ end
22
+
23
+ def deq_cmd()
24
+ @queue.deq
25
+ end
26
+
27
+ def enq_result(res)
28
+ @result_queue.enq(res)
29
+ end
30
+
31
+ def send_cmd(cmd)
32
+ begin
33
+ #cmd = Marshal.load(cmd)
34
+ @queue.enq(cmd)
35
+ ED.fire_event(Event::CommandReceived.new(cmd))
36
+ return @result_queue.deq()
37
+ rescue => e
38
+ Wakame.log.error("#{self.class}:")
39
+ Wakame.log.error(e)
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,93 @@
1
+
2
+
3
+ require 'ostruct'
4
+
5
+ module Wakame
6
+ # System wide configuration parameters
7
+ class Configuration < OpenStruct
8
+
9
+ PARAMS = {
10
+ #:config_template_root => nil,
11
+ #:config_tmp_root => nil,
12
+ :config_root => nil,
13
+ :cluster_class => 'WebCluster',
14
+ :load_paths => [],
15
+ :ssh_private_key => nil,
16
+ :drb_command_server_uri => 'druby://localhost:12345',
17
+ :amqp_server_uri => nil,
18
+ :unused_vm_live_period => 60 * 10,
19
+ :eventmachine_use_epoll => true
20
+ }
21
+
22
+ def initialize(env=WAKAME_ENV)
23
+ super(PARAMS)
24
+ if root_path.nil?
25
+ root_path = Object.const_defined?(:WAKAME_ROOT) ? WAKAME_ROOT : '../'
26
+ end
27
+
28
+ @root_path = root_path
29
+
30
+ self.class.const_get(env).new.process(self)
31
+ end
32
+
33
+ def environment
34
+ ::WAKAME_ENV.to_sym
35
+ end
36
+ alias :vm_environment :environment
37
+
38
+ def environment_path(key=environment)
39
+ File.expand_path("config/environments/#{Util.snake_case(key.to_s)}.rb", root_path)
40
+ end
41
+
42
+ def root_path
43
+ ::WAKAME_ROOT
44
+ end
45
+
46
+ def tmp_path
47
+ File.join(root_path, 'tmp')
48
+ end
49
+
50
+ def ssh_known_hosts
51
+ File.join(self.config_root, "ssh", "known_hosts")
52
+ end
53
+
54
+ def config_tmp_root
55
+ File.join(self.config_root, "tmp")
56
+ end
57
+
58
+ def framework_root_path
59
+ defined?(::WAKAME_FRAMEWORK_ROOT) ? ::WAKAME_FRAMEWORK_ROOT : "#{root_path}/vendor/wakame"
60
+ end
61
+
62
+ def framework_paths
63
+ paths = %w(lib)
64
+
65
+ paths.map{|dir| File.join(framework_root_path, dir) }.select{|path| File.directory?(path) }
66
+ end
67
+ #
68
+ class DefaultSet
69
+ def process(config)
70
+ end
71
+ end
72
+
73
+ class EC2 < DefaultSet
74
+ def process(config)
75
+ super(config)
76
+ config.config_root = File.join(config.root_path, 'tmp', 'config')
77
+
78
+ config.ssh_private_key = '/home/wakame/config/root.id_rsa'
79
+
80
+ end
81
+ end
82
+
83
+ class StandAlone < DefaultSet
84
+ def process(config)
85
+ super(config)
86
+ config.config_root = File.join(config.root_path, 'tmp', 'config')
87
+ config.amqp_server_uri = 'amqp://localhost/'
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,96 @@
1
+
2
+
3
+ require 'daemons/daemonize'
4
+ require 'fileutils'
5
+
6
+ module Process
7
+ # Returns +true+ the process identied by +pid+ is running.
8
+ def running?(pid)
9
+ Process.getpgid(pid) != -1
10
+ rescue Errno::ESRCH
11
+ false
12
+ end
13
+ module_function :running?
14
+ end
15
+
16
+
17
+ module Wakame
18
+ module Daemonize
19
+ # Change privileges of the process
20
+ # to the specified user and group.
21
+ def change_privilege(user, group=user)
22
+ Wakame.log.info("Changing process privilege to #{user}:#{group}")
23
+
24
+ uid, gid = Process.euid, Process.egid
25
+ target_uid = Etc.getpwnam(user).uid
26
+ target_gid = Etc.getgrnam(group).gid
27
+
28
+ if uid != target_uid || gid != target_gid
29
+ if pid_file && File.exist?(pid_file) && uid == 0
30
+ File.chown(target_uid, target_gid, pid_file)
31
+ end
32
+
33
+ # Change process ownership
34
+ Process.initgroups(user, target_gid)
35
+ Process::GID.change_privilege(target_gid)
36
+ Process::UID.change_privilege(target_uid)
37
+ end
38
+ rescue Errno::EPERM => e
39
+ Wakame.log.error("Couldn't change user and group to #{user}:#{group}: #{e}")
40
+ end
41
+
42
+ def pid_file
43
+ @options[:pid_file]
44
+ end
45
+
46
+ def pid
47
+ File.exist?(pid_file) ? open(pid_file).read.to_i : nil
48
+ end
49
+
50
+ def setup_pidfile
51
+ #raise 'Please implement pid_file() method' unless respond_to? :pid_file
52
+
53
+ unless File.exist?(File.dirname(pid_file))
54
+ FileUtils.mkpath(File.dirname(pid_file))
55
+ end
56
+
57
+ open(pid_file, "w") { |f| f.write(Process.pid) }
58
+ File.chmod(0644, pid_file)
59
+ end
60
+
61
+ def daemonize(log_path)
62
+ # Cleanup stale pidfile or prevent from multiple process running.
63
+ if File.exist?(pid_file)
64
+ if pid && Process.running?(pid)
65
+ raise "#{pid_file} already exists, seems like it's already running (process ID: #{pid}). " +
66
+ "Stop the process or delete #{pid_file}."
67
+ else
68
+ Wakame.log.info "Deleting the stale PID file: #{pid_file}"
69
+ remove_pidfile
70
+ end
71
+ end
72
+
73
+ ::Daemonize.daemonize(log_path, File.basename($0.to_s))
74
+
75
+ setup_pidfile
76
+ #Signal.trap('HUP') {}
77
+ end
78
+
79
+ def on_restart(&blk)
80
+ @on_restart = blk
81
+ end
82
+
83
+ def restart
84
+ raise '' if @on_restart.nil?
85
+
86
+ @on_restart.call
87
+ end
88
+
89
+ def remove_pidfile
90
+ File.delete(pid_file) if pid_file && File.exists?(pid_file)
91
+ rescue => e
92
+ Wakame.log.error(e)
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,232 @@
1
+ require 'wakame/util'
2
+
3
+ module Wakame
4
+ module Event
5
+ class Base
6
+ attr_accessor :time
7
+
8
+ def initialize
9
+ @time = Time.now
10
+ end
11
+
12
+ def log_message
13
+ end
14
+ end
15
+
16
+
17
+ class ClusterStatusChanged < Base
18
+ attr_reader :instance_id, :status
19
+ def initialize(instance_id, status)
20
+ super()
21
+ @instance_id = instance_id
22
+ @status = status
23
+ end
24
+
25
+ def log_message
26
+ "#{instance_id}, #{@status}"
27
+ end
28
+
29
+ end
30
+
31
+ class ServiceStatus < Base
32
+ attr_reader :instance_id, :property
33
+ def initialize(instance_id, property)
34
+ super()
35
+ @instance_id = instance_id
36
+ @property = property
37
+ end
38
+ end
39
+
40
+ class ServiceStatusChanged < ServiceStatus
41
+ attr_reader :status, :previous_status
42
+ def initialize(instance_id, property, new_status, prev_status)
43
+ super(instance_id, property)
44
+ @status = new_status
45
+ @previous_status = prev_status
46
+ end
47
+
48
+ def log_message
49
+ "#{instance_id}, #{@previous_status} -> #{@status}"
50
+ end
51
+ end
52
+
53
+ class ServiceOnline < ServiceStatus
54
+ end
55
+ class ServiceOffline < ServiceStatus
56
+ end
57
+ class ServiceFailed < ServiceStatus
58
+ attr_reader :message
59
+ def initialize(instance_id, property, message)
60
+ super(instance_id, property)
61
+ @message = message
62
+ end
63
+ end
64
+
65
+ class AgentEvent < Base
66
+ attr_reader :agent
67
+ def initialize(agent)
68
+ super()
69
+ @agent = agent
70
+ end
71
+ end
72
+
73
+ class AgentPong < AgentEvent
74
+ end
75
+
76
+ class AgentTimedOut < AgentEvent
77
+ end
78
+ class AgentMonitored < AgentEvent
79
+ end
80
+ class AgentUnMonitored < AgentEvent
81
+ end
82
+ class AgentStatusChanged < AgentEvent
83
+ end
84
+
85
+
86
+ class ServiceUnboundAgent < Base
87
+ attr_reader :service, :agent
88
+ def initialize(service, agent)
89
+ super()
90
+ @service = service
91
+ @agent = agent
92
+ end
93
+ end
94
+ class ServiceBoundAgent < Base
95
+ attr_reader :service, :agent
96
+ def initialize(service, agent)
97
+ super()
98
+ @service = service
99
+ @agent = agent
100
+ end
101
+ end
102
+
103
+ class ServiceBoundCluster < Base
104
+ attr_reader :service, :service_cluster
105
+ def initialize(svc_inst, cluster)
106
+ super()
107
+ @service = svc_inst
108
+ @service_cluster = cluster
109
+ end
110
+ end
111
+
112
+ class ServiceUnboundCluster < Base
113
+ attr_reader :service, :service_cluster
114
+ def initialize(svc_inst, cluster)
115
+ super()
116
+ @service = svc_inst
117
+ @service_cluster = cluster
118
+ end
119
+ end
120
+
121
+ class ServiceDestroied < Base
122
+ attr_reader :service
123
+ def initialize(svc_inst)
124
+ super()
125
+ @service = svc_inst
126
+ end
127
+ end
128
+
129
+ class ServicePropagated < Base
130
+ attr_reader :service
131
+ def initialize(svc_inst)
132
+ super()
133
+ @service = svc_inst
134
+ end
135
+ end
136
+
137
+ class CommandReceived < Base
138
+ attr_reader :command
139
+ def initialize(command)
140
+ @command = command
141
+ end
142
+ end
143
+
144
+ class ActionEvent < Base
145
+ attr_reader :action
146
+ def initialize(action)
147
+ super()
148
+ @action = action
149
+ end
150
+
151
+ def log_message
152
+ "#{@action.class}"
153
+ end
154
+
155
+ end
156
+
157
+ class ActionStart < ActionEvent
158
+ end
159
+ class ActionComplete < ActionEvent
160
+ end
161
+ class ActionFailed < ActionEvent
162
+ attr_reader :exception
163
+ def initialize(action, e)
164
+ super(action)
165
+ @exception = e
166
+ end
167
+ end
168
+
169
+ class JobEvent < Base
170
+ attr_reader :job_id
171
+ def initialize(job_id)
172
+ super()
173
+ @action = job_id
174
+ end
175
+
176
+ def log_message
177
+ "#{@action.class}"
178
+ end
179
+ end
180
+ class JobStart < JobEvent
181
+ end
182
+ class JobComplete < JobEvent
183
+ end
184
+ class JobFailed < JobEvent
185
+ attr_reader :exception
186
+ def initialize(job_id, e)
187
+ super(job_id)
188
+ @exception = e
189
+ end
190
+ end
191
+
192
+
193
+ class AgentShutdown < Base; end
194
+ class MasterShutdown < Base; end
195
+
196
+ class InstanceCountChanged < Base
197
+ attr_reader :resource, :prev_count, :count
198
+ def initialize(resource, prev_count, count)
199
+ @resource = resource
200
+ @prev_count = prev_count
201
+ @count = count
202
+ end
203
+
204
+ def increased?
205
+ @prev_count < @count
206
+ end
207
+
208
+ def decreased?
209
+ @prev_count > @count
210
+ end
211
+ end
212
+
213
+ class ActorProgress < Base
214
+ attr_reader :agent_id, :token, :progress
215
+ def initialize(agent_id, token, progress)
216
+ @agent_id = agent_id
217
+ @token = token
218
+ @progress = progress
219
+ end
220
+ end
221
+
222
+ class ActorComplete < Base
223
+ attr_reader :agent_id, :token, :status
224
+ def initialize(agent_id, token, status)
225
+ @agent_id = agent_id
226
+ @token = token
227
+ @status = status
228
+ end
229
+ end
230
+
231
+ end
232
+ end
@@ -0,0 +1,154 @@
1
+
2
+ module Wakame
3
+ class EventDispatcher
4
+ class << self
5
+
6
+ def instance
7
+ if @instance.nil?
8
+ @instance = self.new
9
+ end
10
+ @instance
11
+ end
12
+
13
+ def subscribe(event_class, *args, &blk)
14
+ self.instance.subscribe(event_class, *args, &blk)
15
+ end
16
+
17
+ def unsubscribe(event_class)
18
+ self.instance.unsubscribe(event_class)
19
+ end
20
+
21
+
22
+ def fire_event(event_obj)
23
+ self.instance.fire_event(event_obj)
24
+ end
25
+
26
+ def reset
27
+ @instance = nil
28
+ end
29
+
30
+ end
31
+
32
+ include ThreadImmutable
33
+
34
+ def initialize
35
+ @event_handlers = {}
36
+ @tickets = {}
37
+
38
+ @unsubscribe_queue = []
39
+ end
40
+
41
+ def subscribe(event_class, *args, &blk)
42
+ event_class = case event_class
43
+ when Class
44
+ event_class
45
+ when String
46
+ Util.str2const(event_class)
47
+ else
48
+ raise ArgumentError, "event_class has to be a form of String or Class type"
49
+ end
50
+
51
+ EM.barrier {
52
+ tlist = @event_handlers[event_class]
53
+ if tlist.nil?
54
+ tlist = @event_handlers[event_class] = []
55
+ end
56
+
57
+ tickets = []
58
+ args.each { |o|
59
+ tickets << Util.gen_id
60
+ @tickets.store(tickets.last, [event_class, o])
61
+ tlist << tickets.last
62
+ }
63
+
64
+ if blk
65
+ tickets << Util.gen_id
66
+ @tickets.store(tickets.last, [event_class, blk])
67
+ tlist << tickets.last
68
+ end
69
+
70
+ # Return in array if num of ticket to be returned is more than or equal 2.
71
+ tickets.size > 1 ? tickets : tickets.first
72
+ }
73
+ end
74
+
75
+ def unsubscribe(ticket)
76
+ unless @tickets.has_key?(ticket)
77
+ #Wakame.log.warn("EventHander.unsubscribe(#{ticket}) has been tried but the ticket was not registered.")
78
+ return nil
79
+ end
80
+
81
+ EM.barrier {
82
+ Wakame.log.debug("#{self.class}.unsubscribe(#{ticket})")
83
+
84
+ @unsubscribe_queue << ticket
85
+ ticket
86
+ }
87
+ end
88
+
89
+ def fire_event(event_obj)
90
+ raise ArgumentError unless event_obj.is_a?(Event::Base)
91
+ log_msg = ""
92
+ log_msg = " #{event_obj.log_message}" unless event_obj.log_message.nil?
93
+
94
+ Wakame.log.debug("Event #{event_obj.class} has been fired:" + log_msg )
95
+ tlist = @event_handlers[event_obj.class]
96
+ return if tlist.nil?
97
+
98
+ run_callbacks = proc {
99
+ @unsubscribe_queue.each { |t|
100
+ @tickets.delete(t)
101
+ tlist.delete(t)
102
+ }
103
+
104
+ tlist.each { |t|
105
+ ary = @tickets[t]
106
+ c = ary[1]
107
+ if c.nil?
108
+ next
109
+ end
110
+
111
+ begin
112
+ c.call(event_obj)
113
+ rescue => e
114
+ Wakame.log.error(e)
115
+ #raise e
116
+ end
117
+ }
118
+
119
+ @unsubscribe_queue.each { |t|
120
+ @tickets.delete(t)
121
+ tlist.delete(t)
122
+ }
123
+ }
124
+
125
+ #@handler_run_queue.push(run_handlers)
126
+
127
+ ::EventMachine.barrier {
128
+ begin
129
+ run_callbacks.call
130
+ rescue => e
131
+ Wakame.log.error(e)
132
+ end
133
+ }
134
+ end
135
+
136
+ def reset(event_class=nil)
137
+ if event_class.nil?
138
+ @event_handlers.clear
139
+ @tickets.clear
140
+ else
141
+ unless @event_handlers[event_class.to_s].nil?
142
+ @event_handlers[event_class.to_s].each_key { |k|
143
+ @tickets.delete(k)
144
+ }
145
+ @event_handlers[event_class.to_s].clear
146
+ end
147
+ end
148
+ end
149
+ thread_immutable_methods :reset
150
+
151
+ end
152
+
153
+ ED = EventDispatcher
154
+ end