em-riak 0.2.0 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/em-riak/basic.rb CHANGED
@@ -7,319 +7,367 @@ require 'httpi'
7
7
  require 'yajl'
8
8
 
9
9
  module EmRiak
10
- attr_accessor :bucket, :interface, :adapter, :hosts, :cluster, :async, :http_client, :vector_lock, :replication, :debug
11
- extend self
12
-
13
- # A easy interface to create connections
14
- class Connection
15
- def initialize(*opts)
16
- if opts && opts.length>0
17
- opts=opts.first
18
- methods=[:bucket, :interface, :adapter, :hosts, :cluster, :async, :http_client, :vector_lock, :repliaction, :debug]
19
- opts.each{|key,opt| EmRiak.send "#{key}=".to_sym, opt if opt && methods.index(key.to_sym) }
20
- else
21
- EmRiak.bucket=RIAKBUCKET
22
- end
23
- EmRiak.debug=false if EmRiak.debug.nil?
24
- end
25
- def find; EmRiak.find(self); end
26
- end
27
-
28
- # -- CRUD
29
- class StorageObject < Hash
30
- def find; EmRiak.find(self); end
31
- def save; EmRiak.save(self); end
32
- def destroy; EmRiak.destroy(self); end
33
- def add_tag(*args); EmRiak::SecondaryIndex.add_tag(self,args); end
34
- def remove_tag(*args); EmRiak::SecondaryIndex.remove_tag(self,args); end
35
- def save_as_key(); EmRiak::Grapher.save_object_as_key_name(self) ; end
36
- def method_missing(name,*args)
37
- return self[name] if key? name
38
- if name.to_s.index("=")
39
- sym_name=name.to_s.gsub("=","").to_sym
40
- self[sym_name]=args.first
41
- else
42
- self.each { |k,v| return v if k.to_s.to_sym == name }
43
- super.method_missing name
44
- end
45
- end
46
- end
47
- def create(key,*opts)
48
- data={:body=>{}}
49
- data[:head], data[:query] = handle_options("save",opts)
50
- opts.first.each{|key,value| data[:body][key]=value} if opts && opts.count>0
51
-
52
- url="/buckets/#{bucket}/keys/#{key_handler(key)}"
53
- http("put",key,url,data)
54
- end
55
- def find(key,*opts)
56
- data={}; link=""
57
- data[:head], data[:query] = handle_options("get",opts)
58
- if data[:head][:link]
59
- link=data[:head][:link]
60
- data[:head].reject!{|o| o==:link}
61
- end
62
-
63
- url="/buckets/#{bucket}/keys/#{key_handler(key)}#{link}"
64
- http("get",key,url,data)
65
- end
66
- def save(obj,*opts)
67
- data={:body=>{}}
68
- obj.each{|key,value| data[:body][key]=value }
69
- data[:head], data[:query] = handle_options("save",opts)
70
-
71
- url="/buckets/#{bucket}/keys/#{obj[:riak_key]}"
72
- http("put",obj[:riak_key],url,data)
73
- end
74
- def destroy(key,*opts)
75
- data={}
76
- obj_key=defined?(obj) ? obj[:riak_key] : (key.class==String ? key : key[:riak_key])
77
- data[:head], data[:query] = handle_options("delete",opts)
78
-
79
- url="/buckets/#{bucket}/keys/#{key_handler(obj_key)}"
80
- http("put",obj_key,url,data)
81
- key=nil
82
- end
83
-
84
- # -- Search
85
- def search(*args)
86
- return "you must provide search mode" if !SEARCH_SUPPORT.index(args[0])
87
-
88
- method=args[0]
89
- collect_data=if args[1].class==Hash
90
- opts=args[1]
91
- args[2..args.count]
92
- else
93
- args[1..args.count]
94
- end
95
-
96
- return "you must provide some vars to do search, for example, bucket name, bin name..." if !defined?(opts) && method!=:map_reduce || opts[:bin].nil? && method==:secondary_index
97
-
98
- case method
99
- when :secondary_index
100
- bin=opts[:bin].to_s.index("_bin") ? opts[:bin] : "#{opts[:bin]}_bin"
101
- mapper_key=collect_data.count>1 ? :secondary_index_multiple_query : :secondary_index_single_query
102
-
103
- members={}
104
- EmRiak::MapReduce.submit(mapper_key,{'bucket'=>opts[:bucket],'index'=>bin,'value'=>collect_data.join(',')}).each do |object|
105
- if object[1]["body"]
106
- members[object[0].to_sym]=object[1]["body"]
107
- else
108
- members[object[0].to_sym]=[] if !members[object[0].to_sym]
109
- members[object[0].to_sym] << object[1]
110
- end if object[0]!=false
111
- end
112
- members
113
- when :full_text # TODO : full-text search is still under implement...
114
- []
115
- when :map_reduce
116
- EmRiak::MapReduce.submit(collect_data[0])
117
- end
118
- end
119
-
120
- def http(method,key,url,data,res=nil)
121
- self.async && ["delete","put","post"].index(method) && key!="mapred" ? em_http(method,key,url,data) : open_http(method,key,url,data)
122
- end
123
- def return_body_handler(string,hash_container,handle_type,handle_type_split_mapper={"hash"=>":","string"=>"=","common"=>","})
124
- hash_container={} if !hash_container
125
-
126
- string=string.gsub("{","").gsub("}","") if handle_type!="hash"
127
- split_by= hash_container.class==EmRiak::StorageObject ? "&" : ","
128
- string.split(split_by).each do |vars|
129
- key,value=vars.split(handle_type_split_mapper[handle_type])
130
- value=return_body_handler(value,nil,"hash") if value && value.index("{")
131
- value=json_decode("{#{value}}") if value && value.index(":") && value.index(",")
132
- hash_container[key.to_sym]=value if value
133
- end
134
- hash_container
135
- end
136
-
137
- def open_http(method,key,url,data,res={})
138
- has_http_instance?
139
- data={:body=>{},:head=>{},:query=>{}} if !data
140
-
141
- http_client.url = generate_path(url)
142
- http_client.headers = key!="mapred" ? convert_params_layers(data[:head],:to_s) : data[:head]
143
- http_client.body = key!="mapred" ? convert_params_layers(data[:body],:to_s) : data[:body]
144
-
145
- res=HTTPI.request(method.to_sym,http_client)
146
- res=res.body if res.class==HTTPI::Response
147
-
148
- res=if !["2i","mapred"].index(key) && res && !["not found\n"].index(res) && ["get","put","post"].index(method)
149
- obj=EmRiak::StorageObject.new()
150
- if res && res!="not found\n"
151
- if res.class==String
152
- obj=return_body_handler(URI.unescape(res.force_encoding("UTF-8")).gsub("+"," ").gsub("=>",":"),obj,"string")
153
- elsif res.class==Hash
154
- res.each{|varkey,value| obj[varkey.to_sym]=value }
155
- end
156
-
157
- data.each{|k,v| obj[k]=v } if res.length<1
158
- obj[:riak_key]=key if obj.length>0
159
- end
160
- obj
161
- elsif key=="mapred"
162
- res
163
- else
164
- nil
165
- end
166
- res=nil if res && res.class!=String && res.count<1
167
-
168
- return res
169
- end
170
-
171
- def em_http(method,key,url,data)
172
- data[:retry]=0 if !data[:retry]
173
- begin
174
- raise "Retry too much time" if data[:retry]>RETRY_TIMES
175
-
176
- #conn options
177
- conn_options = {
178
- :connect_timeout => EM_REQUEST_TIMEOUT, # default connection setup timeout
179
- :inactivity_timeout => EM_INACTIVITY_TIMEOUT, # default connection inactivity (post-setup) timeout
180
- }
181
-
182
- #data[:body]=data[:body] if data[:body].class==Hash && data[:head]['Content-Type'] && data[:head]['Content-Type']=="application/json"
183
- #request options
184
- data[:query]="?returnbody=true"
185
- request_options=data.reject{|k,v| k==:retry}
186
-
187
- #do job
188
- case method
189
- when "post"
190
- riakHttp = EventMachine::HttpRequest.new(hosts[rand(hosts.count)]+url).post request_options
191
- when "delete"
192
- riakHttp = EventMachine::HttpRequest.new(hosts[rand(hosts.count)]+url).delete request_options
193
- when "get"
194
- riakHttp = EventMachine::HttpRequest.new(hosts[rand(hosts.count)]+url).get request_options
195
- when "put"
196
- riakHttp = EventMachine::HttpRequest.new(hosts[rand(hosts.count)]+url).put request_options
197
- end
198
-
199
- riakHttp.errback{ #Error Callback
200
- puts "#{method} - #{key} - riak callback error #{riakHttp.response}" if EmRiak.debug
201
- data[:retry]+=1
202
- http(method,key,url,data)
203
- }
204
-
205
- #Success Callback
206
- riakHttp.callback{ puts "#{method} - #{url} - #{key} - riak response #{riakHttp.response}" if EmRiak.debug }
207
- rescue Exception => e
208
- puts "em_http - #{method} - #{url} - #{key} error #{e}" if EmRiak.debug
209
- end
210
-
211
- # Return Response
212
- res=if ["put","post"].index(method)
213
- obj=EmRiak::StorageObject.new()
214
- data.each{|k,v| obj[k]=v }
215
- obj[:riak_key]=key if obj.length>0
216
- obj
217
- else
218
- nil
219
- end
220
- res
221
- end
222
-
223
- def handle_options(action,opts,header={},query="")
224
- #Load default header setting
225
- case action
226
- when "save"
227
- header["Content-Type"]="application/json"
228
- when "get"
229
- header["Content-Type"]="application/json"
230
- when "destroy"
231
-
232
- when "add_link"
233
- header["Content-Type"]="application/json"
234
- when "remove_link"
235
- # else
236
- # header["Content-Type"]="application/json"
237
- end
238
-
239
- if opts && opts.count>0
240
- #Map & overwrite if header specisfic
241
- opts=opts.first if opts.class==Array
242
- opts.each{|k,v|
243
- meta=METAMAPPER[k]
244
- if meta
245
- header[meta[:key]] = meta[:value]
246
- opts.reject!{true}
247
- end
248
- }
249
-
250
- # --- Handle the rest headers
251
- # Link Walk
252
- if opts[:links] && (["save"].index(action))
253
- links=[]
254
- opts[:links].each{|link| links << %Q[</buckets/#{bucket}/keys/#{link[:target]}>; riaktag="#{link[:tag]}"] }
255
- header['Link']= links.join(",")
256
- elsif opts[:links] && (["add_link","remove_link"].index(action))
257
- links=[]
258
- opts[:links].each{|link| links << %Q[</buckets/#{bucket}/keys/#{link[:target]}>; riaktag="#{link[:tag]}"] }
259
- header['Link']= links
260
- elsif opts[:links] && action=="get"
261
- header["Content-Type"]="multipart/mixed"
262
- header["Accept"]="multipart/mixed"
263
- header[:link]=""
264
- keep=opts[:links][:keep] ? '1' : '0' #keep the result
265
- opts[:links][:tag].each{|tag| header[:link]+= "/#{bucket},#{tag},#{keep}" }
266
- end
267
- # 2i
268
- header["x-riak-index-#{opts[:bin].to_s}_bin"]=opts[:secondary_index].join(", ") if opts[:secondary_index]
269
-
270
- # Replication, available configs : w, dw, pw
271
- # read more at http://docs.basho.com/riak/latest/references/apis/http/HTTP-Store-Object/
272
- replication.each{|key,value| hreader[key.to_s]=value} if replication
273
-
274
- header["Content-Type"]=opts[:content_type] if opts[:content_type]
275
- header["X-Riak-Vclock"]=opts[:vlock] if opts[:vlock]
276
- header["ETag"]=opts[:etag] if opts[:etag]
277
- header["Last-Modified"]=opts[:last_modified] if opts[:last_modified]
278
- header["returnbody"]= "true" if !async
279
- #header["unique"] = true if async=false
280
- query="?returnbody=true"
281
- opts[:query].each{|k,v| query+="&#{k}={v}" } if opts[:query]
282
- end
283
- [header,query]
284
- end
285
-
286
- def key_handler(key,map={"["=>"%5B","]"=>"%5D","+"=>"%2B","/"=>"%2F","("=>"%28",")"=>"%29",":"=>"%3A"})
287
- # To match the key rule from Basho : If your field contains special characters, such as (‘+’,‘/’,‘[’,‘]’,‘(’,‘)’,‘:’ or space), then either surround the phrase in single quotes, or escape each special character with a backslash.
288
- # map.each{|origin,value| key.gsub!(origin,value) }
289
- EscapeUtils.escape_url(key.to_s.encode('UTF-8'))
290
- end
291
-
292
- def json_encode(obj,times=0)
293
- y=Yajl::Encoder.new()
294
- y.encode(obj)
295
- rescue Exception => e
296
- puts "json_encode error : #{e}" if EmRiak.debug
297
- nil
298
- end
299
- def json_decode(obj,times=0)
300
- y=Yajl::Parser.new()
301
- y.parse(obj)
302
- rescue Exception => e
303
- puts "json_decode error : #{e}" if EmRiak.debug
304
- nil
305
- end
306
-
307
- def convert_params_layers(origin,to_type,params={})
308
- origin.each{|key,value|
309
- converted=convert_params_layers(value,to_type) if value.class==Hash
310
- key=key.send(to_type)
311
- params[key]= converted ? converted : value
312
- } if origin
313
- params
314
- end
315
-
316
- private
317
- def generate_path(url); EmRiak.hosts[rand(EmRiak.hosts.length)]+url; end
318
- def has_http_instance?
319
- if !EmRiak.http_client
320
- HTTPI.log=false
321
- HTTPI.adapter=:net_http
322
- EmRiak.http_client=HTTPI::Request.new
323
- end
324
- end
10
+ attr_accessor :bucket, :interface, :adapter, :hosts, :cluster, :async, :http_client, :vector_lock, :replication, :debug
11
+ extend self
12
+
13
+ # A easy interface to create connections
14
+ class Connection
15
+ def initialize(*opts)
16
+ if opts && opts.length>0
17
+ opts=opts.first
18
+ methods=[:bucket, :interface, :adapter, :hosts, :cluster, :async, :http_client, :vector_lock, :repliaction, :debug]
19
+ opts.each{|key,opt| EmRiak.send "#{key}=".to_sym, opt if opt && methods.index(key.to_sym) }
20
+ else
21
+ EmRiak.bucket=RIAKBUCKET
22
+ end
23
+ EmRiak.debug=false if EmRiak.debug.nil?
24
+ end
25
+ end
26
+
27
+ # -- CRUD
28
+ class StorageObject < Hash
29
+ def save(block=nil); EmRiak.save(self,block); end
30
+ def destroy(block=nil); EmRiak.destroy(self,block); end
31
+ def add_tag(*args); EmRiak::SecondaryIndex.add_tag(self,args); end
32
+ def remove_tag(*args); EmRiak::SecondaryIndex.remove_tag(self,args); end
33
+ def save_as_key(); EmRiak::Grapher.save_object_as_key_name(self) ; end
34
+ def method_missing(name,*args)
35
+ return self[name] if key? name
36
+ if name.to_s.index("=")
37
+ sym_name=name.to_s.gsub("=","").to_sym
38
+ self[sym_name]=args.first
39
+ else
40
+ self.each { |k,v| return v if k.to_s.to_sym == name }
41
+ super.method_missing name
42
+ end
43
+ end
44
+ end
45
+ def create(key,*opts,&callback)
46
+ data={:body=>{}}
47
+ opts.first.each{|key,value| data[:body][key]=value} if opts && opts.count>0
48
+ data,callback=handle_callback(key,"save",opts,callback,data)
49
+
50
+ url="/buckets/#{bucket}/keys/#{key_handler(key)}"
51
+ http("put",key,url,data,callback)
52
+ end
53
+ def find(key,*opts,&callback)
54
+ link=""
55
+ data,callback=handle_callback(key,"get",opts,callback)
56
+
57
+ if data[:head][:link]
58
+ link=data[:head][:link]
59
+ data[:head].reject!{|o| o==:link}
60
+ end
61
+
62
+ url="/buckets/#{bucket}/keys/#{key_handler(key)}#{link}"
63
+ http("get",key,url,data,callback)
64
+ end
65
+ def save(obj,*opts,&callback)
66
+ data={:body=>{}}
67
+ obj.each{|key,value| data[:body][key]=value }
68
+ data,callback=handle_callback(obj[:riak_key],"save",opts,callback,data)
69
+
70
+ url="/buckets/#{bucket}/keys/#{obj[:riak_key]}"
71
+ http("put",obj[:riak_key],url,data,callback)
72
+ end
73
+ def destroy(key,*opts,&callback)
74
+ obj_key=defined?(obj) ? obj[:riak_key] : (key.class==String ? key : key[:riak_key])
75
+ data,callback=handle_callback(obj_key,"delete",opts,callback)
76
+
77
+ url="/buckets/#{bucket}/keys/#{key_handler(obj_key)}"
78
+ http("put",obj_key,url,data,callback)
79
+ key=nil
80
+ end
81
+
82
+ # -- Search
83
+ def search(method_name,*args,&callback)
84
+ result_handler=nil
85
+ response=[]
86
+ return "you must provide search mode" if !SEARCH_SUPPORT.index(method_name)
87
+
88
+ collect_data= case
89
+ when args[0].class==Hash && args.last.class==Proc
90
+ opts=args[0]
91
+ callback=args.last
92
+ args[1..args.count-2]
93
+ when args[0].class==Hash
94
+ opts=args[0]
95
+ args[1..args.count]
96
+ when args.last.class==Proc
97
+ callback=args.last
98
+ args[0..args.count-2]
99
+ else
100
+ args[0..args.count]
101
+ end
102
+
103
+ collect_data=collect_data.first if collect_data.count==1
104
+
105
+ return "you must provide some vars to do search, for example, bucket name, bin name..." if !defined?(opts) && method_name!=:map_reduce || opts[:bin].nil? && method_name==:secondary_index
106
+
107
+ case method_name
108
+ when :secondary_index
109
+ bin=opts[:bin].to_s.index("_bin") ? opts[:bin] : "#{opts[:bin]}_bin"
110
+ bucket=opts[:bucket] ? opts[:bucket] : EmRiak.bucket
111
+ mapper_key=collect_data.count>1 ? :secondary_index_multiple_query : :secondary_index_single_query
112
+
113
+ result_handler=Proc.new{|map_reduce_results,results|
114
+ map_reduce_results.each do |object|
115
+ if object[1]["body"]
116
+ results[object[0].to_sym]=object[1]["body"]
117
+ else
118
+ results[object[0].to_sym]=[] if !results[object[0].to_sym]
119
+ results[object[0].to_sym] << object[1]
120
+ end if object[0]!=false
121
+ end
122
+ }
123
+ map_reduce_work=[mapper_key,{'bucket'=>bucket,'index'=>bin,'value'=>collect_data.join(',')},result_handler,callback]
124
+ when :full_text # TODO : full-text search is still under implement...
125
+ map_reduce_work=[]
126
+ end
127
+
128
+ response=EmRiak::MapReduce.submit(map_reduce_work) if map_reduce_work.count>0
129
+ response
130
+ end
131
+
132
+ def http(method,key,url,data,callback=nil,res=nil)
133
+ (callback || self.async && ["delete","put","post"].index(method) && key!="mapred") ? em_http(method,key,url,data,callback) : open_http(method,key,url,data)
134
+ end
135
+ def return_body_handler(string,hash_container,handle_type,handle_type_split_mapper={"hash"=>":","string"=>"=","common"=>","})
136
+ hash_container={} if !hash_container
137
+
138
+ string=string.gsub("{","").gsub("}","") if handle_type!="hash"
139
+ split_by= hash_container.class==EmRiak::StorageObject ? "&" : ","
140
+ string.split(split_by).each do |vars|
141
+ key,value=vars.split(handle_type_split_mapper[handle_type])
142
+ value=return_body_handler(value,nil,"hash") if value && value.index("{")
143
+ value=json_decode("{#{value}}") if value && value.index(":") && value.index(",")
144
+ hash_container[key.to_sym]=value if value
145
+ end
146
+ hash_container
147
+ end
148
+
149
+ def open_http(method,key,url,data,res={})
150
+ has_http_instance?
151
+ data={:body=>{},:head=>{},:query=>{}} if !data
152
+
153
+ http_client.url = generate_path(url)
154
+ http_client.headers = key!="mapred" ? convert_params_layers(data[:head],:to_s) : data[:head]
155
+ http_client.body = key!="mapred" ? convert_params_layers(data[:body],:to_s) : data[:body]
156
+ http_client.open_timeout = 300 # seconds. change it if you need
157
+ http_client.read_timeout = 300 # seconds. change it if you need
158
+
159
+ res=HTTPI.request(method.to_sym,http_client)
160
+ res=res.body if res.class==HTTPI::Response
161
+
162
+ res=handle_response_string_to_object(key,res,method,data)
163
+
164
+ res=nil if res && res.class!=String && res.count<1
165
+
166
+ return res
167
+ end
168
+
169
+ def handle_response_string_to_object(key,res,method,data)
170
+ raise "response can't be nil" if !res
171
+
172
+ return res if key=="mapred"
173
+ return nil if ["2i"].index(key)
174
+
175
+ raise "data not found" if ["not found\n"].index(res)
176
+ raise "method is not match" if !["get","put","post"].index(method)
177
+ raise "data is empty" if method=="get" && res.gsub(" ","").length<1
178
+
179
+ obj=EmRiak::StorageObject.new()
180
+
181
+ if res && res!="not found\n" &&
182
+ if res.class==String
183
+ obj=return_body_handler(URI.unescape(res.force_encoding("UTF-8")).gsub("+"," ").gsub("=>",":"),obj,"string")
184
+ elsif res.class==Hash
185
+ res.each{|varkey,value| obj[varkey.to_sym]=value }
186
+ end
187
+
188
+ data.each{|k,v| obj[k]=v } if res.length<1
189
+ obj[:riak_key]=key if obj.length>0
190
+ end
191
+ return obj
192
+ rescue Exception=>e
193
+ puts "handle response error reason #{e}"
194
+ return nil
195
+ end
196
+
197
+ def em_http(method,key,url,data,async_callback)
198
+ data[:retry]=0 if !data[:retry]
199
+ begin
200
+ raise "Retry too much time" if data[:retry]>RETRY_TIMES
201
+
202
+ #conn options
203
+ conn_options = {
204
+ :connect_timeout => EM_REQUEST_TIMEOUT, # default connection setup timeout
205
+ :inactivity_timeout => EM_INACTIVITY_TIMEOUT, # default connection inactivity (post-setup) timeout
206
+ }
207
+ #data[:body]=data[:body] if data[:body].class==Hash && data[:head]['Content-Type'] && data[:head]['Content-Type']=="application/json"
208
+ #request options
209
+ data[:query]="?returnbody=true"
210
+ request_options=data.reject{|k,v| k==:retry}
211
+
212
+ #do job
213
+ case method
214
+ when "post"
215
+ riakHttp = EventMachine::HttpRequest.new(hosts[rand(hosts.count)]+url).post request_options
216
+ when "delete"
217
+ riakHttp = EventMachine::HttpRequest.new(hosts[rand(hosts.count)]+url).delete request_options
218
+ when "get"
219
+ riakHttp = EventMachine::HttpRequest.new(hosts[rand(hosts.count)]+url).get request_options
220
+ when "put"
221
+ riakHttp = EventMachine::HttpRequest.new(hosts[rand(hosts.count)]+url).put request_options
222
+ end
223
+
224
+ riakHttp.errback{ #Error Callback
225
+ puts "#{method} - #{key} - riak callback error #{riakHttp.response}" if EmRiak.debug
226
+ data[:retry]+=1
227
+ http(method,key,url,data,async_callback)
228
+ }
229
+
230
+ #Success Callback
231
+ riakHttp.callback{
232
+ puts "#{method} - #{url} - #{key} - riak response #{riakHttp.response}" if EmRiak.debug
233
+ async_callback.call(riakHttp.response) if async_callback
234
+ }
235
+ rescue Exception => e
236
+ puts "em_http - #{method} - #{url} - #{key} error #{e}" if EmRiak.debug
237
+ end
238
+
239
+ # Return Response
240
+ res=if ["put","post"].index(method)
241
+ obj=EmRiak::StorageObject.new()
242
+ data.each{|k,v| obj[k]=v }
243
+ obj[:riak_key]=key if obj.length>0
244
+ obj
245
+ else
246
+ nil
247
+ end
248
+ res
249
+ end
250
+
251
+ def handle_callback(key,method,opts,callback,data={})
252
+ option_response=handle_options(method,opts)
253
+ if callback
254
+ data[:head], data[:query] = option_response
255
+ else
256
+ data[:head], data[:query], callback = option_response
257
+ end
258
+
259
+ new_proc=Proc.new{|res|
260
+ obj=handle_response_string_to_object(key,res,method,data)
261
+ callback.call(obj)
262
+ } if callback
263
+
264
+ [data,new_proc]
265
+ end
266
+ def handle_options(action,opts,header={},query="")
267
+ #Load default header setting
268
+ case action
269
+ when "save"
270
+ header["Content-Type"]="application/json"
271
+ when "get"
272
+ header["Content-Type"]="application/json"
273
+ when "destroy","delete"
274
+ header["Content-Type"]="application/json"
275
+ when "add_link"
276
+ header["Content-Type"]="application/json"
277
+ when "remove_link"
278
+ # else
279
+ # header["Content-Type"]="application/json"
280
+ end
281
+ # Map & overwrite if header specisfic
282
+ opts=opts.first if opts && opts.class==Array
283
+
284
+ if opts && opts.count>0
285
+ # Map the options class
286
+ callback=opts.reject!{|obj| obj.class==Proc}
287
+
288
+ opts.each{|k,v|
289
+ meta=METAMAPPER[k]
290
+ if meta
291
+ header[meta[:key]] = meta[:value]
292
+ opts.reject!{true}
293
+ end
294
+ }
295
+
296
+ # --- Handle the rest headers
297
+ # Link Walk
298
+ if opts[:links] && (["save"].index(action))
299
+ links=[]
300
+ opts[:links].each{|link| links << %Q[</buckets/#{bucket}/keys/#{link[:target]}>; riaktag="#{link[:tag]}"] }
301
+ header['Link']= links.join(",")
302
+ elsif opts[:links] && (["add_link","remove_link"].index(action))
303
+ links=[]
304
+ opts[:links].each{|link| links << %Q[</buckets/#{bucket}/keys/#{link[:target]}>; riaktag="#{link[:tag]}"] }
305
+ header['Link']= links
306
+ elsif opts[:links] && action=="get"
307
+ header["Content-Type"]="multipart/mixed"
308
+ header["Accept"]="multipart/mixed"
309
+ header[:link]=""
310
+ keep=opts[:links][:keep] ? '1' : '0' #keep the result
311
+ opts[:links][:tag].each{|tag| header[:link]+= "/#{bucket},#{tag},#{keep}" }
312
+ end
313
+ # 2i
314
+ header["x-riak-index-#{opts[:bin].to_s}_bin"]=opts[:secondary_index].join(", ") if opts[:secondary_index]
315
+
316
+ # Replication, available configs : w, dw, pw
317
+ # read more at http://docs.basho.com/riak/latest/references/apis/http/HTTP-Store-Object/
318
+ replication.each{|key,value| hreader[key.to_s]=value} if replication
319
+
320
+ header["Content-Type"]=opts[:content_type] if opts[:content_type]
321
+ header["X-Riak-Vclock"]=opts[:vlock] if opts[:vlock]
322
+ header["ETag"]=opts[:etag] if opts[:etag]
323
+ header["Last-Modified"]=opts[:last_modified] if opts[:last_modified]
324
+ header["returnbody"]= "true" if !async
325
+ #header["unique"] = true if async=false
326
+ query="?returnbody=true"
327
+ opts[:query].each{|k,v| query+="&#{k}={v}" } if opts[:query]
328
+ end
329
+ res=[header,query]
330
+ res << callback if callback
331
+ res
332
+ end
333
+
334
+ def key_handler(key,map={"["=>"%5B","]"=>"%5D","+"=>"%2B","/"=>"%2F","("=>"%28",")"=>"%29",":"=>"%3A"})
335
+ # To match the key rule from Basho : If your field contains special characters, such as (‘+’,‘/’,‘[’,‘]’,‘(’,‘)’,‘:’ or space), then either surround the phrase in single quotes, or escape each special character with a backslash.
336
+ # map.each{|origin,value| key.gsub!(origin,value) }
337
+ EscapeUtils.escape_url(key.to_s.encode('UTF-8'))
338
+ end
339
+
340
+ def json_encode(obj,times=0)
341
+ y=Yajl::Encoder.new()
342
+ y.encode(obj)
343
+ rescue Exception => e
344
+ puts "json_encode error : #{e}" if EmRiak.debug
345
+ obj
346
+ end
347
+ def json_decode(obj,times=0)
348
+ y=Yajl::Parser.new()
349
+ y.parse(obj)
350
+ rescue Exception => e
351
+ puts "json_decode error : #{e}" if EmRiak.debug
352
+ obj
353
+ end
354
+
355
+ def convert_params_layers(origin,to_type,params={})
356
+ origin.each{|key,value|
357
+ converted=convert_params_layers(value,to_type) if value.class==Hash
358
+ key=key.send(to_type)
359
+ params[key]= converted ? converted : value
360
+ } if origin
361
+ params
362
+ end
363
+
364
+ private
365
+ def generate_path(url); EmRiak.hosts[rand(EmRiak.hosts.length)]+url; end
366
+ def has_http_instance?
367
+ if !EmRiak.http_client
368
+ HTTPI.log=false
369
+ HTTPI.adapter=:net_http
370
+ EmRiak.http_client=HTTPI::Request.new
371
+ end
372
+ end
325
373
  end