spiderfw 0.6.5 → 0.6.6
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/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)
|