tengine_core 0.5.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +40 -0
  4. data/Gemfile.lock +95 -0
  5. data/README.md +54 -0
  6. data/Rakefile +44 -0
  7. data/VERSION +1 -0
  8. data/bin/tengine_atd +8 -0
  9. data/bin/tengine_heartbeat_watchd +8 -0
  10. data/bin/tengined +182 -0
  11. data/examples/VERSION +1 -0
  12. data/examples/uc01_execute_processing_for_event.rb +11 -0
  13. data/examples/uc02_fire_another_event.rb +16 -0
  14. data/examples/uc03_2handlers_for_1event.rb +16 -0
  15. data/examples/uc08_if_both_a_and_b_occurs.rb +11 -0
  16. data/examples/uc10_if_the_event_occurs_at_the_server.rb +15 -0
  17. data/examples/uc50_commit_event_at_first.rb +17 -0
  18. data/examples/uc51_commit_event_at_first_submit.rb +29 -0
  19. data/examples/uc52_commit_event_after_all_handler_submit.rb +31 -0
  20. data/examples/uc52_never_commit_event_unless_all_handler_submit.rb +31 -0
  21. data/examples/uc60_event_in_handler.rb +18 -0
  22. data/examples/uc62_session_in_driver.rb +16 -0
  23. data/examples/uc64_safety_countup.rb +14 -0
  24. data/examples/uc70_driver_enabled_on_activation.rb +13 -0
  25. data/examples/uc71_driver_disabled_on_activation.rb +14 -0
  26. data/examples/uc72_setup_eventmachine.rb +17 -0
  27. data/examples/uc80_raise_io_error.rb +10 -0
  28. data/examples/uc81_raise_runtime_error.rb +10 -0
  29. data/examples2/driver01.rb +18 -0
  30. data/examples2/driver02.rb +19 -0
  31. data/examples2/uc08_if_both_a_and_b_occurs.rb +13 -0
  32. data/examples2/uc10_if_the_event_occurs_at_the_server.rb +18 -0
  33. data/examples2/uc51_commit_event_at_first_submit_1.rb +16 -0
  34. data/examples2/uc51_commit_event_at_first_submit_2.rb +17 -0
  35. data/examples2/uc51_commit_event_at_first_submit_3.rb +17 -0
  36. data/examples2/uc62_session_in_driver.rb +16 -0
  37. data/examples2/uc71_driver_disabled_on_activation.rb +16 -0
  38. data/failure_examples/VERSION +1 -0
  39. data/failure_examples/uc53_submit_outside_of_handler.rb +15 -0
  40. data/failure_examples/uc61_event_outside_of_handler.rb +12 -0
  41. data/failure_examples/uc63_session_outside_of_driver.rb +13 -0
  42. data/lib/tengine/core.rb +74 -0
  43. data/lib/tengine/core/bootstrap.rb +123 -0
  44. data/lib/tengine/core/collection_accessible.rb +34 -0
  45. data/lib/tengine/core/config.rb +10 -0
  46. data/lib/tengine/core/config/atd.rb +225 -0
  47. data/lib/tengine/core/config/core.rb +319 -0
  48. data/lib/tengine/core/config/heartbeat_watcher.rb +229 -0
  49. data/lib/tengine/core/connection_test/.gitignore +1 -0
  50. data/lib/tengine/core/connection_test/fire_bar_on_foo.rb +16 -0
  51. data/lib/tengine/core/driveable.rb +213 -0
  52. data/lib/tengine/core/driver.rb +69 -0
  53. data/lib/tengine/core/driver/finder.rb +42 -0
  54. data/lib/tengine/core/dsl_evaluator.rb +110 -0
  55. data/lib/tengine/core/dsl_filter_def.rb +11 -0
  56. data/lib/tengine/core/dsl_loader.rb +108 -0
  57. data/lib/tengine/core/event.rb +145 -0
  58. data/lib/tengine/core/event/finder.rb +82 -0
  59. data/lib/tengine/core/event_exception_reportable.rb +88 -0
  60. data/lib/tengine/core/event_wrapper.rb +21 -0
  61. data/lib/tengine/core/find_by_name.rb +31 -0
  62. data/lib/tengine/core/handler.rb +152 -0
  63. data/lib/tengine/core/handler_path.rb +33 -0
  64. data/lib/tengine/core/heartbeat_watcher.rb +161 -0
  65. data/lib/tengine/core/io_to_logger.rb +22 -0
  66. data/lib/tengine/core/kernel.rb +510 -0
  67. data/lib/tengine/core/kernel_runtime.rb +91 -0
  68. data/lib/tengine/core/method_traceable.rb +38 -0
  69. data/lib/tengine/core/mongoid_fix.rb +19 -0
  70. data/lib/tengine/core/mutex.rb +177 -0
  71. data/lib/tengine/core/optimistic_lock.rb +69 -0
  72. data/lib/tengine/core/plugins.rb +54 -0
  73. data/lib/tengine/core/schedule.rb +21 -0
  74. data/lib/tengine/core/scheduler.rb +156 -0
  75. data/lib/tengine/core/selectable_attr.rb +29 -0
  76. data/lib/tengine/core/session.rb +21 -0
  77. data/lib/tengine/core/session_wrapper.rb +68 -0
  78. data/lib/tengine/core/setting.rb +21 -0
  79. data/lib/tengine/core/validation.rb +36 -0
  80. data/lib/tengine/errors.rb +18 -0
  81. data/lib/tengine/rspec.rb +8 -0
  82. data/lib/tengine/rspec/context_wrapper.rb +51 -0
  83. data/lib/tengine/rspec/extension.rb +53 -0
  84. data/lib/tengine_core.rb +23 -0
  85. data/spec/factories/tengine_core_drivers.rb +10 -0
  86. data/spec/factories/tengine_core_events.rb +14 -0
  87. data/spec/factories/tengine_core_handler_paths.rb +9 -0
  88. data/spec/factories/tengine_core_handlers.rb +9 -0
  89. data/spec/factories/tengine_core_sessions.rb +9 -0
  90. data/spec/mongoid.yml +35 -0
  91. data/spec/spec_helper.rb +48 -0
  92. data/spec/support/mongo_index_key_log.rb +91 -0
  93. data/spec/tengine/core/bootstrap_spec.rb +278 -0
  94. data/spec/tengine/core/bugfix/bind_dsl_file_in_multi_byte_dir_spec.rb +21 -0
  95. data/spec/tengine/core/bugfix/enabled_on_activation_spec.rb +112 -0
  96. data/spec/tengine/core/bugfix/receive_event_spec.rb +133 -0
  97. data/spec/tengine/core/bugfix/use_dsl_version_method.rb +12 -0
  98. data/spec/tengine/core/bugfix/use_dsl_version_method_spec.rb +28 -0
  99. data/spec/tengine/core/bugfix/use_event_in_handler_dsl.rb +11 -0
  100. data/spec/tengine/core/bugfix//351/235/236ACSII/343/201/256/343/203/206/343/202/231/343/202/243/343/203/254/343/202/257/343/203/210/343/203/252/345/220/215/source_location_encoding.rb +35 -0
  101. data/spec/tengine/core/bugfix//351/235/236ACSII/343/201/256/343/203/206/343/202/231/343/202/243/343/203/254/343/202/257/343/203/210/343/203/252/345/220/215//351/235/236ASCII/343/201/256/343/203/225/343/202/241/343/202/244/343/203/253/345/220/215_dsl.rb +38 -0
  102. data/spec/tengine/core/bugfix//351/235/236ACSII/343/201/256/343/203/207/343/202/243/343/203/254/343/202/257/343/203/210/343/203/252/345/220/215/source_location_encoding.rb +35 -0
  103. data/spec/tengine/core/bugfix//351/235/236ACSII/343/201/256/343/203/207/343/202/243/343/203/254/343/202/257/343/203/210/343/203/252/345/220/215//351/235/236ASCII/343/201/256/343/203/225/343/202/241/343/202/244/343/203/253/345/220/215_dsl.rb +38 -0
  104. data/spec/tengine/core/config/atd_spec.rb +62 -0
  105. data/spec/tengine/core/config/core_spec.rb +479 -0
  106. data/spec/tengine/core/config/heartbeat_watcher_spec.rb +62 -0
  107. data/spec/tengine/core/config/syntax_error_in_erb.yml.erb +13 -0
  108. data/spec/tengine/core/config/wrong_category_name.yml.erb +13 -0
  109. data/spec/tengine/core/config/wrong_field_name.yml.erb +12 -0
  110. data/spec/tengine/core/config/wrong_yaml.yml.erb +13 -0
  111. data/spec/tengine/core/config_spec/another_port.yml +54 -0
  112. data/spec/tengine/core/config_spec/config_with_dir_absolute_load_path.yml +16 -0
  113. data/spec/tengine/core/config_spec/config_with_dir_relative_load_path.yml +16 -0
  114. data/spec/tengine/core/config_spec/config_with_file_absolute_load_path.yml +16 -0
  115. data/spec/tengine/core/config_spec/config_with_file_relative_load_path.yml +16 -0
  116. data/spec/tengine/core/config_spec/log_config_spec.rb +235 -0
  117. data/spec/tengine/core/driveable_spec.rb +240 -0
  118. data/spec/tengine/core/driver_spec.rb +159 -0
  119. data/spec/tengine/core/dsl_loader_spec.rb +172 -0
  120. data/spec/tengine/core/dsls/uc08_if_both_a_and_b_occurs_spec.rb +35 -0
  121. data/spec/tengine/core/dsls/uc10_if_the_event_occurs_at_the_server_spec.rb +58 -0
  122. data/spec/tengine/core/dsls/uc50_commit_event_at_first_spec.rb +29 -0
  123. data/spec/tengine/core/dsls/uc52_commit_event_after_all_handler_submit_spec.rb +33 -0
  124. data/spec/tengine/core/dsls/uc52_never_commit_event_unless_all_handler_submit_spec.rb +37 -0
  125. data/spec/tengine/core/dsls/uc53_submit_outside_of_handler_spec.rb +37 -0
  126. data/spec/tengine/core/dsls/uc60_event_in_handler_spec.rb +31 -0
  127. data/spec/tengine/core/dsls/uc61_event_outside_of_handler_spec.rb +37 -0
  128. data/spec/tengine/core/dsls/uc62_session_in_driver_spec.rb +36 -0
  129. data/spec/tengine/core/dsls/uc63_session_outside_of_driver_spec.rb +35 -0
  130. data/spec/tengine/core/dsls/uc64_safety_countup_spec.rb +134 -0
  131. data/spec/tengine/core/dsls/uc70_driver_enabled_on_activation_spec.rb +39 -0
  132. data/spec/tengine/core/dsls/uc71_driver_disabled_on_activation_spec.rb +36 -0
  133. data/spec/tengine/core/dsls/uc72_setup_eventmachine_spec.rb +39 -0
  134. data/spec/tengine/core/dsls/uc80_raise_io_error_spec.rb +53 -0
  135. data/spec/tengine/core/dsls/uc81_raise_runtime_error_spec.rb +49 -0
  136. data/spec/tengine/core/event/finder_spec.rb +136 -0
  137. data/spec/tengine/core/event_exception_reportable_spec.rb +33 -0
  138. data/spec/tengine/core/event_spec.rb +161 -0
  139. data/spec/tengine/core/event_wrapper_spec.rb +35 -0
  140. data/spec/tengine/core/handler_path_spec.rb +87 -0
  141. data/spec/tengine/core/handler_spec.rb +190 -0
  142. data/spec/tengine/core/heartbeat_watcher_spec.rb +131 -0
  143. data/spec/tengine/core/io_to_logger_spec.rb +30 -0
  144. data/spec/tengine/core/kernel_spec.rb +885 -0
  145. data/spec/tengine/core/mutex_spec.rb +184 -0
  146. data/spec/tengine/core/optimistic_lock_spec.rb +55 -0
  147. data/spec/tengine/core/scheculer_spec.rb +121 -0
  148. data/spec/tengine/core/selectable_attr_spec.rb +30 -0
  149. data/spec/tengine/core/session_spec.rb +104 -0
  150. data/spec/tengine/core/setting_spec.rb +79 -0
  151. data/spec/tengine/core_spec.rb +13 -0
  152. data/spec/tengine_spec.rb +14 -0
  153. data/tengine_core.gemspec +248 -0
  154. data/tmp/log/.gitignore +1 -0
  155. data/tmp/tengined_status/.gitignore +1 -0
  156. metadata +421 -0
@@ -0,0 +1,319 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine/core/config'
3
+
4
+ require 'yaml'
5
+ require 'optparse'
6
+ require 'active_support/memoizable'
7
+ require 'active_support/core_ext/class/attribute_accessors'
8
+
9
+ require 'tengine/support/yaml_with_erb'
10
+
11
+ Tengine::Support::Config::Definition::Group.module_eval do
12
+ def symbolize_keys
13
+ to_hash
14
+ end
15
+ end
16
+
17
+ class Tengine::Core::Config::Core < Tengine::Support::Config::Definition::Suite
18
+ # memoize については http://wota.jp/ac/?date=20081025#p11 などを参照してください
19
+ extend ActiveSupport::Memoizable
20
+
21
+ class << self
22
+ # この辺は以前のTengine::Core::Configとの互換のために用意してあります
23
+ def [](hash_or_suite)
24
+ case hash_or_suite
25
+ when Tengine::Core::Config::Core then hash_or_suite
26
+ when Hash then
27
+ result = Tengine::Core::Config::Core.new
28
+ result.load(hash_or_suite)
29
+ result
30
+ else
31
+ raise "unsupported class: #{hash_or_suite.class.inspect}"
32
+ end
33
+ end
34
+
35
+ def default_hash
36
+ new.to_hash
37
+ end
38
+ alias_method :skelton_hash, :default_hash
39
+
40
+ def parse_to_hash(args)
41
+ config = new
42
+ config.parse!(args)
43
+ result = new
44
+ result.config = config.config
45
+ result.to_hash
46
+ end
47
+
48
+ def parse(args)
49
+ config = new
50
+ config.parse!(args)
51
+ config
52
+ end
53
+
54
+ end
55
+
56
+ def initialize(hash_or_filepath = nil)
57
+ build if respond_to?(:build)
58
+ case hash_or_filepath
59
+ when Hash then
60
+ if config = hash_or_filepath[:config]
61
+ load_file(config)
62
+ else
63
+ load(hash_or_filepath)
64
+ end
65
+ when String then load_file(hash_or_filepath)
66
+ end
67
+ end
68
+
69
+ def load_file(filepath)
70
+ super
71
+ rescue Exception => e
72
+ msg = e.message
73
+ unless msg.include?(filepath)
74
+ msg = "#{msg} in #{filepath}"
75
+ end
76
+ raise Tengine::Core::ConfigError, msg
77
+ end
78
+
79
+
80
+ def build
81
+ banner <<EOS
82
+ Usage: tengined [-k action] [-f path_to_config] [-T path/to/file_or_dir]
83
+ [-o mq_conn_host] [-p mq_conn_port] [-u mq_conn_user]
84
+ [-s mq_conn_pass] [-e mq_exchange_name] [-q mq_queue_name]
85
+ EOS
86
+
87
+ field(:action, "test|load|start|enable|stop|force-stop|status|activate", :type => :string, :default => "start")
88
+ load_config(:config, "path/to/config_file", :type => :string)
89
+
90
+ add(:process, Tengine::Core::Config::Core::Process)
91
+ add(:tengined, Tengine::Core::Config::Core::Tengined)
92
+ field(:db, "settings to connect to db", :type => :hash, :default => {
93
+ 'host' => 'localhost',
94
+ 'port' => 27017,
95
+ 'username' => nil,
96
+ 'password' => nil,
97
+ 'database' => 'tengine_production',
98
+ })
99
+
100
+ group(:event_queue, :hidden => true) do
101
+ add(:connection, AmqpConnection)
102
+ add(:exchange , Tengine::Support::Config::Amqp::Exchange, :defaults => {:name => 'tengine_event_exchange'})
103
+ add(:queue , Tengine::Support::Config::Amqp::Queue , :defaults => {:name => 'tengine_event_queue'})
104
+ end
105
+
106
+ add(:log_common, Tengine::Support::Config::Logger,
107
+ :defaults => {
108
+ :rotation => 3 ,
109
+ :rotation_size => 1024 * 1024,
110
+ :level => 'info' ,
111
+ })
112
+ add(:application_log, Tengine::Core::Config::Core::LoggerConfig,
113
+ :parameters => {:logger_name => "application"},
114
+ :dependencies => { :process_config => :process, :log_common => :log_common,}){
115
+ self.formatter = lambda{|level, t, prog, msg| "#{t.iso8601} #{level} #{@process_identifier} #{msg}\n"}
116
+ }
117
+ add(:process_stdout_log, Tengine::Core::Config::Core::LoggerConfig,
118
+ :parameters => {:logger_name => "#{File.basename($PROGRAM_NAME)}_#{::Process.pid}_stdout"},
119
+ :dependencies => { :process_config => :process, :log_common => :log_common,}){
120
+ self.formatter = lambda{|level, t, prog, msg| "#{t.iso8601} STDOUT #{@process_identifier} #{msg}\n"}
121
+ }
122
+ add(:process_stderr_log, Tengine::Core::Config::Core::LoggerConfig,
123
+ :parameters => {:logger_name => "#{File.basename($PROGRAM_NAME)}_#{::Process.pid}_stderr"},
124
+ :dependencies => { :process_config => :process, :log_common => :log_common,},
125
+ :defaults => {
126
+ :output => proc{ process_config.daemon ? "./log/#{logger_name}.log" : "STDERR" }}){
127
+ self.formatter = lambda{|level, t, prog, msg| "#{t.iso8601} STDERR #{@process_identifier} #{msg}\n"}
128
+ }
129
+
130
+ group(:heartbeat) do
131
+ add(:core , Tengine::Core::Config::Core::Heartbeat)
132
+ # add(:job , Tengine::Core::Config::Core::Heartbeat, :defaults => {:interval => 5, :expire => 20})
133
+ # add(:hbw , Tengine::Core::Config::Core::Heartbeat)
134
+ # add(:resourcew, Tengine::Core::Config::Core::Heartbeat)
135
+ # add(:atd , Tengine::Core::Config::Core::Heartbeat)
136
+ end
137
+
138
+ separator("\nGeneral:")
139
+ field(:verbose, "Show detail to this command", :type => :boolean)
140
+ __action__(:version, "show version"){ STDOUT.puts Tengine::Core.version.to_s; exit }
141
+ __action__(:dump_skelton, "dump skelton of config"){ STDOUT.puts YAML.dump(root.to_hash); exit }
142
+ __action__(:help , "show this help message"){ STDOUT.puts option_parser.help; exit }
143
+
144
+ mapping({
145
+ [:action] => :k,
146
+ [:config] => :f,
147
+ [:tengined, :daemon] => :D,
148
+ [:tengined, :load_path] => :T,
149
+ # [:tengined, :heartbeat_period] => :G,
150
+ [:tengined, :confirmation_threshold] => :C,
151
+
152
+ [:event_queue, :connection, :host] => :o,
153
+ [:event_queue, :connection, :port] => :p,
154
+ [:event_queue, :connection, :user] => :u,
155
+ [:event_queue, :connection, :pass] => :s,
156
+ [:event_queue, :exchange , :name] => :e,
157
+ [:event_queue, :queue , :name] => :q,
158
+
159
+ [:heartbeat, :core, :interval] => :G,
160
+
161
+ [:verbose] => :V,
162
+ [:version] => :v,
163
+ [:help] => :h
164
+ })
165
+ end
166
+
167
+ class Process
168
+ include Tengine::Support::Config::Definition
169
+
170
+ field :daemon, "process works on background.", :type => :boolean, :default => false
171
+ field :pid_dir, "path/to/dir for PID created.", :type => :directory, :default => "./tmp/tengined_pids"
172
+ end
173
+
174
+ class Tengined
175
+ include Tengine::Support::Config::Definition
176
+
177
+ cattr_accessor :default_cache_drivers
178
+
179
+ field :load_path , "[REQUIRED] path/to/file_or_dir. ignored with \"-k test\".", :type => :string
180
+ field :cache_drivers , "if set this, tengine doesn't reload driver.", :type => :boolean,
181
+ :default => proc{ Tengine::Core::Config::Core::Tengined.default_cache_drivers} # spec/spec_helper.rb でtrueに設定しています。
182
+ field :skip_load , "doesn't load event handler when start. usually use with --daemon option. [only for command]", :type => :boolean
183
+ field :skip_enablement , "doesn't enable event handler when start. usually use with --daemon option. [only for command]", :type => :boolean
184
+ field :wait_activation , "wait activation when start. usually use with --daemon option [only for command]", :type => :boolean
185
+ field :activation_timeout , "period to wait for making activation file.", :type => :integer, :default => 300
186
+ field :status_dir , "path/to/dir.", :type => :directory, :default => "./tmp/tengined_status"
187
+ field :activation_dir , "path/to/dir.", :type => :directory, :default => "./tmp/tengined_activations"
188
+ # field :heartbeat_period , "the second of period which heartbeat event be fired. disable heartbeat if 0.", :type => :integer, :default => 0
189
+ field :confirmation_threshold, "the event which is this level or less will be made confirmed automatically. debug/info/warn/error/fatal. ", :type => :string, :default => 'info'
190
+ end
191
+
192
+ class AmqpConnection < Tengine::Support::Config::Amqp::Connection
193
+ field :vhost, :default => '/'
194
+ field :user , :default => 'guest'
195
+ field :pass , :default => 'guest'
196
+ field :logging, :type => :boolean, :default => false
197
+ field :insist, :type => :boolean, :default => false
198
+ field :auto_reconnect_delay, :type => :integer, :default => 1
199
+ end
200
+
201
+ class LoggerConfig < Tengine::Support::Config::Logger
202
+ parameter :logger_name
203
+ depends :process_config
204
+ depends :log_common
205
+ field :output,
206
+ :default => proc{
207
+ process_config.daemon ?
208
+ "./log/#{logger_name}.log" : "STDOUT" },
209
+ :default_description => proc{"if daemon process then \"./log/#{logger_name}.log\" else \"STDOUT\""}
210
+ field :rotation,
211
+ :default => proc{ log_common.rotation },
212
+ :default_description => proc{"value of #{log_common.long_opt}-rotation"}
213
+ field :rotation_size,
214
+ :default => proc{ log_common.rotation_size },
215
+ :default_description => proc{"value of #{log_common.long_opt}-rotation-size"}
216
+ field :level,
217
+ :default => proc{ log_common.level },
218
+ :default_description => proc{"value of #{log_common.long_opt}-level"}
219
+
220
+ def new_logger *;
221
+ super.tap {|i| i.formatter = self.formatter }
222
+ end
223
+ end
224
+
225
+ class Heartbeat
226
+ include Tengine::Support::Config::Definition
227
+ field :interval, "heartbeat interval seconds. usually about 30 seconds", :type => :integer, :default => 0
228
+ field :expire , "heartbeat expire seconds" , :type => :integer, :default => 120
229
+ end
230
+
231
+ def dsl_load_path
232
+ original = self[:tengined][:load_path]
233
+ # 本来は指定する必要はありませんが、specでDir.pwdをstubで返すようにするために、明示的に第2引数にDir.pwdを指定しています
234
+ original ? File.expand_path(original, Dir.pwd) : nil
235
+ end
236
+ memoize :dsl_load_path
237
+
238
+ def prepare_dir_and_paths(force = false)
239
+ return if !force && @prepare_dir_and_paths_done
240
+ path = dsl_load_path(true) # キャッシュをクリア
241
+ if path.nil?
242
+ @dsl_dir_path = nil
243
+ @dsl_file_paths = []
244
+ elsif Dir.exist?(path)
245
+ @dsl_dir_path = File.expand_path(path)
246
+ @dsl_file_paths = Dir.glob("#{@dsl_dir_path}/**/*.rb")
247
+ elsif File.exist?(path)
248
+ @dsl_dir_path = File.expand_path(File.dirname(path))
249
+ @dsl_dir_path.force_encoding(@dsl_dir_path.encoding)
250
+ @dsl_file_paths = [dsl_load_path]
251
+ else
252
+ raise Tengine::Core::ConfigError, "file or directory doesn't exist. #{path}"
253
+ end
254
+ @prepare_dir_and_paths_done = true
255
+ end
256
+
257
+ def dsl_dir_path
258
+ prepare_dir_and_paths
259
+ @dsl_dir_path
260
+ end
261
+
262
+ def dsl_file_paths
263
+ prepare_dir_and_paths
264
+ @dsl_file_paths
265
+ end
266
+
267
+ def dsl_version_path
268
+ path = dsl_dir_path
269
+ path ? File.expand_path("VERSION", path) : nil
270
+ end
271
+ memoize :dsl_version_path
272
+
273
+ def dsl_version
274
+ path = dsl_version_path
275
+ (path && File.exist?(dsl_version_path)) ? File.read(dsl_version_path).strip : Time.now.strftime("%Y%m%d%H%M%S")
276
+ end
277
+ memoize :dsl_version
278
+
279
+ def relative_path_from_dsl_dir(filepath)
280
+ path = Pathname.new(filepath)
281
+ path.relative? ? path.to_s : path.relative_path_from(Pathname.new(dsl_dir_path)).to_s
282
+ end
283
+
284
+ def status_dir
285
+ self[:tengined][:status_dir]
286
+ end
287
+ memoize :status_dir
288
+
289
+ def activation_dir
290
+ self[:tengined][:activation_dir]
291
+ end
292
+ memoize :activation_dir
293
+
294
+ def confirmation_threshold
295
+ Tengine::Event::LEVELS_INV[ self[:tengined][:confirmation_threshold].to_sym ]
296
+ end
297
+ memoize :confirmation_threshold
298
+
299
+ def heartbeat_period
300
+ # [:][:heartbeat_period].to_i
301
+ heartbeat.core.interval.to_i
302
+ end
303
+
304
+ def heartbeat_enabled?
305
+ heartbeat_period > 0
306
+ end
307
+
308
+ def setup_loggers
309
+ Tengine.logger = application_log.new_logger
310
+ Tengine::Core.stdout_logger = process_stdout_log.new_logger
311
+ Tengine::Core.stderr_logger = process_stderr_log.new_logger
312
+
313
+ Tengine::Core.stdout_logger.info("#{self.class.name}#setup_loggers complete")
314
+ rescue Exception
315
+ Tengine::Core.stderr_logger.info("#{self.class.name}#setup_loggers failure")
316
+ raise
317
+ end
318
+
319
+ end
@@ -0,0 +1,229 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine/core/config'
3
+
4
+ require 'yaml'
5
+ require 'optparse'
6
+ require 'active_support/memoizable'
7
+
8
+ require 'tengine/support/yaml_with_erb'
9
+
10
+ Tengine::Support::Config::Definition::Group.module_eval do
11
+ def symbolize_keys
12
+ to_hash
13
+ end
14
+ end
15
+
16
+ class Tengine::Core::Config::HeartbeatWatcher < Tengine::Support::Config::Definition::Suite
17
+ # memoize については http://wota.jp/ac/?date=20081025#p11 などを参照してください
18
+ extend ActiveSupport::Memoizable
19
+
20
+ class << self
21
+ # この辺は以前のTengine::Core::Configとの互換のために用意してあります
22
+ def [](hash_or_suite)
23
+ case hash_or_suite
24
+ when Tengine::Core::Config::HeartbeatWatcher then hash_or_suite
25
+ when Hash then
26
+ result = Tengine::Core::Config::HeartbeatWatcher.new
27
+ result.load(hash_or_suite)
28
+ result
29
+ else
30
+ raise "unsupported class: #{hash_or_suite.class.inspect}"
31
+ end
32
+ end
33
+
34
+ def default_hash
35
+ new.to_hash
36
+ end
37
+ alias_method :skelton_hash, :default_hash
38
+
39
+ def parse_to_hash(args)
40
+ config = new
41
+ config.parse!(args)
42
+ result = new
43
+ result.config = config.config
44
+ result.to_hash
45
+ end
46
+
47
+ def parse(args)
48
+ config = new
49
+ config.parse!(args)
50
+ config
51
+ end
52
+
53
+ end
54
+
55
+ def initialize(hash_or_filepath = nil)
56
+ build if respond_to?(:build)
57
+ case hash_or_filepath
58
+ when Hash then
59
+ if config = hash_or_filepath[:config]
60
+ load_file(config)
61
+ else
62
+ load(hash_or_filepath)
63
+ end
64
+ when String then load_file(hash_or_filepath)
65
+ end
66
+ end
67
+
68
+ def load_file(filepath)
69
+ super
70
+ rescue Exception => e
71
+ msg = e.message
72
+ unless msg.include?(filepath)
73
+ msg = "#{msg} in #{filepath}"
74
+ end
75
+ raise Tengine::Core::ConfigError, msg
76
+ end
77
+
78
+
79
+ def build
80
+ banner <<EOS
81
+ Usage: tengine_heartbeat_watchd [-k action] [-f path_to_config] [-D process_daemon]
82
+ [-o mq_conn_host] [-p mq_conn_port] [-u mq_conn_user]
83
+ [-s mq_conn_pass] [-e mq_exchange_name] [-q mq_queue_name]
84
+ [-G heartbeat_hbw_interval]
85
+ EOS
86
+
87
+ field(:action, "start|stop", :type => :string, :default => "start")
88
+ load_config(:config, "path/to/config_file", :type => :string)
89
+
90
+ add(:process, Tengine::Core::Config::HeartbeatWatcher::Process)
91
+ field(:db, "settings to connect to db", :type => :hash, :default => {
92
+ 'host' => 'localhost',
93
+ 'port' => 27017,
94
+ 'username' => nil,
95
+ 'password' => nil,
96
+ 'database' => 'tengine_production',
97
+ })
98
+
99
+ group(:heartbeat) do
100
+ add(:core , Tengine::Core::Config::Core::Heartbeat)
101
+ add(:job , Tengine::Core::Config::Core::Heartbeat, :defaults => {:interval => 5, :expire => 20})
102
+ add(:hbw , Tengine::Core::Config::Core::Heartbeat)
103
+ add(:resourcew, Tengine::Core::Config::Core::Heartbeat)
104
+ add(:atd , Tengine::Core::Config::Core::Heartbeat)
105
+ end
106
+
107
+ group(:event_queue, :hidden => true) do
108
+ add(:connection, AmqpConnection)
109
+ add(:exchange , Tengine::Support::Config::Amqp::Exchange, :defaults => {:name => 'tengine_event_exchange'})
110
+ add(:queue , Tengine::Support::Config::Amqp::Queue , :defaults => {:name => 'tengine_event_queue'})
111
+ end
112
+
113
+ add(:log_common, Tengine::Support::Config::Logger,
114
+ :defaults => {
115
+ :rotation => 3 ,
116
+ :rotation_size => 1024 * 1024,
117
+ :level => 'info' ,
118
+ })
119
+ add(:application_log, Tengine::Core::Config::HeartbeatWatcher::LoggerConfig,
120
+ :parameters => {:logger_name => "application"},
121
+ :dependencies => { :process_config => :process, :log_common => :log_common,}){
122
+ self.formatter = lambda{|level, t, prog, msg| "#{t.iso8601} #{level} #{@process_identifier} #{msg}\n"}
123
+ }
124
+ add(:process_stdout_log, Tengine::Core::Config::HeartbeatWatcher::LoggerConfig,
125
+ :parameters => {:logger_name => "#{File.basename($PROGRAM_NAME)}_#{::Process.pid}_stdout"},
126
+ :dependencies => { :process_config => :process, :log_common => :log_common,}){
127
+ self.formatter = lambda{|level, t, prog, msg| "#{t.iso8601} STDOUT #{@process_identifier} #{msg}\n"}
128
+ }
129
+ add(:process_stderr_log, Tengine::Core::Config::HeartbeatWatcher::LoggerConfig,
130
+ :parameters => {:logger_name => "#{File.basename($PROGRAM_NAME)}_#{::Process.pid}_stderr"},
131
+ :dependencies => { :process_config => :process, :log_common => :log_common,},
132
+ :defaults => {
133
+ :output => proc{ process_config.daemon ? "./log/#{logger_name}.log" : "STDERR" }}){
134
+ self.formatter = lambda{|level, t, prog, msg| "#{t.iso8601} STDERR #{@process_identifier} #{msg}\n"}
135
+ }
136
+
137
+ separator("\nGeneral:")
138
+ field(:verbose, "Show detail to this command", :type => :boolean)
139
+ __action__(:version, "show version"){ STDOUT.puts Tengine::Core.version.to_s; exit }
140
+ __action__(:dump_skelton, "dump skelton of config"){ STDOUT.puts YAML.dump(root.to_hash); exit }
141
+ __action__(:help , "show this help message"){ STDOUT.puts option_parser.help; exit }
142
+
143
+ mapping({
144
+ [:action] => :k,
145
+ [:config] => :f,
146
+ [:process, :daemon] => :D,
147
+
148
+ [:event_queue, :connection, :host] => :o,
149
+ [:event_queue, :connection, :port] => :p,
150
+ [:event_queue, :connection, :user] => :u,
151
+ [:event_queue, :connection, :pass] => :s,
152
+ [:event_queue, :exchange , :name] => :e,
153
+ [:event_queue, :queue , :name] => :q,
154
+
155
+ [:heartbeat, :hbw, :interval] => :G,
156
+
157
+ [:verbose] => :V,
158
+ [:version] => :v,
159
+ [:help] => :h
160
+ })
161
+ end
162
+
163
+ class Process
164
+ include Tengine::Support::Config::Definition
165
+
166
+ field :daemon, "process works on background.", :type => :boolean, :default => false
167
+ field :pid_dir, "path/to/dir for PID created.", :type => :directory, :default => "./pids"
168
+ end
169
+
170
+ def heartbeat_period
171
+ # [:][:heartbeat_period].to_i
172
+ heartbeat.interval.to_i
173
+ end
174
+
175
+ def heartbeat_enabled?
176
+ heartbeat_period > 0
177
+ end
178
+
179
+ class AmqpConnection < Tengine::Support::Config::Amqp::Connection
180
+ field :vhost, :default => '/'
181
+ field :user , :default => 'guest'
182
+ field :pass , :default => 'guest'
183
+ field :logging, :type => :boolean, :default => false
184
+ field :insist, :type => :boolean, :default => false
185
+ field :auto_reconnect_delay, :type => :integer, :default => 1
186
+ end
187
+
188
+ class LoggerConfig < Tengine::Support::Config::Logger
189
+ parameter :logger_name
190
+ depends :process_config
191
+ depends :log_common
192
+ field :output, {
193
+ :default => proc {
194
+ process_config.daemon ? "./log/#{logger_name}.log" : "STDOUT"
195
+ },
196
+ :default_description => proc {
197
+ "if daemon process then \"./log/#{logger_name}.log\" else \"STDOUT\""
198
+ }
199
+ }
200
+ field :rotation, {
201
+ :default => proc{ log_common.rotation },
202
+ :default_description => proc{ "value of #{log_common.long_opt}-rotation" }
203
+ }
204
+ field :rotation_size, {
205
+ :default => proc{ log_common.rotation_size },
206
+ :default_description => proc{ "value of #{log_common.long_opt}-rotation-size" }
207
+ }
208
+ field :level, {
209
+ :default => proc{ log_common.level },
210
+ :default_description => proc{ "value of #{log_common.long_opt}-level" }
211
+ }
212
+
213
+ def new_logger *;
214
+ super.tap {|i| i.formatter = self.formatter }
215
+ end
216
+ end
217
+
218
+ def setup_loggers
219
+ Tengine.logger = application_log.new_logger
220
+ Tengine::Core.stdout_logger = process_stdout_log.new_logger
221
+ Tengine::Core.stderr_logger = process_stderr_log.new_logger
222
+
223
+ Tengine::Core.stdout_logger.info("#{self.class.name}#setup_loggers complete")
224
+ rescue Exception
225
+ Tengine::Core.stderr_logger.info("#{self.class.name}#setup_loggers failure")
226
+ raise
227
+ end
228
+
229
+ end