GUID
[Entity: Types, Identity and Instance Framework]


Detailed Description

Globally Unique ID's provide a way to uniquely identify some thing. A GUID is a unique, cryptographically random 128-bit value. The identifier is so random that it is safe to assume that there is no other such item on the planet Earth, and indeed, not even in the Galaxy or beyond.

QOF GUID's can be used independently of any other subsystem in QOF. In particular, they do not require the use of other parts of the object subsystem. New GUID's are usually created by initialising a new entity using qof_instance_init, rather than calling GUID functions directly.


Files

file  guid.h
 globally unique ID User API

Data Structures

union  _GUID

Defines

#define GUID_DATA_SIZE   16
#define GUID_ENCODING_LENGTH   32

Typedefs

typedef _GUID GUID

Functions

void guid_init (void)
void guid_init_with_salt (const void *salt, size_t salt_len)
void guid_init_only_salt (const void *salt, size_t salt_len)
void guid_shutdown (void)
void guid_new (GUID *guid)
GUID guid_new_return (void)
const GUIDguid_null (void)
GUIDguid_malloc (void)
void guid_free (GUID *guid)
const gchar * guid_to_string (const GUID *guid)
gchar * guid_to_string_buff (const GUID *guid, gchar *buff)
gboolean string_to_guid (const gchar *string, GUID *guid)
gboolean guid_equal (const GUID *guid_1, const GUID *guid_2)
gint guid_compare (const GUID *g1, const GUID *g2)
guint guid_hash_to_guint (gconstpointer ptr)
GHashTable * guid_hash_table_new (void)


Define Documentation

#define GUID_DATA_SIZE   16
 

The type used to store guids

Definition at line 52 of file guid.h.

#define GUID_ENCODING_LENGTH   32
 

number of characters needed to encode a guid as a string not including the null terminator.

Definition at line 64 of file guid.h.


Function Documentation

gboolean guid_equal const GUID guid_1,
const GUID guid_2
 

Given two GUIDs, return TRUE if they are non-NULL and equal. Return FALSE, otherwise.

Definition at line 649 of file guid.c.

00650 {
00651   if (guid_1 && guid_2)
00652     return (memcmp(guid_1, guid_2, GUID_DATA_SIZE) == 0);
00653   else
00654     return FALSE;
00655 }

guint guid_hash_to_guint gconstpointer  ptr  ) 
 

Given a GUID *, hash it to a guint

Definition at line 674 of file guid.c.

00675 {
00676   const GUID *guid = ptr;
00677 
00678   if (!guid)
00679   {
00680     PERR ("received NULL guid pointer.");
00681     return 0;
00682   }
00683 
00684   if (sizeof(guint) <= sizeof(guid->data))
00685   {
00686     return (*((guint *) guid->data));
00687   }
00688   else
00689   {
00690     guint hash = 0;
00691     unsigned int i, j;
00692 
00693     for (i = 0, j = 0; i < sizeof(guint); i++, j++) {
00694       if (j == GUID_DATA_SIZE) j = 0;
00695 
00696       hash <<= 4;
00697       hash |= guid->data[j];
00698     }
00699 
00700     return hash;
00701   }
00702 }

void guid_init void   ) 
 

Initialize the id generator with a variety of random sources.

Note:
Only one of guid_init(), guid_init_with_salt() and guid_init_only_salt() should be called. Calling any initialization function a second time will reset the generator and erase the effect of the first call.

Definition at line 327 of file guid.c.

00328 {
00329   size_t bytes = 0;
00330 
00331   /* Not needed; taken care of on first malloc.
00332    * guid_memchunk_init(); */
00333 
00334   md5_init_ctx(&guid_context);
00335 
00336   /* entropy pool */
00337   bytes += init_from_file ("/dev/urandom", 512);
00338 
00339   /* files */
00340   {
00341     const char * files[] =
00342     { "/etc/passwd",
00343       "/proc/loadavg",
00344       "/proc/meminfo",
00345       "/proc/net/dev",
00346       "/proc/rtc",
00347       "/proc/self/environ",
00348       "/proc/self/stat",
00349       "/proc/stat",
00350       "/proc/uptime",
00351       NULL
00352     };
00353     int i;
00354 
00355     for (i = 0; files[i] != NULL; i++)
00356       bytes += init_from_file(files[i], BLOCKSIZE);
00357   }
00358 
00359   /* directories */
00360   {
00361     const char * dirname;
00362     const char * dirs[] =
00363     {
00364       "/proc",
00365       P_tmpdir,
00366       "/var/lock",
00367       "/var/log",
00368       "/var/mail",
00369       "/var/spool/mail",
00370       "/var/run",
00371       NULL
00372     };
00373     int i;
00374 
00375     for (i = 0; dirs[i] != NULL; i++)
00376       bytes += init_from_dir(dirs[i], 32);
00377 
00378     dirname = g_get_home_dir();
00379     if (dirname != NULL)
00380       bytes += init_from_dir(dirname, 32);
00381   }
00382 
00383   /* process and parent ids */
00384   {
00385     pid_t pid;
00386 
00387     pid = getpid();
00388     md5_process_bytes(&pid, sizeof(pid), &guid_context);
00389     bytes += sizeof(pid);
00390 
00391 #ifdef HAVE_GETPPID
00392     pid = getppid();
00393     md5_process_bytes(&pid, sizeof(pid), &guid_context);
00394     bytes += sizeof(pid);
00395 #endif
00396   }
00397 
00398   /* user info */
00399   {
00400 #ifdef HAVE_GETUID
00401     uid_t uid;
00402     gid_t gid;
00403     char *s;
00404 
00405     s = getlogin();
00406     if (s != NULL)
00407     {
00408       md5_process_bytes(s, strlen(s), &guid_context);
00409       bytes += strlen(s);
00410     }
00411 
00412     uid = getuid();
00413     md5_process_bytes(&uid, sizeof(uid), &guid_context);
00414     bytes += sizeof(uid);
00415 
00416     gid = getgid();
00417     md5_process_bytes(&gid, sizeof(gid), &guid_context);
00418     bytes += sizeof(gid);
00419 #endif
00420   }
00421 
00422   /* host info */
00423   {
00424 #ifdef HAVE_GETHOSTNAME
00425     char string[1024];
00426 
00427     memset(string, 0, sizeof(string));
00428     gethostname(string, sizeof(string));
00429     md5_process_bytes(string, sizeof(string), &guid_context);
00430     bytes += sizeof(string);
00431 #endif
00432   }
00433 
00434   /* plain old random */
00435   {
00436     int n, i;
00437 
00438     srand((unsigned int) time(NULL));
00439 
00440     for (i = 0; i < 32; i++)
00441     {
00442       n = rand();
00443 
00444       md5_process_bytes(&n, sizeof(n), &guid_context);
00445       bytes += sizeof(n);
00446     }
00447   }
00448 
00449   /* time in secs and clock ticks */
00450   bytes += init_from_time();
00451 
00452   PINFO ("got %llu bytes", (unsigned long long int) bytes);
00453 
00454   if (bytes < THRESHOLD)
00455     PWARN("only got %llu bytes.\n"
00456               "The identifiers might not be very random.\n",
00457           (unsigned long long int)bytes);
00458 
00459   guid_initialized = TRUE;
00460 }

void guid_init_only_salt const void *  salt,
size_t  salt_len
 

Initialize the id generator with the data given in the salt argument, but not with any other source. Calling this function with a specific argument will reliably produce a specific sequence of ids.

Parameters:
salt The additional random values to add to the generator.
salt_len The length of the additional random values.
Note:
Only one of guid_init(), guid_init_with_salt() and guid_init_only_salt() should be called. Calling any initialization function a second time will reset the generator and erase the effect of the first call.

Definition at line 471 of file guid.c.

00472 {
00473   md5_init_ctx(&guid_context);
00474 
00475   md5_process_bytes(salt, salt_len, &guid_context);
00476 
00477   guid_initialized = TRUE;
00478 }

void guid_init_with_salt const void *  salt,
size_t  salt_len
 

Initialize the id generator with a variety of random sources. and with the data given in the salt argument. This argument can be used to add additional randomness to the generated ids.

Parameters:
salt The additional random values to add to the generator.
salt_len The length of the additional random values.
Note:
Only one of guid_init(), guid_init_with_salt() and guid_init_only_salt() should be called. Calling any initialization function a second time will reset the generator and erase the effect of the first call.

Definition at line 463 of file guid.c.

00464 {
00465   guid_init();
00466 
00467   md5_process_bytes(salt, salt_len, &guid_context);
00468 }

GUID* guid_malloc void   ) 
 

Efficiently allocate & free memory for GUIDs

Definition at line 104 of file guid.c.

00105 {
00106   if (!guid_memchunk) guid_memchunk_init();
00107   return g_chunk_new (GUID, guid_memchunk);
00108 }

void guid_new GUID guid  ) 
 

Generate a new id. If no initialization function has been called, guid_init() will be called before the id is created.

Parameters:
guid A pointer to an existing guid data structure. The existing value will be replaced with a new value.
This routine uses the md5 algorithm to build strong random guids. Note that while guid's are generated randomly, the odds of this routine returning a non-unique id are astronomically small. (Literally astronomically: If you had Cray's on every solar system in the universe running for the entire age of the universe, you'd still have less than a one-in-a-million chance of coming up with a duplicate id. 2^128 == 10^38 is a really really big number.)

Definition at line 491 of file guid.c.

00492 {
00493   static int counter = 0;
00494   struct md5_ctx ctx;
00495 
00496   if (guid == NULL)
00497     return;
00498 
00499   if (!guid_initialized)
00500     guid_init();
00501 
00502   /* make the id */
00503   ctx = guid_context;
00504   md5_finish_ctx(&ctx, guid->data);
00505 
00506   /* update the global context */
00507   init_from_time();
00508 
00509   /* Make it a little extra salty.  I think init_from_time was buggy,
00510         * or something, since duplicate id's actually happened. Or something
00511         * like that.  I think this is because init_from_time kept returning
00512         * the same values too many times in a row.  So we'll do some 'block
00513         * chaining', and feed in the old guid as new random data.
00514         *
00515         * Anyway, I think the whole fact that I saw a bunch of duplicate 
00516         * id's at one point, but can't reproduce the bug is rather alarming.
00517         * Something must be broken somewhere, and merely adding more salt
00518         * is just hiding the problem, not fixing it.
00519         */
00520   init_from_int (433781*counter);
00521   init_from_buff (guid->data, GUID_DATA_SIZE);
00522 
00523   if (counter == 0)
00524   {
00525     FILE *fp;
00526 
00527     fp = fopen ("/dev/urandom", "r");
00528     if (fp == NULL)
00529       return;
00530 
00531     init_from_stream(fp, 32);
00532 
00533     fclose(fp);
00534 
00535     counter = GUID_PERIOD;
00536   }
00537 
00538   counter--;
00539 }

GUID guid_new_return void   ) 
 

Generate a new id. If no initialization function has been called, guid_init() will be called before the id is created.

Returns:
guid A data structure containing a newly allocated GUID. Caller is responsible for calling guid_free().

Definition at line 542 of file guid.c.

00543 {
00544   GUID guid;
00545 
00546   guid_new (&guid);
00547 
00548   return guid;
00549 }

const GUID* guid_null void   ) 
 

Returns a GUID which is guaranteed to never reference any entity.

Definition at line 122 of file guid.c.

00123 {
00124   static int null_inited = 0;
00125   static GUID null_guid;
00126 
00127   if (!null_inited)
00128   {
00129     int i;
00130     char *tmp = "NULLGUID.EMPTY.";
00131 
00132       /* 16th space for '\O' */
00133           for (i = 0; i < GUID_DATA_SIZE; i++)
00134       null_guid.data[i] = tmp[i];
00135 
00136     null_inited = 1;
00137   }
00138 
00139   return &null_guid;
00140 }

void guid_shutdown void   ) 
 

Release the memory chunk associated with gui storage. Use this only when shutting down the program, as it invalidates *all* GUIDs at once.

Definition at line 481 of file guid.c.

00482 {
00483 #ifndef HAVE_GLIB29
00484         guid_memchunk_shutdown();
00485 #endif
00486 }

const gchar* guid_to_string const GUID guid  ) 
 

The guid_to_string() routine returns a null-terminated string encoding of the id. String encodings of identifiers are hex numbers printed only with the characters '0' through '9' and 'a' through 'f'. The encoding will always be GUID_ENCODING_LENGTH characters long.

XXX This routine is not thread safe and is deprecated. Please use the routine guid_to_string_buff() instead.

Parameters:
guid The guid to print.
Returns:
A pointer to the starting character of the string. The returned memory is owned by this routine and may not be freed by the caller.

Definition at line 610 of file guid.c.

00611 {
00612 #ifdef G_THREADS_ENABLED
00613   static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT;
00614   gchar *string;
00615 
00616   string = g_static_private_get (&guid_buffer_key);
00617   if (string == NULL) {
00618     string = malloc(GUID_ENCODING_LENGTH+1);
00619     g_static_private_set (&guid_buffer_key, string, g_free);
00620   }
00621 #else
00622   static char string[64];
00623 #endif
00624 
00625   encode_md5_data(guid->data, string);
00626   string[GUID_ENCODING_LENGTH] = '\0';
00627 
00628   return string;
00629 }

gchar* guid_to_string_buff const GUID guid,
gchar *  buff
 

The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory pointed at by buff. The buffer must be at least GUID_ENCODING_LENGTH+1 characters long. This routine is handy for avoiding a malloc/free cycle. It returns a pointer to the >>end<< of what was written. (i.e. it can be used like 'stpcpy' during string concatenation)

Parameters:
guid The guid to print.
buff The buffer to print it into.
Returns:
A pointer to the terminating null character of the string.

gboolean string_to_guid const gchar *  string,
GUID guid
 

Given a string, decode the id into the guid if guid is non-NULL. The function returns TRUE if the string was a valid 32 character hexadecimal number. This function accepts both upper and lower case hex digits. If the return value is FALSE, the effect on guid is undefined.


Generated on Fri May 12 17:57:22 2006 for QOF by  doxygen 1.4.4