GUID
[Class: Getting and setting entity values.]


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 union _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 GUID * guid_null (void)
GUID * guid_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 652 of file guid.c.

00653 {
00654     if (guid_1 && guid_2)
00655         return (memcmp (guid_1, guid_2, GUID_DATA_SIZE) == 0);
00656     else
00657         return FALSE;
00658 }

guint guid_hash_to_guint ( gconstpointer  ptr  ) 

Given a GUID *, hash it to a guint

Definition at line 677 of file guid.c.

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

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

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

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

00468 {
00469     md5_init_ctx (&guid_context);
00470 
00471     md5_process_bytes (salt, salt_len, &guid_context);
00472 
00473     guid_initialized = TRUE;
00474 }

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

00460 {
00461     guid_init ();
00462 
00463     md5_process_bytes (salt, salt_len, &guid_context);
00464 }

GUID* guid_malloc ( void   ) 

Efficiently allocate & free memory for GUIDs

Definition at line 100 of file guid.c.

00101 {
00102     if (!guid_memchunk)
00103         guid_memchunk_init ();
00104     return g_chunk_new (GUID, guid_memchunk);
00105 }

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

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

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

00539 {
00540     GUID guid;
00541 
00542     guid_new (&guid);
00543 
00544     return guid;
00545 }

const GUID* guid_null ( void   ) 

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

Definition at line 119 of file guid.c.

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

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

00478 {
00479 #ifndef HAVE_GLIB29
00480     guid_memchunk_shutdown ();
00481 #endif
00482 }

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

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

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 Thu Jan 31 22:50:27 2008 for QOF by  doxygen 1.5.4