Subject: | uuid collision |
The attached patch fixes the problem that Data::UUID can generate same uuid on smp machine, demostrated in the test. The solution is to hash pid into the nodeid (assuming pid is not larger than 6 bytes). We probably just want cpu id here, I am not sure if there's side effect for the nodeid to be changing.
----------------------------------------------------------------------
r47034 (orig r44366): clkao | 2005-10-13 12:05:36 +0100
Hash the pid into nodeid for uuid generation. We should really
use CPU id if we have a way doing so. This fixes the collision
demostrated on smp machines.
----------------------------------------------------------------------
=== work/trunk/vendor/CPAN/Data-UUID/UUID.xs
==================================================================
--- work/trunk/vendor/CPAN/Data-UUID/UUID.xs (revision 47033)
+++ work/trunk/vendor/CPAN/Data-UUID/UUID.xs (revision 47034)
@@ -266,8 +266,11 @@
RETVAL->next_save = timestamp;
}
if ((fd = fopen(UUID_NODEID_NV_STORE, "rb"))) {
+ pid_t *hate = (pid_t *) &(RETVAL->nodeid);
fread(&(RETVAL->nodeid), sizeof(uuid_node_t), 1, fd );
fclose(fd);
+
+ *hate += getpid();
} else {
get_random_info(seed);
seed[0] |= 0x80;
=== work/trunk/vendor/CPAN/Data-UUID/smp-test/uuid-fork.pl
==================================================================
--- work/trunk/vendor/CPAN/Data-UUID/smp-test/uuid-fork.pl (revision 47033)
+++ work/trunk/vendor/CPAN/Data-UUID/smp-test/uuid-fork.pl (revision 47034)
@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+
+use Data::UUID 'NameSpace_URL';
+
+#my $du = Data::UUID->new;
+
+
+#$du->create_str;
+
+
+if (fork()) {
+ print "GOT :".Data::UUID->new->create_str;
+ exit;
+}
+
+print "GOT :".Data::UUID->new->create_str;
=== work/trunk/vendor/CPAN/Data-UUID/smp-test/collision.t
==================================================================
--- work/trunk/vendor/CPAN/Data-UUID/smp-test/collision.t (revision 47033)
+++ work/trunk/vendor/CPAN/Data-UUID/smp-test/collision.t (revision 47034)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl -w
+
+my $cnt = shift || 1000;
+
+my $collision = 0;
+
+for (1..$cnt) {
+ my $foo = `$^X -l -Mblib smp-test/uuid-fork.pl`;
+ my @ret = ($foo =~ m/^(.*)$/mg);
+ ++$collision#, print "==> collision ($foo)\n"
+ if $ret[0] eq $ret[1];
+}
+
+print sprintf("%5.3f %% collision\n", $collision*100/$cnt);