em-rserve 0.1.0 → 0.1.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/Gemfile CHANGED
@@ -1,4 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in em-rserve.gemspec
4
- gemspec
3
+ gem "eventmachine"
4
+
5
+ group :development, :test do
6
+ gem "rspec"
7
+ end
data/README CHANGED
@@ -15,7 +15,6 @@ So far it can:
15
15
  - handle pools of connections with ruby fibers
16
16
 
17
17
  Limitations:
18
- - large QAP1 messages (>8MB) are not supported, this limitation means that you cannot transfer large object directly over RServe protocol
19
18
  - no support for the connections with a password. somehow, password without encryption defeats the purpose. hence, if you need a password, you should setup an SSH proxy instead
20
19
 
21
20
  Links:
data/TODO CHANGED
@@ -4,7 +4,7 @@
4
4
  - Table
5
5
  * RESP_ERR as a flag and not an OR-ed value
6
6
  -> will need to modify Header#error? and Header#error
7
- * support for long (>8M) messages
7
+ * factorize headers parsing/dumping for SEXP and QAP1 parameters
8
8
  * login command
9
9
  support crypt and store salt from connection setup
10
10
  * better attach method
@@ -21,6 +21,7 @@ module EM::Rserve
21
21
  @connections = []
22
22
  @size = size
23
23
  @connection_class = klass
24
+ fill size
24
25
  end
25
26
 
26
27
  def empty?
@@ -11,7 +11,7 @@ module EM::Rserve
11
11
  end
12
12
 
13
13
  def message_length
14
- length #TODO: use length2
14
+ length | length2 << 32
15
15
  end
16
16
 
17
17
  def body?
@@ -37,9 +37,6 @@ module EM::Rserve
37
37
  def error
38
38
  ((command & ~Constants::RESP_ERR) >> 24) & 0xff
39
39
  end
40
-
41
- # -> self.for_message
42
- # -> prepare_message
43
40
  end
44
41
  end
45
42
  end
@@ -8,13 +8,21 @@ module EM::Rserve
8
8
  include Constants
9
9
  include R
10
10
 
11
+ LARGE_SIZE_TRESHOLD = 0xfffff0
12
+
11
13
  def parameter_head(type, len)
12
- #TODO: support long parameter, type: 0xbf + DT_LARGE if len overflows
13
- (type & 0x000000ff) | ((len << 8) & 0xffffff00)
14
+ if len > LARGE_SIZE_TRESHOLD
15
+ head = (type & 0x000000bf) | ((len << 8) & 0xffffff00) | DT_LARGE
16
+ extra_len_bits = (len & ~0xffffff) >> 24
17
+ [head, extra_len_bits].pack('VV')
18
+ else
19
+ head = (type & 0x000000bf) | ((len << 8) & 0xffffff00)
20
+ [head].pack('V')
21
+ end
14
22
  end
15
23
 
16
24
  def pack_parameter(type, len, val, rule)
17
- [parameter_head(type, len), val].flatten.pack('V'+rule)
25
+ [parameter_head(type, len), val].flatten.pack('a*'+rule)
18
26
  end
19
27
 
20
28
  def encode_parameter(param, type=nil)
@@ -76,9 +84,9 @@ module EM::Rserve
76
84
  end
77
85
 
78
86
  def head_parameter(head)
79
- type = head & 0x000000bf
87
+ type = head & 0x000000bf
80
88
  large = (head & DT_LARGE) > 0
81
- len = (head & 0xffffff00) >> 8
89
+ len = (head & 0xffffff00) >> 8
82
90
  [type, len, large]
83
91
  end
84
92
 
@@ -112,7 +120,10 @@ module EM::Rserve
112
120
  until buffer.empty? do
113
121
  head, buffer = buffer.unpack('Va*')
114
122
  type, len, large = head_parameter(head)
115
- raise NotImplementedError, "too long QAP1 message" if large
123
+ if large
124
+ long_len, buffer = buffer.unpack('Va*')
125
+ len = long_len << 24 | len
126
+ end
116
127
  if buffer.size < len
117
128
  raise RuntimeError, "cannot decode #{buffer} (not enough bytes)"
118
129
  end
@@ -57,6 +57,8 @@ module EM::Rserve
57
57
  end
58
58
  end
59
59
 
60
+ LARGE_SIZE_TRESHOLD = 0xfffff0 #recommandation
61
+
60
62
  def dump_sexp
61
63
  body = dumped_value_with_attribute
62
64
  children_data = children.map do |n|
@@ -64,8 +66,9 @@ module EM::Rserve
64
66
  end.join('')
65
67
  size = body.size + children_data.size
66
68
  flags = {:large => false, :attr => attribute && true}
69
+ flags[:large] = true if size > LARGE_SIZE_TRESHOLD
67
70
  head = self.class.parameter_head(self.class.code, flags, size)
68
- [head, body + children_data].pack('Va*')
71
+ [head, body + children_data].join('')
69
72
  end
70
73
 
71
74
  def dumped_value_with_attribute
@@ -84,10 +87,16 @@ module EM::Rserve
84
87
  head_bits = type & 0x3f #high bits are for flags
85
88
  len_bits = (len & 0xffffff) << 8
86
89
  flags_bits = 0
87
- flags_bits |= 0x40 if flags[:large]
88
90
  flags_bits |= 0x80 if flags[:attr]
89
- ret = head_bits | len_bits | flags_bits
90
- ret
91
+ if flags[:large]
92
+ flags_bits |= 0x40
93
+ head = head_bits | len_bits | flags_bits
94
+ extra_len_bits = (len & ~0xffffff) >> 24
95
+ [head, extra_len_bits].pack('VV')
96
+ else
97
+ head = head_bits | len_bits | flags_bits
98
+ [head].pack('V')
99
+ end
91
100
  end
92
101
 
93
102
  class << self
@@ -392,6 +401,10 @@ module EM::Rserve
392
401
  def self.decode_nodes(buffer)
393
402
  head, buffer = buffer.unpack('Va*')
394
403
  type, flags, len = head_parameter(head)
404
+ if flags[:large]
405
+ long_len, buffer = buffer.unpack('Va*')
406
+ len = long_len << 24 | len
407
+ end
395
408
 
396
409
  # Cuts the buffer at the correct length and give away the remainder
397
410
  buffer, remainder = buffer.unpack("a#{len}a*")
@@ -1,5 +1,5 @@
1
1
  module EM
2
2
  module Rserve
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
  end
5
5
  end
data/samples/assign.rb CHANGED
@@ -10,13 +10,25 @@ class DevelConnection < EM::Rserve::Connection
10
10
  def dump_sexp(msg)
11
11
  raise unless msg.parameters.size == 1
12
12
  root = msg.parameters.first
13
- pp root
14
13
  val = EM::Rserve::R::RtoRuby::Translator.r_to_ruby(root)
15
- p val
14
+ if val.respond_to? :size
15
+ if val.size > 100
16
+ puts "too large to dump: #{val.class}"
17
+ else
18
+ pp root
19
+ p val
20
+ end
21
+ else
22
+ pp root
23
+ p val
24
+ end
16
25
  end
17
26
 
18
27
  def dump_r_val(str)
19
28
  r_eval(str) do |req|
29
+ req.errback do |msg|
30
+ puts "could not dump"
31
+ end
20
32
  req.callback do |msg|
21
33
  dump_sexp msg
22
34
  end
@@ -38,11 +50,16 @@ class DevelConnection < EM::Rserve::Connection
38
50
  def loop_parse_r_val(str)
39
51
  r_eval(str) do |req|
40
52
  req.callback do |msg|
53
+ puts "callback> #{str}"
41
54
  raise unless msg.parameters.size == 1
42
55
  root = msg.parameters.first
43
- new_root = EM::Rserve::R::Sexp.parse(root.dump_sexp)
56
+ puts 'got parsed SEXP parameter'
44
57
  val1 = EM::Rserve::R::RtoRuby::Translator.r_to_ruby(root)
58
+ puts 'translated SEXP'
59
+ new_root = EM::Rserve::R::Sexp.parse(root.dump_sexp)
60
+ puts 'dumped SEXP'
45
61
  val2 = EM::Rserve::R::RtoRuby::Translator.r_to_ruby(new_root)
62
+ puts 're-translated dumped SEXP'
46
63
  if val1 == val2
47
64
  p "ok: #{str}"
48
65
  else
@@ -155,9 +172,14 @@ class DevelConnection < EM::Rserve::Connection
155
172
  def ready
156
173
  puts "ready"
157
174
 
158
- loop_parse_r_val '1+1i'
159
- loop_parse_r_val 'c(1:1000)'
160
- loop_parse_r_val 'c(1:10000000)'
175
+ #do_array_int((1 .. 10).to_a)
176
+ #do_array_int((1 .. 10000000).to_a)
177
+ loop_parse_r_val 'c(1:5)'
178
+ loop_parse_r_val "c(1:10000000)"
179
+ loop_parse_r_val 'table(c(1,2,3,2,2))'
180
+ loop_parse_r_val "data.frame(foo=c(1:8), bar=seq(100,800,100))"
181
+ loop_parse_r_val "data.frame(foo=c(1,2,3), bar=c(NA,FALSE,TRUE), row.names=c('foo','bar','baz'))"
182
+
161
183
 
162
184
  return
163
185
 
@@ -173,10 +195,6 @@ class DevelConnection < EM::Rserve::Connection
173
195
 
174
196
  return
175
197
 
176
- loop_parse_r_val 'c(1:5)'
177
- loop_parse_r_val 'table(c(1,2,3,2,2))'
178
- loop_parse_r_val "data.frame(foo=c(1:8), bar=seq(100,800,100))"
179
- loop_parse_r_val "data.frame(foo=c(1,2,3), bar=c(NA,FALSE,TRUE), row.names=c('foo','bar','baz'))"
180
198
 
181
199
  #do_int
182
200
  #do_double
metadata CHANGED
@@ -1,34 +1,23 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: em-rserve
3
- version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 1
9
- - 0
10
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - crapooze
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-10-10 00:00:00 +02:00
19
- default_executable:
12
+ date: 2011-10-21 00:00:00.000000000Z
20
13
  dependencies: []
21
-
22
14
  description: Do evented stats with EventMachine and RServe
23
- email:
15
+ email:
24
16
  - crapooze@gmail.com
25
17
  executables: []
26
-
27
18
  extensions: []
28
-
29
19
  extra_rdoc_files: []
30
-
31
- files:
20
+ files:
32
21
  - .gitignore
33
22
  - Gemfile
34
23
  - README
@@ -63,39 +52,28 @@ files:
63
52
  - specs/parser_spec.rb
64
53
  - specs/ruby_to_r_translator_spec.rb
65
54
  - specs/spec_helper.rb
66
- has_rdoc: true
67
- homepage: ""
55
+ homepage: ''
68
56
  licenses: []
69
-
70
57
  post_install_message:
71
58
  rdoc_options: []
72
-
73
- require_paths:
59
+ require_paths:
74
60
  - lib
75
- required_ruby_version: !ruby/object:Gem::Requirement
61
+ required_ruby_version: !ruby/object:Gem::Requirement
76
62
  none: false
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- hash: 3
81
- segments:
82
- - 0
83
- version: "0"
84
- required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
68
  none: false
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- hash: 3
90
- segments:
91
- - 0
92
- version: "0"
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
93
73
  requirements: []
94
-
95
74
  rubyforge_project: em-rserve
96
- rubygems_version: 1.3.7
75
+ rubygems_version: 1.8.6
97
76
  signing_key:
98
77
  specification_version: 3
99
78
  summary: An EventMachine client for RServe
100
79
  test_files: []
101
-