sdb_dal 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,366 @@
1
+ module SdbDal
2
+ $KCODE = 'u'
3
+ require "aws_sdb"
4
+ require "sdb_dal/storage.rb"
5
+ require 'ya2yaml'
6
+ require File.dirname(__FILE__) +"/memory_repository.rb"
7
+ require File.dirname(__FILE__) +"/domain_object_cache_item.rb"
8
+ class Repository
9
+ attr_accessor :use_cache
10
+ attr_accessor :storage
11
+ def initialize(
12
+ sdb_domain_prefix,#MyDevPayApp
13
+ clob_bucket,
14
+ aws_key_id,
15
+ aws_secret_key,
16
+ memcache_servers = nil ,
17
+ a_storage=nil,
18
+ append_table_to_domain=true,
19
+ options={}
20
+
21
+ )
22
+
23
+ @use_cache=true
24
+ @storage=a_storage
25
+ @storage||=Storage.new(aws_key_id,aws_secret_key,memcache_servers)
26
+ @sdb_domain_prefix = sdb_domain_prefix
27
+ @clob_bucket = clob_bucket
28
+ @memcache_servers = memcache_servers
29
+ @aws_key_id = aws_key_id
30
+ @aws_secret_key = aws_secret_key
31
+ @append_table_to_domain=append_table_to_domain
32
+ @logger = options[:logger]
33
+ if !@logger
34
+ @logger = Logger.new(STDOUT)
35
+ @logger.level = Logger::ERROR
36
+ end
37
+
38
+ @sdb=AwsSdb::Service.new(:access_key_id=>aws_key_id,:secret_access_key=>aws_secret_key,:url=>"http://sdb.amazonaws.com",:logger=>@logger)
39
+ @session_cache=MemoryRepository.new
40
+
41
+ #create_domain()
42
+ end
43
+
44
+ def clear_session_cache
45
+ @session_cache.clear
46
+ end
47
+ def make_clob_key(table_name,primary_key,clob_name)
48
+ return "clobs/#{table_name}/#{CGI.escape(primary_key.to_s)}/#{clob_name}"
49
+ end
50
+ def make_cache_key(table_name,primary_key)
51
+ return "cached_objects/#{table_name}/#{CGI.escape(primary_key.to_s)}"
52
+ end
53
+ def get_clob(table_name,primary_key,clob_name)
54
+ return @storage.get(@clob_bucket,make_clob_key(table_name,primary_key,clob_name))
55
+
56
+ end
57
+ def save(table_name, primary_key, attributes)
58
+ @session_cache.save(table_name,primary_key,attributes)
59
+ formatted_attributes={}
60
+ attributes.each do |description,value|
61
+ if value || description.value_type==:boolean
62
+ if description.is_clob
63
+ @storage.put(
64
+ @clob_bucket,
65
+ make_clob_key(table_name,primary_key,description.name),
66
+ value.to_s,
67
+ {})
68
+ else
69
+ formatted_attributes[description.name]=description.format_for_sdb(value)
70
+ end
71
+ end
72
+ end
73
+
74
+ put_attributes(table_name,primary_key, formatted_attributes )
75
+ # put_into_cache(table_name, primary_key, formatted_attributes)
76
+
77
+ end
78
+ # def put_into_cache(table_name, primary_key, formatted_attributes)
79
+ # if @use_cache
80
+ # cacheItem=DomainObjectCacheItem.new(table_name, primary_key, formatted_attributes)
81
+ #
82
+ # yaml=cacheItem.ya2yaml(:syck_compatible => true)
83
+ #
84
+ # @storage.put(
85
+ # @clob_bucket,
86
+ # make_cache_key(table_name,primary_key),
87
+ # yaml ,
88
+ # {})
89
+ # end
90
+ # end
91
+ def create_domain
92
+ 20.times do |i|
93
+ begin
94
+ @sdb.create_domain(@sdb_domain)
95
+ return
96
+
97
+ rescue => e
98
+ s= "#{e.message}\n#{e.backtrace}"
99
+ @logger.warn(s) if @logger
100
+ sleep(i*i)
101
+
102
+ end
103
+ end
104
+
105
+ end
106
+ def put_attributes(table_name,primary_key, formatted_attributes,options={})
107
+ 20.times do |i|
108
+ begin
109
+ @sdb.put_attributes(make_domain_name(table_name),primary_key.to_s, formatted_attributes, true )
110
+ return
111
+
112
+ rescue Exception => e
113
+ s= "#{e.message}\n#{e.backtrace}"
114
+ @logger.warn(s) if @logger
115
+
116
+ sleep(i*i)
117
+ end
118
+ end
119
+
120
+ end
121
+ def extend_query(query,new_clause)
122
+ if query.length>0
123
+ query << " intersection "
124
+ end
125
+
126
+ query << new_clause
127
+ end
128
+ def escape_quotes(value)
129
+ value.gsub( "'","\\'")
130
+ end
131
+ def query_ids(table_name,attribute_descriptions,options={})
132
+
133
+ if options.has_key?(:limit) and !options.has_key?(:order_by)
134
+ session_cache_result=@session_cache.query_ids(table_name,attribute_descriptions,options)
135
+ if options[:limit]==session_cache_result.length
136
+ return session_cache_result
137
+ end
138
+ end
139
+ query=""
140
+
141
+ if options
142
+ if options.has_key?(:query)
143
+ extend_query(query,"["+options[:query]+"]")
144
+ end
145
+ if options.has_key?(:params)
146
+ options[:params].each do |key,value|
147
+ got_something=false
148
+ if attribute_descriptions.has_key?(key)
149
+ if value==:NOT_NULL
150
+ got_something=true
151
+ extend_query(query," ['#{key}' starts-with '']")
152
+ end
153
+ if value==:NULL
154
+ got_something=true
155
+ extend_query(query," not ['#{key}' starts-with '']")
156
+ end
157
+ if value.respond_to?(:less_than) && value.less_than
158
+ got_something=true
159
+ extend_query(query," ['#{key}' < '#{escape_quotes(attribute_descriptions[key].format_for_sdb_single( value.less_than))}']")
160
+ end
161
+ if value.respond_to?(:greater_than) && value.greater_than
162
+ got_something=true
163
+ extend_query(query," ['#{key}' > '#{escape_quotes( attribute_descriptions[key].format_for_sdb_single( value.greater_than))}']")
164
+ end
165
+ if value.respond_to?(:less_than_or_equal_to) && value.less_than_or_equal_to
166
+ got_something=true
167
+ extend_query(query,"['#{key}' <= '#{escape_quotes( attribute_descriptions[key].format_for_sdb_single( value.less_than_or_equal_to))}']")
168
+ end
169
+ if value.respond_to?(:greater_than_or_equal_to) && value.greater_than_or_equal_to
170
+ got_something=true
171
+ extend_query(query," ['#{key}' >= '#{escape_quotes(attribute_descriptions[key].format_for_sdb_single( value.greater_than_or_equal_to))}']")
172
+ end
173
+ if value==false
174
+ got_something=true
175
+ extend_query(query," ['#{key}' != 'true' ]")
176
+ end
177
+ if !got_something
178
+ extend_query(query," ['#{key}' = '#{escape_quotes( attribute_descriptions[key].format_for_sdb_single(value))}']")
179
+ end
180
+ else
181
+ #it must be formatted already. likely an index
182
+ extend_query(query,"['#{key}' = '#{escape_quotes value}']")
183
+ end
184
+ end
185
+ end
186
+ if options.has_key?(:order_by) && options[:order_by]
187
+ clause=" ['#{options[:order_by]}' starts-with ''] sort '#{options[:order_by]}' "
188
+ if options.has_key?(:order) and options[:order]==:descending
189
+ clause<<" desc "
190
+ end
191
+ extend_query(query,clause)
192
+ end
193
+ if options.has_key?(:conditions)
194
+ options[:conditions].each do |condition|
195
+
196
+ extend_query(query," [ "+condition.to_sdb_query()+"]")
197
+ end
198
+ end
199
+
200
+ end
201
+
202
+ max=250
203
+ if options[:limit]
204
+ max=options[:limit].to_i
205
+
206
+ end
207
+ page_size=max>250?250:max
208
+ sdb_results,token=sdb_query(table_name,query,page_size)
209
+
210
+ while !(token.nil? || token.empty? || sdb_results.length>=max)
211
+ page_size=max- sdb_results.length
212
+ page_size=page_size>250?250:page_size
213
+ partial_results,token=sdb_query(table_name,query,page_size,token)
214
+ sdb_results.concat( partial_results)
215
+ end
216
+ sdb_results
217
+
218
+
219
+ return sdb_results
220
+ end
221
+ def query(table_name,attribute_descriptions,options)
222
+ ids=query_ids(table_name,attribute_descriptions,options)
223
+ result=[]
224
+ ids.each do |primary_key|
225
+ if primary_key
226
+ (0..4).each do |try_count|
227
+ this_one=find_one(table_name,primary_key,attribute_descriptions)
228
+ if this_one
229
+ result<<this_one
230
+ break
231
+ else
232
+ #sdb query just told us it was there so keep trying
233
+ sleep(try_count*try_count)
234
+ end
235
+ end
236
+ else
237
+ @logger.error("blank primary key")
238
+ end
239
+ end
240
+ if options and options[:order_by]
241
+ result.sort! do |a,b|
242
+ a_value=a[options[:order_by]]
243
+ b_value=b[options[:order_by]]
244
+ if options[:order] && options[:order]!=:ascending
245
+ if !a_value
246
+ 1
247
+ else
248
+ if b_value
249
+ b_value <=> a_value
250
+ else
251
+ -1
252
+ end
253
+ end
254
+ else
255
+ if !b_value
256
+ 1
257
+ else
258
+ if a_value
259
+ a_value <=> b_value
260
+ else
261
+ -1
262
+ end
263
+ end
264
+ end
265
+ end
266
+ end
267
+ if options[:limit] && result.length>options[:limit]
268
+ result=result[0..(options[:limit]-1)]
269
+ end
270
+ return result
271
+ end
272
+ def find_one(table_name, primary_key,attribute_descriptions)#, non_clob_attribute_names, clob_attribute_names)
273
+ session_cache_result=@session_cache.find_one(table_name, primary_key,attribute_descriptions)
274
+ return session_cache_result if session_cache_result
275
+ # if @use_cache
276
+ # yaml=@storage.get(@clob_bucket,make_cache_key(table_name,primary_key))
277
+ # if yaml
278
+ # result=YAML::load( yaml)
279
+ # if result.respond_to?(:non_clob_attributes) && result.non_clob_attributes!=nil
280
+ # return parse_attributes(attribute_descriptions, result.non_clob_attributes)
281
+ # end
282
+ #
283
+ # end
284
+ # end
285
+ attributes=parse_attributes(attribute_descriptions,sdb_get_attributes(table_name,primary_key))
286
+ if attributes
287
+ attributes[:primary_key]=primary_key
288
+ #put_into_cache(table_name, primary_key, attributes)
289
+ end
290
+
291
+ attributes
292
+ end
293
+ def make_domain_name(table_name)
294
+ if @append_table_to_domain
295
+ @sdb_domain_prefix+"_"+table_name
296
+ else
297
+ @sdb_domain_prefix
298
+ end
299
+ end
300
+ def sdb_get_attributes(table_name,primary_key)
301
+
302
+ @logger.debug( "SDB get_attributes #{table_name} : #{primary_key}") if @logger
303
+
304
+ 20.times do |i|
305
+ begin
306
+ return @sdb.get_attributes(make_domain_name(table_name), primary_key)
307
+ rescue Exception => e
308
+ s= "#{e.message}\n#{e.backtrace}"
309
+ @logger.warn(s) if @logger
310
+
311
+ sleep(i*i)
312
+ ensure
313
+
314
+ end
315
+ end
316
+
317
+ end
318
+ def sdb_query(table_name,query,max,token=nil)
319
+
320
+ @logger.debug( "SDB query:#{table_name}(#{max}) : #{query} #{token}" ) if @logger
321
+ puts "#{table_name} #{query} (#{max}) #{token}"
322
+ 20.times do |i|
323
+ begin
324
+ return @sdb.query(make_domain_name(table_name),query,max,token)
325
+
326
+ rescue Exception => e
327
+ s= "#{e.message}\n#{e.backtrace}"
328
+ @logger.error(s) if @logger
329
+
330
+ sleep(i*i)
331
+ ensure
332
+
333
+ end
334
+ end
335
+
336
+ end
337
+
338
+ def parse_attributes(attribute_descriptions,attributes)
339
+ if !attributes || attributes.length==0
340
+ return nil
341
+ end
342
+ parsed_attributes={}
343
+ attribute_descriptions.each do |attribute_name,attribute_description|
344
+ value=attributes[attribute_name.to_sym]
345
+ if !value
346
+ value=attributes[attribute_name]
347
+ end
348
+ #sdb attributes are often array of one
349
+ if !attribute_description.is_collection && value.respond_to?(:flatten) && value.length==1
350
+ value=value[0]
351
+ end
352
+ parsed_attributes[attribute_name.to_sym]=attribute_description.parse_from_sdb(value)
353
+ end
354
+ parsed_attributes
355
+ end
356
+ def destroy(table_name, primary_key)
357
+ @sdb.delete_attributes(make_domain_name(table_name), primary_key)
358
+ if @use_cache
359
+ @storage.delete(@clob_bucket,make_cache_key(table_name,primary_key))
360
+ end
361
+ end
362
+ #parse date in yyyy-mm-dd format
363
+
364
+ end
365
+
366
+ end