waz-storage 1.3.1 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -9
- data/CHANGELOG.rdoc +72 -72
- data/Gemfile +4 -4
- data/Gemfile.lock +46 -46
- data/LICENSE +18 -18
- data/README.rdoc +310 -310
- data/lib/waz-blobs.rb +4 -4
- data/lib/waz-queues.rb +6 -6
- data/lib/waz-storage.rb +39 -39
- data/lib/waz-tables.rb +4 -4
- data/lib/waz/blobs/blob_object.rb +122 -122
- data/lib/waz/blobs/container.rb +172 -172
- data/lib/waz/blobs/exceptions.rb +10 -10
- data/lib/waz/blobs/service.rb +181 -181
- data/lib/waz/queues/exceptions.rb +28 -28
- data/lib/waz/queues/message.rb +64 -64
- data/lib/waz/queues/queue.rb +164 -164
- data/lib/waz/queues/service.rb +105 -105
- data/lib/waz/storage/base.rb +70 -70
- data/lib/waz/storage/core_service.rb +2 -1
- data/lib/waz/storage/exceptions.rb +33 -33
- data/lib/waz/storage/validation_rules.rb +25 -25
- data/lib/waz/tables/edm_type_helper.rb +44 -44
- data/lib/waz/tables/exceptions.rb +44 -44
- data/lib/waz/tables/service.rb +178 -178
- data/lib/waz/tables/table.rb +74 -74
- data/lib/waz/tables/table_array.rb +10 -10
- data/rakefile +7 -7
- data/spec/configuration.rb +22 -22
- data/spec/waz/blobs/blob_object_spec.rb +80 -80
- data/spec/waz/blobs/container_spec.rb +175 -175
- data/spec/waz/blobs/service_spec.rb +336 -336
- data/spec/waz/queues/message_spec.rb +32 -32
- data/spec/waz/queues/queue_spec.rb +205 -205
- data/spec/waz/queues/service_spec.rb +298 -298
- data/spec/waz/storage/base_tests.rb +81 -81
- data/spec/waz/storage/shared_key_core_service_spec.rb +141 -141
- data/spec/waz/tables/service_spec.rb +613 -613
- data/spec/waz/tables/table_spec.rb +97 -97
- data/waz-storage.gemspec +29 -29
- metadata +3 -3
data/lib/waz/blobs/exceptions.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
module WAZ
|
2
|
-
module Blobs
|
3
|
-
# This exception is raised when the user tries to perform an operation over a snapshoted blob. Since
|
4
|
-
# Snapshots are read-only copies of the original blob they cannot be modified
|
5
|
-
class InvalidOperation < WAZ::Storage::StorageException
|
6
|
-
def initialize()
|
7
|
-
super("A snapshoted blob cannot be modified.")
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
1
|
+
module WAZ
|
2
|
+
module Blobs
|
3
|
+
# This exception is raised when the user tries to perform an operation over a snapshoted blob. Since
|
4
|
+
# Snapshots are read-only copies of the original blob they cannot be modified
|
5
|
+
class InvalidOperation < WAZ::Storage::StorageException
|
6
|
+
def initialize()
|
7
|
+
super("A snapshoted blob cannot be modified.")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
11
|
end
|
data/lib/waz/blobs/service.rb
CHANGED
@@ -1,181 +1,181 @@
|
|
1
|
-
module WAZ
|
2
|
-
module Blobs
|
3
|
-
# This is internally used by the waz-blobs part of the gem and it exposes the Windows Azure Blob API REST methods
|
4
|
-
# implementation. You can use this class to perform an specific operation that isn't provided by the current API.
|
5
|
-
class Service
|
6
|
-
include WAZ::Storage::SharedKeyCoreService
|
7
|
-
|
8
|
-
# Creates a container on the current Windows Azure Storage account.
|
9
|
-
def create_container(container_name)
|
10
|
-
execute :put, container_name, {:restype => 'container'}, {:x_ms_version => '2011-08-18'}
|
11
|
-
end
|
12
|
-
|
13
|
-
# Retrieves all the properties existing on the container.
|
14
|
-
def get_container_properties(container_name)
|
15
|
-
execute(:get, container_name, {:restype => 'container'}, {:x_ms_version => '2011-08-18'}).headers
|
16
|
-
end
|
17
|
-
|
18
|
-
# Set the container properties (metadata).
|
19
|
-
#
|
20
|
-
# Remember that custom properties should be named as :x_ms_meta_{propertyName} in order
|
21
|
-
# to have Windows Azure to persist them.
|
22
|
-
def set_container_properties(container_name, properties = {})
|
23
|
-
execute :put, container_name, { :restype => 'container', :comp => 'metadata' }, properties.merge!({:x_ms_version => '2011-08-18'})
|
24
|
-
end
|
25
|
-
|
26
|
-
# Retrieves the value of the :x_ms_prop_publicaccess header from the
|
27
|
-
# container properties indicating whether the container is publicly
|
28
|
-
# accessible or not.
|
29
|
-
def get_container_acl(container_name)
|
30
|
-
headers = execute(:get, container_name, { :restype => 'container', :comp => 'acl' }, {:x_ms_version => '2011-08-18'}).headers
|
31
|
-
headers[:x_ms_blob_public_access]
|
32
|
-
end
|
33
|
-
|
34
|
-
# Sets the value of the :x_ms_prop_publicaccess header from the
|
35
|
-
# container properties indicating whether the container is publicly
|
36
|
-
# accessible or not.
|
37
|
-
#
|
38
|
-
# Default is _false_
|
39
|
-
def set_container_acl(container_name, public_available = WAZ::Blobs::BlobSecurity::Private)
|
40
|
-
publicity = {:x_ms_version => '2011-08-18' }
|
41
|
-
publicity[:x_ms_blob_public_access] = public_available unless public_available == WAZ::Blobs::BlobSecurity::Private
|
42
|
-
execute :put, container_name, { :restype => 'container', :comp => 'acl' }, publicity
|
43
|
-
end
|
44
|
-
|
45
|
-
# Lists all the containers existing on the current storage account.
|
46
|
-
def list_containers(options = {})
|
47
|
-
content = execute(:get, nil, options.merge(:comp => 'list'))
|
48
|
-
doc = REXML::Document.new(content)
|
49
|
-
containers = []
|
50
|
-
REXML::XPath.each(doc, '//Container/') do |item|
|
51
|
-
containers << { :name => REXML::XPath.first(item, "Name").text,
|
52
|
-
:url => REXML::XPath.first(item, "Url").text,
|
53
|
-
:last_modified => REXML::XPath.first(item, "LastModified").text}
|
54
|
-
end
|
55
|
-
return containers
|
56
|
-
end
|
57
|
-
|
58
|
-
# Deletes the given container from the Windows Azure Storage account.
|
59
|
-
def delete_container(container_name)
|
60
|
-
execute :delete, container_name, {:restype => 'container'}, {:x_ms_version => '2011-08-18'}
|
61
|
-
end
|
62
|
-
|
63
|
-
# Lists all the blobs inside the given container.
|
64
|
-
def list_blobs(container_name)
|
65
|
-
content = execute(:get, container_name, { :restype => 'container', :comp => 'list'}, {:x_ms_version => '2011-08-18'})
|
66
|
-
doc = REXML::Document.new(content)
|
67
|
-
containers = []
|
68
|
-
REXML::XPath.each(doc, '//Blob/') do |item|
|
69
|
-
containers << { :name => REXML::XPath.first(item, "Name").text,
|
70
|
-
:url => REXML::XPath.first(item, "Url").text,
|
71
|
-
:content_type => REXML::XPath.first(item.elements["Properties"], "Content-Type").text }
|
72
|
-
|
73
|
-
end
|
74
|
-
return containers
|
75
|
-
end
|
76
|
-
|
77
|
-
# Returns statistics of the given container.
|
78
|
-
#
|
79
|
-
# @param [String] container_name
|
80
|
-
# @param [Hash] add_options
|
81
|
-
# @option add_options [String] :maxresults max blobs(5,000 at most)
|
82
|
-
# @option add_options [String] :marker marker of a page("2!80!MDAwMDE0***********--")
|
83
|
-
#
|
84
|
-
# @return [Hash] {:size => Integer, :files => Integer, :marker => String}
|
85
|
-
def statistics(container_name, add_options={})
|
86
|
-
options = { :restype => 'container', :comp => 'list'}
|
87
|
-
options.merge!(add_options)
|
88
|
-
|
89
|
-
content = execute(:get, container_name, options, {:x_ms_version => '2011-08-18'})
|
90
|
-
doc = REXML::Document.new(content)
|
91
|
-
size = 0
|
92
|
-
files = 0
|
93
|
-
REXML::XPath.each(doc, '//Blob/') do |item|
|
94
|
-
size = size + REXML::XPath.first(item.elements["Properties"], "Content-Length").text.to_i
|
95
|
-
files = files + 1
|
96
|
-
end
|
97
|
-
|
98
|
-
next_marker = REXML::XPath.first(doc, '//NextMarker')
|
99
|
-
{:size => size, :files => files, :next_marker => next_marker.text}
|
100
|
-
end
|
101
|
-
|
102
|
-
# Stores a blob on the given container.
|
103
|
-
#
|
104
|
-
# Remarks path and payload are just text.
|
105
|
-
#
|
106
|
-
# content_type is required by the blobs api, but on this method is defaulted to "application/octect-stream"
|
107
|
-
#
|
108
|
-
# metadata is a hash that stores all the properties that you want to add to the blob when creating it.
|
109
|
-
def put_blob(path, payload, content_type = "application/octet-stream", metadata = {})
|
110
|
-
default_headers = {"Content-Type" => content_type, :x_ms_version => "2011-08-18", :x_ms_blob_type => "BlockBlob", :x_ms_meta_railsetag => Digest::MD5.hexdigest(payload)}
|
111
|
-
execute :put, path, nil, metadata.merge(default_headers), payload
|
112
|
-
end
|
113
|
-
|
114
|
-
# Commits a list of blocks to the given blob.
|
115
|
-
#
|
116
|
-
# blockids is a list of valid, already-uploaded block IDs (base64-encoded)
|
117
|
-
#
|
118
|
-
# content_type is required by the blobs api, but on this method is defaulted to "application/octect-stream"
|
119
|
-
#
|
120
|
-
# metadata is a hash that stores all the properties that you want to add to the blob when creating it.
|
121
|
-
def put_block_list(path, blockids, content_type = "application/octet-stream", metadata = {})
|
122
|
-
default_headers = {"Content-Type" => content_type, :x_ms_version => "2011-08-18"}
|
123
|
-
execute :put, path, { :comp => 'blocklist' }, metadata.merge(default_headers), '<?xml version="1.0" encoding="utf-8"?><BlockList>' + blockids.map {|id| "<Latest>#{id.rstrip}</Latest>"}.join + '</BlockList>'
|
124
|
-
end
|
125
|
-
|
126
|
-
# Retrieves a blob (content + headers) from the current path.
|
127
|
-
def get_blob(path, options = {})
|
128
|
-
execute :get, path, options, {:x_ms_version => "2011-08-18"}
|
129
|
-
end
|
130
|
-
|
131
|
-
# Deletes the blob existing on the current path.
|
132
|
-
def delete_blob(path)
|
133
|
-
execute :delete, path, nil, {:x_ms_version => "2011-08-18"}
|
134
|
-
end
|
135
|
-
|
136
|
-
# Retrieves the properties associated with the blob at the given path.
|
137
|
-
def get_blob_properties(path, options = {})
|
138
|
-
execute(:head, path, options, {:x_ms_version => "2011-08-18"}).headers
|
139
|
-
end
|
140
|
-
|
141
|
-
# Sets the properties (metadata) associated to the blob at given path.
|
142
|
-
def set_blob_properties(path, properties ={})
|
143
|
-
execute :put, path, { :comp => 'properties' }, properties.merge({:x_ms_version => "2011-08-18"})
|
144
|
-
end
|
145
|
-
|
146
|
-
# Set user defined metadata - overwrites any previous metadata key:value pairs
|
147
|
-
def set_blob_metadata(path, metadata = {})
|
148
|
-
execute :put, path, { :comp => 'metadata' }, metadata.merge({:x_ms_version => "2011-08-18"})
|
149
|
-
end
|
150
|
-
|
151
|
-
# Copies a blob within the same account (not necessarily to the same container)
|
152
|
-
def copy_blob(source_path, dest_path)
|
153
|
-
execute :put, dest_path, nil, { :x_ms_version => "2011-08-18", :x_ms_copy_source => canonicalize_message(source_path) }
|
154
|
-
end
|
155
|
-
|
156
|
-
# Adds a block to the block list of the given blob
|
157
|
-
def put_block(path, identifier, payload)
|
158
|
-
execute :put, path, { :comp => 'block', :blockid => identifier }, {'Content-Type' => "application/octet-stream"}, payload
|
159
|
-
end
|
160
|
-
|
161
|
-
# Retrieves the list of blocks associated with a single blob. The list is filtered (or not) by type of blob
|
162
|
-
def list_blocks(path, block_list_type = 'all')
|
163
|
-
raise WAZ::Storage::InvalidParameterValue , {:name => :blocklisttype, :values => ['all', 'uncommitted', 'committed']} unless (block_list_type or "") =~ /all|committed|uncommitted/i
|
164
|
-
content = execute(:get, path, {:comp => 'blocklist'}.merge(:blocklisttype => block_list_type.downcase), { :x_ms_version => "2009-04-14" })
|
165
|
-
doc = REXML::Document.new(content)
|
166
|
-
blocks = []
|
167
|
-
REXML::XPath.each(doc, '//Block/') do |item|
|
168
|
-
blocks << { :name => REXML::XPath.first(item, "Name").text,
|
169
|
-
:size => REXML::XPath.first(item, "Size").text,
|
170
|
-
:committed => item.parent.name == "CommittedBlocks" }
|
171
|
-
end
|
172
|
-
return blocks
|
173
|
-
end
|
174
|
-
|
175
|
-
# Creates a read-only snapshot of a blob as it looked like in time.
|
176
|
-
def snapshot_blob(path)
|
177
|
-
execute(:put, path, { :comp => 'snapshot' }, {:x_ms_version => "2011-08-18"}).headers[:x_ms_snapshot]
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
1
|
+
module WAZ
|
2
|
+
module Blobs
|
3
|
+
# This is internally used by the waz-blobs part of the gem and it exposes the Windows Azure Blob API REST methods
|
4
|
+
# implementation. You can use this class to perform an specific operation that isn't provided by the current API.
|
5
|
+
class Service
|
6
|
+
include WAZ::Storage::SharedKeyCoreService
|
7
|
+
|
8
|
+
# Creates a container on the current Windows Azure Storage account.
|
9
|
+
def create_container(container_name)
|
10
|
+
execute :put, container_name, {:restype => 'container'}, {:x_ms_version => '2011-08-18'}
|
11
|
+
end
|
12
|
+
|
13
|
+
# Retrieves all the properties existing on the container.
|
14
|
+
def get_container_properties(container_name)
|
15
|
+
execute(:get, container_name, {:restype => 'container'}, {:x_ms_version => '2011-08-18'}).headers
|
16
|
+
end
|
17
|
+
|
18
|
+
# Set the container properties (metadata).
|
19
|
+
#
|
20
|
+
# Remember that custom properties should be named as :x_ms_meta_{propertyName} in order
|
21
|
+
# to have Windows Azure to persist them.
|
22
|
+
def set_container_properties(container_name, properties = {})
|
23
|
+
execute :put, container_name, { :restype => 'container', :comp => 'metadata' }, properties.merge!({:x_ms_version => '2011-08-18'})
|
24
|
+
end
|
25
|
+
|
26
|
+
# Retrieves the value of the :x_ms_prop_publicaccess header from the
|
27
|
+
# container properties indicating whether the container is publicly
|
28
|
+
# accessible or not.
|
29
|
+
def get_container_acl(container_name)
|
30
|
+
headers = execute(:get, container_name, { :restype => 'container', :comp => 'acl' }, {:x_ms_version => '2011-08-18'}).headers
|
31
|
+
headers[:x_ms_blob_public_access]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Sets the value of the :x_ms_prop_publicaccess header from the
|
35
|
+
# container properties indicating whether the container is publicly
|
36
|
+
# accessible or not.
|
37
|
+
#
|
38
|
+
# Default is _false_
|
39
|
+
def set_container_acl(container_name, public_available = WAZ::Blobs::BlobSecurity::Private)
|
40
|
+
publicity = {:x_ms_version => '2011-08-18' }
|
41
|
+
publicity[:x_ms_blob_public_access] = public_available unless public_available == WAZ::Blobs::BlobSecurity::Private
|
42
|
+
execute :put, container_name, { :restype => 'container', :comp => 'acl' }, publicity
|
43
|
+
end
|
44
|
+
|
45
|
+
# Lists all the containers existing on the current storage account.
|
46
|
+
def list_containers(options = {})
|
47
|
+
content = execute(:get, nil, options.merge(:comp => 'list'))
|
48
|
+
doc = REXML::Document.new(content)
|
49
|
+
containers = []
|
50
|
+
REXML::XPath.each(doc, '//Container/') do |item|
|
51
|
+
containers << { :name => REXML::XPath.first(item, "Name").text,
|
52
|
+
:url => REXML::XPath.first(item, "Url").text,
|
53
|
+
:last_modified => REXML::XPath.first(item, "LastModified").text}
|
54
|
+
end
|
55
|
+
return containers
|
56
|
+
end
|
57
|
+
|
58
|
+
# Deletes the given container from the Windows Azure Storage account.
|
59
|
+
def delete_container(container_name)
|
60
|
+
execute :delete, container_name, {:restype => 'container'}, {:x_ms_version => '2011-08-18'}
|
61
|
+
end
|
62
|
+
|
63
|
+
# Lists all the blobs inside the given container.
|
64
|
+
def list_blobs(container_name)
|
65
|
+
content = execute(:get, container_name, { :restype => 'container', :comp => 'list'}, {:x_ms_version => '2011-08-18'})
|
66
|
+
doc = REXML::Document.new(content)
|
67
|
+
containers = []
|
68
|
+
REXML::XPath.each(doc, '//Blob/') do |item|
|
69
|
+
containers << { :name => REXML::XPath.first(item, "Name").text,
|
70
|
+
:url => REXML::XPath.first(item, "Url").text,
|
71
|
+
:content_type => REXML::XPath.first(item.elements["Properties"], "Content-Type").text }
|
72
|
+
|
73
|
+
end
|
74
|
+
return containers
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns statistics of the given container.
|
78
|
+
#
|
79
|
+
# @param [String] container_name
|
80
|
+
# @param [Hash] add_options
|
81
|
+
# @option add_options [String] :maxresults max blobs(5,000 at most)
|
82
|
+
# @option add_options [String] :marker marker of a page("2!80!MDAwMDE0***********--")
|
83
|
+
#
|
84
|
+
# @return [Hash] {:size => Integer, :files => Integer, :marker => String}
|
85
|
+
def statistics(container_name, add_options={})
|
86
|
+
options = { :restype => 'container', :comp => 'list'}
|
87
|
+
options.merge!(add_options)
|
88
|
+
|
89
|
+
content = execute(:get, container_name, options, {:x_ms_version => '2011-08-18'})
|
90
|
+
doc = REXML::Document.new(content)
|
91
|
+
size = 0
|
92
|
+
files = 0
|
93
|
+
REXML::XPath.each(doc, '//Blob/') do |item|
|
94
|
+
size = size + REXML::XPath.first(item.elements["Properties"], "Content-Length").text.to_i
|
95
|
+
files = files + 1
|
96
|
+
end
|
97
|
+
|
98
|
+
next_marker = REXML::XPath.first(doc, '//NextMarker')
|
99
|
+
{:size => size, :files => files, :next_marker => next_marker.text}
|
100
|
+
end
|
101
|
+
|
102
|
+
# Stores a blob on the given container.
|
103
|
+
#
|
104
|
+
# Remarks path and payload are just text.
|
105
|
+
#
|
106
|
+
# content_type is required by the blobs api, but on this method is defaulted to "application/octect-stream"
|
107
|
+
#
|
108
|
+
# metadata is a hash that stores all the properties that you want to add to the blob when creating it.
|
109
|
+
def put_blob(path, payload, content_type = "application/octet-stream", metadata = {})
|
110
|
+
default_headers = {"Content-Type" => content_type, :x_ms_version => "2011-08-18", :x_ms_blob_type => "BlockBlob", :x_ms_meta_railsetag => Digest::MD5.hexdigest(payload)}
|
111
|
+
execute :put, path, nil, metadata.merge(default_headers), payload
|
112
|
+
end
|
113
|
+
|
114
|
+
# Commits a list of blocks to the given blob.
|
115
|
+
#
|
116
|
+
# blockids is a list of valid, already-uploaded block IDs (base64-encoded)
|
117
|
+
#
|
118
|
+
# content_type is required by the blobs api, but on this method is defaulted to "application/octect-stream"
|
119
|
+
#
|
120
|
+
# metadata is a hash that stores all the properties that you want to add to the blob when creating it.
|
121
|
+
def put_block_list(path, blockids, content_type = "application/octet-stream", metadata = {})
|
122
|
+
default_headers = {"Content-Type" => content_type, :x_ms_version => "2011-08-18"}
|
123
|
+
execute :put, path, { :comp => 'blocklist' }, metadata.merge(default_headers), '<?xml version="1.0" encoding="utf-8"?><BlockList>' + blockids.map {|id| "<Latest>#{id.rstrip}</Latest>"}.join + '</BlockList>'
|
124
|
+
end
|
125
|
+
|
126
|
+
# Retrieves a blob (content + headers) from the current path.
|
127
|
+
def get_blob(path, options = {})
|
128
|
+
execute :get, path, options, {:x_ms_version => "2011-08-18"}
|
129
|
+
end
|
130
|
+
|
131
|
+
# Deletes the blob existing on the current path.
|
132
|
+
def delete_blob(path)
|
133
|
+
execute :delete, path, nil, {:x_ms_version => "2011-08-18"}
|
134
|
+
end
|
135
|
+
|
136
|
+
# Retrieves the properties associated with the blob at the given path.
|
137
|
+
def get_blob_properties(path, options = {})
|
138
|
+
execute(:head, path, options, {:x_ms_version => "2011-08-18"}).headers
|
139
|
+
end
|
140
|
+
|
141
|
+
# Sets the properties (metadata) associated to the blob at given path.
|
142
|
+
def set_blob_properties(path, properties ={})
|
143
|
+
execute :put, path, { :comp => 'properties' }, properties.merge({:x_ms_version => "2011-08-18"})
|
144
|
+
end
|
145
|
+
|
146
|
+
# Set user defined metadata - overwrites any previous metadata key:value pairs
|
147
|
+
def set_blob_metadata(path, metadata = {})
|
148
|
+
execute :put, path, { :comp => 'metadata' }, metadata.merge({:x_ms_version => "2011-08-18"})
|
149
|
+
end
|
150
|
+
|
151
|
+
# Copies a blob within the same account (not necessarily to the same container)
|
152
|
+
def copy_blob(source_path, dest_path)
|
153
|
+
execute :put, dest_path, nil, { :x_ms_version => "2011-08-18", :x_ms_copy_source => canonicalize_message(source_path) }
|
154
|
+
end
|
155
|
+
|
156
|
+
# Adds a block to the block list of the given blob
|
157
|
+
def put_block(path, identifier, payload)
|
158
|
+
execute :put, path, { :comp => 'block', :blockid => identifier }, {'Content-Type' => "application/octet-stream"}, payload
|
159
|
+
end
|
160
|
+
|
161
|
+
# Retrieves the list of blocks associated with a single blob. The list is filtered (or not) by type of blob
|
162
|
+
def list_blocks(path, block_list_type = 'all')
|
163
|
+
raise WAZ::Storage::InvalidParameterValue , {:name => :blocklisttype, :values => ['all', 'uncommitted', 'committed']} unless (block_list_type or "") =~ /all|committed|uncommitted/i
|
164
|
+
content = execute(:get, path, {:comp => 'blocklist'}.merge(:blocklisttype => block_list_type.downcase), { :x_ms_version => "2009-04-14" })
|
165
|
+
doc = REXML::Document.new(content)
|
166
|
+
blocks = []
|
167
|
+
REXML::XPath.each(doc, '//Block/') do |item|
|
168
|
+
blocks << { :name => REXML::XPath.first(item, "Name").text,
|
169
|
+
:size => REXML::XPath.first(item, "Size").text,
|
170
|
+
:committed => item.parent.name == "CommittedBlocks" }
|
171
|
+
end
|
172
|
+
return blocks
|
173
|
+
end
|
174
|
+
|
175
|
+
# Creates a read-only snapshot of a blob as it looked like in time.
|
176
|
+
def snapshot_blob(path)
|
177
|
+
execute(:put, path, { :comp => 'snapshot' }, {:x_ms_version => "2011-08-18"}).headers[:x_ms_snapshot]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -1,29 +1,29 @@
|
|
1
|
-
module WAZ
|
2
|
-
module Queues
|
3
|
-
# This exception is raised while trying when calling WAZ::Queues::Queue.create('queue_name') and
|
4
|
-
# the metadata existing on the Queues Storage subsytem on the cloud contains different metadata from
|
5
|
-
# the given one.
|
6
|
-
class QueueAlreadyExists < WAZ::Storage::StorageException
|
7
|
-
def initialize(name)
|
8
|
-
super("The queue #{name} already exists on your account.")
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
# This exception is raised when an initialization parameter of any of the WAZ::Queues classes falls of
|
13
|
-
# the specified values.
|
14
|
-
class OptionOutOfRange < WAZ::Storage::StorageException
|
15
|
-
def initialize(args = {})
|
16
|
-
super("The #{args[:name]} parameter is out of range allowed values go from #{args[:min]} to #{args[:max]}.")
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# This exception is raised when the user tries to perform a delete operation over a peeked message. Since
|
21
|
-
# peeked messages cannot by deleted given the fact that there's no pop_receipt associated with it
|
22
|
-
# this exception will be raised.
|
23
|
-
class InvalidOperation < WAZ::Storage::StorageException
|
24
|
-
def initialize()
|
25
|
-
super("A peeked message cannot be delete, you need to lock it first (pop_receipt required).")
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
1
|
+
module WAZ
|
2
|
+
module Queues
|
3
|
+
# This exception is raised while trying when calling WAZ::Queues::Queue.create('queue_name') and
|
4
|
+
# the metadata existing on the Queues Storage subsytem on the cloud contains different metadata from
|
5
|
+
# the given one.
|
6
|
+
class QueueAlreadyExists < WAZ::Storage::StorageException
|
7
|
+
def initialize(name)
|
8
|
+
super("The queue #{name} already exists on your account.")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# This exception is raised when an initialization parameter of any of the WAZ::Queues classes falls of
|
13
|
+
# the specified values.
|
14
|
+
class OptionOutOfRange < WAZ::Storage::StorageException
|
15
|
+
def initialize(args = {})
|
16
|
+
super("The #{args[:name]} parameter is out of range allowed values go from #{args[:min]} to #{args[:max]}.")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# This exception is raised when the user tries to perform a delete operation over a peeked message. Since
|
21
|
+
# peeked messages cannot by deleted given the fact that there's no pop_receipt associated with it
|
22
|
+
# this exception will be raised.
|
23
|
+
class InvalidOperation < WAZ::Storage::StorageException
|
24
|
+
def initialize()
|
25
|
+
super("A peeked message cannot be delete, you need to lock it first (pop_receipt required).")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
29
|
end
|
data/lib/waz/queues/message.rb
CHANGED
@@ -1,65 +1,65 @@
|
|
1
|
-
module WAZ
|
2
|
-
module Queues
|
3
|
-
# This class is used to model a Message inside Windows Azure Queues the usage
|
4
|
-
# it's pretty simple, here you can see a couple of samples. Messages consist on an UTF-8 string up-to 8KB and some metadata
|
5
|
-
# regarding its status and visibility. Here are all the things that you can do with a message:
|
6
|
-
#
|
7
|
-
# message.message_id #=> returns message id
|
8
|
-
#
|
9
|
-
# # this is the most important method regarding messages
|
10
|
-
# message.message_text #=> returns message contents
|
11
|
-
#
|
12
|
-
# message.pop_receipt #=> used for correlating your dequeue request + a delete operation
|
13
|
-
#
|
14
|
-
# message.expiration_time #=> returns when the message will be removed from the queue
|
15
|
-
#
|
16
|
-
# message.time_next_visible #=> when the message will be visible to other users
|
17
|
-
#
|
18
|
-
# message.insertion_time #=> when the message will be visible to other users
|
19
|
-
#
|
20
|
-
# message.queue_name #=> returns the queue name where the message belongs
|
21
|
-
#
|
22
|
-
# # remove the message from the queue
|
23
|
-
# message.destroy!
|
24
|
-
#
|
25
|
-
class Message
|
26
|
-
class << self
|
27
|
-
# This method is internally used by this class. It's the way we keep a single instance of the
|
28
|
-
# service that wraps the calls the Windows Azure Queues API. It's initialized with the values
|
29
|
-
# from the default_connection on WAZ::Storage::Base initialized thru establish_connection!
|
30
|
-
def service_instance
|
31
|
-
options = WAZ::Storage::Base.default_connection.merge(:type_of_service => "queue")
|
32
|
-
(@service_instances ||= {})[options[:account_name]] ||= Service.new(options)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
attr_accessor :message_id, :message_text, :pop_receipt, :expiration_time, :insertion_time, :time_next_visible, :dequeue_count
|
37
|
-
|
38
|
-
# Creates an instance of Message class, this method is intended to be used internally from the
|
39
|
-
# Queue.
|
40
|
-
def initialize(params = {})
|
41
|
-
self.message_id = params[:message_id]
|
42
|
-
self.message_text = params[:message_text]
|
43
|
-
self.pop_receipt = params[:pop_receipt]
|
44
|
-
self.expiration_time = params[:expiration_time]
|
45
|
-
self.insertion_time = params[:insertion_time]
|
46
|
-
self.time_next_visible = params[:time_next_visible]
|
47
|
-
self.dequeue_count = params[:dequeue_count]
|
48
|
-
@queue_name = params[:queue_name]
|
49
|
-
end
|
50
|
-
|
51
|
-
# Returns the Queue name where the Message belongs to
|
52
|
-
def queue_name
|
53
|
-
return @queue_name
|
54
|
-
end
|
55
|
-
|
56
|
-
# Marks the message for deletion (to later be removed from the queue by the garbage collector). If the message
|
57
|
-
# where the message is being actually called was peeked from the queue instead of locked it will raise the
|
58
|
-
# WAZ::Queues:InvalidOperation exception since it's not a permited operation.
|
59
|
-
def destroy!
|
60
|
-
raise WAZ::Queues::InvalidOperation if pop_receipt.nil?
|
61
|
-
self.class.service_instance.delete_message(queue_name, message_id, pop_receipt)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
1
|
+
module WAZ
|
2
|
+
module Queues
|
3
|
+
# This class is used to model a Message inside Windows Azure Queues the usage
|
4
|
+
# it's pretty simple, here you can see a couple of samples. Messages consist on an UTF-8 string up-to 8KB and some metadata
|
5
|
+
# regarding its status and visibility. Here are all the things that you can do with a message:
|
6
|
+
#
|
7
|
+
# message.message_id #=> returns message id
|
8
|
+
#
|
9
|
+
# # this is the most important method regarding messages
|
10
|
+
# message.message_text #=> returns message contents
|
11
|
+
#
|
12
|
+
# message.pop_receipt #=> used for correlating your dequeue request + a delete operation
|
13
|
+
#
|
14
|
+
# message.expiration_time #=> returns when the message will be removed from the queue
|
15
|
+
#
|
16
|
+
# message.time_next_visible #=> when the message will be visible to other users
|
17
|
+
#
|
18
|
+
# message.insertion_time #=> when the message will be visible to other users
|
19
|
+
#
|
20
|
+
# message.queue_name #=> returns the queue name where the message belongs
|
21
|
+
#
|
22
|
+
# # remove the message from the queue
|
23
|
+
# message.destroy!
|
24
|
+
#
|
25
|
+
class Message
|
26
|
+
class << self
|
27
|
+
# This method is internally used by this class. It's the way we keep a single instance of the
|
28
|
+
# service that wraps the calls the Windows Azure Queues API. It's initialized with the values
|
29
|
+
# from the default_connection on WAZ::Storage::Base initialized thru establish_connection!
|
30
|
+
def service_instance
|
31
|
+
options = WAZ::Storage::Base.default_connection.merge(:type_of_service => "queue")
|
32
|
+
(@service_instances ||= {})[options[:account_name]] ||= Service.new(options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_accessor :message_id, :message_text, :pop_receipt, :expiration_time, :insertion_time, :time_next_visible, :dequeue_count
|
37
|
+
|
38
|
+
# Creates an instance of Message class, this method is intended to be used internally from the
|
39
|
+
# Queue.
|
40
|
+
def initialize(params = {})
|
41
|
+
self.message_id = params[:message_id]
|
42
|
+
self.message_text = params[:message_text]
|
43
|
+
self.pop_receipt = params[:pop_receipt]
|
44
|
+
self.expiration_time = params[:expiration_time]
|
45
|
+
self.insertion_time = params[:insertion_time]
|
46
|
+
self.time_next_visible = params[:time_next_visible]
|
47
|
+
self.dequeue_count = params[:dequeue_count]
|
48
|
+
@queue_name = params[:queue_name]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the Queue name where the Message belongs to
|
52
|
+
def queue_name
|
53
|
+
return @queue_name
|
54
|
+
end
|
55
|
+
|
56
|
+
# Marks the message for deletion (to later be removed from the queue by the garbage collector). If the message
|
57
|
+
# where the message is being actually called was peeked from the queue instead of locked it will raise the
|
58
|
+
# WAZ::Queues:InvalidOperation exception since it's not a permited operation.
|
59
|
+
def destroy!
|
60
|
+
raise WAZ::Queues::InvalidOperation if pop_receipt.nil?
|
61
|
+
self.class.service_instance.delete_message(queue_name, message_id, pop_receipt)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
65
|
end
|