summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNickNorth <North.N@gmail.com>2012-08-06 11:02:44 +0100
committerRobert Newson <rnewson@apache.org>2012-08-06 12:46:35 +0100
commit5ab712a235d51dfba78fa8c4bf29943f90062585 (patch)
treeb4c608d17b6910281008deb9e95772080e1ffad1
parentce7204b7eb64ac98d4445130fc4e647ed5181da9 (diff)
downloadcouchdb-5ab712a235d51dfba78fa8c4bf29943f90062585.tar.gz
Add utc_id_suffix UUID algorithm
-rw-r--r--CHANGES4
-rw-r--r--NEWS1
-rw-r--r--etc/couchdb/default.ini.tpl.in5
-rw-r--r--share/www/script/test/uuids.js27
-rw-r--r--src/couchdb/couch_uuids.erl10
-rw-r--r--test/etap/041-uuid-gen-id.ini20
-rwxr-xr-xtest/etap/041-uuid-gen.t33
7 files changed, 96 insertions, 4 deletions
diff --git a/CHANGES b/CHANGES
index e3777beed..a56f63783 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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
-------------
diff --git a/NEWS b/NEWS
index 30b0d27d1..d4e50e52a 100644
--- a/NEWS
+++ b/NEWS
@@ -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.