rtext 0.9.3 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +4 -1
- data/Project.yaml +3 -2
- data/lib/rtext/frontend/connector.rb +10 -3
- data/lib/rtext/serializer.rb +2 -2
- data/lib/rtext/service.rb +68 -51
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0e14d27070197af864d0b24a38f9d41cb4115c3
|
4
|
+
data.tar.gz: '0984afc951a23e67def08c00be574c3b9b92647d'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8ad0fbe93721f12c413f839d4448cc606e50c0ad001272d35f47f67c57fe54b404472a7164f2abee3dec526d9dbd33c60bc16ea80a2b68fc0b7c486ce1ac43f
|
7
|
+
data.tar.gz: bc569b6b09999d14abf10f05c606b738880ffe6f480c520982b052ef3a39124548932e9dfd7901bc92b6f99e6495d6ddf3f87e88a04a97e4f52ec405caeb5b67
|
data/CHANGELOG
CHANGED
data/Project.yaml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
name: rtext
|
2
|
-
version: 0.9.
|
2
|
+
version: 0.9.4
|
3
3
|
git: https://github.com/mthiede/rtext.git
|
4
4
|
summary: Ruby Textual Modelling
|
5
5
|
email: martin dot thiede at gmx de
|
@@ -8,7 +8,8 @@ description: RText can be used to derive textual languages from an RGen metamode
|
|
8
8
|
authors: [Martin Thiede]
|
9
9
|
dependencies:
|
10
10
|
http://rubygems.org:
|
11
|
-
- {name: rgen,
|
11
|
+
- {name: rgen, version: '~> 0.8.0'}
|
12
|
+
- {name: filelock, version: '~> 1.1.0'}
|
12
13
|
rdoc_options: [--main, README.rdoc, -x, test]
|
13
14
|
extra_rdoc_files: [README.rdoc, CHANGELOG, MIT-LICENSE, RText_Users_Guide, RText_Protocol]
|
14
15
|
encrypt_sources: false
|
@@ -39,6 +39,7 @@ def execute_command(obj, options={})
|
|
39
39
|
obj["invocation_id"] = @invocation_id
|
40
40
|
obj["type"] = "request"
|
41
41
|
@socket.send(serialize_message(obj), 0)
|
42
|
+
@logger.debug('Sent request') if @logger
|
42
43
|
result = nil
|
43
44
|
@busy = true
|
44
45
|
@busy_start_time = Time.now
|
@@ -72,6 +73,7 @@ def execute_command(obj, options={})
|
|
72
73
|
result
|
73
74
|
end
|
74
75
|
else
|
76
|
+
@logger.debug('connecting')
|
75
77
|
:connecting
|
76
78
|
end
|
77
79
|
end
|
@@ -87,7 +89,7 @@ def stop
|
|
87
89
|
end
|
88
90
|
if connected?
|
89
91
|
execute_command({"type" => "request", "command" => "stop"})
|
90
|
-
while do_work
|
92
|
+
while do_work
|
91
93
|
sleep(0.1)
|
92
94
|
end
|
93
95
|
end
|
@@ -184,6 +186,7 @@ def connect
|
|
184
186
|
if @process_id.nil?
|
185
187
|
File.unlink(@out_file) if File.exist?(@out_file)
|
186
188
|
Dir.chdir(File.dirname(@config.file)) do
|
189
|
+
@logger.debug(@config.command.strip + " > #{@out_file} 2>&1") if @logger
|
187
190
|
@process_id = spawn(@config.command.strip + " > #{@out_file} 2>&1")
|
188
191
|
@state = :wait_for_file
|
189
192
|
end
|
@@ -191,8 +194,9 @@ def connect
|
|
191
194
|
end
|
192
195
|
|
193
196
|
def do_work
|
194
|
-
|
197
|
+
unless @process_id
|
195
198
|
@state = :off
|
199
|
+
@logger.debug('No process id') if @logger
|
196
200
|
return false
|
197
201
|
end
|
198
202
|
if @state == :wait_for_port && !File.exist?(@out_file)
|
@@ -263,6 +267,7 @@ def do_work
|
|
263
267
|
@logger.info "server socket closed (end of file)" if @logger
|
264
268
|
end
|
265
269
|
if data
|
270
|
+
@logger.debug('Got data') if @logger
|
266
271
|
repeat = true
|
267
272
|
response_data.concat(data)
|
268
273
|
while obj = extract_message(response_data)
|
@@ -277,6 +282,7 @@ def do_work
|
|
277
282
|
elsif !backend_running? || socket_closed
|
278
283
|
cleanup
|
279
284
|
@state = :off
|
285
|
+
@logger.debug("backend_running?: #{backend_running?}, socket_closed: #{socket_closed}") if @logger
|
280
286
|
return false
|
281
287
|
end
|
282
288
|
end
|
@@ -291,7 +297,8 @@ def cleanup
|
|
291
297
|
break unless backend_running?
|
292
298
|
sleep(0.1)
|
293
299
|
end
|
294
|
-
ensure_process_cleanup(@process_id, @keep_outfile ?
|
300
|
+
ensure_process_cleanup(@process_id, @keep_outfile ? nil : @out_file, 10)
|
301
|
+
@process_id = nil
|
295
302
|
end
|
296
303
|
|
297
304
|
end
|
data/lib/rtext/serializer.rb
CHANGED
@@ -152,7 +152,7 @@ class Serializer
|
|
152
152
|
result << v.to_s
|
153
153
|
end
|
154
154
|
elsif feature.eType.instanceClass == String
|
155
|
-
if @lang.unquoted?(feature) && v.to_s =~ /^[a-zA-Z_]\w*$/ && v.to_s != "true" && v.to_s != "false"
|
155
|
+
if @lang.unquoted?(feature) && v.to_s =~ /^[a-zA-Z_]\w*$/m && v.to_s != "true" && v.to_s != "false"
|
156
156
|
result << v.to_s
|
157
157
|
else
|
158
158
|
result << "\"#{v.gsub("\\","\\\\\\\\").gsub("\"","\\\"").gsub("\n","\\n").
|
@@ -166,7 +166,7 @@ class Serializer
|
|
166
166
|
# formatting not available for BigDecimals
|
167
167
|
else
|
168
168
|
if arg_format
|
169
|
-
|
169
|
+
result << sprintf(arg_format, v)
|
170
170
|
else
|
171
171
|
result << v.to_s
|
172
172
|
end
|
data/lib/rtext/service.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'socket'
|
2
|
+
require 'yaml'
|
3
|
+
require 'filelock'
|
2
4
|
require 'rtext/context_builder'
|
3
5
|
require 'rtext/message_helper'
|
4
6
|
require 'rtext/link_detector'
|
@@ -6,7 +8,7 @@ require 'rtext/link_detector'
|
|
6
8
|
# optimization: garbage collect while service is idle
|
7
9
|
|
8
10
|
module RText
|
9
|
-
|
11
|
+
|
10
12
|
class Service
|
11
13
|
include RText::MessageHelper
|
12
14
|
|
@@ -33,62 +35,77 @@ class Service
|
|
33
35
|
@timeout = options[:timeout] || 60
|
34
36
|
@logger = options[:logger]
|
35
37
|
@on_startup = options[:on_startup]
|
38
|
+
@lock_file_path = options[:lock_file_path] || File.expand_path('.rtext.lock')
|
39
|
+
@config_file_path = options[:config_file_path] || File.expand_path('.rtext.config')
|
40
|
+
@lock_file = nil
|
36
41
|
end
|
37
42
|
|
38
43
|
def run
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
last_access_time = Time.now
|
45
|
-
last_flush_time = Time.now
|
46
|
-
@stop_requested = false
|
47
|
-
sockets = []
|
48
|
-
request_data = {}
|
49
|
-
while !@stop_requested
|
44
|
+
Filelock @lock_file_path, :timeout => 0, :wait => 1 do
|
45
|
+
server = create_server
|
46
|
+
puts "RText service, listening on port #{server.addr[1]}"
|
47
|
+
@logger.debug('Server started') if @logger
|
48
|
+
File.write(@config_file_path, YAML.dump({'port' => server.addr[1], 'pid' => Process.pid}))
|
50
49
|
begin
|
51
|
-
|
52
|
-
sock.sync = true
|
53
|
-
sockets << sock
|
54
|
-
@logger.info "accepted connection" if @logger
|
55
|
-
rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR, Errno::EWOULDBLOCK
|
56
|
-
rescue Exception => e
|
57
|
-
@logger.warn "unexpected exception during socket accept: #{e.class}"
|
58
|
-
end
|
59
|
-
sockets.dup.each do |sock|
|
60
|
-
data = nil
|
61
|
-
begin
|
62
|
-
data = sock.read_nonblock(100000)
|
63
|
-
rescue Errno::EWOULDBLOCK
|
64
|
-
rescue IOError, EOFError, Errno::ECONNRESET, Errno::ECONNABORTED
|
65
|
-
sock.close
|
66
|
-
request_data[sock] = nil
|
67
|
-
sockets.delete(sock)
|
68
|
-
rescue Exception => e
|
69
|
-
# catch Exception to make sure we don't crash due to unexpected exceptions
|
70
|
-
@logger.warn "unexpected exception during socket read: #{e.class}"
|
71
|
-
sock.close
|
72
|
-
request_data[sock] = nil
|
73
|
-
sockets.delete(sock)
|
74
|
-
end
|
75
|
-
if data
|
76
|
-
last_access_time = Time.now
|
77
|
-
request_data[sock] ||= ""
|
78
|
-
request_data[sock].concat(data)
|
79
|
-
while obj = extract_message(request_data[sock])
|
80
|
-
message_received(sock, obj)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
IO.select([server] + sockets, [], [], 1)
|
85
|
-
if Time.now > last_access_time + @timeout
|
86
|
-
@logger.info("RText service, stopping now (timeout)") if @logger
|
87
|
-
break
|
88
|
-
end
|
89
|
-
if Time.now > last_flush_time + FlushInterval
|
50
|
+
@on_startup.call if @on_startup
|
90
51
|
$stdout.flush
|
52
|
+
|
53
|
+
last_access_time = Time.now
|
91
54
|
last_flush_time = Time.now
|
55
|
+
@stop_requested = false
|
56
|
+
sockets = []
|
57
|
+
request_data = {}
|
58
|
+
while !@stop_requested
|
59
|
+
begin
|
60
|
+
sock = server.accept_nonblock
|
61
|
+
sock.sync = true
|
62
|
+
sockets << sock
|
63
|
+
@logger.info "accepted connection" if @logger
|
64
|
+
rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR, Errno::EWOULDBLOCK
|
65
|
+
rescue Exception => e
|
66
|
+
@logger.warn "unexpected exception during socket accept: #{e.class}"
|
67
|
+
end
|
68
|
+
sockets.dup.each do |sock|
|
69
|
+
data = nil
|
70
|
+
begin
|
71
|
+
data = sock.read_nonblock(100000)
|
72
|
+
@logger.debug('Got data') if @logger
|
73
|
+
rescue Errno::EWOULDBLOCK
|
74
|
+
rescue IOError, EOFError, Errno::ECONNRESET, Errno::ECONNABORTED
|
75
|
+
sock.close
|
76
|
+
request_data[sock] = nil
|
77
|
+
sockets.delete(sock)
|
78
|
+
rescue Exception => e
|
79
|
+
# catch Exception to make sure we don't crash due to unexpected exceptions
|
80
|
+
@logger.warn "unexpected exception during socket read: #{e.class}"
|
81
|
+
sock.close
|
82
|
+
request_data[sock] = nil
|
83
|
+
sockets.delete(sock)
|
84
|
+
end
|
85
|
+
if data
|
86
|
+
last_access_time = Time.now
|
87
|
+
request_data[sock] ||= ""
|
88
|
+
request_data[sock].concat(data)
|
89
|
+
@logger.debug("Data available: #{request_data[sock]}") if @logger
|
90
|
+
while obj = extract_message(request_data[sock])
|
91
|
+
@logger.debug("Got message #{obj.inspect}") if @logger
|
92
|
+
message_received(sock, obj)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
IO.select([server] + sockets, [], [], 1)
|
97
|
+
if Time.now > last_access_time + @timeout
|
98
|
+
@logger.info("RText service, stopping now (timeout)") if @logger
|
99
|
+
break
|
100
|
+
end
|
101
|
+
if Time.now > last_flush_time + FlushInterval
|
102
|
+
$stdout.flush
|
103
|
+
last_flush_time = Time.now
|
104
|
+
end
|
105
|
+
end
|
106
|
+
ensure
|
107
|
+
@logger.warn("Config file doesn't exist, but lock is acquired, it could be a bug") unless File.exist?(@config_file_path)
|
108
|
+
File.unlink(@config_file_path) if File.exist?(@config_file_path)
|
92
109
|
end
|
93
110
|
end
|
94
111
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rtext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Thiede
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rgen
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.8.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: filelock
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.1.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.1.0
|
27
41
|
description: RText can be used to derive textual languages from an RGen metamodel
|
28
42
|
with very little effort.
|
29
43
|
email:
|
@@ -84,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
98
|
version: '0'
|
85
99
|
requirements: []
|
86
100
|
rubyforge_project:
|
87
|
-
rubygems_version: 2.
|
101
|
+
rubygems_version: 2.6.14
|
88
102
|
signing_key:
|
89
103
|
specification_version: 4
|
90
104
|
summary: Ruby Textual Modelling
|