rtext 0.9.3 → 0.9.4
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.
- 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
|