hayabusa 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +20 -0
- data/Gemfile.lock +59 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/bin/check_running.rb +69 -0
- data/bin/hayabusa_benchmark.rb +82 -0
- data/bin/hayabusa_cgi.rb +84 -0
- data/bin/hayabusa_fcgi.fcgi +159 -0
- data/bin/hayabusa_fcgi.rb +159 -0
- data/bin/knjappserver_start.rb +42 -0
- data/conf/apache2_cgi_rhtml_conf.conf +10 -0
- data/conf/apache2_fcgi_rhtml_conf.conf +22 -0
- data/hayabusa.gemspec +151 -0
- data/lib/hayabusa.rb +518 -0
- data/lib/hayabusa_cgi_session.rb +128 -0
- data/lib/hayabusa_cgi_tools.rb +102 -0
- data/lib/hayabusa_custom_io.rb +22 -0
- data/lib/hayabusa_database.rb +125 -0
- data/lib/hayabusa_erb_handler.rb +27 -0
- data/lib/hayabusa_ext/cleaner.rb +140 -0
- data/lib/hayabusa_ext/cmdline.rb +52 -0
- data/lib/hayabusa_ext/errors.rb +135 -0
- data/lib/hayabusa_ext/logging.rb +404 -0
- data/lib/hayabusa_ext/mailing.rb +158 -0
- data/lib/hayabusa_ext/sessions.rb +71 -0
- data/lib/hayabusa_ext/threadding.rb +96 -0
- data/lib/hayabusa_ext/threadding_timeout.rb +101 -0
- data/lib/hayabusa_ext/translations.rb +43 -0
- data/lib/hayabusa_ext/web.rb +190 -0
- data/lib/hayabusa_http_server.rb +102 -0
- data/lib/hayabusa_http_session.rb +361 -0
- data/lib/hayabusa_http_session_contentgroup.rb +176 -0
- data/lib/hayabusa_http_session_page_environment.rb +66 -0
- data/lib/hayabusa_http_session_post_multipart.rb +135 -0
- data/lib/hayabusa_http_session_request.rb +219 -0
- data/lib/hayabusa_http_session_response.rb +144 -0
- data/lib/hayabusa_models.rb +8 -0
- data/lib/kernel_ext/gettext_methods.rb +22 -0
- data/lib/kernel_ext/magic_methods.rb +61 -0
- data/lib/models/log.rb +130 -0
- data/lib/models/log_access.rb +88 -0
- data/lib/models/log_data.rb +27 -0
- data/lib/models/log_data_link.rb +3 -0
- data/lib/models/log_data_value.rb +21 -0
- data/lib/models/log_link.rb +65 -0
- data/lib/models/session.rb +35 -0
- data/pages/benchmark.rhtml +0 -0
- data/pages/benchmark_print.rhtml +14 -0
- data/pages/benchmark_simple.rhtml +3 -0
- data/pages/benchmark_threadded_content.rhtml +21 -0
- data/pages/debug_database_connections.rhtml +46 -0
- data/pages/debug_http_sessions.rhtml +40 -0
- data/pages/debug_memory_usage.rhtml +16 -0
- data/pages/error_notfound.rhtml +12 -0
- data/pages/logs_latest.rhtml +57 -0
- data/pages/logs_show.rhtml +32 -0
- data/pages/spec.rhtml +41 -0
- data/pages/spec_post.rhtml +3 -0
- data/pages/spec_test_multiple_clients.rhtml +3 -0
- data/pages/spec_thread_joins.rhtml +21 -0
- data/pages/spec_threadded_content.rhtml +40 -0
- data/pages/tests.rhtml +14 -0
- data/spec/cgi_spec.rb +47 -0
- data/spec/custom_urls_spec.rb +35 -0
- data/spec/fcgi_multiple_processes_spec.rb +32 -0
- data/spec/fcgi_spec.rb +69 -0
- data/spec/hayabusa_spec.rb +194 -0
- data/spec/spec_helper.rb +12 -0
- data/tests/cgi_test/config_cgi.rb +6 -0
- data/tests/cgi_test/threadded_content_test.rhtml +23 -0
- data/tests/cgi_test/vars_get_test.rhtml +4 -0
- data/tests/cgi_test/vars_header_test.rhtml +3 -0
- data/tests/cgi_test/vars_post_test.rhtml +4 -0
- data/tests/fcgi_test/config_fcgi.rb +6 -0
- data/tests/fcgi_test/index.rhtml +3 -0
- data/tests/fcgi_test/sleeper.rhtml +4 -0
- data/tests/fcgi_test/threadded_content_test.rhtml +23 -0
- data/tests/fcgi_test/vars_get_test.rhtml +4 -0
- data/tests/fcgi_test/vars_header_test.rhtml +3 -0
- data/tests/fcgi_test/vars_post_test.rhtml +4 -0
- metadata +257 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
class Hayabusa::Cgi_session
|
2
|
+
attr_accessor :data, :alert_sent
|
3
|
+
attr_reader :cookie, :get, :headers, :session, :session_id, :session_hash, :hb, :active, :out, :eruby, :browser, :debug, :resp, :page_path, :post, :cgroup, :meta, :httpsession_var, :handler, :working
|
4
|
+
|
5
|
+
def initialize(args)
|
6
|
+
@args = args
|
7
|
+
@hb = @args[:hb]
|
8
|
+
|
9
|
+
@config = @hb.config
|
10
|
+
@handlers_cache = @config[:handlers_cache]
|
11
|
+
cgi_conf = @config[:cgi]
|
12
|
+
@get, @post, @meta, @headers = cgi_conf[:get], cgi_conf[:post], cgi_conf[:meta], cgi_conf[:headers]
|
13
|
+
|
14
|
+
if cgi_conf[:cgi]
|
15
|
+
@out = cgi_conf[:cgi]
|
16
|
+
else
|
17
|
+
@out = $stdout
|
18
|
+
end
|
19
|
+
|
20
|
+
@written_size = 0
|
21
|
+
@size_send = @config[:size_send]
|
22
|
+
|
23
|
+
@eruby = Knj::Eruby.new(
|
24
|
+
:cache_hash => @hb.eruby_cache,
|
25
|
+
:binding_callback => self.method(:create_binding)
|
26
|
+
)
|
27
|
+
|
28
|
+
self.init_thread
|
29
|
+
|
30
|
+
|
31
|
+
#Parse URI (page_path and get).
|
32
|
+
match = @meta["SERVER_PROTOCOL"].match(/^HTTP\/1\.(\d+)\s*/)
|
33
|
+
raise "Could match HTTP-protocol from: '#{@meta["SERVER_PROTOCOL"]}'." if !match
|
34
|
+
http_version = "1.#{match[1]}"
|
35
|
+
|
36
|
+
|
37
|
+
Dir.chdir(@config[:doc_root])
|
38
|
+
@page_path = @meta["PATH_TRANSLATED"]
|
39
|
+
@ext = File.extname(@page_path).downcase[1..-1].to_s
|
40
|
+
|
41
|
+
@resp = Hayabusa::Http_session::Response.new(:socket => self)
|
42
|
+
@resp.reset(:http_version => http_version, :mode => :cgi)
|
43
|
+
@resp.header("Content-Type", "text/html")
|
44
|
+
|
45
|
+
@cgroup = Hayabusa::Http_session::Contentgroup.new(:socket => self, :hb => @hb, :resp => @resp, :httpsession => self)
|
46
|
+
@cgroup.reset
|
47
|
+
|
48
|
+
@resp.cgroup = @cgroup
|
49
|
+
|
50
|
+
begin
|
51
|
+
@hb.events.call(:request_begin, :httpsession => self) if @hb.events
|
52
|
+
|
53
|
+
Timeout.timeout(@hb.config[:timeout]) do
|
54
|
+
if @handlers_cache.key?(@ext)
|
55
|
+
STDOUT.print "Calling handler.\n" if @debug
|
56
|
+
@handlers_cache[@ext].call(self)
|
57
|
+
else
|
58
|
+
raise "CGI-mode shouldnt serve static files."
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
@cgroup.mark_done
|
63
|
+
@cgroup.write_output
|
64
|
+
@cgroup.join
|
65
|
+
|
66
|
+
@hb.events.call(:request_done, {
|
67
|
+
:httpsession => self
|
68
|
+
}) if @hb.events
|
69
|
+
rescue SystemExit
|
70
|
+
#do nothing - ignore.
|
71
|
+
rescue Timeout::Error
|
72
|
+
@resp.status = 500
|
73
|
+
print "The request timed out."
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
#Creates a new Hayabusa::Binding-object and returns the binding for that object.
|
78
|
+
def create_binding
|
79
|
+
return Hayabusa::Http_session::Page_environment.new(:httpsession => self, :hb => @hb).get_binding
|
80
|
+
end
|
81
|
+
|
82
|
+
#Is called when content is added and begings to write the output if it goes above the limit.
|
83
|
+
def add_size(size)
|
84
|
+
@written_size += size
|
85
|
+
@cgroup.write_output if @written_size >= @size_send
|
86
|
+
end
|
87
|
+
|
88
|
+
#Called from content-group.
|
89
|
+
def write(str)
|
90
|
+
@out.print(str)
|
91
|
+
end
|
92
|
+
|
93
|
+
def threadded_content(block)
|
94
|
+
raise "No block was given." if !block
|
95
|
+
cgroup = Thread.current[:hayabusa][:contentgroup].new_thread
|
96
|
+
|
97
|
+
Thread.new do
|
98
|
+
begin
|
99
|
+
self.init_thread
|
100
|
+
cgroup.register_thread
|
101
|
+
|
102
|
+
@hb.db_handler.get_and_register_thread if @hb and @hb.db_handler.opts[:threadsafe]
|
103
|
+
@hb.ob.db.get_and_register_thread if @hb and @hb.ob.db.opts[:threadsafe]
|
104
|
+
|
105
|
+
block.call
|
106
|
+
rescue Exception => e
|
107
|
+
Thread.current[:hayabusa][:contentgroup].write Knj::Errors.error_str(e, {:html => true})
|
108
|
+
_hb.handle_error(e)
|
109
|
+
ensure
|
110
|
+
Thread.current[:hayabusa][:contentgroup].mark_done
|
111
|
+
@hb.ob.db.free_thread if @hb and @hb.ob.db.opts[:threadsafe]
|
112
|
+
@hb.db_handler.free_thread if @hb and @hb.db_handler.opts[:threadsafe]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def init_thread
|
118
|
+
Thread.current[:hayabusa] = {
|
119
|
+
:hb => @hb,
|
120
|
+
:httpsession => self,
|
121
|
+
:session => @session,
|
122
|
+
:get => @get,
|
123
|
+
:post => @post,
|
124
|
+
:meta => @meta,
|
125
|
+
:cookie => @cookie
|
126
|
+
}
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
class Hayabusa::Cgi_tools
|
2
|
+
attr_accessor :cgi
|
3
|
+
|
4
|
+
def convert_fcgi_post(params)
|
5
|
+
post_hash = {}
|
6
|
+
|
7
|
+
params.each do |key, val|
|
8
|
+
post_hash[key] = val.first
|
9
|
+
end
|
10
|
+
|
11
|
+
post_ret = {}
|
12
|
+
post_hash.each do |varname, value|
|
13
|
+
Knj::Web.parse_name(post_ret, varname, value, :urldecode => true)
|
14
|
+
end
|
15
|
+
|
16
|
+
return post_ret
|
17
|
+
end
|
18
|
+
|
19
|
+
def env_table
|
20
|
+
return ENV
|
21
|
+
end
|
22
|
+
|
23
|
+
def request_method
|
24
|
+
return ENV["REQUEST_METHOD"]
|
25
|
+
end
|
26
|
+
|
27
|
+
def content_type
|
28
|
+
return ENV["CONTENT_TYPE"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def params
|
32
|
+
return self.cgi.params
|
33
|
+
end
|
34
|
+
|
35
|
+
def print(arg)
|
36
|
+
Kernel.print arg.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
#This method is used to proxy a request to another FCGI-process, since a single FCGI-process cant handle more requests simultanious.
|
40
|
+
def proxy_request_to(args)
|
41
|
+
cgi = args[:cgi]
|
42
|
+
http = args[:http]
|
43
|
+
|
44
|
+
File.open("/tmp/debug_#{Process.pid}_#{Time.new.to_f}.log", "w") do |fp_log|
|
45
|
+
|
46
|
+
headers = {"Hayabusa_mode" => "proxy"}
|
47
|
+
cgi.env_table.each do |key, val|
|
48
|
+
if key[0, 5] == "HTTP_" and key != "HTTP_HAYABUSA_CGI_CONFIG"
|
49
|
+
key = key[5, key.length].gsub("_", " ")
|
50
|
+
key = key.to_s.split(" ").select{|w| w.capitalize! or w }.join(" ")
|
51
|
+
key = key.gsub(" ", "-")
|
52
|
+
headers[key] = val
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
#Make request.
|
57
|
+
uri = Knj::Web.parse_uri(cgi.env_table["REQUEST_URI"])
|
58
|
+
url = File.basename(uri[:path])
|
59
|
+
|
60
|
+
if cgi.env_table["QUERY_STRING"].to_s.length > 0
|
61
|
+
url << "?#{cgi.env_table["QUERY_STRING"]}"
|
62
|
+
end
|
63
|
+
|
64
|
+
#cgi.print "Content-Type: text/html\r\n"
|
65
|
+
#cgi.print "\r\n"
|
66
|
+
|
67
|
+
if cgi.request_method == "POST" and cgi.content_type.to_s.downcase.index("multipart/form-data") != nil
|
68
|
+
count = 0
|
69
|
+
http.post_multipart(:url => url, :post => self.convert_fcgi_post(cgi.params),
|
70
|
+
:default_headers => headers,
|
71
|
+
:cookies => false,
|
72
|
+
:on_content => proc{|line|
|
73
|
+
cgi.print(line) if count > 0
|
74
|
+
count += 1
|
75
|
+
}
|
76
|
+
)
|
77
|
+
elsif cgi.request_method == "POST"
|
78
|
+
count = 0
|
79
|
+
http.post(:url => url, :post => self.convert_fcgi_post(cgi.params),
|
80
|
+
:default_headers => headers,
|
81
|
+
:cookies => false,
|
82
|
+
:on_content => proc{|line|
|
83
|
+
cgi.print(line) if count > 0
|
84
|
+
count += 1
|
85
|
+
}
|
86
|
+
)
|
87
|
+
else
|
88
|
+
count = 0
|
89
|
+
http.get(:url => url,
|
90
|
+
:default_headers => headers,
|
91
|
+
:cookies => false,
|
92
|
+
:on_content => proc{|line|
|
93
|
+
fp_log.puts("Line: '#{line}'.")
|
94
|
+
cgi.print(line) if count > 0
|
95
|
+
count += 1
|
96
|
+
}
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Hayabusa::Custom_io < StringIO
|
2
|
+
def print(str)
|
3
|
+
str = str.to_s
|
4
|
+
|
5
|
+
if appsrv = Thread.current[:hayabusa] and cgroup = appsrv[:contentgroup] and httpsession = appsrv[:httpsession]
|
6
|
+
httpsession.add_size(str.size)
|
7
|
+
cgroup.write(str)
|
8
|
+
else
|
9
|
+
STDOUT.print(str) if !STDOUT.closed?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def puts(str)
|
14
|
+
res = self.print(str)
|
15
|
+
self.print "\n"
|
16
|
+
return res
|
17
|
+
end
|
18
|
+
|
19
|
+
alias << print
|
20
|
+
alias write print
|
21
|
+
alias p print
|
22
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
class Hayabusa::Database
|
2
|
+
SCHEMA = {
|
3
|
+
"tables" => {
|
4
|
+
"Log" => {
|
5
|
+
"columns" => [
|
6
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
7
|
+
{"name" => "text_value_id", "type" => "bigint"},
|
8
|
+
{"name" => "date_saved", "type" => "datetime"},
|
9
|
+
{"name" => "get_keys_data_id", "type" => "bigint"},
|
10
|
+
{"name" => "get_values_data_id", "type" => "bigint"},
|
11
|
+
{"name" => "post_keys_data_id", "type" => "bigint"},
|
12
|
+
{"name" => "post_values_data_id", "type" => "bigint"},
|
13
|
+
{"name" => "cookie_keys_data_id", "type" => "bigint"},
|
14
|
+
{"name" => "cookie_values_data_id", "type" => "bigint"},
|
15
|
+
{"name" => "meta_keys_data_id", "type" => "bigint"},
|
16
|
+
{"name" => "meta_values_data_id", "type" => "bigint"},
|
17
|
+
{"name" => "session_keys_data_id", "type" => "bigint"},
|
18
|
+
{"name" => "session_values_data_id", "type" => "bigint"},
|
19
|
+
{"name" => "tag_data_id", "type" => "bigint"},
|
20
|
+
{"name" => "comment_data_id", "type" => "bigint"}
|
21
|
+
],
|
22
|
+
"indexes" => [
|
23
|
+
{"name" => "text_value_id", "columns" => ["text_value_id"]},
|
24
|
+
{"name" => "tag_data_id", "columns" => ["tag_data_id"]},
|
25
|
+
{"name" => "comment_data_id", "columns" => ["comment_data_id"]}
|
26
|
+
]
|
27
|
+
},
|
28
|
+
"Log_access" => {
|
29
|
+
"columns" => [
|
30
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
31
|
+
{"name" => "session_id", "type" => "bigint"},
|
32
|
+
{"name" => "date_request", "type" => "datetime"},
|
33
|
+
{"name" => "ip_data_id", "type" => "bigint"},
|
34
|
+
{"name" => "get_keys_data_id", "type" => "bigint"},
|
35
|
+
{"name" => "get_values_data_id", "type" => "bigint"},
|
36
|
+
{"name" => "post_keys_data_id", "type" => "bigint"},
|
37
|
+
{"name" => "post_values_data_id", "type" => "bigint"},
|
38
|
+
{"name" => "cookie_keys_data_id", "type" => "bigint"},
|
39
|
+
{"name" => "cookie_values_data_id", "type" => "bigint"},
|
40
|
+
{"name" => "meta_keys_data_id", "type" => "bigint"},
|
41
|
+
{"name" => "meta_values_data_id", "type" => "bigint"}
|
42
|
+
],
|
43
|
+
"indexes" => [
|
44
|
+
{"name" => "session_id", "columns" => ["session_id"]},
|
45
|
+
{"name" => "date_request", "columns" => ["date_request"]}
|
46
|
+
]
|
47
|
+
},
|
48
|
+
"Log_data" => {
|
49
|
+
"columns" => [
|
50
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
51
|
+
{"name" => "id_hash", "type" => "varchar"}
|
52
|
+
],
|
53
|
+
"indexes" => [
|
54
|
+
{"name" => "id_hash", "columns" => ["id_hash"]}
|
55
|
+
]
|
56
|
+
},
|
57
|
+
"Log_data_link" => {
|
58
|
+
"columns" => [
|
59
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
60
|
+
{"name" => "no", "type" => "int"},
|
61
|
+
{"name" => "data_id", "type" => "bigint"},
|
62
|
+
{"name" => "value_id", "type" => "bigint"}
|
63
|
+
],
|
64
|
+
"indexes" => [
|
65
|
+
{"name" => "data_id", "columns" => ["data_id"]},
|
66
|
+
{"name" => "value_id", "columns" => ["value_id"]}
|
67
|
+
]
|
68
|
+
},
|
69
|
+
"Log_data_value" => {
|
70
|
+
"columns" => [
|
71
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
72
|
+
{"name" => "value", "type" => "text"}
|
73
|
+
]
|
74
|
+
},
|
75
|
+
"Log_link" => {
|
76
|
+
"columns" => [
|
77
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
78
|
+
{"name" => "log_id", "type" => "bigint"},
|
79
|
+
{"name" => "object_class_value_id", "type" => "bigint"},
|
80
|
+
{"name" => "object_id", "type" => "bigint"}
|
81
|
+
],
|
82
|
+
"indexes" => [
|
83
|
+
{"name" => "log_id", "columns" => ["log_id"]},
|
84
|
+
{"name" => "object_id", "columns" => ["object_id"]},
|
85
|
+
{"name" => "object_class_value_id", "columns" => ["object_class_value_id"]},
|
86
|
+
{"name" => "object_lookup", "columns" => ["object_class_value_id", "object_id"]},
|
87
|
+
{"name" => "log_lookup", "columns" => ["object_class_value_id", "object_id", "log_id"]}
|
88
|
+
]
|
89
|
+
},
|
90
|
+
"Session" => {
|
91
|
+
"columns" => [
|
92
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
93
|
+
{"name" => "idhash", "type" => "varchar"},
|
94
|
+
{"name" => "sess_data", "type" => "text"},
|
95
|
+
{"name" => "date_added", "type" => "datetime"},
|
96
|
+
{"name" => "date_lastused", "type" => "datetime", "on_created" => proc{|d| d["db"].query("UPDATE Session SET date_lastused = '#{Datet.new.dbstr}'")}},
|
97
|
+
{"name" => "ip", "type" => "varchar", "maxlength" => 15},
|
98
|
+
{"name" => "user_agent", "type" => "text"},
|
99
|
+
{"name" => "remember", "type" => "enum", "maxlength" => "'0','1'", "default" => 0, "comment" => "If the session should be remembered or not."}
|
100
|
+
],
|
101
|
+
"indexes" => [
|
102
|
+
{"name" => "date_added", "columns" => ["date_added"]},
|
103
|
+
{"name" => "idhash", "columns" => ["idhash"]}
|
104
|
+
],
|
105
|
+
"renames" => ["sessions"]
|
106
|
+
},
|
107
|
+
"Translation" => {
|
108
|
+
"columns" => [
|
109
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
110
|
+
{"name" => "object_class", "type" => "varchar", "maxlength" => 50},
|
111
|
+
{"name" => "object_id", "type" => "bigint"},
|
112
|
+
{"name" => "key", "type" => "varchar", "maxlength" => 50},
|
113
|
+
{"name" => "locale", "type" => "varchar", "maxlength" => 5},
|
114
|
+
{"name" => "value", "type" => "text"}
|
115
|
+
],
|
116
|
+
"indexes" => [
|
117
|
+
{"name" => "lookup", "columns" => ["object_class", "object_id", "key", "locale"]}
|
118
|
+
],
|
119
|
+
"indexes_remove" => {
|
120
|
+
"object_class" => true
|
121
|
+
}
|
122
|
+
}
|
123
|
+
}
|
124
|
+
}
|
125
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Hayabusa::Erb_handler
|
2
|
+
def initialize
|
3
|
+
@connected = {}
|
4
|
+
end
|
5
|
+
|
6
|
+
def erb_handler(httpsess)
|
7
|
+
eruby = httpsess.eruby
|
8
|
+
|
9
|
+
if !@connected.key?(eruby.__id__)
|
10
|
+
eruby.connect("error", &self.method(:on_error))
|
11
|
+
@connected[eruby.__id__] = true
|
12
|
+
end
|
13
|
+
|
14
|
+
if !File.exists?(httpsess.page_path)
|
15
|
+
eruby.import("#{File.dirname(__FILE__)}/../pages/error_notfound.rhtml")
|
16
|
+
else
|
17
|
+
eruby.import(httpsess.page_path)
|
18
|
+
end
|
19
|
+
|
20
|
+
httpsess.resp.status = 500 if eruby.error
|
21
|
+
end
|
22
|
+
|
23
|
+
#Handels the event when an error in the eruby-instance occurs.
|
24
|
+
def on_error(e)
|
25
|
+
_hb.handle_error(e)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
class Hayabusa
|
2
|
+
def initialize_cleaner
|
3
|
+
#This should not be runned via _hb.timeout because timeout wont run when @should_restart is true! - knj
|
4
|
+
Thread.new(&self.method(:clean_autorestart))
|
5
|
+
|
6
|
+
#This flushes (writes) all session-data to the server and deletes old unused sessions from the database.
|
7
|
+
self.timeout(:time => @config[:cleaner_timeout], &self.method(:clean_sessions))
|
8
|
+
end
|
9
|
+
|
10
|
+
def clean
|
11
|
+
self.clean_sessions
|
12
|
+
self.clean_autorestart
|
13
|
+
end
|
14
|
+
|
15
|
+
def clean_autorestart
|
16
|
+
begin
|
17
|
+
if @config[:autorestart]
|
18
|
+
time = 1
|
19
|
+
else
|
20
|
+
time = 15
|
21
|
+
end
|
22
|
+
|
23
|
+
loop do
|
24
|
+
sleep time
|
25
|
+
|
26
|
+
if @config.has_key?(:restart_when_used_memory) and !@should_restart
|
27
|
+
mbs_used = (Php4r.memory_get_usage / 1024) / 1024
|
28
|
+
STDOUT.print "Restart when over #{@config[:restart_when_used_memory]}mb\n" if @config[:debug]
|
29
|
+
STDOUT.print "Used: #{mbs_used}mb\n" if @config[:debug]
|
30
|
+
|
31
|
+
if mbs_used.to_i >= @config[:restart_when_used_memory].to_i
|
32
|
+
STDOUT.print "Memory is over #{@config[:restart_when_used_memory]} - restarting.\n"
|
33
|
+
@should_restart = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if @should_restart and !@should_restart_done and !@should_restart_runnning
|
38
|
+
begin
|
39
|
+
@should_restart_runnning = true
|
40
|
+
|
41
|
+
#When we begin to restart it should go as fast as possible - so start by flushing out any emails waiting so it goes faster the last time...
|
42
|
+
STDOUT.print "Flushing mails.\n"
|
43
|
+
self.mail_flush
|
44
|
+
|
45
|
+
#Lets try to find a time where no thread is working within the next 30 seconds. If we cant - we interrupt after 10 seconds and restart the server.
|
46
|
+
begin
|
47
|
+
Timeout.timeout(30) do
|
48
|
+
loop do
|
49
|
+
working_count = self.httpserv.working_count
|
50
|
+
working = false
|
51
|
+
|
52
|
+
if working_count and working_count > 0
|
53
|
+
working = true
|
54
|
+
STDOUT.print "Someone is working - wait two sec and try to restart again!\n"
|
55
|
+
end
|
56
|
+
|
57
|
+
if !working
|
58
|
+
STDOUT.print "Found window where no sessions were active - restarting!\n"
|
59
|
+
break
|
60
|
+
else
|
61
|
+
sleep 0.2
|
62
|
+
end
|
63
|
+
|
64
|
+
STDOUT.print "Trying to find window with no active sessions to restart...\n"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
rescue Timeout::Error
|
68
|
+
STDOUT.print "Could not find a timing window for restarting... Forcing restart!\n"
|
69
|
+
end
|
70
|
+
|
71
|
+
#Flush emails again if any are pending (while we tried to find a window to restart)...
|
72
|
+
STDOUT.print "Flushing mails.\n"
|
73
|
+
self.mail_flush
|
74
|
+
|
75
|
+
STDOUT.print "Stopping appserver.\n"
|
76
|
+
self.stop
|
77
|
+
|
78
|
+
STDOUT.print "Figuring out restart-command.\n"
|
79
|
+
mycmd = @config[:restart_cmd]
|
80
|
+
|
81
|
+
if !mycmd or mycmd.to_s.strip.length <= 0
|
82
|
+
fpath = File.realpath("#{File.dirname(__FILE__)}/../hayabusa.rb")
|
83
|
+
mycmd = Knj::Os.executed_cmd
|
84
|
+
|
85
|
+
STDOUT.print "Previous cmd: #{mycmd}\n"
|
86
|
+
mycmd = mycmd.gsub(/\s+hayabusa.rb/, " #{Knj::Strings.unixsafe(fpath)}")
|
87
|
+
end
|
88
|
+
|
89
|
+
STDOUT.print "Restarting knjAppServer with command: #{mycmd}\n"
|
90
|
+
@should_restart_done = true
|
91
|
+
print exec(mycmd)
|
92
|
+
exit
|
93
|
+
rescue => e
|
94
|
+
STDOUT.puts e.inspect
|
95
|
+
STDOUT.puts e.backtrace
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
rescue => e
|
100
|
+
self.handle_error(e)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
#This method can be used to clean the appserver. Dont call this from a HTTP-request.
|
105
|
+
def clean_sessions
|
106
|
+
STDOUT.print "Cleaning sessions on appserver.\n" if @config[:debug]
|
107
|
+
|
108
|
+
#Clean up various inactive sessions.
|
109
|
+
session_not_ids = []
|
110
|
+
time_check = Time.now.to_i - 300
|
111
|
+
newsessions = {}
|
112
|
+
@sessions.each do |session_hash, session_data|
|
113
|
+
session_data[:dbobj].flush
|
114
|
+
|
115
|
+
if session_data[:time_lastused].to_i > time_check
|
116
|
+
newsessions[session_hash] = session_data
|
117
|
+
session_not_ids << session_data[:dbobj].id
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
@sessions = newsessions
|
122
|
+
|
123
|
+
STDOUT.print "Delete sessions...\n" if @config[:debug]
|
124
|
+
@ob.list(:Session, {"id_not" => session_not_ids, "date_lastused_below" => (Time.now - 5356800)}) do |session|
|
125
|
+
idhash = session[:idhash]
|
126
|
+
STDOUT.print "Deleting session: '#{session.id}'.\n" if @config[:debug]
|
127
|
+
@ob.delete(session)
|
128
|
+
@sessions.delete(idhash)
|
129
|
+
end
|
130
|
+
|
131
|
+
#Clean database weak references from the tables-module.
|
132
|
+
@db.clean
|
133
|
+
|
134
|
+
#Clean the object-handler.
|
135
|
+
@ob.clean_all
|
136
|
+
|
137
|
+
#Call various user-connected methods.
|
138
|
+
@events.call(:on_clean) if @events
|
139
|
+
end
|
140
|
+
end
|