rhosync 2.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. data/CHANGELOG +5 -0
  2. data/LICENSE +674 -0
  3. data/README.md +26 -0
  4. data/Rakefile +109 -0
  5. data/bench/bench +6 -0
  6. data/bench/benchapp/Rakefile +14 -0
  7. data/bench/benchapp/application.rb +13 -0
  8. data/bench/benchapp/config.ru +32 -0
  9. data/bench/benchapp/settings/license.key +1 -0
  10. data/bench/benchapp/settings/settings.yml +18 -0
  11. data/bench/benchapp/sources/mock_adapter.rb +55 -0
  12. data/bench/benchapp/sources/queue_mock_adapter.rb +2 -0
  13. data/bench/benchapp/vendor/rhosync/lib/rhosync.rb +7 -0
  14. data/bench/lib/bench/cli.rb +16 -0
  15. data/bench/lib/bench/logging.rb +18 -0
  16. data/bench/lib/bench/mock_client.rb +41 -0
  17. data/bench/lib/bench/result.rb +50 -0
  18. data/bench/lib/bench/runner.rb +44 -0
  19. data/bench/lib/bench/session.rb +65 -0
  20. data/bench/lib/bench/statistics.rb +56 -0
  21. data/bench/lib/bench/test_data.rb +55 -0
  22. data/bench/lib/bench/timer.rb +10 -0
  23. data/bench/lib/bench/utils.rb +49 -0
  24. data/bench/lib/bench.rb +128 -0
  25. data/bench/lib/testdata/100-data.txt +148 -0
  26. data/bench/lib/testdata/5-data.txt +11 -0
  27. data/bench/scripts/cud_script.rb +77 -0
  28. data/bench/scripts/helpers.rb +101 -0
  29. data/bench/scripts/query_md_script.rb +46 -0
  30. data/bench/scripts/query_script.rb +46 -0
  31. data/bench/spec/bench_spec_helper.rb +65 -0
  32. data/bench/spec/logging_spec.rb +19 -0
  33. data/bench/spec/mock_adapter_spec.rb +61 -0
  34. data/bench/spec/mock_client_spec.rb +64 -0
  35. data/bench/spec/result_spec.rb +59 -0
  36. data/bench/spec/utils_spec.rb +35 -0
  37. data/bin/rhosync +34 -0
  38. data/doc/protocol.html +1901 -0
  39. data/doc/public/css/print.css +29 -0
  40. data/doc/public/css/screen.css +257 -0
  41. data/doc/public/css/style.css +20 -0
  42. data/examples/simple/application.rb +13 -0
  43. data/examples/simple/sources/sample_adapter.rb +5 -0
  44. data/examples/simple/sources/simple_adapter.rb +5 -0
  45. data/examples/simple/vendor/rhosync/lib/rhosync.rb +7 -0
  46. data/generators/rhosync.rb +98 -0
  47. data/generators/templates/application/Rakefile +19 -0
  48. data/generators/templates/application/application.rb +27 -0
  49. data/generators/templates/application/config.ru +33 -0
  50. data/generators/templates/application/settings/license.key +1 -0
  51. data/generators/templates/application/settings/settings.yml +14 -0
  52. data/generators/templates/source/source_adapter.rb +49 -0
  53. data/lib/rhosync/api/create_client.rb +3 -0
  54. data/lib/rhosync/api/create_user.rb +7 -0
  55. data/lib/rhosync/api/delete_client.rb +5 -0
  56. data/lib/rhosync/api/delete_user.rb +5 -0
  57. data/lib/rhosync/api/get_api_token.rb +7 -0
  58. data/lib/rhosync/api/get_client_params.rb +3 -0
  59. data/lib/rhosync/api/get_db_doc.rb +7 -0
  60. data/lib/rhosync/api/get_license_info.rb +7 -0
  61. data/lib/rhosync/api/get_source_params.rb +3 -0
  62. data/lib/rhosync/api/list_client_docs.rb +12 -0
  63. data/lib/rhosync/api/list_clients.rb +3 -0
  64. data/lib/rhosync/api/list_source_docs.rb +10 -0
  65. data/lib/rhosync/api/list_sources.rb +15 -0
  66. data/lib/rhosync/api/list_users.rb +3 -0
  67. data/lib/rhosync/api/ping.rb +7 -0
  68. data/lib/rhosync/api/push_deletes.rb +6 -0
  69. data/lib/rhosync/api/push_objects.rb +6 -0
  70. data/lib/rhosync/api/reset.rb +10 -0
  71. data/lib/rhosync/api/set_db_doc.rb +8 -0
  72. data/lib/rhosync/api/set_refresh_time.rb +8 -0
  73. data/lib/rhosync/api/update_user.rb +4 -0
  74. data/lib/rhosync/api/upload_file.rb +4 -0
  75. data/lib/rhosync/api_token.rb +19 -0
  76. data/lib/rhosync/app.rb +69 -0
  77. data/lib/rhosync/bulk_data/bulk_data.rb +75 -0
  78. data/lib/rhosync/bulk_data/syncdb.index.schema +3 -0
  79. data/lib/rhosync/bulk_data/syncdb.schema +37 -0
  80. data/lib/rhosync/bulk_data.rb +2 -0
  81. data/lib/rhosync/client.rb +74 -0
  82. data/lib/rhosync/client_sync.rb +296 -0
  83. data/lib/rhosync/console/app/helpers/auth_helper.rb +18 -0
  84. data/lib/rhosync/console/app/helpers/extensions.rb +19 -0
  85. data/lib/rhosync/console/app/helpers/helpers.rb +52 -0
  86. data/lib/rhosync/console/app/public/main.css +7 -0
  87. data/lib/rhosync/console/app/public/text.txt +0 -0
  88. data/lib/rhosync/console/app/routes/auth.rb +29 -0
  89. data/lib/rhosync/console/app/routes/client.rb +32 -0
  90. data/lib/rhosync/console/app/routes/docs.rb +84 -0
  91. data/lib/rhosync/console/app/routes/home.rb +22 -0
  92. data/lib/rhosync/console/app/routes/user.rb +63 -0
  93. data/lib/rhosync/console/app/views/client.erb +30 -0
  94. data/lib/rhosync/console/app/views/doc.erb +56 -0
  95. data/lib/rhosync/console/app/views/docs.erb +29 -0
  96. data/lib/rhosync/console/app/views/index.erb +50 -0
  97. data/lib/rhosync/console/app/views/layout.erb +12 -0
  98. data/lib/rhosync/console/app/views/newuser.erb +17 -0
  99. data/lib/rhosync/console/app/views/ping.erb +28 -0
  100. data/lib/rhosync/console/app/views/result.erb +11 -0
  101. data/lib/rhosync/console/app/views/user.erb +32 -0
  102. data/lib/rhosync/console/app/views/users.erb +14 -0
  103. data/lib/rhosync/console/rhosync_api.rb +102 -0
  104. data/lib/rhosync/console/server.rb +27 -0
  105. data/lib/rhosync/credential.rb +9 -0
  106. data/lib/rhosync/document.rb +43 -0
  107. data/lib/rhosync/indifferent_access.rb +132 -0
  108. data/lib/rhosync/jobs/bulk_data_job.rb +104 -0
  109. data/lib/rhosync/jobs/ping_job.rb +19 -0
  110. data/lib/rhosync/jobs/source_job.rb +16 -0
  111. data/lib/rhosync/license.rb +79 -0
  112. data/lib/rhosync/lock_ops.rb +11 -0
  113. data/lib/rhosync/model.rb +410 -0
  114. data/lib/rhosync/ping/blackberry.rb +55 -0
  115. data/lib/rhosync/ping/iphone.rb +44 -0
  116. data/lib/rhosync/ping.rb +2 -0
  117. data/lib/rhosync/read_state.rb +27 -0
  118. data/lib/rhosync/server/views/index.erb +12 -0
  119. data/lib/rhosync/server.rb +242 -0
  120. data/lib/rhosync/source.rb +112 -0
  121. data/lib/rhosync/source_adapter.rb +95 -0
  122. data/lib/rhosync/source_sync.rb +245 -0
  123. data/lib/rhosync/store.rb +199 -0
  124. data/lib/rhosync/tasks.rb +151 -0
  125. data/lib/rhosync/user.rb +83 -0
  126. data/lib/rhosync/version.rb +3 -0
  127. data/lib/rhosync.rb +251 -0
  128. data/spec/api/api_helper.rb +44 -0
  129. data/spec/api/create_client_spec.rb +13 -0
  130. data/spec/api/create_user_spec.rb +16 -0
  131. data/spec/api/delete_client_spec.rb +13 -0
  132. data/spec/api/delete_user_spec.rb +18 -0
  133. data/spec/api/get_api_token_spec.rb +25 -0
  134. data/spec/api/get_client_params_spec.rb +18 -0
  135. data/spec/api/get_db_doc_spec.rb +21 -0
  136. data/spec/api/get_license_info_spec.rb +16 -0
  137. data/spec/api/get_source_params_spec.rb +26 -0
  138. data/spec/api/list_client_docs_spec.rb +33 -0
  139. data/spec/api/list_clients_spec.rb +23 -0
  140. data/spec/api/list_source_docs_spec.rb +26 -0
  141. data/spec/api/list_sources_spec.rb +27 -0
  142. data/spec/api/list_users_spec.rb +21 -0
  143. data/spec/api/ping_spec.rb +24 -0
  144. data/spec/api/push_deletes_spec.rb +16 -0
  145. data/spec/api/push_objects_spec.rb +27 -0
  146. data/spec/api/reset_spec.rb +22 -0
  147. data/spec/api/set_db_doc_spec.rb +20 -0
  148. data/spec/api/set_refresh_time_spec.rb +43 -0
  149. data/spec/api/update_user_spec.rb +31 -0
  150. data/spec/api/upload_file_spec.rb +26 -0
  151. data/spec/api_token_spec.rb +13 -0
  152. data/spec/app_spec.rb +20 -0
  153. data/spec/apps/rhotestapp/Rakefile +1 -0
  154. data/spec/apps/rhotestapp/application.rb +16 -0
  155. data/spec/apps/rhotestapp/config.ru +1 -0
  156. data/spec/apps/rhotestapp/settings/apple_fake_cert.pem +1 -0
  157. data/spec/apps/rhotestapp/settings/license.key +1 -0
  158. data/spec/apps/rhotestapp/settings/settings.yml +23 -0
  159. data/spec/apps/rhotestapp/sources/base_adapter.rb +9 -0
  160. data/spec/apps/rhotestapp/sources/sample_adapter.rb +66 -0
  161. data/spec/apps/rhotestapp/sources/simple_adapter.rb +39 -0
  162. data/spec/apps/rhotestapp/sources/sub_adapter.rb +7 -0
  163. data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem/mygem.rb +8 -0
  164. data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem.rb +1 -0
  165. data/spec/bulk_data/bulk_data_spec.rb +79 -0
  166. data/spec/client_spec.rb +58 -0
  167. data/spec/client_sync_spec.rb +377 -0
  168. data/spec/doc/base.html +72 -0
  169. data/spec/doc/doc_spec.rb +303 -0
  170. data/spec/doc/footer.html +4 -0
  171. data/spec/doc/header.html +30 -0
  172. data/spec/document_spec.rb +27 -0
  173. data/spec/generator/generator_spec.rb +53 -0
  174. data/spec/generator/generator_spec_helper.rb +8 -0
  175. data/spec/jobs/bulk_data_job_spec.rb +76 -0
  176. data/spec/jobs/ping_job_spec.rb +26 -0
  177. data/spec/jobs/source_job_spec.rb +25 -0
  178. data/spec/license_spec.rb +48 -0
  179. data/spec/model_spec.rb +269 -0
  180. data/spec/perf/bulk_data_perf_spec.rb +33 -0
  181. data/spec/perf/perf_spec_helper.rb +51 -0
  182. data/spec/perf/store_perf_spec.rb +28 -0
  183. data/spec/ping/blackberry_spec.rb +62 -0
  184. data/spec/ping/iphone_spec.rb +50 -0
  185. data/spec/read_state_spec.rb +25 -0
  186. data/spec/rhosync_spec.rb +43 -0
  187. data/spec/server/server_spec.rb +341 -0
  188. data/spec/source_adapter_spec.rb +114 -0
  189. data/spec/source_spec.rb +77 -0
  190. data/spec/source_sync_spec.rb +248 -0
  191. data/spec/spec_helper.rb +240 -0
  192. data/spec/store_spec.rb +149 -0
  193. data/spec/sync_states_spec.rb +101 -0
  194. data/spec/testdata/1000-data.txt +1414 -0
  195. data/spec/testdata/compressed/compress-data.txt +1 -0
  196. data/spec/testdata/upload1.txt +1 -0
  197. data/spec/testdata/upload2.txt +1 -0
  198. data/spec/user_spec.rb +79 -0
  199. data/tasks/redis.rake +134 -0
  200. metadata +545 -0
@@ -0,0 +1,102 @@
1
+ require 'rest_client'
2
+
3
+ module RhosyncApi
4
+ class << self
5
+
6
+ def get_token(server,login,password)
7
+ res = RestClient.post("#{server}/login",
8
+ {:login => login, :password => password}.to_json, :content_type => :json)
9
+ RestClient.post("#{server}/api/get_api_token",'',{:cookies => res.cookies})
10
+ end
11
+
12
+ def list_users(server,app_name,token)
13
+ JSON.parse(RestClient.post("#{server}/api/list_users",
14
+ {:app_name => app_name, :api_token => token}.to_json, :content_type => :json).body)
15
+ end
16
+
17
+ def create_user(server,app_name,token,login,password)
18
+ RestClient.post("#{server}/api/create_user",
19
+ {:app_name => app_name, :api_token => token,
20
+ :attributes => {:login => login, :password => password}}.to_json,
21
+ :content_type => :json)
22
+ end
23
+
24
+ def delete_user(server,app_name,token,user_id)
25
+ RestClient.post("#{server}/api/delete_user",
26
+ {:app_name => app_name, :api_token => token, :user_id => user_id}.to_json,
27
+ :content_type => :json)
28
+ end
29
+
30
+ def list_clients(server,app_name,token,user_id)
31
+ JSON.parse(RestClient.post("#{server}/api/list_clients", {:app_name => app_name,
32
+ :api_token => token, :user_id => user_id}.to_json, :content_type => :json).body)
33
+ end
34
+
35
+ def create_client(server,app_name,token,user_id)
36
+ RestClient.post("#{server}/api/create_client",
37
+ {:app_name => app_name, :api_token => token, :user_id => user_id}.to_json,
38
+ :content_type => :json).body
39
+ end
40
+
41
+ def delete_client(server,app_name,token,user_id,client_id)
42
+ RestClient.post("#{server}/api/delete_client",
43
+ {:app_name => app_name, :api_token => token, :user_id => user_id,
44
+ :client_id => client_id}.to_json, :content_type => :json)
45
+ end
46
+
47
+ def get_client_params(server,app_name,token,client_id)
48
+ JSON.parse(RestClient.post("#{server}/api/get_client_params", {:app_name => app_name,
49
+ :api_token => token, :client_id => client_id}.to_json, :content_type => :json).body)
50
+ end
51
+
52
+ def list_sources(server,app_name,token,partition='all')
53
+ JSON.parse(RestClient.post("#{server}/api/list_sources", {:app_name => app_name,
54
+ :api_token => token, :partition_type => partition}.to_json, :content_type => :json).body)
55
+ end
56
+
57
+ def get_source_params(server,app_name,token,source_id)
58
+ JSON.parse(RestClient.post("#{server}/api/get_source_params", {:app_name => app_name,
59
+ :api_token => token, :source_id => source_id}.to_json, :content_type => :json).body)
60
+ end
61
+
62
+ def list_source_docs(server,app_name,token,source_id,user_id='*')
63
+ JSON.parse(RestClient.post("#{server}/api/list_source_docs", {:app_name => app_name,
64
+ :api_token => token, :source_id => source_id, :user_id => user_id}.to_json, :content_type => :json).body)
65
+ end
66
+
67
+ def list_client_docs(server,app_name,token,source_id,client_id)
68
+ JSON.parse(RestClient.post("#{server}/api/list_client_docs", {:app_name => app_name,
69
+ :api_token => token, :source_id => source_id, :client_id => client_id}.to_json, :content_type => :json).body)
70
+ end
71
+
72
+ def get_db_doc(server,token,doc,data_type='')
73
+ res = RestClient.post("#{server}/api/get_db_doc",
74
+ {:api_token => token, :doc => doc, :data_type => data_type}.to_json, :content_type => :json).body
75
+ data_type=='' ? JSON.parse(res) : res
76
+ end
77
+
78
+ def set_db_doc(server,token,doc,data={},data_type='')
79
+ RestClient.post("#{server}/api/set_db_doc",
80
+ {:api_token => token, :doc => doc, :data => data, :data_type => data_type}.to_json, :content_type => :json)
81
+ end
82
+
83
+ def reset(server,token)
84
+ RestClient.post("#{server}/api/reset",
85
+ {:api_token => token}.to_json, :content_type => :json)
86
+ end
87
+
88
+ def ping(server,token,user_id,params)
89
+ ping_params = {:api_token => token, :user_id => user_id}
90
+ [:message,:badge,:sound,:vibrate,:sources].each do |part|
91
+ ping_params.merge!(part => params[part]) if params[part]
92
+ end
93
+ RestClient.post("#{server}/api/ping",ping_params.to_json, :content_type => :json)
94
+ end
95
+
96
+ def get_license_info(server,token)
97
+ JSON.parse(RestClient.post("#{server}/api/get_license_info",
98
+ {:api_token => token}.to_json, :content_type => :json).body)
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,27 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'rubygems'
3
+ require 'sinatra/base'
4
+ require 'erb'
5
+ require 'json'
6
+ require 'rhosync_api'
7
+
8
+ module RhosyncConsole
9
+ class << self
10
+ ROOT_DIR = File.dirname(File.expand_path(__FILE__)) unless defined? ROOT_DIR
11
+
12
+ def root_path(*args)
13
+ File.join(ROOT_DIR, *args)
14
+ end
15
+ end
16
+
17
+ class Server < Sinatra::Base
18
+ set :views, RhosyncConsole::root_path("app","views")
19
+ set :public, RhosyncConsole::root_path("app","public")
20
+ set :static, true
21
+ use Rack::Session::Cookie
22
+ end
23
+ end
24
+
25
+ Dir[File.join(File.dirname(__FILE__),"app/**/*.rb")].each do |file|
26
+ require file
27
+ end
@@ -0,0 +1,9 @@
1
+ module Rhosync
2
+ class Credential
3
+ attr_accessor :login,:password,:token,:url
4
+
5
+ def initialize(login,password,token,url)
6
+ @login,@password,@token,@url = login,password,token,url
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,43 @@
1
+ module Document
2
+
3
+ # Store wrapper methods for document
4
+ def get_data(doctype,type=Hash)
5
+ Store.get_data(docname(doctype),type)
6
+ end
7
+
8
+ def get_value(doctype)
9
+ Store.get_value(docname(doctype))
10
+ end
11
+
12
+ def put_data(doctype,data,append=false)
13
+ Store.put_data(docname(doctype),data,append)
14
+ end
15
+
16
+ def put_value(doctype,data)
17
+ Store.put_value(docname(doctype),data)
18
+ end
19
+
20
+ def delete_data(doctype,data)
21
+ Store.delete_data(docname(doctype),data)
22
+ end
23
+
24
+ def flash_data(doctype)
25
+ Store.flash_data(docname(doctype))
26
+ end
27
+
28
+ def rename(srcdoctype,dstdoctype)
29
+ Store.rename(docname(srcdoctype),docname(dstdoctype))
30
+ end
31
+
32
+ # Generate the fully-qualified docname
33
+ def docname(doctype)
34
+ "#{self.class.class_prefix(self.class)}:#{self.app_id}:#{self.doc_suffix(doctype)}"
35
+ end
36
+
37
+ # Update count for a given document
38
+ def update_count(doctype,count)
39
+ name = docname(doctype)
40
+ value = Store.db.get(name).to_i + count
41
+ Store.db.set(name,value < 0 ? 0 : value)
42
+ end
43
+ end
@@ -0,0 +1,132 @@
1
+ # This class has dubious semantics and we only have it so that
2
+ # people can write params[:key] instead of params['key']
3
+ # and they get the same value for both keys.
4
+
5
+ class HashWithIndifferentAccess < Hash
6
+ def initialize(constructor = {})
7
+ if constructor.is_a?(Hash)
8
+ super()
9
+ update(constructor)
10
+ # else
11
+ # super(constructor)
12
+ end
13
+ end
14
+
15
+ def default(key = nil)
16
+ if key.is_a?(Symbol) && include?(key = key.to_s)
17
+ self[key]
18
+ else
19
+ super
20
+ end
21
+ end
22
+
23
+ alias_method :regular_writer, :[]= #unless method_defined?(:regular_writer)
24
+ alias_method :regular_update, :update #unless method_defined?(:regular_update)
25
+
26
+ # Assigns a new value to the hash:
27
+ #
28
+ # hash = HashWithIndifferentAccess.new
29
+ # hash[:key] = "value"
30
+ #
31
+ def []=(key, value)
32
+ regular_writer(convert_key(key), convert_value(value))
33
+ end
34
+
35
+ # Updates the instantized hash with values from the second:
36
+ #
37
+ # hash_1 = HashWithIndifferentAccess.new
38
+ # hash_1[:key] = "value"
39
+ #
40
+ # hash_2 = HashWithIndifferentAccess.new
41
+ # hash_2[:key] = "New Value!"
42
+ #
43
+ # hash_1.update(hash_2) # => {"key"=>"New Value!"}
44
+ #
45
+ def update(other_hash)
46
+ other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
47
+ self
48
+ end
49
+
50
+ alias_method :merge!, :update
51
+
52
+ # Checks the hash for a key matching the argument passed in:
53
+ #
54
+ # hash = HashWithIndifferentAccess.new
55
+ # hash["key"] = "value"
56
+ # hash.key? :key # => true
57
+ # hash.key? "key" # => true
58
+ #
59
+ def key?(key)
60
+ super(convert_key(key))
61
+ end
62
+
63
+ alias_method :include?, :key?
64
+ alias_method :has_key?, :key?
65
+ alias_method :member?, :key?
66
+
67
+ # Fetches the value for the specified key, same as doing hash[key]
68
+ # def fetch(key, *extras)
69
+ # super(convert_key(key), *extras)
70
+ # end
71
+
72
+ # Returns an array of the values at the specified indices:
73
+ #
74
+ # hash = HashWithIndifferentAccess.new
75
+ # hash[:a] = "x"
76
+ # hash[:b] = "y"
77
+ # hash.values_at("a", "b") # => ["x", "y"]
78
+ #
79
+ # def values_at(*indices)
80
+ # indices.collect {|key| self[convert_key(key)]}
81
+ # end
82
+
83
+ # Returns an exact copy of the hash.
84
+ # def dup
85
+ # HashWithIndifferentAccess.new(self)
86
+ # end
87
+
88
+ # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
89
+ # Does not overwrite the existing hash.
90
+ # def merge(hash)
91
+ # self.dup.update(hash)
92
+ # end
93
+
94
+ # Removes a specified key from the hash.
95
+ # def delete(key)
96
+ # super(convert_key(key))
97
+ # end
98
+
99
+ def stringify_keys!; self end
100
+ def symbolize_keys!; self end
101
+ def to_options!; self end
102
+
103
+ # Convert to a Hash with String keys.
104
+ # def to_hash
105
+ # Hash.new(default).merge(self)
106
+ # end
107
+
108
+ protected
109
+ def convert_key(key)
110
+ key.kind_of?(Symbol) ? key.to_s : key
111
+ end
112
+
113
+ def convert_value(value)
114
+ # case value
115
+ # when Hash
116
+ # value.with_indifferent_access
117
+ # when Array
118
+ # value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
119
+ # else
120
+ value
121
+ # end
122
+ end
123
+ end
124
+
125
+ class Hash
126
+ public
127
+ def with_indifferent_access
128
+ hash = HashWithIndifferentAccess.new(self)
129
+ hash.default = self.default
130
+ hash
131
+ end
132
+ end
@@ -0,0 +1,104 @@
1
+ require 'sqlite3'
2
+
3
+ module Rhosync
4
+ module BulkDataJob
5
+ @queue = :bulk_data
6
+
7
+ def self.perform(params)
8
+ bulk_data = nil
9
+ begin
10
+ bulk_data = BulkData.load(params["data_name"]) if BulkData.is_exist?(params["data_name"])
11
+ if bulk_data
12
+ timer = start_timer('starting bulk data process')
13
+ bulk_data.process_sources
14
+ timer = lap_timer('process_sources',timer)
15
+ ts = Time.now.to_i.to_s
16
+ create_sqlite_data_file(bulk_data,ts)
17
+ timer = lap_timer('create_sqlite_data_file',timer)
18
+ create_hsql_data_file(bulk_data,ts) if Rhosync.blackberry_bulk_sync
19
+ timer = lap_timer('create_hsql_data_file',timer)
20
+ bulk_data.state = :completed
21
+ else
22
+ raise Exception.new("No bulk data found for #{params["data_name"]}")
23
+ end
24
+ rescue Exception => e
25
+ bulk_data.delete if bulk_data
26
+ raise e
27
+ end
28
+ end
29
+
30
+ def self.import_data_to_object_values(db,source)
31
+ data = source.get_data(:md)
32
+ counter = {}
33
+ db.transaction do |database|
34
+ database.prepare("insert into object_values
35
+ (source_id,attrib,object,value) values (?,?,?,?)") do |stmt|
36
+ data.each do |object_id,object|
37
+ object.each do |attrib,value|
38
+ counter[attrib] = counter[attrib] ? counter[attrib] + 1 : 1
39
+ stmt.execute(source.source_id.to_i,attrib,object_id,value)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ counter
45
+ end
46
+
47
+ def self.refs_to_s(refs)
48
+ str = ''
49
+ refs.sort.each do |name,value|
50
+ str << "#{name},#{value},"
51
+ end
52
+ str[0..-2]
53
+ end
54
+
55
+ def self.populate_sources_table(db,sources_refs)
56
+ db.transaction do |database|
57
+ database.prepare("insert into sources
58
+ (source_id,name,priority,partition,sync_type,source_attribs)
59
+ values (?,?,?,?,?,?)") do |stmt|
60
+ sources_refs.each do |source_name,ref|
61
+ s = ref[:source]
62
+ stmt.execute(s.source_id,s.name,s.priority,s.partition_type,
63
+ s.sync_type,refs_to_s(ref[:refs]))
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ def self.create_sqlite_data_file(bulk_data,ts)
70
+ sources_refs = {}
71
+ schema,index,bulk_data.dbfile = get_file_args(bulk_data.name,ts)
72
+ FileUtils.mkdir_p(File.dirname(bulk_data.dbfile))
73
+ db = SQLite3::Database.new(bulk_data.dbfile)
74
+ db.execute_batch(File.open(schema,'r').read)
75
+ src_counter = 1
76
+ bulk_data.sources.members.sort.each do |source_name|
77
+ source = Source.load(source_name,{:app_id => bulk_data.app_id,
78
+ :user_id => bulk_data.user_id})
79
+ source.source_id = src_counter
80
+ src_counter += 1
81
+ source_attrib_refs = import_data_to_object_values(db,source)
82
+ sources_refs[source_name] =
83
+ {:source => source, :refs => source_attrib_refs}
84
+ end
85
+ populate_sources_table(db,sources_refs)
86
+ db.execute_batch(File.open(index,'r').read)
87
+ end
88
+
89
+ def self.create_hsql_data_file(bulk_data,ts)
90
+ schema,index,dbfile = get_file_args(bulk_data.name,ts)
91
+ hsql_file = dbfile + ".hsqldb"
92
+ raise Exception.new("Error running hsqldata") unless
93
+ system('java','-cp', File.join(File.dirname(__FILE__),'..','..','..','vendor','hsqldata.jar'),
94
+ 'com.rhomobile.hsqldata.HsqlData', dbfile, hsql_file, schema, index)
95
+ end
96
+
97
+ def self.get_file_args(bulk_data_name,ts)
98
+ schema = BulkData.schema_file
99
+ index = BulkData.index_file
100
+ dbfile = File.join(Rhosync.data_directory,bulk_data_name+'_'+ts+'.data')
101
+ [schema,index,dbfile]
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,19 @@
1
+ require 'rhosync/ping'
2
+
3
+ module Rhosync
4
+ module PingJob
5
+ @queue = :ping
6
+
7
+ # Perform a ping for all clients registered to a user
8
+ def self.perform(params)
9
+ user = User.load(params["user_id"])
10
+ user.clients.members.each do |client_id|
11
+ client = Client.load(client_id,{:source_name => '*'})
12
+ params.merge!('device_port' => client.device_port,
13
+ 'device_pin' => client.device_pin)
14
+ klass = Object.const_get(camelize(client.device_type.downcase))
15
+ klass.ping(params) if klass
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ module Rhosync
2
+ class SourceJob
3
+ class << self
4
+ attr_accessor :queue
5
+ end
6
+
7
+ def self.perform(job_type,source_id,app_id,user_id,client_id,params)
8
+ source = Source.load(source_id,{:app_id => app_id,:user_id => user_id})
9
+ source_sync = SourceSync.new(source)
10
+ case job_type.to_sym
11
+ when :query then source_sync.do_query(params)
12
+ when :cud then source_sync.do_cud(client_id)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,79 @@
1
+ require 'openssl'
2
+
3
+ module Rhosync
4
+ class LicenseException < RuntimeError; end
5
+ class LicenseSeatsExceededException < LicenseException; end
6
+
7
+ class License
8
+ attr_reader :rhosync_version, :licensee, :seats, :issued
9
+ #attr_accessor :license
10
+
11
+ # ships with rhosync
12
+ RHO_PUBLICKEY = "99068e3a2708e6fe918252be8880eac539a1d2b2402651d75de5c7a2333a1cb2"
13
+ CLIENT_DOCKEY = 'rho_client_count'
14
+
15
+ def initialize
16
+ begin
17
+ settings = Rhosync.get_config(Rhosync.base_directory)[Rhosync.environment]
18
+ @license = IO.read(File.join(Rhosync.base_directory,settings[:licensefile])).strip
19
+ _decrypt
20
+ rescue Exception => e
21
+ #puts e.backtrace.join('\n')
22
+ raise LicenseException.new("Error verifying license.")
23
+ end
24
+ end
25
+
26
+ def check_and_use_seat
27
+ incr = false
28
+ Store.lock(CLIENT_DOCKEY) do
29
+ current = Store.get_value(CLIENT_DOCKEY)
30
+ current = current ? current.to_i : 0
31
+ if current < self.seats
32
+ Store.put_value CLIENT_DOCKEY, current + 1
33
+ incr = true
34
+ end
35
+ end
36
+ unless incr
37
+ msg = "WARNING: Maximum # of clients exceeded for this license."
38
+ log msg; raise LicenseSeatsExceededException.new(msg)
39
+ end
40
+ end
41
+
42
+ def free_seat
43
+ Store.lock(CLIENT_DOCKEY) do
44
+ current = Store.get_value(CLIENT_DOCKEY)
45
+ current = current ? current.to_i : 0
46
+ if current > 0
47
+ Store.put_value CLIENT_DOCKEY, current - 1
48
+ end
49
+ end
50
+ end
51
+
52
+ def available
53
+ current = Store.get_value(CLIENT_DOCKEY)
54
+ current = current ? current.to_i : 0
55
+ available = self.seats - current
56
+ available > 0 ? available : 0
57
+ end
58
+
59
+ private
60
+
61
+ def _decrypt
62
+ cipher = OpenSSL::Cipher::Cipher.new("aes-256-ecb")
63
+ cipher.key = _extract_str(RHO_PUBLICKEY)
64
+ cipher.decrypt
65
+
66
+ decrypted = cipher.update(_extract_str(@license))
67
+ decrypted << cipher.final
68
+ parts = decrypted.split(',')
69
+ @rhosync_version = parts[0].strip
70
+ @licensee = parts[1].strip
71
+ @seats = parts[2].strip.to_i
72
+ @issued = parts[3].strip
73
+ end
74
+
75
+ def _extract_str(str)
76
+ str.gsub(/(..)/){|h| h.hex.chr}
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,11 @@
1
+
2
+ # Collection of methods for locking shared
3
+ # source documents when source_sync and client_sync
4
+ # need to access them
5
+ module LockOps
6
+ def lock(doc)
7
+ Store.lock(docname(doc)) do
8
+ yield self
9
+ end
10
+ end
11
+ end