hayabusa 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +20 -0
  4. data/Gemfile.lock +59 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +19 -0
  7. data/Rakefile +49 -0
  8. data/VERSION +1 -0
  9. data/bin/check_running.rb +69 -0
  10. data/bin/hayabusa_benchmark.rb +82 -0
  11. data/bin/hayabusa_cgi.rb +84 -0
  12. data/bin/hayabusa_fcgi.fcgi +159 -0
  13. data/bin/hayabusa_fcgi.rb +159 -0
  14. data/bin/knjappserver_start.rb +42 -0
  15. data/conf/apache2_cgi_rhtml_conf.conf +10 -0
  16. data/conf/apache2_fcgi_rhtml_conf.conf +22 -0
  17. data/hayabusa.gemspec +151 -0
  18. data/lib/hayabusa.rb +518 -0
  19. data/lib/hayabusa_cgi_session.rb +128 -0
  20. data/lib/hayabusa_cgi_tools.rb +102 -0
  21. data/lib/hayabusa_custom_io.rb +22 -0
  22. data/lib/hayabusa_database.rb +125 -0
  23. data/lib/hayabusa_erb_handler.rb +27 -0
  24. data/lib/hayabusa_ext/cleaner.rb +140 -0
  25. data/lib/hayabusa_ext/cmdline.rb +52 -0
  26. data/lib/hayabusa_ext/errors.rb +135 -0
  27. data/lib/hayabusa_ext/logging.rb +404 -0
  28. data/lib/hayabusa_ext/mailing.rb +158 -0
  29. data/lib/hayabusa_ext/sessions.rb +71 -0
  30. data/lib/hayabusa_ext/threadding.rb +96 -0
  31. data/lib/hayabusa_ext/threadding_timeout.rb +101 -0
  32. data/lib/hayabusa_ext/translations.rb +43 -0
  33. data/lib/hayabusa_ext/web.rb +190 -0
  34. data/lib/hayabusa_http_server.rb +102 -0
  35. data/lib/hayabusa_http_session.rb +361 -0
  36. data/lib/hayabusa_http_session_contentgroup.rb +176 -0
  37. data/lib/hayabusa_http_session_page_environment.rb +66 -0
  38. data/lib/hayabusa_http_session_post_multipart.rb +135 -0
  39. data/lib/hayabusa_http_session_request.rb +219 -0
  40. data/lib/hayabusa_http_session_response.rb +144 -0
  41. data/lib/hayabusa_models.rb +8 -0
  42. data/lib/kernel_ext/gettext_methods.rb +22 -0
  43. data/lib/kernel_ext/magic_methods.rb +61 -0
  44. data/lib/models/log.rb +130 -0
  45. data/lib/models/log_access.rb +88 -0
  46. data/lib/models/log_data.rb +27 -0
  47. data/lib/models/log_data_link.rb +3 -0
  48. data/lib/models/log_data_value.rb +21 -0
  49. data/lib/models/log_link.rb +65 -0
  50. data/lib/models/session.rb +35 -0
  51. data/pages/benchmark.rhtml +0 -0
  52. data/pages/benchmark_print.rhtml +14 -0
  53. data/pages/benchmark_simple.rhtml +3 -0
  54. data/pages/benchmark_threadded_content.rhtml +21 -0
  55. data/pages/debug_database_connections.rhtml +46 -0
  56. data/pages/debug_http_sessions.rhtml +40 -0
  57. data/pages/debug_memory_usage.rhtml +16 -0
  58. data/pages/error_notfound.rhtml +12 -0
  59. data/pages/logs_latest.rhtml +57 -0
  60. data/pages/logs_show.rhtml +32 -0
  61. data/pages/spec.rhtml +41 -0
  62. data/pages/spec_post.rhtml +3 -0
  63. data/pages/spec_test_multiple_clients.rhtml +3 -0
  64. data/pages/spec_thread_joins.rhtml +21 -0
  65. data/pages/spec_threadded_content.rhtml +40 -0
  66. data/pages/tests.rhtml +14 -0
  67. data/spec/cgi_spec.rb +47 -0
  68. data/spec/custom_urls_spec.rb +35 -0
  69. data/spec/fcgi_multiple_processes_spec.rb +32 -0
  70. data/spec/fcgi_spec.rb +69 -0
  71. data/spec/hayabusa_spec.rb +194 -0
  72. data/spec/spec_helper.rb +12 -0
  73. data/tests/cgi_test/config_cgi.rb +6 -0
  74. data/tests/cgi_test/threadded_content_test.rhtml +23 -0
  75. data/tests/cgi_test/vars_get_test.rhtml +4 -0
  76. data/tests/cgi_test/vars_header_test.rhtml +3 -0
  77. data/tests/cgi_test/vars_post_test.rhtml +4 -0
  78. data/tests/fcgi_test/config_fcgi.rb +6 -0
  79. data/tests/fcgi_test/index.rhtml +3 -0
  80. data/tests/fcgi_test/sleeper.rhtml +4 -0
  81. data/tests/fcgi_test/threadded_content_test.rhtml +23 -0
  82. data/tests/fcgi_test/vars_get_test.rhtml +4 -0
  83. data/tests/fcgi_test/vars_header_test.rhtml +3 -0
  84. data/tests/fcgi_test/vars_post_test.rhtml +4 -0
  85. 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