diff options
author | NickNorth <North.N@gmail.com> | 2012-08-06 11:02:44 +0100 |
---|---|---|
committer | Robert Newson <rnewson@apache.org> | 2012-08-06 12:46:35 +0100 |
commit | 5ab712a235d51dfba78fa8c4bf29943f90062585 (patch) | |
tree | b4c608d17b6910281008deb9e95772080e1ffad1 | |
parent | ce7204b7eb64ac98d4445130fc4e647ed5181da9 (diff) | |
download | couchdb-5ab712a235d51dfba78fa8c4bf29943f90062585.tar.gz |
Add utc_id_suffix UUID algorithm
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | etc/couchdb/default.ini.tpl.in | 5 | ||||
-rw-r--r-- | share/www/script/test/uuids.js | 27 | ||||
-rw-r--r-- | src/couchdb/couch_uuids.erl | 10 | ||||
-rw-r--r-- | test/etap/041-uuid-gen-id.ini | 20 | ||||
-rwxr-xr-x | test/etap/041-uuid-gen.t | 33 |
7 files changed, 96 insertions, 4 deletions
@@ -46,6 +46,10 @@ Test Suite: * Improved tracebacks printed by the JS CLI tests * Improved the reliability of a number of tests +UUID Algorithms: + + * Added the utc_id algorithm. + Version 1.2.1 ------------- @@ -22,6 +22,7 @@ This version has not been released yet. * Added Server-Sent Events protocol to db changes API. * Moved the JS test suite to the CLI * Make password hashing synchronous when using the /_config/admins API. + * Added utc_id UUID algorithm. Version 1.2.1 ------------- diff --git a/etc/couchdb/default.ini.tpl.in b/etc/couchdb/default.ini.tpl.in index ce849057f..79ece5cd3 100644 --- a/etc/couchdb/default.ini.tpl.in +++ b/etc/couchdb/default.ini.tpl.in @@ -178,7 +178,12 @@ _view = {couch_mrview_http, handle_view_req} ; random prefix is regenerated and the process starts over. ; utc_random - Time since Jan 1, 1970 UTC with microseconds ; First 14 characters are the time in hex. Last 18 are random. +; utc_id - Time since Jan 1, 1970 UTC with microseconds, plus utc_id_suffix string +; First 14 characters are the time in hex. uuids/utc_id_suffix string value is appended to these. algorithm = sequential +; The utc_id_suffix value will be appended to uuids generated by the utc_id algorithm. +; Replicating instances should have unique utc_id_suffix values to ensure uniqueness of utc_id ids. +utc_id_suffix = [stats] ; rate is in milliseconds diff --git a/share/www/script/test/uuids.js b/share/www/script/test/uuids.js index fc33a1059..6f5d223a6 100644 --- a/share/www/script/test/uuids.js +++ b/share/www/script/test/uuids.js @@ -117,4 +117,29 @@ couchTests.uuids = function(debug) { utc_testfun ); -}; + // Test utc_id uuids + var utc_id_suffix = "frog"; + var suffix_testfun = function() { + xhr = CouchDB.request("GET", "/_uuids?count=10"); + T(xhr.status == 200); + result = JSON.parse(xhr.responseText); + for(var i = 1; i < result.uuids.length; i++) { + T(result.uuids[i].length == 14 + utc_id_suffix.length); + T(result.uuids[i].substring(14) == utc_id_suffix); + T(result.uuids[i-1] < result.uuids[i], "utc_id_suffix uuids are ordered."); + } + }; + + run_on_modified_server([{ + "section": "uuids", + "key": "algorithm", + "value": "utc_id" + }, { + "section": "uuids", + "key": "utc_id_suffix", + "value": utc_id_suffix + }], + suffix_testfun + ); + + }; diff --git a/src/couchdb/couch_uuids.erl b/src/couchdb/couch_uuids.erl index e1851e1d4..6ed75a1f4 100644 --- a/src/couchdb/couch_uuids.erl +++ b/src/couchdb/couch_uuids.erl @@ -33,12 +33,15 @@ random() -> list_to_binary(couch_util:to_hex(crypto:rand_bytes(16))). utc_random() -> + utc_suffix(couch_util:to_hex(crypto:rand_bytes(9))). + +utc_suffix(Suffix) -> Now = {_, _, Micro} = now(), Nowish = calendar:now_to_universal_time(Now), Nowsecs = calendar:datetime_to_gregorian_seconds(Nowish), Then = calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}), Prefix = io_lib:format("~14.16.0b", [(Nowsecs - Then) * 1000000 + Micro]), - list_to_binary(Prefix ++ couch_util:to_hex(crypto:rand_bytes(9))). + list_to_binary(Prefix ++ Suffix). init([]) -> ok = couch_config:register( @@ -53,6 +56,8 @@ handle_call(create, _From, random) -> {reply, random(), random}; handle_call(create, _From, utc_random) -> {reply, utc_random(), utc_random}; +handle_call(create, _From, {utc_id, UtcIdSuffix}) -> + {reply, utc_suffix(UtcIdSuffix), {utc_id, UtcIdSuffix}}; handle_call(create, _From, {sequential, Pref, Seq}) -> Result = ?l2b(Pref ++ io_lib:format("~6.16.0b", [Seq])), case Seq >= 16#fff000 of @@ -88,6 +93,9 @@ state() -> random; utc_random -> utc_random; + utc_id -> + UtcIdSuffix = couch_config:get("uuids", "utc_id_suffix", ""), + {utc_id, UtcIdSuffix}; sequential -> {sequential, new_prefix(), inc()}; Unknown -> diff --git a/test/etap/041-uuid-gen-id.ini b/test/etap/041-uuid-gen-id.ini new file mode 100644 index 000000000..6886efdb7 --- /dev/null +++ b/test/etap/041-uuid-gen-id.ini @@ -0,0 +1,20 @@ +; Licensed to the Apache Software Foundation (ASF) under one +; or more contributor license agreements. See the NOTICE file +; distributed with this work for additional information +; regarding copyright ownership. The ASF licenses this file +; to you under the Apache License, Version 2.0 (the +; "License"); you may not use this file except in compliance +; with the License. You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, +; software distributed under the License is distributed on an +; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +; KIND, either express or implied. See the License for the +; specific language governing permissions and limitations +; under the License. + +[uuids] +algorithm = utc_id +utc_id_suffix = bozo diff --git a/test/etap/041-uuid-gen.t b/test/etap/041-uuid-gen.t index 1e6aa9eee..72349698e 100755 --- a/test/etap/041-uuid-gen.t +++ b/test/etap/041-uuid-gen.t @@ -22,6 +22,9 @@ seq_alg_config() -> utc_alg_config() -> test_util:source_file("test/etap/041-uuid-gen-utc.ini"). +utc_id_alg_config() -> + test_util:source_file("test/etap/041-uuid-gen-id.ini"). + % Run tests and wait for the gen_servers to shutdown run_test(IniFiles, Test) -> {ok, Pid} = couch_config:start_link(IniFiles), @@ -40,7 +43,7 @@ run_test(IniFiles, Test) -> main(_) -> test_util:init_code_path(), application:start(crypto), - etap:plan(6), + etap:plan(9), case (catch test()) of ok -> @@ -63,6 +66,7 @@ test() -> run_test([default_config()], TestUnique), run_test([default_config(), seq_alg_config()], TestUnique), run_test([default_config(), utc_alg_config()], TestUnique), + run_test([default_config(), utc_id_alg_config()], TestUnique), TestMonotonic = fun () -> etap:is( @@ -73,6 +77,7 @@ test() -> end, run_test([default_config(), seq_alg_config()], TestMonotonic), run_test([default_config(), utc_alg_config()], TestMonotonic), + run_test([default_config(), utc_id_alg_config()], TestMonotonic), % Pretty sure that the average of a uniform distribution is the % midpoint of the range. Thus, to exceed a threshold, we need @@ -94,7 +99,18 @@ test() -> "should roll over every so often." ) end, - run_test([default_config(), seq_alg_config()], TestRollOver). + run_test([default_config(), seq_alg_config()], TestRollOver), + + TestSuffix = fun() -> + UUID = binary_to_list(couch_uuids:new()), + Suffix = get_suffix(UUID), + etap:is( + test_same_suffix(100, Suffix), + true, + "utc_id ids should have the same suffix." + ) + end, + run_test([default_config(), utc_id_alg_config()], TestSuffix). test_unique(0, _) -> true; @@ -116,3 +132,16 @@ gen_until_pref_change(Prefix, N) -> Prefix -> gen_until_pref_change(Prefix, N+1); _ -> N end. + +get_suffix(UUID) when is_binary(UUID)-> + get_suffix(binary_to_list(UUID)); +get_suffix(UUID) -> + element(2, lists:split(14, UUID)). + +test_same_suffix(0, _) -> + true; +test_same_suffix(N, Suffix) -> + case get_suffix(couch_uuids:new()) of + Suffix -> test_same_suffix(N-1, Suffix); + _ -> false + end. |