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.
- data/CHANGELOG +5 -0
- data/LICENSE +674 -0
- data/README.md +26 -0
- data/Rakefile +109 -0
- data/bench/bench +6 -0
- data/bench/benchapp/Rakefile +14 -0
- data/bench/benchapp/application.rb +13 -0
- data/bench/benchapp/config.ru +32 -0
- data/bench/benchapp/settings/license.key +1 -0
- data/bench/benchapp/settings/settings.yml +18 -0
- data/bench/benchapp/sources/mock_adapter.rb +55 -0
- data/bench/benchapp/sources/queue_mock_adapter.rb +2 -0
- data/bench/benchapp/vendor/rhosync/lib/rhosync.rb +7 -0
- data/bench/lib/bench/cli.rb +16 -0
- data/bench/lib/bench/logging.rb +18 -0
- data/bench/lib/bench/mock_client.rb +41 -0
- data/bench/lib/bench/result.rb +50 -0
- data/bench/lib/bench/runner.rb +44 -0
- data/bench/lib/bench/session.rb +65 -0
- data/bench/lib/bench/statistics.rb +56 -0
- data/bench/lib/bench/test_data.rb +55 -0
- data/bench/lib/bench/timer.rb +10 -0
- data/bench/lib/bench/utils.rb +49 -0
- data/bench/lib/bench.rb +128 -0
- data/bench/lib/testdata/100-data.txt +148 -0
- data/bench/lib/testdata/5-data.txt +11 -0
- data/bench/scripts/cud_script.rb +77 -0
- data/bench/scripts/helpers.rb +101 -0
- data/bench/scripts/query_md_script.rb +46 -0
- data/bench/scripts/query_script.rb +46 -0
- data/bench/spec/bench_spec_helper.rb +65 -0
- data/bench/spec/logging_spec.rb +19 -0
- data/bench/spec/mock_adapter_spec.rb +61 -0
- data/bench/spec/mock_client_spec.rb +64 -0
- data/bench/spec/result_spec.rb +59 -0
- data/bench/spec/utils_spec.rb +35 -0
- data/bin/rhosync +34 -0
- data/doc/protocol.html +1901 -0
- data/doc/public/css/print.css +29 -0
- data/doc/public/css/screen.css +257 -0
- data/doc/public/css/style.css +20 -0
- data/examples/simple/application.rb +13 -0
- data/examples/simple/sources/sample_adapter.rb +5 -0
- data/examples/simple/sources/simple_adapter.rb +5 -0
- data/examples/simple/vendor/rhosync/lib/rhosync.rb +7 -0
- data/generators/rhosync.rb +98 -0
- data/generators/templates/application/Rakefile +19 -0
- data/generators/templates/application/application.rb +27 -0
- data/generators/templates/application/config.ru +33 -0
- data/generators/templates/application/settings/license.key +1 -0
- data/generators/templates/application/settings/settings.yml +14 -0
- data/generators/templates/source/source_adapter.rb +49 -0
- data/lib/rhosync/api/create_client.rb +3 -0
- data/lib/rhosync/api/create_user.rb +7 -0
- data/lib/rhosync/api/delete_client.rb +5 -0
- data/lib/rhosync/api/delete_user.rb +5 -0
- data/lib/rhosync/api/get_api_token.rb +7 -0
- data/lib/rhosync/api/get_client_params.rb +3 -0
- data/lib/rhosync/api/get_db_doc.rb +7 -0
- data/lib/rhosync/api/get_license_info.rb +7 -0
- data/lib/rhosync/api/get_source_params.rb +3 -0
- data/lib/rhosync/api/list_client_docs.rb +12 -0
- data/lib/rhosync/api/list_clients.rb +3 -0
- data/lib/rhosync/api/list_source_docs.rb +10 -0
- data/lib/rhosync/api/list_sources.rb +15 -0
- data/lib/rhosync/api/list_users.rb +3 -0
- data/lib/rhosync/api/ping.rb +7 -0
- data/lib/rhosync/api/push_deletes.rb +6 -0
- data/lib/rhosync/api/push_objects.rb +6 -0
- data/lib/rhosync/api/reset.rb +10 -0
- data/lib/rhosync/api/set_db_doc.rb +8 -0
- data/lib/rhosync/api/set_refresh_time.rb +8 -0
- data/lib/rhosync/api/update_user.rb +4 -0
- data/lib/rhosync/api/upload_file.rb +4 -0
- data/lib/rhosync/api_token.rb +19 -0
- data/lib/rhosync/app.rb +69 -0
- data/lib/rhosync/bulk_data/bulk_data.rb +75 -0
- data/lib/rhosync/bulk_data/syncdb.index.schema +3 -0
- data/lib/rhosync/bulk_data/syncdb.schema +37 -0
- data/lib/rhosync/bulk_data.rb +2 -0
- data/lib/rhosync/client.rb +74 -0
- data/lib/rhosync/client_sync.rb +296 -0
- data/lib/rhosync/console/app/helpers/auth_helper.rb +18 -0
- data/lib/rhosync/console/app/helpers/extensions.rb +19 -0
- data/lib/rhosync/console/app/helpers/helpers.rb +52 -0
- data/lib/rhosync/console/app/public/main.css +7 -0
- data/lib/rhosync/console/app/public/text.txt +0 -0
- data/lib/rhosync/console/app/routes/auth.rb +29 -0
- data/lib/rhosync/console/app/routes/client.rb +32 -0
- data/lib/rhosync/console/app/routes/docs.rb +84 -0
- data/lib/rhosync/console/app/routes/home.rb +22 -0
- data/lib/rhosync/console/app/routes/user.rb +63 -0
- data/lib/rhosync/console/app/views/client.erb +30 -0
- data/lib/rhosync/console/app/views/doc.erb +56 -0
- data/lib/rhosync/console/app/views/docs.erb +29 -0
- data/lib/rhosync/console/app/views/index.erb +50 -0
- data/lib/rhosync/console/app/views/layout.erb +12 -0
- data/lib/rhosync/console/app/views/newuser.erb +17 -0
- data/lib/rhosync/console/app/views/ping.erb +28 -0
- data/lib/rhosync/console/app/views/result.erb +11 -0
- data/lib/rhosync/console/app/views/user.erb +32 -0
- data/lib/rhosync/console/app/views/users.erb +14 -0
- data/lib/rhosync/console/rhosync_api.rb +102 -0
- data/lib/rhosync/console/server.rb +27 -0
- data/lib/rhosync/credential.rb +9 -0
- data/lib/rhosync/document.rb +43 -0
- data/lib/rhosync/indifferent_access.rb +132 -0
- data/lib/rhosync/jobs/bulk_data_job.rb +104 -0
- data/lib/rhosync/jobs/ping_job.rb +19 -0
- data/lib/rhosync/jobs/source_job.rb +16 -0
- data/lib/rhosync/license.rb +79 -0
- data/lib/rhosync/lock_ops.rb +11 -0
- data/lib/rhosync/model.rb +410 -0
- data/lib/rhosync/ping/blackberry.rb +55 -0
- data/lib/rhosync/ping/iphone.rb +44 -0
- data/lib/rhosync/ping.rb +2 -0
- data/lib/rhosync/read_state.rb +27 -0
- data/lib/rhosync/server/views/index.erb +12 -0
- data/lib/rhosync/server.rb +242 -0
- data/lib/rhosync/source.rb +112 -0
- data/lib/rhosync/source_adapter.rb +95 -0
- data/lib/rhosync/source_sync.rb +245 -0
- data/lib/rhosync/store.rb +199 -0
- data/lib/rhosync/tasks.rb +151 -0
- data/lib/rhosync/user.rb +83 -0
- data/lib/rhosync/version.rb +3 -0
- data/lib/rhosync.rb +251 -0
- data/spec/api/api_helper.rb +44 -0
- data/spec/api/create_client_spec.rb +13 -0
- data/spec/api/create_user_spec.rb +16 -0
- data/spec/api/delete_client_spec.rb +13 -0
- data/spec/api/delete_user_spec.rb +18 -0
- data/spec/api/get_api_token_spec.rb +25 -0
- data/spec/api/get_client_params_spec.rb +18 -0
- data/spec/api/get_db_doc_spec.rb +21 -0
- data/spec/api/get_license_info_spec.rb +16 -0
- data/spec/api/get_source_params_spec.rb +26 -0
- data/spec/api/list_client_docs_spec.rb +33 -0
- data/spec/api/list_clients_spec.rb +23 -0
- data/spec/api/list_source_docs_spec.rb +26 -0
- data/spec/api/list_sources_spec.rb +27 -0
- data/spec/api/list_users_spec.rb +21 -0
- data/spec/api/ping_spec.rb +24 -0
- data/spec/api/push_deletes_spec.rb +16 -0
- data/spec/api/push_objects_spec.rb +27 -0
- data/spec/api/reset_spec.rb +22 -0
- data/spec/api/set_db_doc_spec.rb +20 -0
- data/spec/api/set_refresh_time_spec.rb +43 -0
- data/spec/api/update_user_spec.rb +31 -0
- data/spec/api/upload_file_spec.rb +26 -0
- data/spec/api_token_spec.rb +13 -0
- data/spec/app_spec.rb +20 -0
- data/spec/apps/rhotestapp/Rakefile +1 -0
- data/spec/apps/rhotestapp/application.rb +16 -0
- data/spec/apps/rhotestapp/config.ru +1 -0
- data/spec/apps/rhotestapp/settings/apple_fake_cert.pem +1 -0
- data/spec/apps/rhotestapp/settings/license.key +1 -0
- data/spec/apps/rhotestapp/settings/settings.yml +23 -0
- data/spec/apps/rhotestapp/sources/base_adapter.rb +9 -0
- data/spec/apps/rhotestapp/sources/sample_adapter.rb +66 -0
- data/spec/apps/rhotestapp/sources/simple_adapter.rb +39 -0
- data/spec/apps/rhotestapp/sources/sub_adapter.rb +7 -0
- data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem/mygem.rb +8 -0
- data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem.rb +1 -0
- data/spec/bulk_data/bulk_data_spec.rb +79 -0
- data/spec/client_spec.rb +58 -0
- data/spec/client_sync_spec.rb +377 -0
- data/spec/doc/base.html +72 -0
- data/spec/doc/doc_spec.rb +303 -0
- data/spec/doc/footer.html +4 -0
- data/spec/doc/header.html +30 -0
- data/spec/document_spec.rb +27 -0
- data/spec/generator/generator_spec.rb +53 -0
- data/spec/generator/generator_spec_helper.rb +8 -0
- data/spec/jobs/bulk_data_job_spec.rb +76 -0
- data/spec/jobs/ping_job_spec.rb +26 -0
- data/spec/jobs/source_job_spec.rb +25 -0
- data/spec/license_spec.rb +48 -0
- data/spec/model_spec.rb +269 -0
- data/spec/perf/bulk_data_perf_spec.rb +33 -0
- data/spec/perf/perf_spec_helper.rb +51 -0
- data/spec/perf/store_perf_spec.rb +28 -0
- data/spec/ping/blackberry_spec.rb +62 -0
- data/spec/ping/iphone_spec.rb +50 -0
- data/spec/read_state_spec.rb +25 -0
- data/spec/rhosync_spec.rb +43 -0
- data/spec/server/server_spec.rb +341 -0
- data/spec/source_adapter_spec.rb +114 -0
- data/spec/source_spec.rb +77 -0
- data/spec/source_sync_spec.rb +248 -0
- data/spec/spec_helper.rb +240 -0
- data/spec/store_spec.rb +149 -0
- data/spec/sync_states_spec.rb +101 -0
- data/spec/testdata/1000-data.txt +1414 -0
- data/spec/testdata/compressed/compress-data.txt +1 -0
- data/spec/testdata/upload1.txt +1 -0
- data/spec/testdata/upload2.txt +1 -0
- data/spec/user_spec.rb +79 -0
- data/tasks/redis.rake +134 -0
- 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,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
|