knjappserver 0.0.29 → 0.0.30
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.
- data/Gemfile +1 -0
- data/Gemfile.lock +4 -0
- data/VERSION +1 -1
- data/bin/check_running.rb +0 -1
- data/knjappserver.gemspec +6 -2
- data/lib/include/class_erbhandler.rb +6 -4
- data/lib/include/class_httpserver.rb +15 -9
- data/lib/include/class_httpsession.rb +70 -76
- data/lib/include/class_knjappserver.rb +22 -21
- data/lib/include/class_knjappserver_cleaner.rb +87 -80
- data/lib/include/class_knjappserver_cmdline.rb +12 -9
- data/lib/include/class_knjappserver_errors.rb +8 -10
- data/lib/include/class_knjappserver_leakproxy_server.rb +1 -1
- data/lib/include/class_knjappserver_logging.rb +6 -6
- data/lib/include/class_knjappserver_mailing.rb +5 -4
- data/lib/include/class_knjappserver_threadding.rb +7 -3
- data/lib/include/class_knjappserver_translations.rb +11 -5
- data/lib/include/class_knjappserver_web.rb +17 -12
- data/lib/pages/benchmark_simple.rhtml +1 -1
- data/lib/pages/debug_memory_usage.rhtml +16 -0
- data/lib/scripts/knjappserver_cgi.rb +1 -1
- data/lib/scripts/knjappserver_fcgi.rb +2 -2
- metadata +25 -13
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -22,6 +22,9 @@ GEM
|
|
22
22
|
mime-types (~> 1.16)
|
23
23
|
treetop (~> 1.4.8)
|
24
24
|
mime-types (1.19)
|
25
|
+
php4r (0.0.0)
|
26
|
+
datet
|
27
|
+
http2
|
25
28
|
polyglot (0.3.3)
|
26
29
|
rake (0.9.2.2)
|
27
30
|
rspec (2.3.0)
|
@@ -51,6 +54,7 @@ DEPENDENCIES
|
|
51
54
|
json
|
52
55
|
knjrbfw
|
53
56
|
mail
|
57
|
+
php4r
|
54
58
|
rspec (~> 2.3.0)
|
55
59
|
sqlite3
|
56
60
|
tsafe
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.30
|
data/bin/check_running.rb
CHANGED
data/knjappserver.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{knjappserver}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.30"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kasper Johansen"]
|
12
|
-
s.date = %q{2012-
|
12
|
+
s.date = %q{2012-08-03}
|
13
13
|
s.description = %q{Which supports a lot of undocumented stuff.}
|
14
14
|
s.email = %q{k@spernj.org}
|
15
15
|
s.executables = ["check_running.rb", "knjappserver_start.rb"]
|
@@ -73,6 +73,7 @@ Gem::Specification.new do |s|
|
|
73
73
|
"lib/pages/benchmark_threadded_content.rhtml",
|
74
74
|
"lib/pages/debug_database_connections.rhtml",
|
75
75
|
"lib/pages/debug_http_sessions.rhtml",
|
76
|
+
"lib/pages/debug_memory_usage.rhtml",
|
76
77
|
"lib/pages/error_notfound.rhtml",
|
77
78
|
"lib/pages/logs_latest.rhtml",
|
78
79
|
"lib/pages/logs_show.rhtml",
|
@@ -106,6 +107,7 @@ Gem::Specification.new do |s|
|
|
106
107
|
s.add_runtime_dependency(%q<tsafe>, [">= 0"])
|
107
108
|
s.add_runtime_dependency(%q<datet>, [">= 0"])
|
108
109
|
s.add_runtime_dependency(%q<http2>, [">= 0"])
|
110
|
+
s.add_runtime_dependency(%q<php4r>, [">= 0"])
|
109
111
|
s.add_development_dependency(%q<json>, [">= 0"])
|
110
112
|
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
111
113
|
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
@@ -118,6 +120,7 @@ Gem::Specification.new do |s|
|
|
118
120
|
s.add_dependency(%q<tsafe>, [">= 0"])
|
119
121
|
s.add_dependency(%q<datet>, [">= 0"])
|
120
122
|
s.add_dependency(%q<http2>, [">= 0"])
|
123
|
+
s.add_dependency(%q<php4r>, [">= 0"])
|
121
124
|
s.add_dependency(%q<json>, [">= 0"])
|
122
125
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
123
126
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
@@ -131,6 +134,7 @@ Gem::Specification.new do |s|
|
|
131
134
|
s.add_dependency(%q<tsafe>, [">= 0"])
|
132
135
|
s.add_dependency(%q<datet>, [">= 0"])
|
133
136
|
s.add_dependency(%q<http2>, [">= 0"])
|
137
|
+
s.add_dependency(%q<php4r>, [">= 0"])
|
134
138
|
s.add_dependency(%q<json>, [">= 0"])
|
135
139
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
136
140
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
@@ -7,10 +7,7 @@ class Knjappserver::ERBHandler
|
|
7
7
|
eruby = httpsess.eruby
|
8
8
|
|
9
9
|
if !@connected.key?(eruby.__id__)
|
10
|
-
eruby.connect("error")
|
11
|
-
_kas.handle_error(e)
|
12
|
-
end
|
13
|
-
|
10
|
+
eruby.connect("error", &self.method(:on_error))
|
14
11
|
@connected[eruby.__id__] = true
|
15
12
|
end
|
16
13
|
|
@@ -22,4 +19,9 @@ class Knjappserver::ERBHandler
|
|
22
19
|
|
23
20
|
httpsess.resp.status = 500 if eruby.error
|
24
21
|
end
|
22
|
+
|
23
|
+
#Handels the event when an error in the eruby-instance occurs.
|
24
|
+
def on_error(e)
|
25
|
+
_kas.handle_error(e)
|
26
|
+
end
|
25
27
|
end
|
@@ -82,15 +82,21 @@ class Knjappserver::Httpserver
|
|
82
82
|
@http_sessions << Knjappserver::Httpsession.new(self, socket)
|
83
83
|
end
|
84
84
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
85
|
+
def count_block
|
86
|
+
begin
|
87
|
+
added = false
|
88
|
+
@mutex_count.synchronize do
|
89
|
+
@working_count += 1 if @working_count != nil
|
90
|
+
added = true
|
91
|
+
end
|
92
|
+
|
93
|
+
yield
|
94
|
+
ensure
|
95
|
+
@kas.served += 1 if @kas
|
96
|
+
|
97
|
+
@mutex_count.synchronize do
|
98
|
+
@working_count -= 1 if @working_count != nil and added
|
99
|
+
end
|
94
100
|
end
|
95
101
|
end
|
96
102
|
end
|
@@ -23,7 +23,7 @@ class Knjappserver::Httpsession
|
|
23
23
|
|
24
24
|
@eruby = Knj::Eruby.new(
|
25
25
|
:cache_hash => @kas.eruby_cache,
|
26
|
-
:binding_callback => self.method(
|
26
|
+
:binding_callback => self.method(:create_binding)
|
27
27
|
)
|
28
28
|
|
29
29
|
#Set socket stuff.
|
@@ -49,92 +49,86 @@ class Knjappserver::Httpsession
|
|
49
49
|
|
50
50
|
@resp = Knjappserver::Httpsession::Http_response.new(:socket => @socket)
|
51
51
|
@handler = Knjappserver::Httpsession::Http_request.new(:kas => @kas, :httpsession => self)
|
52
|
-
|
53
|
-
@cgroup = Knjappserver::Httpsession::Contentgroup.new(
|
54
|
-
:socket => @socket,
|
55
|
-
:kas => @kas,
|
56
|
-
:resp => @resp,
|
57
|
-
:httpsession => self
|
58
|
-
)
|
52
|
+
@cgroup = Knjappserver::Httpsession::Contentgroup.new(:socket => @socket, :kas => @kas, :resp => @resp, :httpsession => self)
|
59
53
|
@resp.cgroup = @cgroup
|
60
54
|
|
61
55
|
Dir.chdir(@config[:doc_root])
|
62
56
|
ObjectSpace.define_finalizer(self, self.class.method(:finalize).to_proc) if @debug
|
63
57
|
STDOUT.print "New httpsession #{self.__id__} (total: #{@httpserver.http_sessions.count}).\n" if @debug
|
64
58
|
|
65
|
-
@thread_request = Thread.new
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
59
|
+
@thread_request = Thread.new(&self.method(:thread_request_run))
|
60
|
+
end
|
61
|
+
|
62
|
+
def thread_request_run
|
63
|
+
Thread.current[:knjappserver] = {} if !Thread.current[:knjappserver]
|
64
|
+
Thread.current[:type] = :httpsession
|
65
|
+
|
66
|
+
if @config.key?(:max_requests_working)
|
67
|
+
max_requests_working = @config[:max_requests_working].to_i
|
68
|
+
else
|
69
|
+
max_requests_working = false
|
70
|
+
end
|
71
|
+
|
72
|
+
begin
|
73
|
+
while @active
|
74
|
+
begin
|
75
|
+
@cgroup.reset
|
76
|
+
@written_size = 0
|
77
|
+
@size_send = @config[:size_send]
|
78
|
+
@alert_sent = false
|
79
|
+
@working = false
|
80
|
+
break if @kas.should_restart
|
81
|
+
|
82
|
+
STDOUT.print "#{__id__} - Waiting to parse from socket.\n" if @debug
|
83
|
+
Timeout.timeout(1800) do
|
84
|
+
@handler.socket_parse(@socket)
|
85
|
+
end
|
86
|
+
|
87
|
+
STDOUT.print "#{__id__} - Done parsing from socket.\n" if @debug
|
88
|
+
|
89
|
+
while @kas.paused? #Check if we should be waiting with executing the pending request.
|
90
|
+
STDOUT.print "#{__id__} - Paused! (#{@kas.paused}) - sleeping.\n" if @debug
|
91
|
+
sleep 0.1
|
92
|
+
end
|
93
|
+
|
94
|
+
break if @kas.should_restart
|
95
|
+
|
96
|
+
if max_requests_working and @httpserver
|
97
|
+
while @httpserver.working_count.to_i >= max_requests_working
|
98
|
+
STDOUT.print "#{__id__} - Maximum amounts of requests are working (#{@httpserver.working_count}, #{max_requests_working}) - sleeping.\n" if @debug
|
93
99
|
sleep 0.1
|
94
100
|
end
|
95
|
-
|
96
|
-
break if @kas.should_restart
|
97
|
-
|
98
|
-
if @config.key?(:max_requests_working)
|
99
|
-
while @httpserver and @config and @httpserver.working_count.to_i >= @config[:max_requests_working].to_i
|
100
|
-
STDOUT.print "#{__id__} - Maximum amounts of requests are working (#{@httpserver.working_count}, #{@config[:max_requests_working]}) - sleeping.\n" if @debug
|
101
|
-
sleep 0.1
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
#Reserve database connections.
|
106
|
-
@kas.db_handler.get_and_register_thread if @kas.db_handler.opts[:threadsafe]
|
107
|
-
@kas.ob.db.get_and_register_thread if @kas.ob.db.opts[:threadsafe]
|
108
|
-
|
109
|
-
@httpserver.count_add
|
110
|
-
@working = true
|
111
|
-
STDOUT.print "#{__id__} - Serving.\n" if @debug
|
112
|
-
|
113
|
-
begin
|
114
|
-
self.serve
|
115
|
-
ensure
|
116
|
-
@httpserver.count_remove
|
117
|
-
@kas.served += 1 if @kas
|
118
|
-
@working = false
|
119
|
-
end
|
120
|
-
ensure
|
121
|
-
STDOUT.print "#{__id__} - Closing request.\n" if @debug
|
122
|
-
#Free reserved database-connections.
|
123
|
-
@kas.db_handler.free_thread if @kas and @kas.db_handler.opts[:threadsafe]
|
124
|
-
@kas.ob.db.free_thread if @kas and @kas.ob.db.opts[:threadsafe]
|
125
101
|
end
|
102
|
+
|
103
|
+
#Reserve database connections.
|
104
|
+
@kas.db_handler.get_and_register_thread if @kas.db_handler.opts[:threadsafe]
|
105
|
+
@kas.ob.db.get_and_register_thread if @kas.ob.db.opts[:threadsafe]
|
106
|
+
|
107
|
+
@working = true
|
108
|
+
STDOUT.print "#{__id__} - Serving.\n" if @debug
|
109
|
+
|
110
|
+
@httpserver.count_block do
|
111
|
+
self.serve
|
112
|
+
end
|
113
|
+
ensure
|
114
|
+
STDOUT.print "#{__id__} - Closing request.\n" if @debug
|
115
|
+
@working = false
|
116
|
+
|
117
|
+
#Free reserved database-connections.
|
118
|
+
@kas.db_handler.free_thread if @kas and @kas.db_handler.opts[:threadsafe]
|
119
|
+
@kas.ob.db.free_thread if @kas and @kas.ob.db.opts[:threadsafe]
|
126
120
|
end
|
127
|
-
rescue Timeout::Error
|
128
|
-
STDOUT.print "#{__id__} - Closing httpsession because of timeout.\n" if @debug
|
129
|
-
rescue Errno::ECONNRESET, Errno::ENOTCONN, Errno::EPIPE => e
|
130
|
-
STDOUT.print "#{__id__} - Connection error (#{e.inspect})...\n" if @debug
|
131
|
-
rescue Interrupt => e
|
132
|
-
raise e
|
133
|
-
rescue Exception => e
|
134
|
-
STDOUT.puts Knj::Errors.error_str(e)
|
135
|
-
ensure
|
136
|
-
self.destruct
|
137
121
|
end
|
122
|
+
rescue Timeout::Error
|
123
|
+
STDOUT.print "#{__id__} - Closing httpsession because of timeout.\n" if @debug
|
124
|
+
rescue Errno::ECONNRESET, Errno::ENOTCONN, Errno::EPIPE => e
|
125
|
+
STDOUT.print "#{__id__} - Connection error (#{e.inspect})...\n" if @debug
|
126
|
+
rescue Interrupt => e
|
127
|
+
raise e
|
128
|
+
rescue Exception => e
|
129
|
+
STDOUT.puts Knj::Errors.error_str(e)
|
130
|
+
ensure
|
131
|
+
self.destruct
|
138
132
|
end
|
139
133
|
end
|
140
134
|
|
@@ -1,9 +1,10 @@
|
|
1
|
-
require "
|
1
|
+
require "base64"
|
2
2
|
require "digest"
|
3
3
|
require "erubis"
|
4
|
-
require "
|
4
|
+
require "monitor"
|
5
5
|
require "stringio"
|
6
6
|
require "socket"
|
7
|
+
require "timeout"
|
7
8
|
require "tsafe" if !Kernel.const_defined?(:Tsafe)
|
8
9
|
|
9
10
|
#The class that stands for the whole appserver / webserver.
|
@@ -44,7 +45,7 @@ class Knjappserver
|
|
44
45
|
|
45
46
|
|
46
47
|
#Require gems.
|
47
|
-
gems = %w[datet]
|
48
|
+
gems = %w[datet php4r]
|
48
49
|
gems.each do |gem|
|
49
50
|
puts "Loading gem: '#{gem}'." if @debug
|
50
51
|
require gem
|
@@ -67,9 +68,7 @@ class Knjappserver
|
|
67
68
|
|
68
69
|
|
69
70
|
#Add extra handlers if given.
|
70
|
-
if @config[:handlers_extra]
|
71
|
-
@config[:handlers] += @config[:handlers_extra]
|
72
|
-
end
|
71
|
+
@config[:handlers] += @config[:handlers_extra] if @config[:handlers_extra]
|
73
72
|
|
74
73
|
|
75
74
|
#Setup cache to make .rhtml-calls faster.
|
@@ -108,11 +107,7 @@ class Knjappserver
|
|
108
107
|
]
|
109
108
|
|
110
109
|
print "Auto restarting.\n" if @debug
|
111
|
-
@mod_event = Knj::Event_filemod.new(:wait => 2, :paths => paths
|
112
|
-
print "File changed - restart server: #{path}\n"
|
113
|
-
@should_restart = true
|
114
|
-
@mod_event.destroy if @mod_event
|
115
|
-
end
|
110
|
+
@mod_event = Knj::Event_filemod.new(:wait => 2, :paths => paths, &self.method(:on_event_filemod))
|
116
111
|
end
|
117
112
|
|
118
113
|
|
@@ -166,15 +161,15 @@ class Knjappserver
|
|
166
161
|
|
167
162
|
if !@config.key?(:dbrev) or @config[:dbrev]
|
168
163
|
print "Updating database.\n" if @debug
|
169
|
-
require "knj/knjdb/revision.rb"
|
170
164
|
|
171
165
|
dbschemapath = "#{File.dirname(__FILE__)}/../files/database_schema.rb"
|
172
166
|
raise "'#{dbschemapath}' did not exist." if !File.exists?(dbschemapath)
|
173
167
|
require dbschemapath
|
174
168
|
raise "No schema-variable was spawned." if !Knjappserver::DATABASE_SCHEMA
|
175
|
-
|
176
|
-
|
177
|
-
|
169
|
+
dbrev_args = {"schema" => Knjappserver::DATABASE_SCHEMA, "db" => @db}
|
170
|
+
dbrev_args.merge!(@config[:dbrev_args]) if @config.key?(:dbrev_args)
|
171
|
+
Knj::Db::Revision.new.init_db(dbrev_args)
|
172
|
+
dbrev_args = nil
|
178
173
|
end
|
179
174
|
|
180
175
|
|
@@ -186,9 +181,7 @@ class Knjappserver
|
|
186
181
|
:datarow => true,
|
187
182
|
:knjappserver => self
|
188
183
|
)
|
189
|
-
@ob.events.connect(:no_date
|
190
|
-
"[no date]"
|
191
|
-
end
|
184
|
+
@ob.events.connect(:no_date, &self.method(:no_date))
|
192
185
|
|
193
186
|
|
194
187
|
if @config[:httpsession_db_args]
|
@@ -312,14 +305,22 @@ class Knjappserver
|
|
312
305
|
|
313
306
|
|
314
307
|
#Clear memory at exit.
|
315
|
-
Kernel.at_exit
|
316
|
-
self.stop
|
317
|
-
end
|
308
|
+
Kernel.at_exit(&self.method(:stop))
|
318
309
|
|
319
310
|
|
320
311
|
print "Appserver spawned.\n" if @debug
|
321
312
|
end
|
322
313
|
|
314
|
+
def no_date(event, classname)
|
315
|
+
return "[no date]"
|
316
|
+
end
|
317
|
+
|
318
|
+
def on_event_filemod(event, path)
|
319
|
+
print "File changed - restart server: #{path}\n"
|
320
|
+
@should_restart = true
|
321
|
+
@mod_event.destroy if @mod_event
|
322
|
+
end
|
323
|
+
|
323
324
|
#If you want to use auto-restart, every file reloaded through loadfile will be watched for changes. When changed the server will do a restart to reflect that.
|
324
325
|
def loadfile(fpath)
|
325
326
|
if !@config[:autorestart]
|
@@ -1,101 +1,108 @@
|
|
1
1
|
class Knjappserver
|
2
2
|
def initialize_cleaner
|
3
|
-
if @config[:autorestart]
|
4
|
-
time = 1
|
5
|
-
else
|
6
|
-
time = 15
|
7
|
-
end
|
8
|
-
|
9
3
|
#This should not be runned via _kas.timeout because timeout wont run when @should_restart is true! - knj
|
10
|
-
Thread.new
|
11
|
-
|
12
|
-
|
13
|
-
|
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]
|
14
30
|
|
15
|
-
if @config
|
16
|
-
|
17
|
-
|
18
|
-
STDOUT.print "Used: #{mbs_used}mb\n" if @config[:debug]
|
19
|
-
|
20
|
-
if mbs_used.to_i >= @config[:restart_when_used_memory].to_i
|
21
|
-
STDOUT.print "Memory is over #{@config[:restart_when_used_memory]} - restarting.\n"
|
22
|
-
@should_restart = true
|
23
|
-
end
|
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
|
24
34
|
end
|
25
|
-
|
26
|
-
|
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.
|
27
46
|
begin
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
STDOUT.print "Someone is working - wait two sec and try to restart again!\n"
|
44
|
-
end
|
45
|
-
|
46
|
-
if !working
|
47
|
-
STDOUT.print "Found window where no sessions were active - restarting!\n"
|
48
|
-
break
|
49
|
-
else
|
50
|
-
sleep 0.2
|
51
|
-
end
|
52
|
-
|
53
|
-
STDOUT.print "Trying to find window with no active sessions to restart...\n"
|
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
|
54
62
|
end
|
63
|
+
|
64
|
+
STDOUT.print "Trying to find window with no active sessions to restart...\n"
|
55
65
|
end
|
56
|
-
rescue Timeout::Error
|
57
|
-
STDOUT.print "Could not find a timing window for restarting... Forcing restart!\n"
|
58
|
-
end
|
59
|
-
|
60
|
-
#Flush emails again if any are pending (while we tried to find a window to restart)...
|
61
|
-
STDOUT.print "Flushing mails.\n"
|
62
|
-
self.mail_flush
|
63
|
-
|
64
|
-
STDOUT.print "Stopping appserver.\n"
|
65
|
-
self.stop
|
66
|
-
|
67
|
-
STDOUT.print "Figuring out restart-command.\n"
|
68
|
-
mycmd = @config[:restart_cmd]
|
69
|
-
|
70
|
-
if !mycmd or mycmd.to_s.strip.length <= 0
|
71
|
-
fpath = File.realpath("#{File.dirname(__FILE__)}/../knjappserver.rb")
|
72
|
-
mycmd = Knj::Os.executed_cmd
|
73
|
-
|
74
|
-
STDOUT.print "Previous cmd: #{mycmd}\n"
|
75
|
-
mycmd = mycmd.gsub(/\s+knjappserver.rb/, " #{Knj::Strings.unixsafe(fpath)}")
|
76
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__)}/../knjappserver.rb")
|
83
|
+
mycmd = Knj::Os.executed_cmd
|
77
84
|
|
78
|
-
STDOUT.print "
|
79
|
-
|
80
|
-
print exec(mycmd)
|
81
|
-
exit
|
82
|
-
rescue => e
|
83
|
-
STDOUT.puts e.inspect
|
84
|
-
STDOUT.puts e.backtrace
|
85
|
+
STDOUT.print "Previous cmd: #{mycmd}\n"
|
86
|
+
mycmd = mycmd.gsub(/\s+knjappserver.rb/, " #{Knj::Strings.unixsafe(fpath)}")
|
85
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
|
86
96
|
end
|
87
97
|
end
|
88
|
-
rescue => e
|
89
|
-
self.handle_error(e)
|
90
98
|
end
|
99
|
+
rescue => e
|
100
|
+
self.handle_error(e)
|
91
101
|
end
|
92
|
-
|
93
|
-
#This flushes (writes) all session-data to the server and deletes old unused sessions from the database.
|
94
|
-
self.timeout(:time => @config[:cleaner_timeout], &self.method("clean"))
|
95
102
|
end
|
96
103
|
|
97
104
|
#This method can be used to clean the appserver. Dont call this from a HTTP-request.
|
98
|
-
def
|
105
|
+
def clean_sessions
|
99
106
|
STDOUT.print "Cleaning sessions on appserver.\n" if @config[:debug]
|
100
107
|
|
101
108
|
#Clean up various inactive sessions.
|
@@ -30,15 +30,18 @@ class Knjappserver
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
self.cmd_connect(/^\s*restart\s*$/i)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
self.cmd_connect(/^\s*restart\s*$/i, &self.method(:cmdline_on_restart_cmd))
|
34
|
+
self.cmd_connect(/^\s*stop\s*$/i, &self.method(:cmdline_on_stop_cmd))
|
35
|
+
end
|
36
|
+
|
37
|
+
def cmdline_on_restart_cmd(data)
|
38
|
+
print "Restart will begin shortly.\n"
|
39
|
+
self.should_restart = true
|
40
|
+
end
|
41
|
+
|
42
|
+
def cmdline_on_stop_cmd(data)
|
43
|
+
print "Stopping appserver.\n"
|
44
|
+
self.stop
|
42
45
|
end
|
43
46
|
|
44
47
|
#Connects a proc to a specific command in the command-line (key should be a regex).
|
@@ -13,9 +13,7 @@ class Knjappserver
|
|
13
13
|
@error_emails_time = 180
|
14
14
|
end
|
15
15
|
|
16
|
-
self.timeout(:time => @error_emails_time)
|
17
|
-
self.flush_error_emails
|
18
|
-
end
|
16
|
+
self.timeout(:time => @error_emails_time, &self.method(:flush_error_emails))
|
19
17
|
end
|
20
18
|
|
21
19
|
#Send error-emails based on error-emails-cache (cached so the same error isnt send out every time it occurrs to prevent spamming).
|
@@ -99,12 +97,12 @@ class Knjappserver
|
|
99
97
|
html << "#{Knj::Web.html(line)}<br />"
|
100
98
|
end
|
101
99
|
|
102
|
-
html << "<br /><b>Post:</b><br /><pre>#{
|
103
|
-
html << "<br /><b>Get:</b><br /><pre>#{
|
104
|
-
html << "<br /><b>Server:</b><br /><pre>#{
|
105
|
-
html << "<br /><b>Cookie:</b><br /><pre>#{
|
106
|
-
html << "<br /><b>Session:</b><br /><pre>#{
|
107
|
-
html << "<br /><b>Session hash:</b><br /><pre>#{
|
100
|
+
html << "<br /><b>Post:</b><br /><pre>#{Php4r.print_r(_post, true)}</pre>" if _post
|
101
|
+
html << "<br /><b>Get:</b><br /><pre>#{Php4r.print_r(_get, true)}</pre>" if _get
|
102
|
+
html << "<br /><b>Server:</b><br /><pre>#{Php4r.print_r(_server, true).html}</pre>" if _server
|
103
|
+
html << "<br /><b>Cookie:</b><br /><pre>#{Php4r.print_r(_cookie, true).html}</pre>" if _meta
|
104
|
+
html << "<br /><b>Session:</b><br /><pre>#{Php4r.print_r(_session, true).html}</pre>" if _session
|
105
|
+
html << "<br /><b>Session hash:</b><br /><pre>#{Php4r.print_r(_session_hash, true).html}</pre>" if _session_hash
|
108
106
|
|
109
107
|
error_hash = @error_emails_pending[backtrace_hash]
|
110
108
|
error_hash[:last_time] = Time.new
|
@@ -124,7 +122,7 @@ class Knjappserver
|
|
124
122
|
|
125
123
|
#Prints a detailed overview of the object in the terminal from where the appserver was started. This can be used for debugging.
|
126
124
|
def dprint(obj)
|
127
|
-
STDOUT.print
|
125
|
+
STDOUT.print Php4r.print_r(obj, true)
|
128
126
|
end
|
129
127
|
|
130
128
|
#Prints a string with a single file-line-backtrace prepended which is useful for debugging.
|
@@ -4,16 +4,14 @@ class Knjappserver
|
|
4
4
|
@logs_mutex = Mutex.new
|
5
5
|
|
6
6
|
if @config[:logging] and @config[:logging][:access_db]
|
7
|
-
self.timeout(:time => 30)
|
8
|
-
if @logs_access_pending.length > 0
|
9
|
-
flush_access_log
|
10
|
-
end
|
11
|
-
end
|
7
|
+
self.timeout(:time => 30, &self.method(:flush_access_log))
|
12
8
|
end
|
13
9
|
end
|
14
10
|
|
15
11
|
#Writes all queued access-logs to the database.
|
16
12
|
def flush_access_log
|
13
|
+
return nil if @logs_access_pending.empty?
|
14
|
+
|
17
15
|
@logs_mutex.synchronize do
|
18
16
|
ins_arr = @logs_access_pending
|
19
17
|
@logs_access_pending = []
|
@@ -306,7 +304,9 @@ class Knjappserver
|
|
306
304
|
def logs_table(obj, args = {})
|
307
305
|
links = @ob.list(:Log_link, {"object_class" => obj.class.name, "object_id" => obj.id, "limit" => 500, "orderby" => [["id", "desc"]]})
|
308
306
|
|
309
|
-
html = "
|
307
|
+
html = ""
|
308
|
+
|
309
|
+
html << "<table class=\"list knjappserver_log_table\">"
|
310
310
|
html << "<thead>"
|
311
311
|
html << "<tr>"
|
312
312
|
html << "<th>ID</th>"
|
@@ -8,10 +8,7 @@ class Knjappserver
|
|
8
8
|
@mails_waiting = []
|
9
9
|
@mails_mutex = Monitor.new
|
10
10
|
@mails_queue_mutex = Monitor.new
|
11
|
-
@mails_timeout = self.timeout(:time => 30)
|
12
|
-
STDOUT.print "Flushing mails.\n" if @debug
|
13
|
-
self.mail_flush
|
14
|
-
end
|
11
|
+
@mails_timeout = self.timeout(:time => 30, &self.method(:mail_flush))
|
15
12
|
end
|
16
13
|
|
17
14
|
#Queue a mail for sending. Possible keys are: :subject, :from, :to, :text and :html.
|
@@ -40,6 +37,8 @@ class Knjappserver
|
|
40
37
|
#Sends all queued mails to the respective servers, if we are online.
|
41
38
|
def mail_flush
|
42
39
|
@mails_mutex.synchronize do
|
40
|
+
STDOUT.print "Flushing mails.\n" if @debug
|
41
|
+
|
43
42
|
if @mails_waiting.length <= 0
|
44
43
|
STDOUT.print "No mails to flush - skipping.\n" if @debug
|
45
44
|
return false
|
@@ -83,6 +82,8 @@ class Knjappserver
|
|
83
82
|
subproc.destroy if subproc
|
84
83
|
subproc = nil
|
85
84
|
end
|
85
|
+
|
86
|
+
return nil
|
86
87
|
end
|
87
88
|
end
|
88
89
|
|
@@ -4,9 +4,12 @@ class Knjappserver
|
|
4
4
|
@config[:threadding][:max_running] = 8 if !@config[:threadding].has_key?(:max_running)
|
5
5
|
|
6
6
|
@threadpool = Knj::Threadpool.new(:threads => @config[:threadding][:max_running], :sleep => 0.1)
|
7
|
-
@threadpool.events.connect(:on_error
|
8
|
-
|
9
|
-
|
7
|
+
@threadpool.events.connect(:on_error, &self.method(:threadpool_on_error))
|
8
|
+
end
|
9
|
+
|
10
|
+
#Callback for when an error occurs in the threadpool.
|
11
|
+
def threadpool_on_error(event, error)
|
12
|
+
self.handle_error(error)
|
10
13
|
end
|
11
14
|
|
12
15
|
#Inits the thread so it has access to the appserver and various magic methods can be used.
|
@@ -71,6 +74,7 @@ class Knjappserver
|
|
71
74
|
#Spawns a thread to run the given proc and add the output of that block in the correct order to the HTML.
|
72
75
|
def threadded_content(&block)
|
73
76
|
_httpsession.threadded_content(block)
|
77
|
+
return nil
|
74
78
|
end
|
75
79
|
end
|
76
80
|
|
@@ -1,15 +1,15 @@
|
|
1
1
|
class Knjappserver
|
2
|
+
#Translates a given key for a given object.
|
3
|
+
#===Examples
|
4
|
+
# print _kas.trans(obj, :title) #=> "Trala"
|
2
5
|
def trans(obj, key, args = {})
|
3
6
|
args[:locale] = self.trans_locale if !args[:locale]
|
4
7
|
trans_val = @translations.get(obj, key, args).to_s
|
5
|
-
|
6
|
-
if trans_val.length <= 0
|
7
|
-
trans_val = @events.call(:trans_no_str, {:obj => obj, :key => key, :args => args})
|
8
|
-
end
|
9
|
-
|
8
|
+
trans_val = @events.call(:trans_no_str, {:obj => obj, :key => key, :args => args}) if trans_val.length <= 0
|
10
9
|
return trans_val
|
11
10
|
end
|
12
11
|
|
12
|
+
#Returns the locale for the current thread.
|
13
13
|
def trans_locale(args = {})
|
14
14
|
if args.is_a?(Hash) and args[:locale]
|
15
15
|
return args[:locale]
|
@@ -26,11 +26,17 @@ class Knjappserver
|
|
26
26
|
raise "Could not figure out locale."
|
27
27
|
end
|
28
28
|
|
29
|
+
#Sets new translations for the given object.
|
30
|
+
#===Examples
|
31
|
+
# _kas.trans_set(obj, {:title => "Trala"})
|
29
32
|
def trans_set(obj, values, args = {})
|
30
33
|
args[:locale] = self.trans_locale if !args[:locale]
|
31
34
|
@translations.set(obj, values, args)
|
32
35
|
end
|
33
36
|
|
37
|
+
#Deletes all translations for the given object.
|
38
|
+
#===Examples
|
39
|
+
# _kas.trans_del(obj)
|
34
40
|
def trans_del(obj)
|
35
41
|
@translations.delete(obj)
|
36
42
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Knjappserver
|
2
2
|
#Imports a .rhtml-file and executes it.
|
3
3
|
#===Examples
|
4
|
-
#
|
4
|
+
# _kas.import("/some/path/page.rhtml")
|
5
5
|
def import(filepath)
|
6
6
|
if filepath.to_s.index("../proc/self") != nil
|
7
7
|
raise Errno::EACCES, "Possible attempt to hack the appserver."
|
@@ -12,8 +12,8 @@ class Knjappserver
|
|
12
12
|
|
13
13
|
#Redirects to another URL.
|
14
14
|
#===Examples
|
15
|
-
#
|
16
|
-
#
|
15
|
+
# _kas.redirect("someotherpage.rhtml")
|
16
|
+
# _kas.redirect("newpage.rhtml", :perm => true)
|
17
17
|
def redirect(url, args = {})
|
18
18
|
#Header way
|
19
19
|
if !_httpsession.alert_sent and !self.headers_sent?
|
@@ -32,7 +32,7 @@ class Knjappserver
|
|
32
32
|
|
33
33
|
#Sends a javascript-alert to the HTML.
|
34
34
|
#===Examples
|
35
|
-
#
|
35
|
+
# _kas.alert("Hello world!")
|
36
36
|
def alert(msg)
|
37
37
|
_httpsession.alert_sent = true
|
38
38
|
Knj::Web.alert(msg)
|
@@ -41,33 +41,36 @@ class Knjappserver
|
|
41
41
|
|
42
42
|
#Define a cookies in the clients browser.
|
43
43
|
#===Examples
|
44
|
-
#
|
44
|
+
# _kas.cookie(:name => "MyCookie", :value => "Trala")
|
45
45
|
def cookie(cookie)
|
46
46
|
raise "No HTTP-session attached to this thread." if !_httpsession
|
47
47
|
raise "HTTP-session not active." if !_httpsession.resp
|
48
48
|
raise "Not a hash: '#{cookie.class.name}', '#{cookie}'." unless cookie.is_a?(Hash)
|
49
49
|
_httpsession.resp.cookie(cookie)
|
50
|
+
return nil
|
50
51
|
end
|
51
52
|
|
52
53
|
#Sends a header to the clients browser.
|
53
54
|
#===Examples
|
54
|
-
#
|
55
|
+
# _kas.header("Content-Type", "text/javascript")
|
55
56
|
def header(key, val)
|
56
57
|
raise "No HTTP-session attached to this thread." if !_httpsession
|
57
58
|
raise "HTTP-session not active." if !_httpsession.resp
|
58
59
|
_httpsession.resp.header(key, val)
|
60
|
+
return nil
|
59
61
|
end
|
60
62
|
|
61
63
|
#Sends a raw header-line to the clients browser.
|
62
64
|
def header_raw(str)
|
63
65
|
raise "No HTTP-session attached to this thread." if !_httpsession
|
64
66
|
raise "HTTP-session not active." if !_httpsession.resp
|
65
|
-
|
67
|
+
Php4r.header(str)
|
68
|
+
return nil
|
66
69
|
end
|
67
70
|
|
68
71
|
#Returns true if the headers are already sent.
|
69
72
|
#===Examples
|
70
|
-
#
|
73
|
+
# _kas.headers_sent? #=> true
|
71
74
|
def headers_sent?
|
72
75
|
return true if _httpsession.resp.headers_sent
|
73
76
|
return false
|
@@ -76,16 +79,17 @@ class Knjappserver
|
|
76
79
|
#Define the size for when to automatically send headers. If you want to send hundres of kilobytes and then a header, you can use this method to do so.
|
77
80
|
#===Examples
|
78
81
|
#Set the size to 200 kb.
|
79
|
-
#
|
82
|
+
# _kas.headers_send_size = (1024 * 200)
|
80
83
|
def headers_send_size=(newsize)
|
81
84
|
raise "The headers are already sent and you cannot modify the send-size any more." if self.headers_sent?
|
82
85
|
_httpsession.size_send = newsize.to_i
|
86
|
+
return nil
|
83
87
|
end
|
84
88
|
|
85
89
|
#Serves the given filepath and enables caching for it. No other content should be written to the page when using this method.
|
86
90
|
#===Examples
|
87
|
-
#
|
88
|
-
#
|
91
|
+
# _kas.header("Content-Type", "text/javascript")
|
92
|
+
# _kas.serve_file("somefile.js")
|
89
93
|
def serve_file(filepath)
|
90
94
|
raise "File doesnt exist: '#{filepath}'." if !File.exists?(filepath)
|
91
95
|
httpsess = _httpsession
|
@@ -115,6 +119,7 @@ class Knjappserver
|
|
115
119
|
end
|
116
120
|
|
117
121
|
httpsess.force_content(:type => :file, :path => filepath)
|
122
|
+
return nil
|
118
123
|
end
|
119
124
|
|
120
125
|
#Sends a javascript back to the browser and exits.
|
@@ -129,7 +134,7 @@ class Knjappserver
|
|
129
134
|
|
130
135
|
#Urlencodes a string.
|
131
136
|
#===Examples
|
132
|
-
#
|
137
|
+
# _kas.redirect("mypage.rhtml?arg=#{_kas.urlenc(value_variable)}")
|
133
138
|
def urlenc(str)
|
134
139
|
return Knj::Web.urlenc(str)
|
135
140
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<%
|
2
|
+
if _get["choice"] == "dogarbagecollect"
|
3
|
+
GC.start
|
4
|
+
_kas.redirect("?show=debug_memory_usage")
|
5
|
+
end
|
6
|
+
%>
|
7
|
+
|
8
|
+
<h1>Memory usage</h1>
|
9
|
+
|
10
|
+
<div style="padding-bottom: 15px;">
|
11
|
+
<input type="button" value="Garbage collect" onclick="location.href='?show=debug_memory_usage&choice=dogarbagecollect';" />
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<%
|
15
|
+
Knj::Memory_analyzer.new.write
|
16
|
+
%>
|
@@ -107,7 +107,7 @@ begin
|
|
107
107
|
|
108
108
|
#cgi.print "Content-Type: text/html\r\n"
|
109
109
|
#cgi.print "\r\n"
|
110
|
-
#cgi.print
|
110
|
+
#cgi.print Php4r.print_r(cgi.params, true)
|
111
111
|
|
112
112
|
if cgi.request_method == "POST" and cgi.content_type.to_s.downcase.index("multipart/form-data") != nil
|
113
113
|
count = 0
|
@@ -74,7 +74,7 @@ FCGI.each_cgi do |cgi|
|
|
74
74
|
headers = {}
|
75
75
|
cgi.env_table.each do |key, val|
|
76
76
|
if key[0, 5] == "HTTP_" and key != "HTTP_KNJAPPSERVER_CGI_CONFIG"
|
77
|
-
key =
|
77
|
+
key = Php4r.ucwords(key[5, key.length].gsub("_", " ")).gsub(" ", "-")
|
78
78
|
headers[key] = val
|
79
79
|
end
|
80
80
|
end
|
@@ -92,7 +92,7 @@ FCGI.each_cgi do |cgi|
|
|
92
92
|
|
93
93
|
#cgi.print "Content-Type: text/html\r\n"
|
94
94
|
#cgi.print "\r\n"
|
95
|
-
#cgi.print
|
95
|
+
#cgi.print Php4r.print_r(cgi.params, true)
|
96
96
|
|
97
97
|
if cgi.request_method == "POST" and cgi.content_type.to_s.downcase.index("multipart/form-data") != nil
|
98
98
|
count = 0
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: knjappserver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.30
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Kasper Johansen
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-08-03 00:00:00 +02:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -80,19 +80,30 @@ dependencies:
|
|
80
80
|
prerelease: false
|
81
81
|
version_requirements: *id006
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
|
-
name:
|
83
|
+
name: php4r
|
84
84
|
requirement: &id007 !ruby/object:Gem::Requirement
|
85
85
|
none: false
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: "0"
|
90
|
-
type: :
|
90
|
+
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: *id007
|
93
93
|
- !ruby/object:Gem::Dependency
|
94
|
-
name:
|
94
|
+
name: json
|
95
95
|
requirement: &id008 !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: "0"
|
101
|
+
type: :development
|
102
|
+
prerelease: false
|
103
|
+
version_requirements: *id008
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: rspec
|
106
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
96
107
|
none: false
|
97
108
|
requirements:
|
98
109
|
- - ~>
|
@@ -100,10 +111,10 @@ dependencies:
|
|
100
111
|
version: 2.3.0
|
101
112
|
type: :development
|
102
113
|
prerelease: false
|
103
|
-
version_requirements: *
|
114
|
+
version_requirements: *id009
|
104
115
|
- !ruby/object:Gem::Dependency
|
105
116
|
name: bundler
|
106
|
-
requirement: &
|
117
|
+
requirement: &id010 !ruby/object:Gem::Requirement
|
107
118
|
none: false
|
108
119
|
requirements:
|
109
120
|
- - ">="
|
@@ -111,10 +122,10 @@ dependencies:
|
|
111
122
|
version: 1.0.0
|
112
123
|
type: :development
|
113
124
|
prerelease: false
|
114
|
-
version_requirements: *
|
125
|
+
version_requirements: *id010
|
115
126
|
- !ruby/object:Gem::Dependency
|
116
127
|
name: jeweler
|
117
|
-
requirement: &
|
128
|
+
requirement: &id011 !ruby/object:Gem::Requirement
|
118
129
|
none: false
|
119
130
|
requirements:
|
120
131
|
- - ~>
|
@@ -122,10 +133,10 @@ dependencies:
|
|
122
133
|
version: 1.6.3
|
123
134
|
type: :development
|
124
135
|
prerelease: false
|
125
|
-
version_requirements: *
|
136
|
+
version_requirements: *id011
|
126
137
|
- !ruby/object:Gem::Dependency
|
127
138
|
name: sqlite3
|
128
|
-
requirement: &
|
139
|
+
requirement: &id012 !ruby/object:Gem::Requirement
|
129
140
|
none: false
|
130
141
|
requirements:
|
131
142
|
- - ">="
|
@@ -133,7 +144,7 @@ dependencies:
|
|
133
144
|
version: "0"
|
134
145
|
type: :development
|
135
146
|
prerelease: false
|
136
|
-
version_requirements: *
|
147
|
+
version_requirements: *id012
|
137
148
|
description: Which supports a lot of undocumented stuff.
|
138
149
|
email: k@spernj.org
|
139
150
|
executables:
|
@@ -200,6 +211,7 @@ files:
|
|
200
211
|
- lib/pages/benchmark_threadded_content.rhtml
|
201
212
|
- lib/pages/debug_database_connections.rhtml
|
202
213
|
- lib/pages/debug_http_sessions.rhtml
|
214
|
+
- lib/pages/debug_memory_usage.rhtml
|
203
215
|
- lib/pages/error_notfound.rhtml
|
204
216
|
- lib/pages/logs_latest.rhtml
|
205
217
|
- lib/pages/logs_show.rhtml
|
@@ -230,7 +242,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
230
242
|
requirements:
|
231
243
|
- - ">="
|
232
244
|
- !ruby/object:Gem::Version
|
233
|
-
hash:
|
245
|
+
hash: 676583393387932093
|
234
246
|
segments:
|
235
247
|
- 0
|
236
248
|
version: "0"
|