neoscout 0.1
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/.gitignore +9 -0
- data/.rspec +3 -0
- data/.rvmrc +2 -0
- data/AUTHORS +1 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +138 -0
- data/LICENSE.txt +21 -0
- data/README.md +194 -0
- data/Rakefile +30 -0
- data/TODO.org +27 -0
- data/etc/neo4j.yml +16 -0
- data/lib/neoscout.rb +12 -0
- data/lib/neoscout/constraints.rb +35 -0
- data/lib/neoscout/gdb_neo4j.rb +147 -0
- data/lib/neoscout/json_schema.rb +136 -0
- data/lib/neoscout/main.rb +205 -0
- data/lib/neoscout/model.rb +148 -0
- data/lib/neoscout/scout.rb +119 -0
- data/lib/neoscout/tools.rb +156 -0
- data/lib/neoscout/version.rb +3 -0
- data/neoscout.gemspec +25 -0
- data/root/README.md +3 -0
- data/script/neoscout +15 -0
- data/spec/lib/neoscout/constraints_spec.rb +25 -0
- data/spec/lib/neoscout/gdb_neo4j_spec.rb +81 -0
- data/spec/lib/neoscout/gdb_neo4j_spec_counts.json +282 -0
- data/spec/lib/neoscout/gdb_neo4j_spec_schema.json +46 -0
- data/spec/lib/neoscout/model_spec.rb +42 -0
- data/spec/lib/neoscout/tools_spec.rb +139 -0
- data/spec/spec_helper.rb +5 -0
- metadata +84 -0
data/etc/neo4j.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
neostore.nodestore.db.mapped_memory: 400M
|
2
|
+
neostore.relationshipstore.db.mapped_memory: 1G
|
3
|
+
neostore.propertystore.db.mapped_memory: 4G
|
4
|
+
neostore.propertystore.db.index.mapped_memory: 50M
|
5
|
+
neostore.propertystore.db.index.keys.mapped_memory: 50M
|
6
|
+
neostore.propertystore.db.strings.mapped_memory: 500M
|
7
|
+
neostore.propertystore.db.arrays.mapped_memory: 500M
|
8
|
+
|
9
|
+
# Keeping the defaults here for reference
|
10
|
+
# neostore.nodestore.db.mapped_memory: 25M
|
11
|
+
# neostore.relationshipstore.db.mapped_memory: 50M
|
12
|
+
# neostore.propertystore.db.mapped_memory: 90M
|
13
|
+
# neostore.propertystore.db.index.mapped_memory: 1M
|
14
|
+
# neostore.propertystore.db.index.keys.mapped_memory: 1M
|
15
|
+
# neostore.propertystore.db.strings.mapped_memory: 130M
|
16
|
+
# neostore.propertystore.db.arrays.mapped_memory: 130M
|
data/lib/neoscout.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'neo4j'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
require 'neoscout/version'
|
6
|
+
|
7
|
+
require 'neoscout/tools'
|
8
|
+
require 'neoscout/constraints'
|
9
|
+
require 'neoscout/model'
|
10
|
+
require 'neoscout/json_schema'
|
11
|
+
require 'neoscout/scout'
|
12
|
+
require 'neoscout/gdb_neo4j'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module NeoScout
|
2
|
+
|
3
|
+
module Constraints
|
4
|
+
|
5
|
+
class Constraint
|
6
|
+
def satisfied_by_node?(typer, node) ; satisfied_by?(typer, node) end
|
7
|
+
def satisfied_by_edge?(typer, edge) ; satisfied_by?(typer, edge) end
|
8
|
+
|
9
|
+
def satisfied_by?(typer, obj) ; raise NotImplementedError end
|
10
|
+
end
|
11
|
+
|
12
|
+
class PropConstraint < Constraint
|
13
|
+
attr_reader :name, :opt, :type
|
14
|
+
|
15
|
+
def initialize(args = {})
|
16
|
+
super(args)
|
17
|
+
@name = args[:name]
|
18
|
+
@opt = args[:opt]
|
19
|
+
@type = args[:type]
|
20
|
+
|
21
|
+
raise ArgumentError unless @name.kind_of? String
|
22
|
+
raise ArgumentError unless @name.length > 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
opt_s = if @opt then " (opt.)" else '' end
|
27
|
+
type_s = if @type then ": #{@type}" else '' end
|
28
|
+
|
29
|
+
"#{@name}#{type_s}#{opt_s}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module NeoScout
|
2
|
+
|
3
|
+
module GDB_Neo4j
|
4
|
+
|
5
|
+
module Constraints
|
6
|
+
|
7
|
+
class PropConstraint < NeoScout::Constraints::PropConstraint
|
8
|
+
|
9
|
+
def satisfied_by?(typer, obj)
|
10
|
+
if obj.property?(@name)
|
11
|
+
then satisfies_type?(typer, @type, obj[@name])
|
12
|
+
else self.opt
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def satisfies_type?(typer, type, value)
|
17
|
+
if type then typer.valid_value?(type, value) else true end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
class Typer < NeoScout::Typer
|
24
|
+
|
25
|
+
attr_accessor :type_attr
|
26
|
+
attr_accessor :nil_type
|
27
|
+
attr_accessor :value_type_table
|
28
|
+
attr_accessor :node_mapper
|
29
|
+
attr_accessor :edge_mapper
|
30
|
+
|
31
|
+
include TyperValueTableMixin
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@type_attr = '_classname'
|
35
|
+
@nil_type = '__NOTYPE__'
|
36
|
+
@node_mapper = nil
|
37
|
+
@edge_mapper = nil
|
38
|
+
@value_type_table = {}
|
39
|
+
end
|
40
|
+
|
41
|
+
def node_type(node)
|
42
|
+
props = node.props
|
43
|
+
return node_mapped(props[@type_attr]) if props.has_key? @type_attr
|
44
|
+
@nil_type
|
45
|
+
end
|
46
|
+
|
47
|
+
def edge_type(edge)
|
48
|
+
type = edge.rel_type
|
49
|
+
if type then edge_mapped(type.to_s) else @nil_type end
|
50
|
+
end
|
51
|
+
|
52
|
+
def checked_node_type?(node_type) ; node_type != self.nil_type end
|
53
|
+
def checked_edge_type?(edge_type) ; edge_type != self.nil_type end
|
54
|
+
|
55
|
+
def unknown_node_type?(type) ; type == @nil_type end
|
56
|
+
def unknown_edge_type?(type) ; type == @nil_type end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def node_mapped(t)
|
61
|
+
if self.node_mapper then self.node_mapper.call(t) else t end
|
62
|
+
end
|
63
|
+
|
64
|
+
def edge_mapped(t)
|
65
|
+
if self.edge_mapper then self.edge_mapper.call(t) else t end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
class ElementIterator < NeoScout::ElementIterator
|
71
|
+
|
72
|
+
def iter_nodes(args)
|
73
|
+
if args[:report_progress]
|
74
|
+
then report = args[:report_progress]
|
75
|
+
else report = lambda { |mode, what, num| } end
|
76
|
+
glops = org.neo4j.tooling.GlobalGraphOperations.at(Neo4j.db.graph)
|
77
|
+
iter = glops.getAllNodes.iterator
|
78
|
+
num = 0
|
79
|
+
while iter.hasNext do
|
80
|
+
node = iter.next
|
81
|
+
num = num + 1
|
82
|
+
report.call(:progress, :nodes, num)
|
83
|
+
yield node unless node.getId == 0
|
84
|
+
end
|
85
|
+
|
86
|
+
report.call(:finish, :nodes, num)
|
87
|
+
num
|
88
|
+
end
|
89
|
+
|
90
|
+
def iter_edges(args)
|
91
|
+
if args[:report_progress]
|
92
|
+
then report = args[:report_progress]
|
93
|
+
else report = lambda { |mode, what, num| } end
|
94
|
+
glops = org.neo4j.tooling.GlobalGraphOperations.at(Neo4j.db.graph)
|
95
|
+
iter = glops.getAllRelationships.iterator
|
96
|
+
num = 0
|
97
|
+
while iter.hasNext do
|
98
|
+
num = num + 1
|
99
|
+
report.call(:progress, :edges, num)
|
100
|
+
yield iter.next
|
101
|
+
end
|
102
|
+
|
103
|
+
report.call(:finish, :edges, num)
|
104
|
+
num
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
class Verifier < NeoScout::Verifier
|
110
|
+
def initialize(typer)
|
111
|
+
super()
|
112
|
+
@typer = typer
|
113
|
+
end
|
114
|
+
|
115
|
+
def new_node_prop_constr(args={})
|
116
|
+
Constraints::PropConstraint.new args
|
117
|
+
end
|
118
|
+
|
119
|
+
def new_edge_prop_constr(args={})
|
120
|
+
Constraints::PropConstraint.new args
|
121
|
+
end
|
122
|
+
|
123
|
+
def init_from_json(json)
|
124
|
+
super(json)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Scout < NeoScout::Scout
|
129
|
+
|
130
|
+
def initialize(args={})
|
131
|
+
args[:typer] = Typer.new unless args[:typer]
|
132
|
+
args[:verifier] = Verifier.new(args[:typer]) unless args[:verifier]
|
133
|
+
args[:iterator] = ElementIterator.new unless args[:iterator]
|
134
|
+
super args
|
135
|
+
end
|
136
|
+
|
137
|
+
def prep_counts(counts)
|
138
|
+
# Ensure __NOTYPE__entries always have a counts array
|
139
|
+
counts.typed_nodes[typer.nil_type]
|
140
|
+
counts.typed_edges[typer.nil_type]
|
141
|
+
counts
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module NeoScout
|
2
|
+
|
3
|
+
class Counter
|
4
|
+
|
5
|
+
def to_json
|
6
|
+
{ 'num_failed' => num_failed, 'num_total' => num_total }
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
# TODO indexes
|
13
|
+
# TODO edges
|
14
|
+
# TODO testing
|
15
|
+
|
16
|
+
class Verifier
|
17
|
+
|
18
|
+
def init_from_json(json)
|
19
|
+
JSON.cd(json, %w(nodes)).each_pair do |type_name, type_json|
|
20
|
+
JSON.cd(type_json, %w(properties)).each_pair do |prop_name, prop_json|
|
21
|
+
prop_constr = new_node_prop_constr name: prop_name, opt: !prop_json['relevant']
|
22
|
+
prop_set = self.node_props[type_name]
|
23
|
+
prop_set << prop_constr
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
JSON.cd(json, %w(connections)).each_pair do |type_name, type_json|
|
28
|
+
JSON.cd(type_json, %w(properties)).each_pair do |prop_name, prop_json|
|
29
|
+
prop_constr = new_edge_prop_constr name: prop_name, opt: !prop_json['relevant']
|
30
|
+
prop_set = self.edge_props[type_name]
|
31
|
+
prop_set << prop_constr
|
32
|
+
end
|
33
|
+
|
34
|
+
sources_json = if type_json.has_key?('sources') then type_json['sources'] else [] end
|
35
|
+
targets_json = if type_json.has_key?('targets') then type_json['targets'] else [] end
|
36
|
+
add_valid_edge_sets type_name, sources_json, targets_json
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
class HashWithDefault
|
44
|
+
|
45
|
+
def to_json
|
46
|
+
self.map_value { |v| v.to_json }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
#noinspection RubyTooManyInstanceVariablesInspection
|
51
|
+
class Counts
|
52
|
+
|
53
|
+
def add_to_json(json)
|
54
|
+
all_json = JSON.cd json, %w(all)
|
55
|
+
all_json['node_counts'] = @all_nodes.to_json
|
56
|
+
all_json['connection_counts'] = @all_edges.to_json
|
57
|
+
|
58
|
+
nodes_json = JSON.cd(json, %w(nodes))
|
59
|
+
@typed_nodes.each_pair do |type, count|
|
60
|
+
skip = skip_from_json(:node, type, count)
|
61
|
+
JSON.cd(nodes_json, [type])['counts'] = count.to_json unless skip
|
62
|
+
end
|
63
|
+
|
64
|
+
nodes_json = JSON.cd(json, %w(nodes))
|
65
|
+
@typed_node_props.each_pair do |type, props|
|
66
|
+
props.each_pair do |name, count|
|
67
|
+
skip = skip_from_json(:node, type, count)
|
68
|
+
JSON.cd(nodes_json, [type, 'properties', name])['counts'] = count.to_json unless skip
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
edges_json = JSON.cd(json, %w(connections))
|
73
|
+
@typed_edges.each_pair do |type, count|
|
74
|
+
skip = skip_from_json(:edge, type, count)
|
75
|
+
JSON.cd(edges_json, [type])['counts'] = count.to_json unless skip
|
76
|
+
end
|
77
|
+
|
78
|
+
edges_json = JSON.cd(json, %w(connections))
|
79
|
+
@typed_edge_props.each_pair do |type, props|
|
80
|
+
props.each_pair do |name, count|
|
81
|
+
skip = skip_from_json(:edge, type, count)
|
82
|
+
JSON.cd(edges_json, [type, 'properties', name])['counts'] = count.to_json unless skip
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
add_link_stats_to_json(json)
|
87
|
+
end
|
88
|
+
|
89
|
+
def skip_from_json(kind, type, count)
|
90
|
+
false unless count.empty?
|
91
|
+
case kind
|
92
|
+
when :node
|
93
|
+
@typer.unknown_node_type?(type)
|
94
|
+
when :edge
|
95
|
+
@typer.unknown_edge_type?(type)
|
96
|
+
else
|
97
|
+
raise ArgumentError
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
protected
|
102
|
+
|
103
|
+
def add_link_stats_to_json(json)
|
104
|
+
nodes_json = JSON.cd(json, %w(nodes))
|
105
|
+
|
106
|
+
@node_link_src_stats.each_pair do |type, hash|
|
107
|
+
JSON.cd(nodes_json, [type])['src_stats'] = hash.to_json
|
108
|
+
end
|
109
|
+
|
110
|
+
@node_link_dst_stats.each_pair do |type, hash|
|
111
|
+
JSON.cd(nodes_json, [type])['dst_stats'] = hash.to_json
|
112
|
+
end
|
113
|
+
|
114
|
+
edges_json = JSON.cd(json, %w(connections))
|
115
|
+
@edge_link_src_stats.each_pair do |type, hash|
|
116
|
+
JSON.cd(edges_json, [type])['src_stats'] = hash_to_json_array('to_dst', hash)
|
117
|
+
end
|
118
|
+
|
119
|
+
@edge_link_dst_stats.each_pair do |type, hash|
|
120
|
+
JSON.cd(edges_json, [type])['dst_stats'] = hash_to_json_array('from_src', hash)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def hash_to_json_array(target, hash)
|
125
|
+
result = []
|
126
|
+
hash.each_pair do |key, value|
|
127
|
+
inner = []
|
128
|
+
value.each_pair do |i_key, i_value|
|
129
|
+
inner << { 'name' => i_key, 'counts' => i_value.to_json }
|
130
|
+
end
|
131
|
+
result << { 'name' => key, target => inner }
|
132
|
+
end
|
133
|
+
result
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'java'
|
2
|
+
require 'yaml'
|
3
|
+
require 'optparse'
|
4
|
+
require 'json'
|
5
|
+
require 'httparty'
|
6
|
+
require 'date'
|
7
|
+
require 'active_model'
|
8
|
+
require 'active_support/inflector'
|
9
|
+
|
10
|
+
module NeoScout
|
11
|
+
|
12
|
+
class Main
|
13
|
+
attr_reader :opt_db
|
14
|
+
attr_reader :opt_schema
|
15
|
+
attr_reader :opt_port
|
16
|
+
attr_reader :opt_webservice
|
17
|
+
attr_reader :opt_bind
|
18
|
+
attr_reader :opt_report
|
19
|
+
attr_reader :opt_no_nodes
|
20
|
+
attr_reader :opt_db_config
|
21
|
+
attr_reader :opt_no_edges
|
22
|
+
attr_reader :opt_type_mapper
|
23
|
+
attr_reader :opt_pre_mapper
|
24
|
+
attr_reader :opt_output_file
|
25
|
+
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@opt_report = 0
|
29
|
+
@opt_webservice = false
|
30
|
+
@opt_output_file = nil
|
31
|
+
@opt_no_nodes = false
|
32
|
+
@opt_db_config = nil
|
33
|
+
@opt_no_edges = false
|
34
|
+
@opt_pre_mapper = lambda { |t| t }
|
35
|
+
@opt_type_mapper = lambda { |t| t }
|
36
|
+
parse_opts
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse_opts
|
40
|
+
optparse = OptionParser.new do |opts|
|
41
|
+
opts.banner = "Usage: --db <neo4j:path> --schema <url> [--port <port>]"
|
42
|
+
opts.on('-d', '--db DB', 'Path to database in the form neo4j:<path>)') do |db|
|
43
|
+
@opt_db = db
|
44
|
+
end
|
45
|
+
opts.on('-u', '--schema-url URL', 'URL to database schema') do |url|
|
46
|
+
@opt_schema = lambda { || ::JSON.parse(HTTParty.get(url)) }
|
47
|
+
end
|
48
|
+
opts.on('-s', '--schema-file FILE', 'schema file') do |file|
|
49
|
+
@opt_schema = lambda { || ::JSON.parse(IO::read(file)) }
|
50
|
+
end
|
51
|
+
opts.on('-o', '--output-file FILE', 'output file in standalone mode') do |f|
|
52
|
+
@opt_output_file = f
|
53
|
+
end
|
54
|
+
opts.on('-w', '--webservice', 'Run inside sinatra') do
|
55
|
+
@opt_webservice = true
|
56
|
+
end
|
57
|
+
opts.on('-p', '--port PORT', 'Port to be used') do |port|
|
58
|
+
@opt_port = port.to_i
|
59
|
+
end
|
60
|
+
opts.on('-b', '--bind ITF', 'Interface to be used') do |itf|
|
61
|
+
@port = itf
|
62
|
+
end
|
63
|
+
opts.on('-r', '--report NUM', 'Report progress every NUM graph elements') do |num|
|
64
|
+
@opt_report = num.to_i
|
65
|
+
end
|
66
|
+
opts.on('--no-nodes', 'Do not iterate over nodes') do
|
67
|
+
@opt_no_nodes = true
|
68
|
+
end
|
69
|
+
opts.on('--no-edges', 'Do not iterate over edges') do
|
70
|
+
@opt_no_edges = true
|
71
|
+
end
|
72
|
+
opts.on('-P', '--pluralize-types', 'Pluralize type names') do
|
73
|
+
@opt_pre_mapper = lambda { |t| t.pluralize }
|
74
|
+
end
|
75
|
+
opts.on('-S', '--singularize-types', 'Singularize type names') do
|
76
|
+
@opt_pre_mapper = lambda { |t| t.singularize }
|
77
|
+
end
|
78
|
+
opts.on('-M', '--type-mapper MAPPER',
|
79
|
+
'Set the type mapper (underscore, downcase, upcase)') do |mapper|
|
80
|
+
@opt_type_mapper = case mapper
|
81
|
+
when 'underscore'
|
82
|
+
lambda { |t| t.underscore }
|
83
|
+
when 'downcase'
|
84
|
+
lambda { |t| t.downcase }
|
85
|
+
when 'upcase'
|
86
|
+
lambda { |t| t.upcase }
|
87
|
+
else
|
88
|
+
raise ArgumentException('Unsupported mapper')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
opts.on('-C', '--db-config FILE', 'Set config file for db driver') do |file|
|
92
|
+
@opt_db_config = file
|
93
|
+
end
|
94
|
+
opts.on('-h', '--help', 'Display this screen') do
|
95
|
+
puts opts
|
96
|
+
exit 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
optparse.parse!
|
100
|
+
@opt_output_file = nil if @opt_webservice
|
101
|
+
end
|
102
|
+
|
103
|
+
def start_db
|
104
|
+
@opt_db.match(/(neo4j:)(.*)/) do |m|
|
105
|
+
Neo4j.config[:storage_path] = m[2] unless (m[2].length == 0)
|
106
|
+
YAML.load_file(@opt_db_config).each_pair { |k,v| Neo4j.config[k] = v } if @opt_db_config
|
107
|
+
Neo4j.start
|
108
|
+
return lambda do
|
109
|
+
scout = ::NeoScout::GDB_Neo4j::Scout.new
|
110
|
+
pre_mapper = self.opt_pre_mapper
|
111
|
+
scout.typer.node_mapper = lambda { |t| self.opt_type_mapper.call(pre_mapper.call(t)) }
|
112
|
+
scout.typer.edge_mapper = lambda { |t| self.opt_type_mapper.call(pre_mapper.call(t)) }
|
113
|
+
scout
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
raise ArgumentError("Unsupported database type")
|
118
|
+
end
|
119
|
+
|
120
|
+
def shutdown_db
|
121
|
+
@opt_db.match(/(neo4j:)(.*)/) do |m|
|
122
|
+
Neo4j.shutdown
|
123
|
+
return
|
124
|
+
end
|
125
|
+
|
126
|
+
raise ArgumentError("Unsupported database type")
|
127
|
+
end
|
128
|
+
|
129
|
+
class SimpleConsoleLogger
|
130
|
+
def method_missing(key, *args)
|
131
|
+
print key
|
132
|
+
print ': '
|
133
|
+
puts *args
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def run
|
138
|
+
### Load schema at least once to know that we're safe
|
139
|
+
self.opt_schema.call()
|
140
|
+
### Run as service if requested
|
141
|
+
return run_webservice(self.opt_schema, self.start_db) if self.opt_webservice
|
142
|
+
|
143
|
+
json = run_standalone(self.opt_schema, self.start_db, SimpleConsoleLogger.new)
|
144
|
+
if self.opt_output_file
|
145
|
+
then File.open(self.opt_output_file, 'w') { |f| f.write(json) }
|
146
|
+
else puts(json) end
|
147
|
+
shutdown_db
|
148
|
+
end
|
149
|
+
|
150
|
+
def run_standalone(schema_maker, scout_maker, logger)
|
151
|
+
schema = schema_maker.call()
|
152
|
+
scout = scout_maker.call()
|
153
|
+
scout.verifier.init_from_json schema
|
154
|
+
counts = scout.new_counts
|
155
|
+
logger = SimpleConsoleLogger.new unless logger
|
156
|
+
progress = lambda do |mode, what, num|
|
157
|
+
if ((num % self.opt_report) == 0) || (mode == :finish)
|
158
|
+
logger.info("#{DateTime.now}: #{what} ITERATOR PROGRESS (#{mode} / #{num})")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
scout.count_edges counts: counts, report_progress: progress unless self.opt_no_edges
|
162
|
+
scout.count_nodes counts: counts, report_progress: progress unless self.opt_no_nodes
|
163
|
+
counts.add_to_json schema
|
164
|
+
schema.to_json
|
165
|
+
end
|
166
|
+
|
167
|
+
def run_webservice(schema_maker, scout_maker)
|
168
|
+
### Run sinatra
|
169
|
+
require 'sinatra'
|
170
|
+
|
171
|
+
set :port, @opt_port if @opt_port
|
172
|
+
set :bind, @opt_bind if @opt_bind
|
173
|
+
set :show_exceptions, true
|
174
|
+
set :sessions, false
|
175
|
+
set :logging, true
|
176
|
+
set :dump_errors, true
|
177
|
+
set :lock, true # -- really?
|
178
|
+
set :root, File.expand_path("../../root", __FILE__)
|
179
|
+
set :run, true
|
180
|
+
# set :public_folder
|
181
|
+
|
182
|
+
### Keep self around for calling helpers in sinatra handlers
|
183
|
+
main = self
|
184
|
+
|
185
|
+
### Return schema
|
186
|
+
get '/schema' do
|
187
|
+
content_type :json
|
188
|
+
schema_maker.call().to_json
|
189
|
+
end
|
190
|
+
|
191
|
+
### Run verify over database and report results
|
192
|
+
get '/verify' do
|
193
|
+
content_type :json
|
194
|
+
main.run_standalone(schema_maker, scout_maker, self.logger)
|
195
|
+
end
|
196
|
+
|
197
|
+
### Shutdown server, the hard way
|
198
|
+
get '/shutdown' do
|
199
|
+
main.shutdown_db
|
200
|
+
java.lang.System.exit(0)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|