amq-protocol 1.0.0.pre2 → 1.0.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,96 @@
1
+ # encoding: utf-8
2
+
3
+ require "amq/bit_set"
4
+
5
+ module AMQ
6
+ # Simple bitset-based integer allocator, heavily inspired by com.rabbitmq.utility.IntAllocator class
7
+ # in the RabbitMQ Java client.
8
+ #
9
+ # Unlike monotonically incrementing identifier, this allocator is suitable for very long running programs
10
+ # that aggressively allocate and release channels.
11
+ class IntAllocator
12
+
13
+ #
14
+ # API
15
+ #
16
+
17
+ # @return [Integer] Number of integers in the allocation range
18
+ attr_reader :number_of_bits
19
+ # @return [Integer] Upper boundary of the integer range available for allocation
20
+ attr_reader :hi
21
+ # @return [Integer] Lower boundary of the integer range available for allocation
22
+ attr_reader :lo
23
+
24
+ # @param [Integer] lo Lower boundary of the integer range available for allocation
25
+ # @param [Integer] hi Upper boundary of the integer range available for allocation
26
+ # @raise [ArgumentError] if upper boundary is not greater than the lower one
27
+ def initialize(lo, hi)
28
+ raise ArgumentError.new "upper boundary must be greater than the lower one (given: hi = #{hi}, lo = #{lo})" unless hi > lo
29
+
30
+ @hi = hi
31
+ @lo = lo
32
+
33
+ @number_of_bits = hi - lo
34
+ @range = Range.new(1, @number_of_bits)
35
+ @free_set = BitSet.new(@number_of_bits)
36
+ end # initialize(hi, lo)
37
+
38
+ # Attempts to allocate next available integer. If allocation succeeds, allocated value is returned.
39
+ # Otherwise, nil is returned.
40
+ #
41
+ # Current implementation of this method is O(n), where n is number of bits in the range available for
42
+ # allocation.
43
+ #
44
+ # @return [Integer] Allocated integer if allocation succeeded. nil otherwise.
45
+ def allocate
46
+ if n = find_unallocated_position
47
+ @free_set.set(n)
48
+
49
+ n
50
+ else
51
+ -1
52
+ end
53
+ end # allocate
54
+
55
+ # Releases previously allocated integer. If integer provided as argument was not previously allocated,
56
+ # this method has no effect.
57
+ #
58
+ # @return [NilClass] nil
59
+ def free(reservation)
60
+ @free_set.unset(reservation)
61
+ end # free(reservation)
62
+ alias release free
63
+
64
+ # @return [Boolean] true if provided argument was previously allocated, false otherwise
65
+ def allocated?(reservation)
66
+ @free_set.get(reservation)
67
+ end # allocated?(reservation)
68
+
69
+ # Releases the whole allocation range
70
+ def reset
71
+ @free_set.clear
72
+ end # reset
73
+
74
+
75
+
76
+ protected
77
+
78
+ # This implementation is significantly less efficient
79
+ # that what the RabbitMQ Java client has (based on java.lang.Long#nextSetBit and
80
+ # java.lang.Long.numberOfTrailingZeros, and thus binary search over bits).
81
+ # But for channel id generation, this is a good enough implementation.
82
+ #
83
+ # @private
84
+ def find_unallocated_position
85
+ r = nil
86
+ @range.each do |i|
87
+ if !@free_set.get(i)
88
+ r = i
89
+ break;
90
+ end
91
+ end
92
+
93
+ r
94
+ end # find_unallocated_position
95
+ end # IntAllocator
96
+ end # AMQ
@@ -1,5 +1,5 @@
1
1
  module AMQ
2
2
  module Protocol
3
- VERSION = "1.0.0.pre2"
3
+ VERSION = "1.0.0.pre3"
4
4
  end # Protocol
5
5
  end # AMQ
@@ -0,0 +1,116 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require "amq/int_allocator"
5
+
6
+ describe AMQ::IntAllocator do
7
+
8
+ #
9
+ # Environment
10
+ #
11
+
12
+ subject do
13
+ described_class.new(1, 5)
14
+ end
15
+
16
+
17
+ # ...
18
+
19
+
20
+ #
21
+ # Examples
22
+ #
23
+
24
+ describe "#number_of_bits" do
25
+ it "returns number of bits available for allocation" do
26
+ subject.number_of_bits.should == 4
27
+ end
28
+ end
29
+
30
+
31
+ describe "#hi" do
32
+ it "returns upper bound of the allocation range" do
33
+ subject.hi.should == 5
34
+ end
35
+ end
36
+
37
+ describe "#lo" do
38
+ it "returns lower bound of the allocation range" do
39
+ subject.lo.should == 1
40
+ end
41
+ end
42
+
43
+
44
+ describe "#allocate" do
45
+ context "when integer in the range is available" do
46
+ it "returns allocated integer" do
47
+ subject.allocate.should == 1
48
+ subject.allocate.should == 2
49
+ subject.allocate.should == 3
50
+ subject.allocate.should == 4
51
+
52
+ subject.allocate.should == -1
53
+ end
54
+ end
55
+
56
+ context "when integer in the range IS NOT available" do
57
+ it "returns -1" do
58
+ 4.times { subject.allocate }
59
+
60
+ subject.allocate.should == -1
61
+ subject.allocate.should == -1
62
+ subject.allocate.should == -1
63
+ subject.allocate.should == -1
64
+ end
65
+ end
66
+ end
67
+
68
+
69
+ describe "#free" do
70
+ context "when the integer WAS allocated" do
71
+ it "returns frees that integer" do
72
+ 4.times { subject.allocate }
73
+ subject.allocate.should == -1
74
+
75
+ subject.free(1)
76
+ subject.allocate.should == 1
77
+ subject.allocate.should == -1
78
+ subject.free(2)
79
+ subject.allocate.should == 2
80
+ subject.allocate.should == -1
81
+ subject.free(3)
82
+ subject.allocate.should == 3
83
+ subject.allocate.should == -1
84
+ end
85
+ end
86
+
87
+ context "when the integer WAS NOT allocated" do
88
+ it "has no effect" do
89
+ 32.times { subject.free(1) }
90
+ subject.allocate.should == 1
91
+ end
92
+ end
93
+ end
94
+
95
+
96
+ describe "#allocated?" do
97
+ context "when given position WAS allocated" do
98
+ it "returns true" do
99
+ 3.times { subject.allocate }
100
+
101
+ subject.allocated?(1).should be_true
102
+ subject.allocated?(2).should be_true
103
+ subject.allocated?(3).should be_true
104
+ end
105
+ end
106
+
107
+ context "when given position WAS NOT allocated" do
108
+ it "returns false" do
109
+ 2.times { subject.allocate }
110
+
111
+ subject.allocated?(3).should be_false
112
+ subject.allocated?(4).should be_false
113
+ end
114
+ end
115
+ end
116
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amq-protocol
3
3
  version: !ruby/object:Gem::Version
4
- hash: -2170921152
4
+ hash: 4271866905
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
9
  - 0
10
10
  - pre
11
- - 2
12
- version: 1.0.0.pre2
11
+ - 3
12
+ version: 1.0.0.pre3
13
13
  platform: ruby
14
14
  authors:
15
15
  - Jakub Stastny
@@ -51,6 +51,7 @@ files:
51
51
  - irb.rb
52
52
  - lib/amq/bit_set.rb
53
53
  - lib/amq/hacks.rb
54
+ - lib/amq/int_allocator.rb
54
55
  - lib/amq/protocol.rb
55
56
  - lib/amq/protocol/client.rb
56
57
  - lib/amq/protocol/frame.rb
@@ -63,6 +64,7 @@ files:
63
64
  - protocol.rb.pytemplate
64
65
  - spec/amq/bit_set_spec.rb
65
66
  - spec/amq/hacks_spec.rb
67
+ - spec/amq/int_allocator_spec.rb
66
68
  - spec/amq/protocol/basic_spec.rb
67
69
  - spec/amq/protocol/blank_body_encoding_spec.rb
68
70
  - spec/amq/protocol/channel_spec.rb