Giter Site home page Giter Site logo

uuid's Introduction

Erlang UUID Implementation

Build Status

http://www.ietf.org/rfc/rfc4122.txt is the reference for official UUIDs. This implementation provides a version 1 UUID that includes both the Erlang pid identifier (ID, Serial, Creation) and the distributed Erlang node name within the 48 bit node ID. To make room for the Erlang pid identifier, the 48 bits from the MAC address (i.e., 3 OCI (Organizationally Unique Identifier) bytes and 3 NIC (Network Interface Controller) specific bytes) and the distributed Erlang node name are bitwise-XORed down to 16 bits. The Erlang pid is bitwise-XORed from 72 bits down to 32 bits. The version 3 (MD5), version 4 (random), and version 5 (SHA) methods are provided as specified within the RFC.

Requires Erlang >= R16B01

Usage

Certain uuid functions require initializing the Erlang process before the function is called. The initialization ensures the quickrand dependency is able to provide randomness for the uuid module use.

If you use the functions uuid:new/1, uuid:new/2 or uuid:get_v4_urandom/0, you should call the function quickrand:seed/0 or quickrand:seed/1 first.

If you use the function uuid:get_v4/1 with a cached argument, you should call the function quickrand_cache:init/0 or quickrand_cache:init/1 first. If you use the function uuid:get_v4/1 with quickrand_cache state, you would have called the function quickrand_cache:new/0 or quickrand_cache:new/1 first. Using the quickrand_cache init function means cached random data is stored in the process dictionary and using the quickrand_cache new function (instead of init) means cached random data is kept in a state variable.

Build

rebar get-deps
rebar compile

Author

Michael Truog (mjtruog at protonmail dot com)

License

MIT License

uuid's People

Contributors

cy6erbr4in avatar ferd avatar getong avatar gregormey avatar jlouis avatar kianmeng avatar konradkaplita avatar louiscb avatar lpgauth avatar okeuday avatar ratelle avatar seansawyer avatar tank-bohr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uuid's Issues

Pid format change in Erlang/OTP 23

Hi, it looks like the PID format changed in OTP-22 and breaks uuid:new/2.

https://github.com/okeuday/uuid/blob/master/src/uuid.erl#L177

Erlang/OTP 22 [RELEASE CANDIDATE 2]

rp(erlang:term_to_binary(self())).

<<131,88,100,0,40,114,116,98,45,103,97,116,101,119,97,121,
  64,108,103,97,45,103,97,116,101,119,97,121,45,49,46,115,
  121,115,46,97,100,103,101,97,114,46,99,111,109,0,0,13,
  101,0,0,3,4,0,0,0,2>>

vs

Erlang/OTP 21 [erts-10.3.2]

rp(erlang:term_to_binary(self())).

<<131,103,100,0,40,114,116,98,45,103,97,116,101,119,97,
  121,64,108,103,97,45,103,97,116,101,119,97,121,45,50,46,
  115,121,115,46,97,100,103,101,97,114,46,99,111,109,0,0,
  115,205,0,0,5,174,2>>

Can't be built with erlang.mk on OTP-20

Makefile

PROJECT = hello
PROJECT_DESCRIPTION = New project
PROJECT_VERSION = 0.1.0

DEPS = uuid

include erlang.mk

When I run make deps

 DEP    uuid (master)
 DEP    quickrand (master)
 DEPEND quickrand.d
 ERLC   quickrand.erl quickrand_cache.erl quickrand_cache_normal.erl quickrand_hash.erl quickrand_normal.erl random_wh06_int.erl random_wh82.erl
Old inliner: threshold=0 functions=[{rotate_32,2},
                                    {rotate_64,2},
                                    {consume_32,2},
                                    {consume_32_part,2},
                                    {consume_64,2},
                                    {add_32,2},
                                    {add_32,3},
                                    {add_64,2},
                                    {add_64,3},
                                    {add_64,4},
                                    {add_64,5},
                                    {add_64,6},
                                    {subtract_32,2}]
 APP    quickrand.app.src
 DEPEND uuid.d
 ERLC   uuid.erl
src/uuid.erl:97: -error("Erlang/OTP version invalid").
make[2]: *** [ebin/uuid.app] Error 1
make[1]: *** [app] Error 2
make: *** [deps] Error 2

My OTP version is Erlang/OTP 20 [erts-9.3]

uuid:get_v4_urandom() always returns these results the first four times it is called

uuid:get_v4_urandom() always returns these results the first four times it is called:

 info {"01056c26-74c1-49f9-9c40-5162c8c7c1aa",
       "3bc859b2-3174-4b3c-986a-52a95f8175f7",
       "50c84cda-e011-49d3-889a-0b2ad8206e6c",
       "774129ae-db15-431e-9ded-fbfb924b33b2"}

The expected result:
uuid:get_v4_urandom() should return a different random unique number

Reproduce this by cloning this repository and running rebar eunit: https://github.com/iambumblehead/edtsredunderline#uuid, try running rebar eunit several times and see if the result is the same each time for you as well.

I'm unsure exactly which circumstances cause this. I found it while trying to understand failing eunit tests around uuid and so I added an eunit test here to reproduce.

My system:
Ubuntu, Erlang/OTP 17 [erts-6.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

R19 crypto error

erlang R19 error:
src/uuid.erl:574: crypto:rand_bytes/1 is deprecated and will be removed in in a future release; use crypto:strong_rand_bytes/1

UUIDv1 generation is incorrect

If I take a UUIDv1generated by this library (with uuid:uuid_to_string(uuid:get_v1(uuid:new(self())))), the result doesn't seem to actually be a v1 UUID: if you, say, try to insert it into a TimeUUID column in Cassandra, you get "TimeUUID supports only version 1 UUIDs". The version/time_hi field of a correct UUID (such as generated by uuidgen -t) right now is 11e2, whereas this library is generating 4001 (which I believe is supposed to mean a v4 UUID). It might be that I'm using the API wrong? (I figured out how to get a result out of the library based on the type signatures of the various functions).

variant bits are incorrect

The variant bits are currently incorrect based on various testing. External usage of the UUID values is probably not checking the variant bits. However, for correctness it is important to fix the problem. Fixing the problem requires a backwards incompatible change.

Correctness of clock sequence handling in uuid v1 generation

RFC 4122 states:

If the clock is set backwards, or might have been set backwards
(e.g., while the system was powered off), and the UUID generator can
not be sure that no UUIDs were generated with timestamps larger than
the value to which the clock was set, then the clock sequence has to
be changed. If the previous value of the clock sequence is known, it
can just be incremented; otherwise it should be set to a random or
high-quality pseudo-random value.

RFC 4122 also states in 4.2.1. Basic Algorithm:

  • If the state was available, but the saved timestamp is later than
    the current timestamp, increment the clock sequence value.

However, in get_v1/1, the clock sequence is never altered. Incrementing the clock is implemented in increment/1, but increment/1 is never called during uuid v1 generation.

In case of a new timestamp being older than the last timestamp instead of adjusting the clock sequence (as intended by RFC 4122) the timestamp itself is altered in timestamp/2, at least for erlang_timestamp. It is obviously arguable what the "correct" timestamp is in such cases but in my opinion messing with the timestamp is not the correct answer, thats exactly what the clock sequence is for.

An example where messing with the timestamp is problematic: This library is used by the Erlang Cassandra driver cqerl. Cassandra in turn relies on extracting the time portion of the uuid v1 (timeuuid in Cassandra) as timestamp.

Both of the these behaviours do not seem to be correct in the sense of RFC 4122. Am I missing something in your implementation? Do I misunderstand the standard?

Timeuuid Version 1 is not valid

I have a gen_server process running.
At times the get_time_uuid function returns a uuid which is not a valid time uuid.

get_time_uuid(Proc, Format) ->
    gen_server:call(time_uuid_proc, get_time_uuid).

sample code in gen_server

init(_) ->
{ok, #{uuid => uuid:new(self())}}.

handle_call(get_time_uuid, _From, #{uuid := UUIDState} = State) ->
    {UUID, UUIDState1} = uuid:get_v1(UUIDState),
    SUUID = uuid:uuid_to_string(UUID,  binary_standard),
    {reply, SUUID, State#{uuid => UUIDState1}};

Generate state once per app or once per process

Hi,
I am currently using uuid in a webserver to give a UUID to each request that my application receive. Is the uuid:new/1 a simple seed that I can run once during my application startup and then pass the state around (for example to any child process that would need to generate a UUID) ? Or should I run the uuid:new/1 inside each new worker process that need to generate a UUID ?

From the code, it looks like uuid:new/1 is just generating a seed, but the fact that it embeds the process pid make me wonder if I am increasing the change of collisions or loosing any information by running it only once.

exit(badarg) is confusing and non-standard?

The uuid codebase uses exit(badarg) in multiple places, which can be a bit confusing (see: https://github.com/okeuday/uuid/blob/master/src/uuid.erl#L960-L961)

The OTP library seems to always use error(badarg) (or error(badarg, Reason)), by comparison:

→ ack -r 'exit\(badarg' | grep badarg | wc -l
      20
→ ack -r 'error\(badarg' | grep badarg | wc -l
     355

half of the 20 calls are in the inet stack and are converted to {error, badarg} as a return value.

The semantics I'm used to (and those can be debated) is that:

  • throw stands for non-local returns to be caught within a module scope, and shouldn't be exposed to the user, but are useful as a control-flow mechanism within a specific context.
  • error are for programming exceptions related to user errors, and that interrupt the flow of a program
  • exit exceptions are specifically for the handling of issues that keep the current process from running and which the user wouldn't be expected to handle (such as a parent or peer process dying, or a message directly indicating the process should terminate)

Historically exits have been using in the days prior to try ... catch where catch Expression was the only mechanism, as a way to avoid building a stacktrace. try ... catch now makes this optional through erlang:get_stacktrace(), so that optimization shouldn't be required anymore.

Would it make sense for this library to change its usage of exit(badarg) into error(badarg) in an attempt to stay in line with the usual OTP mechanisms, and avoid nasty surprises? It can be argued that changing the type will probably be a surprise to established users, but I leave this up to the maintainers to decide.

Usage example?

Is there a usage example?

Can't figure out how to use this.

Release Tag

Hey,

Would you mind tagging uuid? Don't really want to depend on master. Otherwise I have to fork.

Thanks!

Running out of file descriptors...

Hi,
It seems that in 0.1.4 generating a UUID v1 uses an fd? Is that possible? I had to revert to 0.1.0 because my box kept running out of file descriptors and coudn't keep my network connections open.

Cached methods using quickrand_cache need to be initialised first

When calling the cached v4 methods, e.g :uuid.get_v4(:cached) you get errors if you don't first initialise the quickrand_cache module , like so: :quickrand_cache.init(). It required the user looking through the source code of the quickrand module to do that. I think it would be nice to provide a method inside of :uuid called something along the lines of "init_cache()" and then add documentation that explains the required steps. I'm happy to make this pr.

Using master branch instead of v1.7.2 causes compile failure

When compiling cqerl on elixir I get a compilation error when it tries to compile UUID. When I add a dependency override to uuid 1.7.2 the error goes away. I am not sure with which package (cqerl or uuid) the issue lies, but thought I'd mention it.

the error I was getting is:

\===> Compiling uuid ===> Compiling src/uuid.erl failed src/uuid.erl:503: call to crypto:rand_bytes/1 will fail, since it was removed in 20.0; use crypto:strong_rand_bytes/1

** (Mix) Could not compile dependency :uuid, "/./.mix/rebar3 bare compile --paths "/./_build/dev/lib/*/ebin"" command failed. You can recompile this dependency with "mix deps.compile uuid", update it with "mix deps.update uuid" or clean it with "mix deps.clean uuid"

is_uuid doesn't handle nil

RFC 4122

4.1.7. Nil UUID
The nil UUID is special form of UUID that is specified to have all 128 bits set to zero.

Doesn't build on Erlang 18

Doesn't build on Erlang 18 because of compile option warnings_as_errors.

compile: warnings being treated as errors
src/uuid.erl:1192: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
make: *** [ebin/uuid.app] Error 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.