splitclient-rb 4.5.1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +45 -0
- data/CHANGES.txt +147 -0
- data/Detailed-README.md +571 -0
- data/Gemfile +4 -0
- data/LICENSE +13 -0
- data/NEWS +75 -0
- data/README.md +43 -0
- data/Rakefile +24 -0
- data/exe/splitio +96 -0
- data/ext/murmurhash/MurmurHash3.java +162 -0
- data/lib/murmurhash/base.rb +58 -0
- data/lib/murmurhash/murmurhash.jar +0 -0
- data/lib/murmurhash/murmurhash_mri.rb +3 -0
- data/lib/splitclient-rb.rb +90 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapter.rb +12 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb +133 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/queue_adapter.rb +44 -0
- data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +165 -0
- data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +30 -0
- data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +29 -0
- data/lib/splitclient-rb/cache/repositories/events_repository.rb +41 -0
- data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +49 -0
- data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +78 -0
- data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +21 -0
- data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +129 -0
- data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +98 -0
- data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +22 -0
- data/lib/splitclient-rb/cache/repositories/repository.rb +23 -0
- data/lib/splitclient-rb/cache/repositories/segments_repository.rb +82 -0
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +106 -0
- data/lib/splitclient-rb/cache/routers/impression_router.rb +52 -0
- data/lib/splitclient-rb/cache/senders/events_sender.rb +47 -0
- data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +73 -0
- data/lib/splitclient-rb/cache/senders/impressions_sender.rb +67 -0
- data/lib/splitclient-rb/cache/senders/metrics_sender.rb +49 -0
- data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +48 -0
- data/lib/splitclient-rb/cache/stores/segment_store.rb +82 -0
- data/lib/splitclient-rb/cache/stores/split_store.rb +97 -0
- data/lib/splitclient-rb/clients/localhost_split_client.rb +92 -0
- data/lib/splitclient-rb/clients/split_client.rb +214 -0
- data/lib/splitclient-rb/engine/api/client.rb +74 -0
- data/lib/splitclient-rb/engine/api/events.rb +48 -0
- data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +55 -0
- data/lib/splitclient-rb/engine/api/impressions.rb +42 -0
- data/lib/splitclient-rb/engine/api/metrics.rb +61 -0
- data/lib/splitclient-rb/engine/api/segments.rb +62 -0
- data/lib/splitclient-rb/engine/api/splits.rb +60 -0
- data/lib/splitclient-rb/engine/evaluator/splitter.rb +123 -0
- data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +46 -0
- data/lib/splitclient-rb/engine/matchers/between_matcher.rb +56 -0
- data/lib/splitclient-rb/engine/matchers/combiners.rb +9 -0
- data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +86 -0
- data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +21 -0
- data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +19 -0
- data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +30 -0
- data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +20 -0
- data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +26 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +27 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +54 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +19 -0
- data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +53 -0
- data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +53 -0
- data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +24 -0
- data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +60 -0
- data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +23 -0
- data/lib/splitclient-rb/engine/matchers/set_matcher.rb +20 -0
- data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +26 -0
- data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +45 -0
- data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +66 -0
- data/lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb +128 -0
- data/lib/splitclient-rb/engine/metrics/metrics.rb +83 -0
- data/lib/splitclient-rb/engine/models/label.rb +8 -0
- data/lib/splitclient-rb/engine/models/split.rb +17 -0
- data/lib/splitclient-rb/engine/models/treatment.rb +3 -0
- data/lib/splitclient-rb/engine/parser/condition.rb +210 -0
- data/lib/splitclient-rb/engine/parser/evaluator.rb +118 -0
- data/lib/splitclient-rb/engine/parser/partition.rb +35 -0
- data/lib/splitclient-rb/engine/parser/split_adapter.rb +88 -0
- data/lib/splitclient-rb/exceptions/impressions_shutdown_exception.rb +4 -0
- data/lib/splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception.rb +4 -0
- data/lib/splitclient-rb/localhost_split_factory.rb +13 -0
- data/lib/splitclient-rb/localhost_utils.rb +36 -0
- data/lib/splitclient-rb/managers/localhost_split_manager.rb +45 -0
- data/lib/splitclient-rb/managers/split_manager.rb +77 -0
- data/lib/splitclient-rb/split_config.rb +391 -0
- data/lib/splitclient-rb/split_factory.rb +35 -0
- data/lib/splitclient-rb/split_factory_builder.rb +16 -0
- data/lib/splitclient-rb/utilitites.rb +41 -0
- data/lib/splitclient-rb/version.rb +3 -0
- data/splitclient-rb.gemspec +50 -0
- data/splitio.yml.example +7 -0
- data/tasks/benchmark_get_treatment.rake +43 -0
- data/tasks/irb.rake +4 -0
- data/tasks/rspec.rake +3 -0
- metadata +321 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2016 Split Software, Co.
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/NEWS
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
4.5.0
|
2
|
+
|
3
|
+
Add JRuby support
|
4
|
+
|
5
|
+
4.4.0
|
6
|
+
|
7
|
+
Add the ability to send event data to split service (.track() api)
|
8
|
+
|
9
|
+
4.3.0
|
10
|
+
|
11
|
+
Add support for impression listener, there is an ability to use user-defined class to capture all impressions
|
12
|
+
Now you can apply attribute matcher to the traffic type
|
13
|
+
|
14
|
+
4.2.0
|
15
|
+
|
16
|
+
Introduce new matchers: boolean and regexp (string).
|
17
|
+
Remove unneeded dependencies
|
18
|
+
Introduce dependency matcher, which allows treatment of one split to depend on the evaluation of another.
|
19
|
+
|
20
|
+
4.1.0
|
21
|
+
|
22
|
+
Introduce set matchers: part of set, contains all and contains any, starts with, ends with and contains.
|
23
|
+
|
24
|
+
4.0.0
|
25
|
+
|
26
|
+
Add support for murmur3 hashing algorithm
|
27
|
+
Optimize gem memory usage
|
28
|
+
|
29
|
+
3.3.0
|
30
|
+
|
31
|
+
Add support for traffic allocation
|
32
|
+
|
33
|
+
3.1.0
|
34
|
+
|
35
|
+
Now supporting Redis as a cache adapter
|
36
|
+
Factory is build now as SplitIoClient::SplitFactoryBuilder.build('<API_KEY>')
|
37
|
+
|
38
|
+
3.0.2
|
39
|
+
|
40
|
+
now support also client.get_treatment( { :matching_key = 'bb' , "bucketing_key = ''}, ....)
|
41
|
+
|
42
|
+
2.0.1
|
43
|
+
|
44
|
+
No news for this release
|
45
|
+
|
46
|
+
2.0.0
|
47
|
+
|
48
|
+
Instantiation of the split client is now through a factory:
|
49
|
+
|
50
|
+
factory = SplitIoClient::SplitFactory.new("rbk5je8be5qflpa047m17fe4ra", options)
|
51
|
+
client = factory.client
|
52
|
+
manager = factory.manager
|
53
|
+
|
54
|
+
1.0.4
|
55
|
+
|
56
|
+
Added AND combiner for conditions support. Added events_uri config param which is the url where the metrics post are send to.
|
57
|
+
|
58
|
+
1.0.3
|
59
|
+
|
60
|
+
This version of the gem fixes two minor bugs related to the config option for the refresh rates, as well as an inconsistency for the split definitions that are not created from the web app, but directly from the api instead.
|
61
|
+
|
62
|
+
1.0.2
|
63
|
+
|
64
|
+
Support for all the new matchers including: number comparison with >=, <=, =, between; date comparison with is on or before, is on or after, is on, between; attribute value in a defined set of values.
|
65
|
+
No other major updates for this release.
|
66
|
+
|
67
|
+
1.0.1
|
68
|
+
|
69
|
+
isTreatment was removed from the API
|
70
|
+
local environment file was removed to match the rest of the SDKs. "split".
|
71
|
+
No other major updates for this release.
|
72
|
+
|
73
|
+
1.0.0
|
74
|
+
|
75
|
+
No news for this release.
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
[ ![Codeship Status for splitio/ruby-client](https://app.codeship.com/projects/306c6b60-c164-0133-e179-16471d4e6045/status?branch=master)](https://app.codeship.com/projects/137510)
|
2
|
+
|
3
|
+
# Split Ruby SDK
|
4
|
+
|
5
|
+
This SDK is designed to work with [Split](https://www.split.io), the platform for controlled rollouts, serving features to your users via the Split feature flag to manage your complete customer experience.
|
6
|
+
|
7
|
+
### Quick setup
|
8
|
+
|
9
|
+
For specific instructions on how to set up the Split SDK refer to our [Detailed-README](Detailed-README.md) or our [official SDK documentation](http://docs.split.io/docs/sdk-overview).
|
10
|
+
|
11
|
+
### Commitment to Quality:
|
12
|
+
|
13
|
+
Split’s SDKs are in active development and are constantly tested for quality. Unit tests are developed for each SDK based on the unique needs of that language, and integration tests, load and performance tests, and behavior consistency tests are running 24/7 via automated bots. In addition, monitoring instrumentation ensures that these SDKs behave under the expected parameters of memory, CPU, and I/O.
|
14
|
+
|
15
|
+
### About Split:
|
16
|
+
|
17
|
+
Split is the leading platform for feature experimentation, empowering businesses of all sizes to make smarter product decisions. Companies like Vevo, Twilio, and LendingTree rely on Split to securely release new features, target them to customers, and measure the impact of features on their customer experience metrics. Founded in 2015, Split's team comes from some of the most innovative enterprises in Silicon Valley, including Google, LinkedIn, Salesforce and Databricks. Split is based in Redwood City, California and backed by Accel Partners and Lightspeed Venture Partners.
|
18
|
+
|
19
|
+
Our platform is a unified solution for continuous delivery and full-stack experimentation. Split unifies DevOps and product management, helping agile engineering and product teams accelerate the pace of product delivery and make data-driven decisions, through our robust feature flagging and extensive experimentation capabilities. With Split, organizations can now accelerate time to value, mitigate risk, and drive better outcomes, all in a unified platform.
|
20
|
+
|
21
|
+
To learn more about Split, contact hello@split.io, or start a 14-day trial at https://www.split.io/signup/.
|
22
|
+
|
23
|
+
Split has built and maintains a SDKs for:
|
24
|
+
|
25
|
+
* Java [Github](https://github.com/splitio/java-client) [Docs](http://docs.split.io/docs/java-sdk-guide)
|
26
|
+
* Javascript [Github](https://github.com/splitio/javascript-client) [Docs](http://docs.split.io/docs/javascript-sdk-overview)
|
27
|
+
* Node [Github](https://github.com/splitio/javascript-client) [Docs](http://docs.split.io/docs/nodejs-sdk-overview)
|
28
|
+
* .NET [Github](https://github.com/splitio/.net-client) [Docs](http://docs.split.io/docs/net-sdk-overview)
|
29
|
+
* Ruby [Github](https://github.com/splitio/ruby-client) [Docs](http://docs.split.io/docs/ruby-sdk-overview)
|
30
|
+
* PHP [Github](https://github.com/splitio/php-client) [Docs](http://docs.split.io/docs/php-sdk-overview)
|
31
|
+
* Python [Github](https://github.com/splitio/python-client) [Docs](http://docs.split.io/docs/python-sdk-overview)
|
32
|
+
* GO [Github](https://github.com/splitio/go-client) [Docs](http://docs.split.io/docs/go-sdk-overview)
|
33
|
+
* Android [Github](https://github.com/splitio/android-client) [Docs](https://docs.split.io/v1/docs/android-sdk-overview)
|
34
|
+
|
35
|
+
For a comprehensive list of opensource projects visit our [Github page](https://github.com/splitio?utf8=%E2%9C%93&query=%20only%3Apublic%20).
|
36
|
+
|
37
|
+
**Learn more about Split:**
|
38
|
+
|
39
|
+
Visit [split.io/product](https://www.split.io/product) for an overview of Split, or visit our documentation at [docs.split.io](http://docs.split.io) for more detailed information.
|
40
|
+
|
41
|
+
**System Status:**
|
42
|
+
|
43
|
+
We use a status page to monitor the availability of Split’s various services. You can check the current status at [status.split.io](http://status.split.io).
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
Dir['tasks/**/*.rake'].each { |rake| load rake }
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
|
8
|
+
task :spec => :compile
|
9
|
+
case RUBY_PLATFORM
|
10
|
+
when 'java'
|
11
|
+
require 'rake/javaextensiontask'
|
12
|
+
Rake::JavaExtensionTask.new 'murmurhash' do |ext|
|
13
|
+
ext.lib_dir = 'lib/murmurhash'
|
14
|
+
ext.target_version = '1.7'
|
15
|
+
ext.source_version = '1.7'
|
16
|
+
end
|
17
|
+
else
|
18
|
+
require 'rake/extensiontask'
|
19
|
+
Rake::ExtensionTask.new 'murmurhash' do |ext|
|
20
|
+
ext.lib_dir = 'lib/murmurhash'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
task :default => :spec
|
data/exe/splitio
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
lib = File.expand_path('../../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'optparse'
|
7
|
+
require 'yaml'
|
8
|
+
require_relative '../lib/splitclient-rb'
|
9
|
+
|
10
|
+
# ARGV << '-h' if ARGV.empty?
|
11
|
+
|
12
|
+
config_path = ''
|
13
|
+
options = {}
|
14
|
+
opt_parser = OptionParser.new do |opts|
|
15
|
+
opts.banner = "Usage: splitio [options]"
|
16
|
+
|
17
|
+
opts.on("-cPATH", "--config=PATH", "Set the path to splitio.yml config file") do |c|
|
18
|
+
config_path = c
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on("--base-uri=BASE_URI", "Set the base uri for Split SDK") do |c|
|
22
|
+
options[:base_uri] = c
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("--events-uri=EVENTS_URI", "Set the events uri for Split SDK") do |c|
|
26
|
+
options[:events_uri] = c
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("--api-key=API_KEY", "Set the API Key for Split SDK") do |c|
|
30
|
+
options[:api_key] = c
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on("--read-timeout=READ_TIMEOUT", "Read timeout in seconds") do |c|
|
34
|
+
options[:read_timeout] = c
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on("--connection-timeout=CONNECTION_TIMEOUT", "Connection timeout in seconds") do |c|
|
38
|
+
options[:connection_timeout] = c
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on("--features-refresh-rate=FEATURES_REFRESH_RATE", "Features refresh rate in seconds") do |c|
|
42
|
+
options[:features_refresh_rate] = c
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on("--segments-refresh-rate=SEGMENTS_REFRESH_RATE", "Segments refresh rate in seconds") do |c|
|
46
|
+
options[:segments_refresh_rate] = c
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on("--metrics-refresh-rate=METRICS_REFRESH_RATE", "Metrics refresh rate in seconds") do |c|
|
50
|
+
options[:metrics_refresh_rate] = c
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on("--impressions-refresh-rate=IMPRESSIONS_REFRESH_RATE", "Impressions refresh rate in seconds") do |c|
|
54
|
+
options[:impressions_refresh_rate] = c
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.on("--ready=SECONDS", "Seconds to block the app until SDK is ready or false to run in non-blocking mode") do |c|
|
58
|
+
options[:ready] = c
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on("--redis-url=REDIS_URL", "Set base uri for Split SDK") do |c|
|
62
|
+
options[:redis_url] = c
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on("--transport-debug", "Enable transport debug") do
|
66
|
+
options[:transport_debug_enabled] = true
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("-d", "--debug", "Enable debug mode") do
|
70
|
+
options[:debug_enabled] = true
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on_tail("-h", "--help", "Prints this help") do
|
74
|
+
puts opts
|
75
|
+
exit
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
begin
|
80
|
+
opt_parser.parse!(ARGV)
|
81
|
+
rescue OptionParser::InvalidOption => e
|
82
|
+
puts e
|
83
|
+
puts opt_parser
|
84
|
+
exit(1)
|
85
|
+
end
|
86
|
+
|
87
|
+
config = config_path != '' ? YAML.load_file(config_path) : {}
|
88
|
+
config
|
89
|
+
.merge!(mode: :producer, cache_adapter: :redis)
|
90
|
+
.merge!(options)
|
91
|
+
.merge!(api_key: ENV['API_KEY'] || config[:api_key])
|
92
|
+
.merge!(base_uri: ENV['SDK_URI'] || config[:base_uri])
|
93
|
+
.merge!(events_uri: ENV['EVENTS_URI'] || config[:events_uri])
|
94
|
+
# IDENTIFY_BASE_URI
|
95
|
+
|
96
|
+
SplitIoClient::SplitFactory.new(config[:api_key], config)
|
@@ -0,0 +1,162 @@
|
|
1
|
+
/**
|
2
|
+
* The MurmurHash3 algorithm was created by Austin Appleby and placed in the public domain.
|
3
|
+
* This java port was authored by Yonik Seeley and also placed into the public domain.
|
4
|
+
* The author hereby disclaims copyright to this source code.
|
5
|
+
* <p>
|
6
|
+
* This produces exactly the same hash values as the final C++
|
7
|
+
* version of MurmurHash3 and is thus suitable for producing the same hash values across
|
8
|
+
* platforms.
|
9
|
+
* <p>
|
10
|
+
* The 32 bit x86 version of this hash should be the fastest variant for relatively short keys like ids.
|
11
|
+
* murmurhash3_x64_128 is a good choice for longer strings or if you need more than 32 bits of hash.
|
12
|
+
* <p>
|
13
|
+
* Note - The x86 and x64 versions do _not_ produce the same results, as the
|
14
|
+
* algorithms are optimized for their respective platforms.
|
15
|
+
* <p>
|
16
|
+
* See http://github.com/yonik/java_util for future updates to this file.
|
17
|
+
*/
|
18
|
+
public final class MurmurHash3 {
|
19
|
+
|
20
|
+
/**
|
21
|
+
* 128 bits of state
|
22
|
+
*/
|
23
|
+
public static final class LongPair {
|
24
|
+
public long val1;
|
25
|
+
public long val2;
|
26
|
+
}
|
27
|
+
|
28
|
+
public static final int fmix32(int h) {
|
29
|
+
h ^= h >>> 16;
|
30
|
+
h *= 0x85ebca6b;
|
31
|
+
h ^= h >>> 13;
|
32
|
+
h *= 0xc2b2ae35;
|
33
|
+
h ^= h >>> 16;
|
34
|
+
return h;
|
35
|
+
}
|
36
|
+
|
37
|
+
public static final long fmix64(long k) {
|
38
|
+
k ^= k >>> 33;
|
39
|
+
k *= 0xff51afd7ed558ccdL;
|
40
|
+
k ^= k >>> 33;
|
41
|
+
k *= 0xc4ceb9fe1a85ec53L;
|
42
|
+
k ^= k >>> 33;
|
43
|
+
return k;
|
44
|
+
}
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Gets a long from a byte buffer in little endian byte order.
|
48
|
+
*/
|
49
|
+
public static final long getLongLittleEndian(byte[] buf, int offset) {
|
50
|
+
return ((long) buf[offset + 7] << 56) // no mask needed
|
51
|
+
| ((buf[offset + 6] & 0xffL) << 48)
|
52
|
+
| ((buf[offset + 5] & 0xffL) << 40)
|
53
|
+
| ((buf[offset + 4] & 0xffL) << 32)
|
54
|
+
| ((buf[offset + 3] & 0xffL) << 24)
|
55
|
+
| ((buf[offset + 2] & 0xffL) << 16)
|
56
|
+
| ((buf[offset + 1] & 0xffL) << 8)
|
57
|
+
| ((buf[offset] & 0xffL)); // no shift needed
|
58
|
+
}
|
59
|
+
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Returns the MurmurHash3_x86_32 hash of the UTF-8 bytes of the String without actually encoding
|
63
|
+
* the string to a temporary buffer. This is more than 2x faster than hashing the result
|
64
|
+
* of String.getBytes().
|
65
|
+
*/
|
66
|
+
public static long murmurhash3_x86_32(CharSequence data, int seed) {
|
67
|
+
final int c1 = 0xcc9e2d51;
|
68
|
+
final int c2 = 0x1b873593;
|
69
|
+
|
70
|
+
int h1 = seed;
|
71
|
+
|
72
|
+
int offset = 0;
|
73
|
+
int len = data.length();
|
74
|
+
int pos = offset;
|
75
|
+
int end = offset + len;
|
76
|
+
int k1 = 0;
|
77
|
+
int k2 = 0;
|
78
|
+
int shift = 0;
|
79
|
+
int bits = 0;
|
80
|
+
int nBytes = 0; // length in UTF8 bytes
|
81
|
+
|
82
|
+
|
83
|
+
while (pos < end) {
|
84
|
+
int code = data.charAt(pos++);
|
85
|
+
if (code < 0x80) {
|
86
|
+
k2 = code;
|
87
|
+
bits = 8;
|
88
|
+
|
89
|
+
} else if (code < 0x800) {
|
90
|
+
k2 = (0xC0 | (code >> 6))
|
91
|
+
| ((0x80 | (code & 0x3F)) << 8);
|
92
|
+
bits = 16;
|
93
|
+
} else if (code < 0xD800 || code > 0xDFFF || pos >= end) {
|
94
|
+
// we check for pos>=end to encode an unpaired surrogate as 3 bytes.
|
95
|
+
k2 = (0xE0 | (code >> 12))
|
96
|
+
| ((0x80 | ((code >> 6) & 0x3F)) << 8)
|
97
|
+
| ((0x80 | (code & 0x3F)) << 16);
|
98
|
+
bits = 24;
|
99
|
+
} else {
|
100
|
+
// surrogate pair
|
101
|
+
// int utf32 = pos < end ? (int) data.charAt(pos++) : 0;
|
102
|
+
int utf32 = (int) data.charAt(pos++);
|
103
|
+
utf32 = ((code - 0xD7C0) << 10) + (utf32 & 0x3FF);
|
104
|
+
k2 = (0xff & (0xF0 | (utf32 >> 18)))
|
105
|
+
| ((0x80 | ((utf32 >> 12) & 0x3F))) << 8
|
106
|
+
| ((0x80 | ((utf32 >> 6) & 0x3F))) << 16
|
107
|
+
| (0x80 | (utf32 & 0x3F)) << 24;
|
108
|
+
bits = 32;
|
109
|
+
}
|
110
|
+
|
111
|
+
|
112
|
+
k1 |= k2 << shift;
|
113
|
+
|
114
|
+
// int used_bits = 32 - shift; // how many bits of k2 were used in k1.
|
115
|
+
// int unused_bits = bits - used_bits; // (bits-(32-shift)) == bits+shift-32 == bits-newshift
|
116
|
+
|
117
|
+
shift += bits;
|
118
|
+
if (shift >= 32) {
|
119
|
+
// mix after we have a complete word
|
120
|
+
|
121
|
+
k1 *= c1;
|
122
|
+
k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15);
|
123
|
+
k1 *= c2;
|
124
|
+
|
125
|
+
h1 ^= k1;
|
126
|
+
h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13);
|
127
|
+
h1 = h1 * 5 + 0xe6546b64;
|
128
|
+
|
129
|
+
shift -= 32;
|
130
|
+
// unfortunately, java won't let you shift 32 bits off, so we need to check for 0
|
131
|
+
if (shift != 0) {
|
132
|
+
k1 = k2 >>> (bits - shift); // bits used == bits - newshift
|
133
|
+
} else {
|
134
|
+
k1 = 0;
|
135
|
+
}
|
136
|
+
nBytes += 4;
|
137
|
+
}
|
138
|
+
|
139
|
+
} // inner
|
140
|
+
|
141
|
+
// handle tail
|
142
|
+
if (shift > 0) {
|
143
|
+
nBytes += shift >> 3;
|
144
|
+
k1 *= c1;
|
145
|
+
k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15);
|
146
|
+
k1 *= c2;
|
147
|
+
h1 ^= k1;
|
148
|
+
}
|
149
|
+
|
150
|
+
// finalization
|
151
|
+
h1 ^= nBytes;
|
152
|
+
|
153
|
+
// fmix(h1);
|
154
|
+
h1 ^= h1 >>> 16;
|
155
|
+
h1 *= 0x85ebca6b;
|
156
|
+
h1 ^= h1 >>> 13;
|
157
|
+
h1 *= 0xc2b2ae35;
|
158
|
+
h1 ^= h1 >>> 16;
|
159
|
+
|
160
|
+
return h1 & 0xFFFFFFFFL;
|
161
|
+
}
|
162
|
+
}
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Digest
|
2
|
+
ds = Struct.new(:digest_length, :seed_length)
|
3
|
+
s1 = ds.new(4, 4)
|
4
|
+
s2 = ds.new(8, 8)
|
5
|
+
s3 = ds.new(16, 4)
|
6
|
+
{
|
7
|
+
'1' => s1,
|
8
|
+
'2' => s1,
|
9
|
+
'2A' => s1,
|
10
|
+
'64A' => s2,
|
11
|
+
'64B' => s2,
|
12
|
+
'Aligned2' => s1,
|
13
|
+
'Neutral2' => s1,
|
14
|
+
'3_x86_32' => s1,
|
15
|
+
'3_x86_128' => s3,
|
16
|
+
'3_x64_128' => s3,
|
17
|
+
}.each do |name, s|
|
18
|
+
class_eval %Q{
|
19
|
+
class MurmurHashMRI#{name} < Digest::Class
|
20
|
+
DEFAULT_SEED = "#{"\x00" * s.seed_length}".b
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@buffer = ""
|
24
|
+
@seed = DEFAULT_SEED
|
25
|
+
end
|
26
|
+
|
27
|
+
def update(str)
|
28
|
+
@buffer << str
|
29
|
+
self
|
30
|
+
end
|
31
|
+
alias << update
|
32
|
+
|
33
|
+
def reset
|
34
|
+
@buffer.clear
|
35
|
+
@seed = DEFAULT_SEED
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def seed
|
40
|
+
@seed
|
41
|
+
end
|
42
|
+
|
43
|
+
def seed=(s)
|
44
|
+
raise ArgumentError, "seed string should be #{s.seed_length} length" if #{s.seed_length} != s.length
|
45
|
+
@seed = s
|
46
|
+
end
|
47
|
+
|
48
|
+
def digest_length
|
49
|
+
#{s.digest_length}
|
50
|
+
end
|
51
|
+
|
52
|
+
def block_length
|
53
|
+
0
|
54
|
+
end
|
55
|
+
end
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|