aerospike 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +0 -0
- data/LICENSE +203 -0
- data/README.md +123 -0
- data/lib/aerospike.rb +69 -0
- data/lib/aerospike/aerospike_exception.rb +111 -0
- data/lib/aerospike/bin.rb +46 -0
- data/lib/aerospike/client.rb +649 -0
- data/lib/aerospike/cluster/cluster.rb +537 -0
- data/lib/aerospike/cluster/connection.rb +113 -0
- data/lib/aerospike/cluster/node.rb +248 -0
- data/lib/aerospike/cluster/node_validator.rb +85 -0
- data/lib/aerospike/cluster/partition.rb +54 -0
- data/lib/aerospike/cluster/partition_tokenizer_new.rb +128 -0
- data/lib/aerospike/cluster/partition_tokenizer_old.rb +135 -0
- data/lib/aerospike/command/batch_command.rb +120 -0
- data/lib/aerospike/command/batch_command_exists.rb +93 -0
- data/lib/aerospike/command/batch_command_get.rb +150 -0
- data/lib/aerospike/command/batch_item.rb +69 -0
- data/lib/aerospike/command/batch_node.rb +82 -0
- data/lib/aerospike/command/command.rb +680 -0
- data/lib/aerospike/command/delete_command.rb +57 -0
- data/lib/aerospike/command/execute_command.rb +42 -0
- data/lib/aerospike/command/exists_command.rb +57 -0
- data/lib/aerospike/command/field_type.rb +44 -0
- data/lib/aerospike/command/operate_command.rb +37 -0
- data/lib/aerospike/command/read_command.rb +174 -0
- data/lib/aerospike/command/read_header_command.rb +63 -0
- data/lib/aerospike/command/single_command.rb +60 -0
- data/lib/aerospike/command/touch_command.rb +50 -0
- data/lib/aerospike/command/write_command.rb +60 -0
- data/lib/aerospike/host.rb +43 -0
- data/lib/aerospike/info.rb +96 -0
- data/lib/aerospike/key.rb +99 -0
- data/lib/aerospike/language.rb +25 -0
- data/lib/aerospike/ldt/large.rb +69 -0
- data/lib/aerospike/ldt/large_list.rb +100 -0
- data/lib/aerospike/ldt/large_map.rb +82 -0
- data/lib/aerospike/ldt/large_set.rb +78 -0
- data/lib/aerospike/ldt/large_stack.rb +72 -0
- data/lib/aerospike/loggable.rb +55 -0
- data/lib/aerospike/operation.rb +70 -0
- data/lib/aerospike/policy/client_policy.rb +37 -0
- data/lib/aerospike/policy/generation_policy.rb +37 -0
- data/lib/aerospike/policy/policy.rb +54 -0
- data/lib/aerospike/policy/priority.rb +34 -0
- data/lib/aerospike/policy/record_exists_action.rb +45 -0
- data/lib/aerospike/policy/write_policy.rb +61 -0
- data/lib/aerospike/record.rb +42 -0
- data/lib/aerospike/result_code.rb +353 -0
- data/lib/aerospike/task/index_task.rb +59 -0
- data/lib/aerospike/task/task.rb +71 -0
- data/lib/aerospike/task/udf_register_task.rb +55 -0
- data/lib/aerospike/task/udf_remove_task.rb +55 -0
- data/lib/aerospike/udf.rb +24 -0
- data/lib/aerospike/utils/buffer.rb +139 -0
- data/lib/aerospike/utils/epoc.rb +28 -0
- data/lib/aerospike/utils/pool.rb +65 -0
- data/lib/aerospike/value/particle_type.rb +45 -0
- data/lib/aerospike/value/value.rb +380 -0
- data/lib/aerospike/version.rb +4 -0
- metadata +132 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014 Aerospike, Inc.
|
3
|
+
#
|
4
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
|
+
# license agreements.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
8
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
9
|
+
# the License at http:#www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
require 'aerospike/command/single_command'
|
18
|
+
require 'aerospike/result_code'
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
class DeleteCommand < SingleCommand
|
25
|
+
|
26
|
+
attr_reader :existed
|
27
|
+
|
28
|
+
def initialize(cluster, policy, key)
|
29
|
+
super(cluster, key)
|
30
|
+
|
31
|
+
@policy = policy
|
32
|
+
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def write_buffer
|
37
|
+
set_delete(@policy, @key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_result
|
41
|
+
# Read header.
|
42
|
+
@conn.read(@data_buffer, MSG_TOTAL_HEADER_SIZE)
|
43
|
+
|
44
|
+
result_code = @data_buffer.read(13).ord & 0xFF
|
45
|
+
|
46
|
+
if (result_code != 0) && (result_code != Aerospike::ResultCode::KEY_NOT_FOUND_ERROR)
|
47
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
48
|
+
end
|
49
|
+
|
50
|
+
@existed = (result_code == 0)
|
51
|
+
|
52
|
+
empty_socket
|
53
|
+
end
|
54
|
+
|
55
|
+
end # class
|
56
|
+
|
57
|
+
end # module
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014 Aerospike, Inc.
|
3
|
+
#
|
4
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
|
+
# license agreements.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
8
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
9
|
+
# the License at http:#www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
require 'aerospike/value/value'
|
18
|
+
require 'aerospike/command/read_command'
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
class ExecuteCommand < ReadCommand
|
25
|
+
|
26
|
+
def initialize(cluster, policy, key, package_name, function_name, args)
|
27
|
+
super(cluster, policy, key, nil)
|
28
|
+
|
29
|
+
@package_name = package_name
|
30
|
+
@function_name = function_name
|
31
|
+
@args = ListValue.new(args)
|
32
|
+
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def write_buffer
|
37
|
+
set_udf(@key, @package_name, @function_name, @args)
|
38
|
+
end
|
39
|
+
|
40
|
+
end # class
|
41
|
+
|
42
|
+
end # module
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014 Aerospike, Inc.
|
3
|
+
#
|
4
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
|
+
# license agreements.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
8
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
9
|
+
# the License at http:#www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
require 'aerospike/command/single_command'
|
18
|
+
require 'aerospike/result_code'
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
class ExistsCommand < SingleCommand
|
25
|
+
|
26
|
+
attr_reader :exists
|
27
|
+
|
28
|
+
def initialize(cluster, policy, key)
|
29
|
+
super(cluster, key)
|
30
|
+
|
31
|
+
@policy = policy
|
32
|
+
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def write_buffer
|
37
|
+
set_exists(@key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_result
|
41
|
+
# Read header.
|
42
|
+
@conn.read(@data_buffer, MSG_TOTAL_HEADER_SIZE)
|
43
|
+
|
44
|
+
result_code = @data_buffer.read(13).ord & 0xFF
|
45
|
+
|
46
|
+
if (result_code != 0) && (result_code != Aerospike::ResultCode::KEY_NOT_FOUND_ERROR)
|
47
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
48
|
+
end
|
49
|
+
|
50
|
+
@exists = (result_code == 0)
|
51
|
+
|
52
|
+
empty_socket
|
53
|
+
end
|
54
|
+
|
55
|
+
end # class
|
56
|
+
|
57
|
+
end # module
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014 Aerospike, Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http:#www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
module Aerospike
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
module FieldType
|
21
|
+
|
22
|
+
NAMESPACE = 0
|
23
|
+
TABLE = 1
|
24
|
+
KEY = 2
|
25
|
+
#BIN = 3
|
26
|
+
DIGEST_RIPE = 4
|
27
|
+
#GU_TID = 5
|
28
|
+
DIGEST_RIPE_ARRAY = 6
|
29
|
+
TRAN_ID = 7 # user supplied transaction id, which is simply passed back
|
30
|
+
SCAN_OPTIONS = 8
|
31
|
+
INDEX_NAME = 21
|
32
|
+
INDEX_RANGE = 22
|
33
|
+
INDEX_FILTER = 23
|
34
|
+
INDEX_LIMIT = 24
|
35
|
+
INDEX_ORDER_BY = 25
|
36
|
+
UDF_PACKAGE_NAME = 30
|
37
|
+
UDF_FUNCTION = 31
|
38
|
+
UDF_ARGLIST = 32
|
39
|
+
UDF_OP = 33
|
40
|
+
QUERY_BINLIST = 40
|
41
|
+
|
42
|
+
end # module
|
43
|
+
|
44
|
+
end # module
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014 Aerospike, Inc.
|
3
|
+
#
|
4
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
|
+
# license agreements.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
8
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
9
|
+
# the License at http:#www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
require 'aerospike/command/read_command'
|
18
|
+
|
19
|
+
module Aerospike
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
class OperateCommand < ReadCommand
|
24
|
+
|
25
|
+
def initialize(cluster, policy, key, operations)
|
26
|
+
super(cluster, policy, key, nil)
|
27
|
+
|
28
|
+
@operations = operations
|
29
|
+
end
|
30
|
+
|
31
|
+
def write_buffer
|
32
|
+
set_operate(@policy, @key, @operations)
|
33
|
+
end
|
34
|
+
|
35
|
+
end # class
|
36
|
+
|
37
|
+
end # module
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014 Aerospike, Inc.
|
3
|
+
#
|
4
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
|
+
# license agreements.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
8
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
9
|
+
# the License at http:#www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
require 'aerospike/record'
|
18
|
+
|
19
|
+
require 'aerospike/command/single_command'
|
20
|
+
require 'aerospike/utils/epoc'
|
21
|
+
require 'aerospike/value/value'
|
22
|
+
|
23
|
+
module Aerospike
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
class ReadCommand < SingleCommand
|
28
|
+
|
29
|
+
attr_reader :record
|
30
|
+
|
31
|
+
def initialize(cluster, policy, key, bin_names)
|
32
|
+
super(cluster, key)
|
33
|
+
|
34
|
+
@bin_names = bin_names
|
35
|
+
@policy = policy
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def write_buffer
|
41
|
+
set_read(@key, @bin_names)
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_result
|
45
|
+
# Read header.
|
46
|
+
begin
|
47
|
+
@conn.read(@data_buffer, MSG_TOTAL_HEADER_SIZE)
|
48
|
+
rescue => e
|
49
|
+
Aerospike.logger.error("parse result error: #{e}")
|
50
|
+
raise e
|
51
|
+
end
|
52
|
+
|
53
|
+
# A number of these are commented out because we just don't care enough to read
|
54
|
+
# that section of the header. If we do care, uncomment and check!
|
55
|
+
sz = @data_buffer.read_int64(0)
|
56
|
+
header_length = @data_buffer.read(8).ord
|
57
|
+
result_code = @data_buffer.read(13).ord & 0xFF
|
58
|
+
generation = @data_buffer.read_int32(14)
|
59
|
+
expiration = Aerospike.TTL(@data_buffer.read_int32(18))
|
60
|
+
field_count = @data_buffer.read_int16(26) # almost certainly 0
|
61
|
+
op_count = @data_buffer.read_int16(28)
|
62
|
+
receive_size = (sz & 0xFFFFFFFFFFFF) - header_length
|
63
|
+
|
64
|
+
# Read remaining message bytes.
|
65
|
+
if receive_size > 0
|
66
|
+
size_buffer_sz(receive_size)
|
67
|
+
|
68
|
+
begin
|
69
|
+
@conn.read(@data_buffer, receive_size)
|
70
|
+
rescue => e
|
71
|
+
Aerospike.logger.warn("parse result error: #{e}")
|
72
|
+
raise e
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
if result_code != 0
|
78
|
+
return if result_code == Aerospike::ResultCode::KEY_NOT_FOUND_ERROR
|
79
|
+
|
80
|
+
if result_code == Aerospike::ResultCode::UDF_BAD_RESPONSE
|
81
|
+
begin
|
82
|
+
@record = parse_record(op_count, field_count, generation, expiration)
|
83
|
+
handle_udf_error(result_code)
|
84
|
+
rescue => e
|
85
|
+
Aerospike.logger.warn("UDF execution error: #{e}")
|
86
|
+
raise e
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
92
|
+
end
|
93
|
+
|
94
|
+
if op_count == 0
|
95
|
+
# data Bin was not returned.
|
96
|
+
@record = Record.new(@node, @key, nil, nil, generation, expiration)
|
97
|
+
return
|
98
|
+
end
|
99
|
+
|
100
|
+
@record = parse_record(op_count, field_count, generation, expiration)
|
101
|
+
end
|
102
|
+
|
103
|
+
def handle_udf_error(result_code)
|
104
|
+
ret = @record.bins['FAILURE']
|
105
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, ret) if ret
|
106
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
107
|
+
end
|
108
|
+
|
109
|
+
def parse_record(op_count, field_count, generation, expiration)
|
110
|
+
bins = nil
|
111
|
+
duplicates = nil
|
112
|
+
receive_offset = 0
|
113
|
+
|
114
|
+
# There can be fields in the response (setname etc).
|
115
|
+
# But for now, ignore them. Expose them to the API if needed in the future.
|
116
|
+
if field_count != 0
|
117
|
+
# Just skip over all the fields
|
118
|
+
for i in 0...field_count
|
119
|
+
field_size = @data_buffer.read_int32(receive_offset)
|
120
|
+
receive_offset += (4 + field_size)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
for i in 0...op_count
|
125
|
+
op_size = @data_buffer.read_int32(receive_offset)
|
126
|
+
particle_type = @data_buffer.read(receive_offset+5).ord
|
127
|
+
version = @data_buffer.read(receive_offset+6).ord
|
128
|
+
name_size = @data_buffer.read(receive_offset+7).ord
|
129
|
+
name = @data_buffer.read(receive_offset+8, name_size).force_encoding('utf-8')
|
130
|
+
receive_offset += 4 + 4 + name_size
|
131
|
+
|
132
|
+
|
133
|
+
particle_bytes_size = op_size - (4 + name_size)
|
134
|
+
value = Aerospike.bytes_to_particle(particle_type, @data_buffer, receive_offset, particle_bytes_size)
|
135
|
+
receive_offset += particle_bytes_size
|
136
|
+
|
137
|
+
vmap = {}
|
138
|
+
|
139
|
+
if version > 0 || duplicates != nil
|
140
|
+
unless duplicates
|
141
|
+
duplicates = []
|
142
|
+
duplicates << bins
|
143
|
+
bins = nil
|
144
|
+
|
145
|
+
for j in 0..version-1
|
146
|
+
duplicates << nil
|
147
|
+
end
|
148
|
+
else
|
149
|
+
for j in duplicates.length..version
|
150
|
+
duplicates << nil
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
vmap = duplicates[version]
|
155
|
+
unless vmap
|
156
|
+
vmap = {}
|
157
|
+
duplicates[version] = vmap
|
158
|
+
end
|
159
|
+
else
|
160
|
+
bins = {} unless bins
|
161
|
+
vmap = bins
|
162
|
+
end
|
163
|
+
vmap[name] = value
|
164
|
+
end
|
165
|
+
|
166
|
+
# Remove nil duplicates just in case there were holes in the version number space.
|
167
|
+
duplicates.compact! if duplicates
|
168
|
+
|
169
|
+
Record.new(@node, @key, bins, duplicates, generation, expiration)
|
170
|
+
end
|
171
|
+
|
172
|
+
end # class
|
173
|
+
|
174
|
+
end # module
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014 Aerospike, Inc.
|
3
|
+
#
|
4
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
|
+
# license agreements.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
8
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
9
|
+
# the License at http:#www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
require 'aerospike/command/single_command'
|
18
|
+
require 'aerospike/result_code'
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
class ReadHeaderCommand < SingleCommand
|
25
|
+
|
26
|
+
attr_reader :record
|
27
|
+
|
28
|
+
def initialize(cluster, policy, key)
|
29
|
+
super(cluster, key)
|
30
|
+
|
31
|
+
@policy = policy
|
32
|
+
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def write_buffer
|
37
|
+
set_read_header(@key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_result
|
41
|
+
# Read header.
|
42
|
+
@conn.read(@data_buffer, MSG_TOTAL_HEADER_SIZE)
|
43
|
+
|
44
|
+
result_code = @data_buffer.read(13).ord & 0xFF
|
45
|
+
|
46
|
+
if result_code == 0
|
47
|
+
generation = @data_buffer.read_int32(14)
|
48
|
+
expiration = Aerospike.TTL(@data_buffer.read_int32(18))
|
49
|
+
@record = Record.new(@node, @key, nil, nil, generation, expiration)
|
50
|
+
else
|
51
|
+
if result_code == Aerospike::ResultCode::KEY_NOT_FOUND_ERROR
|
52
|
+
@record = nil
|
53
|
+
else
|
54
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
empty_socket
|
59
|
+
end
|
60
|
+
|
61
|
+
end # class
|
62
|
+
|
63
|
+
end # module
|