spiderfw 0.6.5 → 0.6.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +10 -0
- data/VERSION +1 -1
- data/apps/app_server/config/options.rb +2 -2
- data/apps/core/components/assets.rb +1 -5
- data/apps/core/components/widgets/month_calendar/month_calendar.shtml +3 -3
- data/apps/core/components/widgets/table/table.rb +2 -0
- data/apps/core/components/widgets/tabs/tabs.rb +9 -3
- data/apps/core/components/widgets/tabs/tabs.shtml +1 -1
- data/apps/master/_init.rb +3 -1
- data/apps/master/cmd.rb +1 -1
- data/apps/master/controllers/master_controller.rb +107 -103
- data/apps/master/controllers/scout_controller.rb +7 -7
- data/apps/master/controllers/{servant_controller.rb → server_controller.rb} +3 -3
- data/apps/master/data/locale/it/LC_MESSAGES/master.mo +0 -0
- data/apps/master/master.rb +4 -4
- data/apps/master/models/customer.rb +0 -3
- data/apps/master/models/installation.rb +14 -3
- data/apps/master/models/remote_log.rb +11 -0
- data/apps/master/models/scout_plugin_instance.rb +9 -9
- data/apps/master/models/scout_plugin_trigger.rb +2 -2
- data/apps/master/models/{servant.rb → server.rb} +6 -6
- data/apps/master/po/it/{spider_master.po → master.po} +127 -54
- data/apps/master/po/master.pot +23 -23
- data/apps/master/templates/email/alert.html.erb +1 -1
- data/apps/master/views/customer.shtml +3 -3
- data/apps/master/views/index.shtml +1 -2
- data/apps/master/views/installation.shtml +28 -16
- data/apps/master/views/master.layout.shtml +2 -1
- data/apps/master/views/plugin_data.shtml +1 -1
- data/apps/master/views/{servant.shtml → server.shtml} +14 -14
- data/apps/master/views/servers.shtml +11 -0
- data/apps/master/views/site_edit.shtml +1 -1
- data/apps/master/views/trigger_edit.shtml +4 -4
- data/apps/messenger/controllers/mixins/messenger_helper.rb +3 -3
- data/apps/servant/Gemfile +1 -0
- data/apps/servant/_init.rb +5 -1
- data/apps/servant/cmd.rb +14 -45
- data/apps/servant/config/options.rb +1 -0
- data/apps/servant/controllers/servant_controller.rb +7 -1
- data/apps/servant/lib/client.rb +55 -0
- data/apps/servant/servant.appspec +1 -1
- data/apps/servant/servant.rb +90 -0
- data/apps/worker/cmd.rb +9 -4
- data/apps/worker/worker.rb +11 -6
- data/blueprints/bin/spider +7 -0
- data/blueprints/home/config/config.yml +2 -3
- data/blueprints/home/init.rb +1 -1
- data/lib/spiderfw/app.rb +50 -2
- data/lib/spiderfw/cmd/commands/app.rb +22 -12
- data/lib/spiderfw/cmd/commands/config.rb +2 -1
- data/lib/spiderfw/config/configuration_editor.rb +7 -4
- data/lib/spiderfw/config/options/spider.rb +3 -1
- data/lib/spiderfw/controller/helpers/widget_helper.rb +6 -3
- data/lib/spiderfw/controller/mixins/http_mixin.rb +2 -1
- data/lib/spiderfw/controller/mixins/visual.rb +12 -10
- data/lib/spiderfw/env.rb +8 -1
- data/lib/spiderfw/home.rb +31 -4
- data/lib/spiderfw/http/server.rb +32 -14
- data/lib/spiderfw/model/mappers/mapper.rb +2 -2
- data/lib/spiderfw/model/mixins/tree.rb +7 -5
- data/lib/spiderfw/model/storage/db/adapters/mysql.rb +55 -2
- data/lib/spiderfw/model/storage/db/adapters/oracle.rb +80 -3
- data/lib/spiderfw/model/storage/db/connectors/jdbc_oracle.rb +3 -2
- data/lib/spiderfw/model/storage/db/connectors/oci8.rb +3 -2
- data/lib/spiderfw/model/storage/db/db_storage.rb +22 -0
- data/lib/spiderfw/setup/app_manager.rb +6 -2
- data/lib/spiderfw/site.rb +3 -1
- data/lib/spiderfw/spider.rb +145 -18
- data/lib/spiderfw/templates/blocks/parent_context.rb +3 -1
- data/lib/spiderfw/templates/template.rb +14 -5
- data/lib/spiderfw/widget/widget.rb +1 -0
- data/lib/spiderfw/widget/widget_attributes.rb +2 -2
- metadata +16 -16
- data/apps/master/po/spider_master.pot +0 -331
- data/apps/master/views/servants.shtml +0 -11
- data/apps/servant/lib/commands/discovery.rb +0 -0
- data/apps/servant/lib/resource.rb +0 -14
- data/apps/servant/lib/resources/db/mysql.rb +0 -35
- data/apps/servant/lib/resources/db.rb +0 -55
- data/apps/servant/lib/servant.rb +0 -88
- data/apps/servant/var/log/error.log +0 -1
data/lib/spiderfw/app.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'tsort'
|
2
3
|
|
3
4
|
module Spider
|
4
5
|
|
@@ -244,6 +245,7 @@ module Spider
|
|
244
245
|
@#{name} ||= #{options[:default].inspect}
|
245
246
|
@#{name}
|
246
247
|
end
|
248
|
+
alias :#{name}= :#{name}
|
247
249
|
END_OF_EVAL
|
248
250
|
class_eval(str)
|
249
251
|
end
|
@@ -268,6 +270,7 @@ END_OF_EVAL
|
|
268
270
|
array_attribute :authors
|
269
271
|
array_attribute :depends
|
270
272
|
array_attribute :depends_optional
|
273
|
+
array_attribute :load_after
|
271
274
|
array_attribute :can_use
|
272
275
|
array_attribute :gems
|
273
276
|
array_attribute :gems_optional
|
@@ -315,20 +318,65 @@ END_OF_EVAL
|
|
315
318
|
h
|
316
319
|
end
|
317
320
|
|
318
|
-
def to_json
|
321
|
+
def to_json(opts=nil)
|
319
322
|
to_h.to_json
|
320
323
|
end
|
321
324
|
|
322
325
|
def self.parse_hash(h)
|
323
326
|
spec = self.new
|
324
327
|
h.each do |key, value|
|
325
|
-
|
328
|
+
if value.is_a?(Array)
|
329
|
+
spec.send(:"#{key}", *value)
|
330
|
+
else
|
331
|
+
spec.send(:"#{key}", value)
|
332
|
+
end
|
326
333
|
end
|
327
334
|
spec
|
328
335
|
end
|
336
|
+
|
337
|
+
def load_after(*vals)
|
338
|
+
@load_after = vals unless vals.empty?
|
339
|
+
unless @load_after
|
340
|
+
return self.depends + self.depends_optional
|
341
|
+
end
|
342
|
+
end
|
329
343
|
|
330
344
|
end
|
331
345
|
|
346
|
+
class RuntimeSort
|
347
|
+
|
348
|
+
def initialize
|
349
|
+
@apps = []
|
350
|
+
@apps_hash = {}
|
351
|
+
end
|
352
|
+
|
353
|
+
def add(app)
|
354
|
+
@apps << app
|
355
|
+
if app.is_a?(AppSpec)
|
356
|
+
@apps_hash[app.app_id] = app
|
357
|
+
else
|
358
|
+
@apps_hash[app] = app
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def tsort_each_node(&block)
|
363
|
+
@apps.each(&block)
|
364
|
+
end
|
365
|
+
|
366
|
+
def tsort_each_child(node, &block)
|
367
|
+
return unless node.is_a?(AppSpec)
|
368
|
+
node.load_after.map{ |a| @apps_hash[a] }.each(&block)
|
369
|
+
end
|
370
|
+
|
371
|
+
def tsort
|
372
|
+
sorted = super
|
373
|
+
sorted.map{ |a| a.is_a?(AppSpec) ? a.app_id : a }
|
374
|
+
end
|
375
|
+
|
376
|
+
include TSort
|
377
|
+
|
378
|
+
end
|
379
|
+
|
332
380
|
end
|
333
381
|
|
334
382
|
end
|
@@ -39,17 +39,19 @@ class AppCommand < CmdParse::Command
|
|
39
39
|
end
|
40
40
|
list.set_execution_block do |args|
|
41
41
|
if @installed
|
42
|
-
require 'spiderfw'
|
42
|
+
require 'spiderfw/home'
|
43
|
+
home = Spider::Home.new(Dir.pwd)
|
43
44
|
installed = {}
|
44
|
-
Spider.
|
45
|
+
Spider.init_base
|
46
|
+
active = Spider.config.get('apps')
|
47
|
+
Spider.home.apps.each do |app, info|
|
45
48
|
installed[app] = {
|
46
|
-
:active =>
|
49
|
+
:active => active.include?(app)
|
47
50
|
}
|
48
|
-
if
|
49
|
-
info = Spider::App::AppSpec.load(appspec)
|
51
|
+
if spec = info[:spec]
|
50
52
|
installed[app].merge!({
|
51
|
-
:version =>
|
52
|
-
})
|
53
|
+
:version => spec.version
|
54
|
+
})
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
@@ -71,19 +73,19 @@ class AppCommand < CmdParse::Command
|
|
71
73
|
end
|
72
74
|
if @installed
|
73
75
|
puts
|
74
|
-
puts "*** INSTALLED APPS ***"
|
76
|
+
puts "*** "+_('INSTALLED APPS')+" ***"
|
75
77
|
puts
|
76
78
|
installed.keys.sort.each do |app|
|
77
79
|
details = installed[app]
|
78
80
|
str = app
|
79
81
|
str += " #{details[:version]}" if details[:version]
|
80
|
-
str += " (#{_('
|
82
|
+
str += " (#{_('not loaded')})" unless details[:active]
|
81
83
|
puts str
|
82
84
|
end
|
83
85
|
end
|
84
86
|
if @remote
|
85
87
|
puts
|
86
|
-
puts "*** REMOTE APPS ***"
|
88
|
+
puts "*** "+_('REMOTE APPS')+" ***"
|
87
89
|
puts
|
88
90
|
remote.keys.sort.each do |app|
|
89
91
|
details = remote[app]
|
@@ -110,6 +112,7 @@ class AppCommand < CmdParse::Command
|
|
110
112
|
@no_optional_gems = true
|
111
113
|
}
|
112
114
|
opt.on("--ssh-user [USERNAME]", _("SSH user")){ |s| @ssh_user = s }
|
115
|
+
opt.on("--no-activate", _("Don't activate installed apps")){ |s| @no_activate = true }
|
113
116
|
end
|
114
117
|
install.set_execution_block do |args|
|
115
118
|
unless File.exist?('init.rb') && File.directory?('apps')
|
@@ -127,6 +130,7 @@ class AppCommand < CmdParse::Command
|
|
127
130
|
puts "Grit not available; install Grit for Git support"
|
128
131
|
end
|
129
132
|
end
|
133
|
+
|
130
134
|
apps = args
|
131
135
|
existent = []
|
132
136
|
apps.each do |app|
|
@@ -135,7 +139,6 @@ class AppCommand < CmdParse::Command
|
|
135
139
|
existent << app
|
136
140
|
end
|
137
141
|
end
|
138
|
-
apps -= existent
|
139
142
|
require 'spiderfw/setup/app_manager'
|
140
143
|
specs = []
|
141
144
|
client = Spider::AppServerClient.new(@server_url)
|
@@ -155,7 +158,14 @@ class AppCommand < CmdParse::Command
|
|
155
158
|
:no_optional_gems => @no_optional_gems
|
156
159
|
}
|
157
160
|
options[:ssh_user] = @ssh_user if @ssh_user
|
158
|
-
|
161
|
+
inst_specs = specs.reject!{ |s| existent.include? s.app_id }
|
162
|
+
Spider::AppManager.install(inst_specs, Dir.pwd, options)
|
163
|
+
unless @no_activate
|
164
|
+
require 'spiderfw/spider'
|
165
|
+
specs_hash = {}
|
166
|
+
specs.each{ |s| specs_hash[s.app_id] = s }
|
167
|
+
Spider.activate_apps(deps, specs_hash)
|
168
|
+
end
|
159
169
|
end
|
160
170
|
self.add_command(install)
|
161
171
|
|
@@ -52,9 +52,10 @@ class ConfigCommand < CmdParse::Command
|
|
52
52
|
set = CmdParse::Command.new('set', false)
|
53
53
|
set.short_desc = _("Set the value of a configuration option")
|
54
54
|
set.set_execution_block do |args|
|
55
|
-
require 'spiderfw'
|
55
|
+
require 'spiderfw/spider'
|
56
56
|
require 'lib/spiderfw/config/configuration_editor'
|
57
57
|
editor = Spider::ConfigurationEditor.new
|
58
|
+
Spider.init_base
|
58
59
|
Spider.config.loaded_files.each do |f|
|
59
60
|
editor.load(f)
|
60
61
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
1
3
|
module Spider
|
2
4
|
|
3
5
|
class ConfigurationEditor
|
@@ -80,13 +82,13 @@ module Spider
|
|
80
82
|
|
81
83
|
def commit_ml(res, key, val, curr)
|
82
84
|
if curr
|
85
|
+
curr.instance_eval("def to_yaml_style; :multiline; end")
|
83
86
|
res << {key => curr}.to_yaml.split("\n")[2..-1].join("\n") + "\n"
|
84
87
|
else
|
85
88
|
res << val
|
86
89
|
end
|
87
90
|
|
88
91
|
end
|
89
|
-
|
90
92
|
@changed.each do |file, data|
|
91
93
|
dirname = File.dirname(file)
|
92
94
|
basename = File.basename(file)
|
@@ -111,7 +113,7 @@ module Spider
|
|
111
113
|
end
|
112
114
|
add_next = nil
|
113
115
|
end
|
114
|
-
if line =~ /(\s*)(\w[^:]+):\s*(
|
116
|
+
if line =~ /(\s*)(\w[^:]+):\s*(.+)?$/
|
115
117
|
indent = $1
|
116
118
|
key = $2
|
117
119
|
value = $3
|
@@ -149,6 +151,7 @@ module Spider
|
|
149
151
|
if value
|
150
152
|
if curr
|
151
153
|
res << indent
|
154
|
+
curr.instance_eval("def to_yaml_style; :inline; end")
|
152
155
|
res << {key => curr}.to_yaml.split("\n")[1..-1].join("\n") + "\n"
|
153
156
|
else
|
154
157
|
res << line
|
@@ -186,8 +189,8 @@ module Spider
|
|
186
189
|
end
|
187
190
|
|
188
191
|
res.close
|
189
|
-
|
190
|
-
|
192
|
+
FileUtils.mv(file, "#{file}.bak")
|
193
|
+
FileUtils.mv(tmp_file, file)
|
191
194
|
end
|
192
195
|
end
|
193
196
|
end
|
@@ -4,6 +4,8 @@ module Spider
|
|
4
4
|
:action => Proc.new{ |option| Spider.runmode = option unless Spider.runmode || $SPIDER_RUNMODE}
|
5
5
|
)
|
6
6
|
|
7
|
+
config_option('apps', _('Apps to load'), :type => Array, :yaml_style => :inline)
|
8
|
+
|
7
9
|
# Storage
|
8
10
|
# config_option('storage.type', '')
|
9
11
|
# config_option('storage.url', '')
|
@@ -37,7 +39,7 @@ module Spider
|
|
37
39
|
config_option 'static_content.auto_publish', _("Automatically publish content to the home's public folder"),
|
38
40
|
:type => Spider::DataTypes::Bool, :default => false
|
39
41
|
# Client
|
40
|
-
config_option 'client.text_editor', _("The text editor installed on the client")
|
42
|
+
config_option 'client.text_editor', _("The text editor installed on the client"), :default => 'textmate'
|
41
43
|
|
42
44
|
# Templates
|
43
45
|
config_option 'template.cache.disable', _("Refresh template cache every time"), :default => false, :type => Spider::DataTypes::Bool
|
@@ -26,6 +26,7 @@ module Spider; module Helpers
|
|
26
26
|
:id_path => w.id_path,
|
27
27
|
:full_id => w.full_id,
|
28
28
|
:param => param_name(w),
|
29
|
+
:param_u => param_name(w, true),
|
29
30
|
:pub_path => w.class.pub_url,
|
30
31
|
:css_class => w.css_class,
|
31
32
|
:css_classes => w.css_classes.uniq.join(' ')
|
@@ -49,7 +50,7 @@ module Spider; module Helpers
|
|
49
50
|
|
50
51
|
module SceneMethods
|
51
52
|
|
52
|
-
def param_name(widget_desc)
|
53
|
+
def param_name(widget_desc, urlencode=false)
|
53
54
|
if (widget_desc.is_a?(Widget))
|
54
55
|
id_path = widget_desc.id_path
|
55
56
|
elsif (widget_desc.is_a?(Hash))
|
@@ -57,7 +58,9 @@ module Spider; module Helpers
|
|
57
58
|
else
|
58
59
|
id_path = widget_desc
|
59
60
|
end
|
60
|
-
|
61
|
+
open = urlencode ? '%5B' : '['
|
62
|
+
close = urlencode ? '%5D' : ']'
|
63
|
+
pre = id_path.map{ |part| "#{open}#{part}#{close}"}.join('')
|
61
64
|
end
|
62
65
|
|
63
66
|
def params_for(widget_or_id_path, params)
|
@@ -71,4 +74,4 @@ module Spider; module Helpers
|
|
71
74
|
|
72
75
|
end
|
73
76
|
|
74
|
-
end; end
|
77
|
+
end; end
|
@@ -12,7 +12,7 @@ module Spider; module ControllerMixins
|
|
12
12
|
klass.extend(ClassMethods)
|
13
13
|
end
|
14
14
|
|
15
|
-
def redirect(url, code=Spider::HTTP::
|
15
|
+
def redirect(url, code=Spider::HTTP::SEE_OTHER)
|
16
16
|
debug "REDIRECTING TO #{url}"
|
17
17
|
@request.session.persist if @request.session # It might be too late afterwards
|
18
18
|
@response.status = code
|
@@ -26,6 +26,7 @@ module Spider; module ControllerMixins
|
|
26
26
|
return '' unless url
|
27
27
|
if (maps = Spider.conf.get('http.proxy_mapping'))
|
28
28
|
maps.each do |proxy, spider|
|
29
|
+
spider ||= ''
|
29
30
|
return proxy + url[spider.length..-1] if (spider == "" || url[0..spider.length-1] == spider)
|
30
31
|
end
|
31
32
|
end
|
@@ -191,18 +191,20 @@ module Spider; module ControllerMixins
|
|
191
191
|
template = get_template(path, scene, options)
|
192
192
|
end
|
193
193
|
layout = nil
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
194
|
+
unless options.key?(:layout) && !options[:layout]
|
195
|
+
chosen_layouts = options[:layout] || @layout
|
196
|
+
chosen_layouts = [chosen_layouts] if chosen_layouts && !chosen_layouts.is_a?(Array)
|
197
|
+
if (chosen_layouts)
|
198
|
+
t = template
|
199
|
+
layout = nil
|
200
|
+
(chosen_layouts.length-1).downto(0) do |i|
|
201
|
+
layout = init_layout(chosen_layouts[i])
|
202
|
+
layout.template = t
|
203
|
+
t = layout
|
204
|
+
end
|
203
205
|
end
|
206
|
+
layout.init(scene) if layout
|
204
207
|
end
|
205
|
-
layout.init(scene) if layout
|
206
208
|
init_widgets(template, layout)
|
207
209
|
return template if done?
|
208
210
|
if layout
|
data/lib/spiderfw/env.rb
CHANGED
@@ -14,4 +14,11 @@ $:.push($SPIDER_PATH)
|
|
14
14
|
# Dir.chdir($SPIDER_RUN_PATH)
|
15
15
|
|
16
16
|
$SPIDER_RUNMODE ||= ENV['SPIDER_RUNMODE']
|
17
|
-
$SPIDER_CONFIG_SETS = ENV['SPIDER_CONFIG_SETS'].split(/\s+,\s+/) if ENV['SPIDER_CONFIG_SETS']
|
17
|
+
$SPIDER_CONFIG_SETS = ENV['SPIDER_CONFIG_SETS'].split(/\s+,\s+/) if ENV['SPIDER_CONFIG_SETS']
|
18
|
+
|
19
|
+
$SPIDER_SCRIPT = $0
|
20
|
+
if $SPIDER_SCRIPT =~ /Rack|Passenger/
|
21
|
+
$SPIDER_RACK = true
|
22
|
+
$SPIDER_SCRIPT = ::File.expand_path('./bin/spider')
|
23
|
+
$SPIDER_NO_RESPAWN = true
|
24
|
+
end
|
data/lib/spiderfw/home.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'pathname'
|
2
|
+
require 'spiderfw/spider'
|
3
|
+
require 'spiderfw/app'
|
4
|
+
|
2
5
|
|
3
6
|
module Spider
|
4
7
|
|
@@ -21,17 +24,41 @@ module Spider
|
|
21
24
|
def load_apps(*args)
|
22
25
|
Spider.load_apps(*args)
|
23
26
|
end
|
27
|
+
|
28
|
+
def apps_path
|
29
|
+
@apps_path = Spider.paths[:apps] if Spider.respond_to?(:paths)
|
30
|
+
@apps_path ||= File.join(@path, 'apps')
|
31
|
+
end
|
24
32
|
|
25
33
|
def list_apps
|
26
|
-
|
27
|
-
|
34
|
+
apps_dir = Pathname.new(self.apps_path)
|
35
|
+
paths = Spider.find_all_apps(self.apps_path)
|
28
36
|
apps = []
|
29
|
-
|
30
|
-
dir = Pathname.new(
|
37
|
+
paths.each do |path|
|
38
|
+
dir = Pathname.new(path)
|
31
39
|
apps << dir.relative_path_from(apps_dir).to_s
|
32
40
|
end
|
33
41
|
apps
|
34
42
|
end
|
43
|
+
|
44
|
+
def apps
|
45
|
+
apps = {}
|
46
|
+
list_apps.each do |path|
|
47
|
+
spec_file = Dir.glob(File.join(self.apps_path, path, "*.appspec")).first
|
48
|
+
spec = nil
|
49
|
+
if spec_file
|
50
|
+
spec = Spider::App::AppSpec.load(spec_file)
|
51
|
+
app_name = spec.app_id
|
52
|
+
else
|
53
|
+
app_name = path
|
54
|
+
end
|
55
|
+
apps[app_name] = {
|
56
|
+
:path => path,
|
57
|
+
:spec => spec
|
58
|
+
}
|
59
|
+
end
|
60
|
+
apps
|
61
|
+
end
|
35
62
|
|
36
63
|
end
|
37
64
|
|
data/lib/spiderfw/http/server.rb
CHANGED
@@ -78,18 +78,18 @@ module Spider; module HTTP
|
|
78
78
|
:ssl_cert => options[:ssl_cert], :ssl_private_key => options[:ssl_key])
|
79
79
|
end
|
80
80
|
end
|
81
|
-
do_shutdown = lambda{
|
81
|
+
do_shutdown = lambda{
|
82
|
+
Debugger.post_mortem = false
|
83
|
+
# debugger
|
82
84
|
server.shutdown
|
83
85
|
ssl_server.shutdown if ssl_server
|
84
|
-
Spider.shutdown
|
85
86
|
pid_file = File.join(Spider.paths[:var], 'run/server.pid')
|
86
87
|
begin
|
87
88
|
File.unlink(pid_file)
|
88
89
|
rescue Errno::ENOENT
|
89
90
|
end
|
90
91
|
}
|
91
|
-
|
92
|
-
trap('INT', &do_shutdown)
|
92
|
+
Spider.on_shutdown(&do_shutdown)
|
93
93
|
|
94
94
|
thread.join
|
95
95
|
ssl_thread.join if ssl_thread
|
@@ -103,7 +103,11 @@ module Spider; module HTTP
|
|
103
103
|
File.open(pid_file, 'w') do |f|
|
104
104
|
f.write(Process.pid)
|
105
105
|
end
|
106
|
+
$SPIDER_SCRIPT ||= $0
|
106
107
|
$0 = process_name
|
108
|
+
STDIN.reopen "/dev/null" # Free file descriptors and
|
109
|
+
STDOUT.reopen "/dev/null", "a" # point them somewhere sensible
|
110
|
+
STDERR.reopen STDOUT # STDOUT/STDERR should go to a logfile
|
107
111
|
start.call
|
108
112
|
end
|
109
113
|
Process.detach(forked)
|
@@ -125,7 +129,11 @@ module Spider; module HTTP
|
|
125
129
|
Spider.logger.error("Install 'fssm' gem to enable respawning")
|
126
130
|
end
|
127
131
|
end
|
128
|
-
|
132
|
+
unless spawner_started
|
133
|
+
Spider.main_process_startup
|
134
|
+
Spider.startup
|
135
|
+
start.call
|
136
|
+
end
|
129
137
|
end
|
130
138
|
end
|
131
139
|
|
@@ -148,15 +156,22 @@ module Spider; module HTTP
|
|
148
156
|
rd, wr = IO.pipe
|
149
157
|
if pid = fork
|
150
158
|
# Spawner
|
159
|
+
Spider.logger.debug("Spawner forked")
|
151
160
|
@child_pid = pid
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
161
|
+
|
162
|
+
unless @already_forked
|
163
|
+
Spider.main_process_startup
|
164
|
+
exit_spawner = lambda{
|
165
|
+
Spider.logger.debug "Spawner exiting"
|
166
|
+
Process.kill 'KILL', @monitor_thread[:spawner_child_pid]
|
167
|
+
}
|
168
|
+
Spider.on_main_process_shutdown(&exit_spawner)
|
169
|
+
Spider.main_process_startup
|
170
|
+
$SPIDER_SCRIPT ||= $0
|
171
|
+
$0 = 'spider-spawner'
|
172
|
+
end
|
173
|
+
@already_forked = true
|
174
|
+
|
160
175
|
wr.close
|
161
176
|
@monitor_thread[:spawner_child_pid] = pid
|
162
177
|
# TODO
|
@@ -166,6 +181,9 @@ module Spider; module HTTP
|
|
166
181
|
|
167
182
|
else
|
168
183
|
# Child
|
184
|
+
$SPIDER_SPAWNED = true
|
185
|
+
trap('TERM'){ }
|
186
|
+
trap('INT'){ }
|
169
187
|
rd.close
|
170
188
|
Spider.spawner = wr
|
171
189
|
return unless @actions[action]
|
@@ -221,4 +239,4 @@ module Spider; module HTTP
|
|
221
239
|
|
222
240
|
end
|
223
241
|
|
224
|
-
end; end
|
242
|
+
end; end
|
@@ -149,8 +149,8 @@ module Spider; module Model
|
|
149
149
|
if (!el.integrated? && el.required? && (mode == :insert || obj.element_modified?(el)) && !obj.element_has_value?(el))
|
150
150
|
raise RequiredError.new(el)
|
151
151
|
end
|
152
|
-
if (el.unique? && !el.integrated? && obj.element_modified?(el))
|
153
|
-
existent = @model.where(el.name =>
|
152
|
+
if (el.unique? && !el.integrated? && obj.element_modified?(el) && curr_val = obj.get(el))
|
153
|
+
existent = @model.where(el.name => curr_val)
|
154
154
|
if (mode == :insert && existent.length > 0) || (mode == :update && existent.length > 1)
|
155
155
|
raise NotUniqueError.new(el)
|
156
156
|
end
|
@@ -17,13 +17,13 @@ module Spider; module Model
|
|
17
17
|
c = Condition.and
|
18
18
|
c[left_el] = (left..right)
|
19
19
|
q = Query.new(c)
|
20
|
-
q.order_by(left_el)
|
20
|
+
q.order_by(left_el) unless element.attributes[:order] == false
|
21
21
|
res = element.model.find(q)
|
22
22
|
return [] unless res
|
23
23
|
right_stack = []
|
24
24
|
res.each do |obj|
|
25
25
|
if (right_stack.length > 0)
|
26
|
-
right_stack.pop while (right_stack[right_stack.length-1] < obj.get(right_el))
|
26
|
+
right_stack.pop while (right_stack[right_stack.length-1] && right_stack[right_stack.length-1] < obj.get(right_el))
|
27
27
|
obj.set(element.attributes[:tree_depth], right_stack.length)
|
28
28
|
end
|
29
29
|
right_stack << obj.get(right_el)
|
@@ -47,7 +47,8 @@ module Spider; module Model
|
|
47
47
|
attributes[:tree_position] ||= :"#{name}_position"
|
48
48
|
choice(attributes[:reverse], self, attributes[:reverse_attributes])
|
49
49
|
element(name, self, attributes)
|
50
|
-
|
50
|
+
order = attributes[:order] == false ? false : true
|
51
|
+
element(attributes[:tree_left], Fixnum, :hidden => true, :tree_element => name, :order => order)
|
51
52
|
element(attributes[:tree_right], Fixnum, :hidden => true, :tree_element => name)
|
52
53
|
element(attributes[:tree_depth], Fixnum, :unmapped => true, :hidden => true, :tree_element => name)
|
53
54
|
element(attributes[:tree_position], Fixnum, :unmapped => true, :hidden => true, :tree_element => name)
|
@@ -162,9 +163,10 @@ module Spider; module Model
|
|
162
163
|
cnt = 0
|
163
164
|
parent.get(name).each do |sub|
|
164
165
|
cnt += 1
|
165
|
-
|
166
|
+
break if sub == self
|
166
167
|
end
|
167
|
-
|
168
|
+
cnt = nil if cnt = 0
|
169
|
+
cnt
|
168
170
|
end
|
169
171
|
|
170
172
|
end
|
@@ -15,7 +15,7 @@ module Spider; module Model; module Storage; module Db
|
|
15
15
|
:transactions => true,
|
16
16
|
:foreign_keys => true
|
17
17
|
}
|
18
|
-
@reserved_keywords = superclass.reserved_keywords
|
18
|
+
@reserved_keywords = superclass.reserved_keywords + ['interval']
|
19
19
|
@safe_conversions = DbStorage.safe_conversions.merge({
|
20
20
|
'CHAR' => ['VARCHAR', 'CLOB'],
|
21
21
|
'VARCHAR' => ['CLOB'],
|
@@ -337,6 +337,7 @@ module Spider; module Model; module Storage; module Db
|
|
337
337
|
columns = {}
|
338
338
|
primary_keys = []
|
339
339
|
foreign_keys = []
|
340
|
+
order = []
|
340
341
|
connection do |c|
|
341
342
|
res = c.query("select * from #{table} where 1=0")
|
342
343
|
fields = res.fetch_fields
|
@@ -363,6 +364,7 @@ module Spider; module Model; module Storage; module Db
|
|
363
364
|
col[flag_name] = (flags & flag_val == 0) ? false : true
|
364
365
|
end
|
365
366
|
columns[f.name] = col
|
367
|
+
order << f.name
|
366
368
|
primary_keys << f.name if f.is_pri_key?
|
367
369
|
end
|
368
370
|
res = c.query("select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE constraint_schema = '#{@db_name}' and table_name = '#{table}'")
|
@@ -379,7 +381,7 @@ module Spider; module Model; module Storage; module Db
|
|
379
381
|
end
|
380
382
|
|
381
383
|
end
|
382
|
-
return {:columns => columns, :primary_keys => primary_keys, :foreign_key_constraints => foreign_keys}
|
384
|
+
return {:columns => columns, :order => order, :primary_keys => primary_keys, :foreign_key_constraints => foreign_keys}
|
383
385
|
end
|
384
386
|
|
385
387
|
def table_exists?(table)
|
@@ -394,6 +396,57 @@ module Spider; module Model; module Storage; module Db
|
|
394
396
|
end
|
395
397
|
end
|
396
398
|
|
399
|
+
def get_table_create_sql(table)
|
400
|
+
sql = nil
|
401
|
+
connection do |c|
|
402
|
+
res = c.query("SHOW CREATE TABLE #{table}")
|
403
|
+
sql = res.fetch_row[1]
|
404
|
+
end
|
405
|
+
sql
|
406
|
+
end
|
407
|
+
|
408
|
+
|
409
|
+
def dump_table_data(table, stream)
|
410
|
+
connection do |c|
|
411
|
+
res = c.query("select * from #{table}")
|
412
|
+
num = res.num_rows
|
413
|
+
if num > 0
|
414
|
+
fields = res.fetch_fields
|
415
|
+
stream << "INSERT INTO `#{table}` (#{fields.map{ |f| "`#{f.name}`"}.join(', ')})\n"
|
416
|
+
stream << "VALUES\n"
|
417
|
+
cnt = 0
|
418
|
+
while row = res.fetch_row
|
419
|
+
cnt += 1
|
420
|
+
stream << "("
|
421
|
+
fields.each_with_index do |f, i|
|
422
|
+
stream << dump_value(row[i], f)
|
423
|
+
stream << ", " if i < fields.length - 1
|
424
|
+
end
|
425
|
+
stream << ")"
|
426
|
+
if cnt < num
|
427
|
+
stream << ",\n"
|
428
|
+
else
|
429
|
+
stream << ";\n"
|
430
|
+
end
|
431
|
+
end
|
432
|
+
stream << "\n\n"
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
def dump_value(val, field)
|
438
|
+
return 'NULL' if val.nil?
|
439
|
+
type = self.class.field_types[field.type]
|
440
|
+
if ['CHAR', 'VARCHAR', 'BLOB', 'TINY_BLOB', 'MEDIUM_BLOB', 'LONG_BLOB'].include?(type)
|
441
|
+
val = val.gsub("'", "''").gsub("\n", '\n').gsub("\r", '\r')
|
442
|
+
return "'#{val}'"
|
443
|
+
elsif ['DATE', 'TIME', 'DATETIME'].include?(type)
|
444
|
+
return "'#{val}'"
|
445
|
+
else
|
446
|
+
return val.to_s
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
397
450
|
# Schema methods
|
398
451
|
|
399
452
|
def table_name(name)
|