boss-protocol 0.1.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 48d7d49095b00c5a6c7c1fc9c349e623cb52bc62
4
+ data.tar.gz: e15a3c17f710e7e07af4922ab85a70a01990e6a9
5
+ SHA512:
6
+ metadata.gz: 5d8586643c80b3bf34e73e624ca496733ad7e3c5e659f8021d59a42f4c4cb936f4e5385aaaeb0a874197febd98c31a0d56a13b1f7fce1624eb5eecc017de812b
7
+ data.tar.gz: d4835694296bd13626adaaeb10bc5cc1d950e53f1a1c71d9a5d868f38028f7bdc4f1baf8a8e97c1df511767c6dae49f7afbbdad9259329f332f3e2656e178248
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Boss Protocol
2
2
 
3
- BOSS is acronym for Binary Object Streamable Storage.
3
+ BOSS is an acronym for Binary Object Streaming Specification.
4
4
 
5
- The very space-effective, platform-independent^ streamable and traversable
5
+ The bit-effective, platform-independent streamable and traversable
6
6
  typed binary protocol. Allow to effectively store small or any sized integers,
7
7
  strings or binary data of any size, floats and doubles, arrays and hashes in a
8
8
  very effective way. It caches repeating objects and stores/restores links to
@@ -13,7 +13,7 @@ size, signed integers of absolutely any size, arrays and hashes with no limit
13
13
  on items and overall gross size. It is desirable to use build-in compression when
14
14
  appropriate.
15
15
 
16
- Streamable means that you can use a pipe (tcp/ip, wahtever), put the object at
16
+ Streamable means that you can use a pipe (for example tcp/ip), put the object at
17
17
  one side and load it on other, one-by-one, and caching and links will be
18
18
  restored properly.
19
19
 
@@ -23,6 +23,14 @@ json/boss/whatever. For example, typical JSON reduces in size twice with Boss.
23
23
 
24
24
  Boss protocol also allow to transparently compress its representations.
25
25
 
26
+ Boss also supports "stream mode" that lacks tree reconstruction but could be
27
+ effectively use when implementing long-living streams (e.g. stream protocols).
28
+ In regular mode it causes unlimited cache grows as Boss would try to reconstruct
29
+ all possible references to already serialized objects. In the stream mode only
30
+ strings are cached, and cache size and capacity are dynamically limited.
31
+ Boss writes stream mode marker and handles stream mode on receiving end
32
+ automatically.
33
+
26
34
  Supported types:
27
35
 
28
36
  * Signed integers of any length
@@ -86,7 +94,7 @@ To use the transparent compression:
86
94
  ## Streaming sample
87
95
 
88
96
  This sample shows boss object hierarchies passing between 2 forked processes
89
- using a pipe:
97
+ using a pipe (see samples/):
90
98
 
91
99
  if fork
92
100
  wr.close
@@ -1,3 +1,3 @@
1
1
  module Boss
2
- VERSION = "0.1.3"
2
+ VERSION = "1.3.0"
3
3
  end
data/lib/boss-protocol.rb CHANGED
@@ -36,6 +36,8 @@ require 'zlib'
36
36
  # Attn! We removed Bzip2 compression for the sake of compatibility. We may add it back when situation
37
37
  # with bz2 implementations on various platforms will be eased
38
38
  #
39
+ # 1.3 Stream mode added
40
+ #
39
41
  # 1.2 version adds support for booelans and removes support for python __reduce__ - based objects
40
42
  # as absolutely non portable. It also introduces
41
43
  #
@@ -51,8 +53,9 @@ require 'zlib'
51
53
 
52
54
  module Boss
53
55
 
54
- class NotSupportedException < StandardError; end
55
- # Basic types
56
+ class NotSupportedException < StandardError;
57
+ end
58
+ # Basic types
56
59
  TYPE_INT = 0
57
60
  TYPE_EXTRA = 1
58
61
  TYPE_NINT = 2
@@ -85,7 +88,9 @@ module Boss
85
88
  TFALSE = 13
86
89
 
87
90
  TCOMPRESSED = 14
88
- TTIME = 15
91
+ TTIME = 15
92
+
93
+ XT_STREAM_MODE = 16
89
94
 
90
95
  def checkArg(cond, msg=nil)
91
96
  raise ArgumentError unless cond
@@ -94,7 +99,6 @@ module Boss
94
99
  class UnknownTypeException < Exception;
95
100
  end
96
101
 
97
- ##
98
102
  # Formats ruby object hierarchies with BOSS
99
103
  # notation
100
104
  #
@@ -112,6 +116,20 @@ module Boss
112
116
  @cache = { nil => 0 }
113
117
  end
114
118
 
119
+
120
+ # Switch to stream mode. Stream mode limits cache using to strings only in LRU
121
+ # mode using specified parameters. Stream mode writes a marker into output so
122
+ # decoder knows it.
123
+ # @param max_string_size maximum allowed size of the string to be cached.
124
+ # longer strings will not be cached
125
+ # @param max_cache_entries
126
+ def stream_mode max_cache_entries, max_string_size
127
+ @max_cache_entries, @max_string_size = max_cache_entries, max_string_size
128
+ whdr TYPE_EXTRA, XT_STREAM_MODE
129
+ self << max_cache_entries.to_i << max_string_size.to_i
130
+ @cache = { nil => 0 }
131
+ end
132
+
115
133
  ##
116
134
  # same as put but automatically select and use proper compression. Parser.get
117
135
  # will automatically decompress.
@@ -128,8 +146,8 @@ module Boss
128
146
  else
129
147
  data = Zlib::Deflate.new.deflate(data, Zlib::FINISH)
130
148
  1
131
- #data = Bzip2.compress data
132
- #2
149
+ #data = Bzip2.compress data
150
+ #2
133
151
  end
134
152
  whdr type, data.length
135
153
  wbin data
@@ -211,18 +229,39 @@ module Boss
211
229
 
212
230
  private
213
231
 
214
- ##
215
232
  # Write cache ref if the object is cached, and return true
216
233
  # otherwise store object in the cache. Caller should
217
234
  # write object to @io if notCached return true, and skip
218
235
  # writing otherwise
236
+
219
237
  def notCached(obj)
220
238
  n = @cache[obj]
221
239
  if n
222
240
  whdr TYPE_CREF, n
223
241
  false
224
242
  else
225
- @cache[obj] = @cache.length
243
+ # Check stream mode
244
+ if @max_string_size
245
+ if obj.is_a?(String) && obj.length <= @max_string_size
246
+ if @cache.length > @max_cache_entries
247
+ minIndex = @cache.length - @max_cache_entries
248
+ key = nil
249
+ @cache.each { |k, v|
250
+ next if k == nil
251
+ if v == minIndex
252
+ key = k
253
+ else
254
+ @cache[k] = v - 1
255
+ end
256
+ }
257
+ key == nil and raise "Cache implementation failed"
258
+ @cache.delete key
259
+ end
260
+ @cache[obj] = @cache.length
261
+ end
262
+ else
263
+ @cache[obj] = @cache.length
264
+ end
226
265
  true
227
266
  end
228
267
  end
@@ -351,21 +390,26 @@ module Boss
351
390
  end
352
391
  when TTIME
353
392
  Time.at renc
393
+ when XT_STREAM_MODE
394
+ @cache = [nil]
395
+ @max_cache_entries = get + 1 # Count 0th element (always 0)
396
+ @max_string_size = get
397
+ get
354
398
  else
355
399
  raise UnknownTypeException
356
400
  end
357
401
  when TYPE_TEXT, TYPE_BIN
358
402
  s = rbin value
359
403
  s.force_encoding code == TYPE_BIN ? Encoding::BINARY : Encoding::UTF_8
360
- @cache << s
404
+ cache_object s
361
405
  s
362
406
  when TYPE_LIST
363
407
  # p "items", value
364
- @cache << (list = [])
408
+ cache_object (list = [])
365
409
  value.times { list << get }
366
410
  list
367
411
  when TYPE_DICT
368
- @cache << (dict = { })
412
+ cache_object (dict = {})
369
413
  value.times { dict[get] = get }
370
414
  dict
371
415
  when TYPE_CREF
@@ -391,6 +435,19 @@ module Boss
391
435
 
392
436
  private
393
437
 
438
+ def cache_object object
439
+ # Stream mode?
440
+ if @max_cache_entries
441
+ if object.is_a?(String) && object.length <= @max_string_size
442
+ # Should cache
443
+ @cache << object
444
+ @cache.delete_at(1) if @cache.length > @max_cache_entries
445
+ end
446
+ else
447
+ @cache << object
448
+ end
449
+ end
450
+
394
451
  ##
395
452
  # Read header and return code,value
396
453
  def rhdr
data/samples/testp.rb CHANGED
@@ -1,14 +1,18 @@
1
+ # The interprocess communication using BOSS through
2
+ # pipes
3
+
1
4
  require '../lib/boss-protocol'
2
5
 
3
6
  rd, wr = IO.pipe
4
7
 
5
8
  if fork
6
9
  wr.close
7
- if false
10
+ # There is more than one way:
11
+ if true
8
12
  # You can do it with block:
9
13
  Boss::Parser.new(rd).each { |obj| puts "Got an object: #{obj}" }
10
14
  else
11
- # You can do it without block too:
15
+ # You can do it without block:
12
16
  input = Boss::Parser.new rd
13
17
  puts "Got an object: #{input.get}" while !input.eof?
14
18
  end
data/spec/boss_spec.rb CHANGED
@@ -152,6 +152,28 @@ describe 'Boss' do
152
152
  -> { Boss.dump MyObject.new }.should raise_error(Boss::NotSupportedException)
153
153
  end
154
154
 
155
+ it 'should implement stream mode' do
156
+ out = Boss::Formatter.new
157
+ out.stream_mode 3, 10
158
+ 3.times { out << "String too long" }
159
+ (1..6).each { |n| out << "test#{n}" }
160
+ (4..6).each { |n| out << "test#{n}" }
161
+ (4..6).each { |n| out << "test#{n}" }
162
+ out << "test7"
163
+
164
+ res = "\x81\x18P{String too long{String too long{String too long+test1+test2+test3+test4+test5+test6\r\x15\x1D\r\x15\x1D+test7"
165
+ res.force_encoding 'binary'
166
+ out.string.should == res
167
+
168
+ inp = Boss::Parser.new out.string
169
+
170
+ 3.times { inp.get.should == "String too long" }
171
+ (1..6).each { |n| inp.get.should == "test#{n}" }
172
+ (4..6).each { |n| inp.get.should == "test#{n}" }
173
+ (4..6).each { |n| inp.get.should == "test#{n}" }
174
+ inp.get.should == "test7"
175
+ end
176
+
155
177
  def round_check(ob)
156
178
  ob.should == Boss.load(Boss.dump(ob))
157
179
  end
metadata CHANGED
@@ -1,30 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boss-protocol
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
5
- prerelease:
4
+ version: 1.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - sergeych
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-03-28 00:00:00.000000000 Z
11
+ date: 2013-08-21 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rspec
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  description: Binary streamable bit-effective protocol to effectively store object
@@ -37,6 +34,7 @@ extra_rdoc_files: []
37
34
  files:
38
35
  - .gitignore
39
36
  - .rspec
37
+ - .ruby-version
40
38
  - Gemfile
41
39
  - LICENSE.txt
42
40
  - README.md
@@ -49,27 +47,26 @@ files:
49
47
  - spec/spec_helper.rb
50
48
  homepage: ''
51
49
  licenses: []
50
+ metadata: {}
52
51
  post_install_message:
53
52
  rdoc_options: []
54
53
  require_paths:
55
54
  - lib
56
55
  required_ruby_version: !ruby/object:Gem::Requirement
57
- none: false
58
56
  requirements:
59
- - - ! '>='
57
+ - - '>='
60
58
  - !ruby/object:Gem::Version
61
59
  version: '0'
62
60
  required_rubygems_version: !ruby/object:Gem::Requirement
63
- none: false
64
61
  requirements:
65
- - - ! '>='
62
+ - - '>='
66
63
  - !ruby/object:Gem::Version
67
64
  version: '0'
68
65
  requirements: []
69
66
  rubyforge_project:
70
- rubygems_version: 1.8.25
67
+ rubygems_version: 2.0.6
71
68
  signing_key:
72
- specification_version: 3
69
+ specification_version: 4
73
70
  summary: Traversable and streamable to protocol supports lists, hashes, caching, compression
74
71
  and more
75
72
  test_files: