splitclient-rb 4.5.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +45 -0
  3. data/CHANGES.txt +147 -0
  4. data/Detailed-README.md +571 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +13 -0
  7. data/NEWS +75 -0
  8. data/README.md +43 -0
  9. data/Rakefile +24 -0
  10. data/exe/splitio +96 -0
  11. data/ext/murmurhash/MurmurHash3.java +162 -0
  12. data/lib/murmurhash/base.rb +58 -0
  13. data/lib/murmurhash/murmurhash.jar +0 -0
  14. data/lib/murmurhash/murmurhash_mri.rb +3 -0
  15. data/lib/splitclient-rb.rb +90 -0
  16. data/lib/splitclient-rb/cache/adapters/memory_adapter.rb +12 -0
  17. data/lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb +133 -0
  18. data/lib/splitclient-rb/cache/adapters/memory_adapters/queue_adapter.rb +44 -0
  19. data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +165 -0
  20. data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +30 -0
  21. data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +29 -0
  22. data/lib/splitclient-rb/cache/repositories/events_repository.rb +41 -0
  23. data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +49 -0
  24. data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +78 -0
  25. data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +21 -0
  26. data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +129 -0
  27. data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +98 -0
  28. data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +22 -0
  29. data/lib/splitclient-rb/cache/repositories/repository.rb +23 -0
  30. data/lib/splitclient-rb/cache/repositories/segments_repository.rb +82 -0
  31. data/lib/splitclient-rb/cache/repositories/splits_repository.rb +106 -0
  32. data/lib/splitclient-rb/cache/routers/impression_router.rb +52 -0
  33. data/lib/splitclient-rb/cache/senders/events_sender.rb +47 -0
  34. data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +73 -0
  35. data/lib/splitclient-rb/cache/senders/impressions_sender.rb +67 -0
  36. data/lib/splitclient-rb/cache/senders/metrics_sender.rb +49 -0
  37. data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +48 -0
  38. data/lib/splitclient-rb/cache/stores/segment_store.rb +82 -0
  39. data/lib/splitclient-rb/cache/stores/split_store.rb +97 -0
  40. data/lib/splitclient-rb/clients/localhost_split_client.rb +92 -0
  41. data/lib/splitclient-rb/clients/split_client.rb +214 -0
  42. data/lib/splitclient-rb/engine/api/client.rb +74 -0
  43. data/lib/splitclient-rb/engine/api/events.rb +48 -0
  44. data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +55 -0
  45. data/lib/splitclient-rb/engine/api/impressions.rb +42 -0
  46. data/lib/splitclient-rb/engine/api/metrics.rb +61 -0
  47. data/lib/splitclient-rb/engine/api/segments.rb +62 -0
  48. data/lib/splitclient-rb/engine/api/splits.rb +60 -0
  49. data/lib/splitclient-rb/engine/evaluator/splitter.rb +123 -0
  50. data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +46 -0
  51. data/lib/splitclient-rb/engine/matchers/between_matcher.rb +56 -0
  52. data/lib/splitclient-rb/engine/matchers/combiners.rb +9 -0
  53. data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +86 -0
  54. data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +21 -0
  55. data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +19 -0
  56. data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +30 -0
  57. data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +20 -0
  58. data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +26 -0
  59. data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +27 -0
  60. data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +54 -0
  61. data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +19 -0
  62. data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +53 -0
  63. data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +53 -0
  64. data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +24 -0
  65. data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +60 -0
  66. data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +23 -0
  67. data/lib/splitclient-rb/engine/matchers/set_matcher.rb +20 -0
  68. data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +26 -0
  69. data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +45 -0
  70. data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +66 -0
  71. data/lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb +128 -0
  72. data/lib/splitclient-rb/engine/metrics/metrics.rb +83 -0
  73. data/lib/splitclient-rb/engine/models/label.rb +8 -0
  74. data/lib/splitclient-rb/engine/models/split.rb +17 -0
  75. data/lib/splitclient-rb/engine/models/treatment.rb +3 -0
  76. data/lib/splitclient-rb/engine/parser/condition.rb +210 -0
  77. data/lib/splitclient-rb/engine/parser/evaluator.rb +118 -0
  78. data/lib/splitclient-rb/engine/parser/partition.rb +35 -0
  79. data/lib/splitclient-rb/engine/parser/split_adapter.rb +88 -0
  80. data/lib/splitclient-rb/exceptions/impressions_shutdown_exception.rb +4 -0
  81. data/lib/splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception.rb +4 -0
  82. data/lib/splitclient-rb/localhost_split_factory.rb +13 -0
  83. data/lib/splitclient-rb/localhost_utils.rb +36 -0
  84. data/lib/splitclient-rb/managers/localhost_split_manager.rb +45 -0
  85. data/lib/splitclient-rb/managers/split_manager.rb +77 -0
  86. data/lib/splitclient-rb/split_config.rb +391 -0
  87. data/lib/splitclient-rb/split_factory.rb +35 -0
  88. data/lib/splitclient-rb/split_factory_builder.rb +16 -0
  89. data/lib/splitclient-rb/utilitites.rb +41 -0
  90. data/lib/splitclient-rb/version.rb +3 -0
  91. data/splitclient-rb.gemspec +50 -0
  92. data/splitio.yml.example +7 -0
  93. data/tasks/benchmark_get_treatment.rake +43 -0
  94. data/tasks/irb.rake +4 -0
  95. data/tasks/rspec.rake +3 -0
  96. metadata +321 -0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in splitclient-rb.gemspec
4
+ gemspec
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.
@@ -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).
@@ -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
@@ -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