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_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 char * guid_to_string (const GUID *guid)
char * guid_to_string_buff (const GUID *guid, char *buff)
gboolean string_to_guid (const char *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_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.


Typedef Documentation

typedef union _GUID GUID
 

The type used to store guids


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 615 of file guid.c.

00616 {
00617   if (guid_1 && guid_2)
00618     return (memcmp(guid_1, guid_2, sizeof(GUID)) == 0);
00619   else
00620     return FALSE;
00621 }

guint guid_hash_to_guint gconstpointer  ptr  ) 
 

Given a GUID *, hash it to a guint

Definition at line 640 of file guid.c.

00641 {
00642   const GUID *guid = ptr;
00643 
00644   if (!guid)
00645   {
00646     PERR ("received NULL guid pointer.");
00647     return 0;
00648   }
00649 
00650   if (sizeof(guint) <= sizeof(guid->data))
00651   {
00652     return (*((guint *) guid->data));
00653   }
00654   else
00655   {
00656     guint hash = 0;
00657     unsigned int i, j;
00658 
00659     for (i = 0, j = 0; i < sizeof(guint); i++, j++) {
00660       if (j == 16) j = 0;
00661 
00662       hash <<= 4;
00663       hash |= guid->data[j];
00664     }
00665 
00666     return hash;
00667   }
00668 }

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 301 of file guid.c.

00302 {
00303   size_t bytes = 0;
00304 
00305   /* Not needed; taken care of on first malloc.
00306    * guid_memchunk_init(); */
00307 
00308   md5_init_ctx(&guid_context);
00309 
00310   /* entropy pool */
00311   bytes += init_from_file ("/dev/urandom", 512);
00312 
00313   /* files */
00314   {
00315     const char * files[] =
00316     { "/etc/passwd",
00317       "/proc/loadavg",
00318       "/proc/meminfo",
00319       "/proc/net/dev",
00320       "/proc/rtc",
00321       "/proc/self/environ",
00322       "/proc/self/stat",
00323       "/proc/stat",
00324       "/proc/uptime",
00325       NULL
00326     };
00327     int i;
00328 
00329     for (i = 0; files[i] != NULL; i++)
00330       bytes += init_from_file(files[i], BLOCKSIZE);
00331   }
00332 
00333   /* directories */
00334   {
00335     const char * dirname;
00336     const char * dirs[] =
00337     {
00338       "/proc",
00339       P_tmpdir,
00340       "/var/lock",
00341       "/var/log",
00342       "/var/mail",
00343       "/var/spool/mail",
00344       "/var/run",
00345       NULL
00346     };
00347     int i;
00348 
00349     for (i = 0; dirs[i] != NULL; i++)
00350       bytes += init_from_dir(dirs[i], 32);
00351 
00352     dirname = getenv("HOME");
00353     if (dirname != NULL)
00354       bytes += init_from_dir(dirname, 32);
00355   }
00356 
00357   /* process and parent ids */
00358   {
00359     pid_t pid;
00360 
00361     pid = getpid();
00362     md5_process_bytes(&pid, sizeof(pid), &guid_context);
00363     bytes += sizeof(pid);
00364 
00365     pid = getppid();
00366     md5_process_bytes(&pid, sizeof(pid), &guid_context);
00367     bytes += sizeof(pid);
00368   }
00369 
00370   /* user info */
00371   {
00372     uid_t uid;
00373     gid_t gid;
00374     char *s;
00375 
00376     s = getlogin();
00377     if (s != NULL)
00378     {
00379       md5_process_bytes(s, strlen(s), &guid_context);
00380       bytes += strlen(s);
00381     }
00382 
00383     uid = getuid();
00384     md5_process_bytes(&uid, sizeof(uid), &guid_context);
00385     bytes += sizeof(uid);
00386 
00387     gid = getgid();
00388     md5_process_bytes(&gid, sizeof(gid), &guid_context);
00389     bytes += sizeof(gid);
00390   }
00391 
00392   /* host info */
00393   {
00394     char string[1024];
00395 
00396     memset(string, 0, sizeof(string));
00397     gethostname(string, sizeof(string));
00398     md5_process_bytes(string, sizeof(string), &guid_context);
00399     bytes += sizeof(string);
00400   }
00401 
00402   /* plain old random */
00403   {
00404     int n, i;
00405 
00406     srand((unsigned int) time(NULL));
00407 
00408     for (i = 0; i < 32; i++)
00409     {
00410       n = rand();
00411 
00412       md5_process_bytes(&n, sizeof(n), &guid_context);
00413       bytes += sizeof(n);
00414     }
00415   }
00416 
00417   /* time in secs and clock ticks */
00418   bytes += init_from_time();
00419 
00420   PINFO ("got %llu bytes", (unsigned long long int) bytes);
00421 
00422   if (bytes < THRESHOLD)
00423     PWARN("only got %llu bytes.\n"
00424               "The identifiers might not be very random.\n",
00425           (unsigned long long int)bytes);
00426 
00427   guid_initialized = TRUE;
00428 }

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 439 of file guid.c.

00440 {
00441   md5_init_ctx(&guid_context);
00442 
00443   md5_process_bytes(salt, salt_len, &guid_context);
00444 
00445   guid_initialized = TRUE;
00446 }

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 431 of file guid.c.

00432 {
00433   guid_init();
00434 
00435   md5_process_bytes(salt, salt_len, &guid_context);
00436 }

GUID* guid_malloc void   ) 
 

Efficiently allocate & free memory for GUIDs

Definition at line 83 of file guid.c.

00084 {
00085   if (!guid_memchunk) guid_memchunk_init();
00086   return g_chunk_new (GUID, guid_memchunk);
00087 }

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 457 of file guid.c.

00458 {
00459   static int counter = 0;
00460   struct md5_ctx ctx;
00461 
00462   if (guid == NULL)
00463     return;
00464 
00465   if (!guid_initialized)
00466     guid_init();
00467 
00468   /* make the id */
00469   ctx = guid_context;
00470   md5_finish_ctx(&ctx, guid->data);
00471 
00472   /* update the global context */
00473   init_from_time();
00474 
00475   /* Make it a little extra salty.  I think init_from_time was buggy,
00476         * or something, since duplicate id's actually happened. Or something
00477         * like that.  I think this is because init_from_time kept returning
00478         * the same values too many times in a row.  So we'll do some 'block
00479         * chaining', and feed in the old guid as new random data.
00480         *
00481         * Anyway, I think the whole fact that I saw a bunch of duplicate 
00482         * id's at one point, but can't reproduce the bug is rather alarming.
00483         * Something must be broken somewhere, and merely adding more salt
00484         * is just hiding the problem, not fixing it.
00485         */
00486   init_from_int (433781*counter);
00487   init_from_buff (guid->data, 16);
00488 
00489   if (counter == 0)
00490   {
00491     FILE *fp;
00492 
00493     fp = fopen ("/dev/urandom", "r");
00494     if (fp == NULL)
00495       return;
00496 
00497     init_from_stream(fp, 32);
00498 
00499     fclose(fp);
00500 
00501     counter = GUID_PERIOD;
00502   }
00503 
00504   counter--;
00505 }

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 508 of file guid.c.

00509 {
00510   GUID guid;
00511 
00512   guid_new (&guid);
00513 
00514   return guid;
00515 }

const GUID* guid_null void   ) 
 

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

Definition at line 100 of file guid.c.

00101 {
00102   static int null_inited = 0;
00103   static GUID null_guid;
00104 
00105   if (!null_inited)
00106   {
00107     int i;
00108     char *tmp = "NULLGUID.EMPTY.";
00109 
00110       /* 16th space for '\O' */
00111     for (i = 0; i < 16; i++)
00112       null_guid.data[i] = tmp[i];
00113 
00114     null_inited = 1;
00115   }
00116 
00117   return &null_guid;
00118 }

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 449 of file guid.c.

00450 {
00451         guid_memchunk_shutdown();
00452 }

const char* 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 576 of file guid.c.

00577 {
00578 #ifdef G_THREADS_ENABLED
00579   static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT;
00580   gchar *string;
00581 
00582   string = g_static_private_get (&guid_buffer_key);
00583   if (string == NULL) {
00584     string = malloc(GUID_ENCODING_LENGTH+1);
00585     g_static_private_set (&guid_buffer_key, string, g_free);
00586   }
00587 #else
00588   static char string[64];
00589 #endif
00590 
00591   encode_md5_data(guid->data, string);
00592   string[GUID_ENCODING_LENGTH] = '\0';
00593 
00594   return string;
00595 }

char* guid_to_string_buff const GUID guid,
char *  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.

Definition at line 598 of file guid.c.

00599 {
00600   if (!string || !guid) return NULL;
00601 
00602   encode_md5_data(guid->data, string);
00603 
00604   string[GUID_ENCODING_LENGTH] = '\0';
00605   return &string[GUID_ENCODING_LENGTH];
00606 }

gboolean string_to_guid const char *  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.

Definition at line 609 of file guid.c.

00610 {
00611   return decode_md5_string(string, (guid != NULL) ? guid->data : NULL);
00612 }


Generated on Fri Oct 21 15:49:58 2005 for QOF by  doxygen 1.4.5