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 GNC_TYPE_GUID   (gnc_guid_get_type())
#define GNC_VALUE_HOLDS_GUID(value)   G_VALUE_HOLDS(value, GNC_TYPE_GUID)
#define GUID_ENCODING_LENGTH   32

Typedefs

typedef _GUID GUID

Functions

GType gnc_guid_get_type (void)
G_CONST_RETURN GUIDgnc_value_get_guid (const GValue *value)
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)
GUIDguid_copy (const 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 53 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 71 of file guid.h.


Function Documentation

G_CONST_RETURN GUID* gnc_value_get_guid ( const GValue *  value  ) 

gnc_value_get_guid : a GValue whose value we want to get.

Returns: the value stored in .

Definition at line 73 of file guid.c.

00074 {
00075         GUID *val;
00076 
00077         g_return_val_if_fail (value && G_IS_VALUE (value), NULL);
00078         g_return_val_if_fail (GNC_VALUE_HOLDS_GUID (value), NULL);
00079 
00080         val = (GUID*) g_value_get_boxed (value);
00081 
00082         return val;
00083 }

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

00676 {
00677   if (guid_1 && guid_2)
00678     return (memcmp(guid_1, guid_2, GUID_DATA_SIZE) == 0);
00679   else
00680     return FALSE;
00681 }

guint guid_hash_to_guint ( gconstpointer  ptr  ) 

Given a GUID *, hash it to a guint

Definition at line 700 of file guid.c.

00701 {
00702   const GUID *guid = ptr;
00703 
00704   if (!guid)
00705   {
00706     PERR ("received NULL guid pointer.");
00707     return 0;
00708   }
00709 
00710   if (sizeof(guint) <= sizeof(guid->data))
00711   {
00712     return (*((guint *) guid->data));
00713   }
00714   else
00715   {
00716     guint hash = 0;
00717     unsigned int i, j;
00718 
00719     for (i = 0, j = 0; i < sizeof(guint); i++, j++) {
00720       if (j == GUID_DATA_SIZE) j = 0;
00721 
00722       hash <<= 4;
00723       hash |= guid->data[j];
00724     }
00725 
00726     return hash;
00727   }
00728 }

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

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

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

00498 {
00499   md5_init_ctx(&guid_context);
00500 
00501   md5_process_bytes(salt, salt_len, &guid_context);
00502 
00503   guid_initialized = TRUE;
00504 }

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

00490 {
00491   guid_init();
00492 
00493   md5_process_bytes(salt, salt_len, &guid_context);
00494 }

GUID* guid_malloc ( void   ) 

Efficiently allocate & free memory for GUIDs

Definition at line 122 of file guid.c.

00123 {
00124   if (!guid_memchunk) guid_memchunk_init();
00125   return g_chunk_new (GUID, guid_memchunk);
00126 }

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

00518 {
00519   static int counter = 0;
00520   struct md5_ctx ctx;
00521 
00522   if (guid == NULL)
00523     return;
00524 
00525   if (!guid_initialized)
00526     guid_init();
00527 
00528   /* make the id */
00529   ctx = guid_context;
00530   md5_finish_ctx(&ctx, guid->data);
00531 
00532   /* update the global context */
00533   init_from_time();
00534 
00535   /* Make it a little extra salty.  I think init_from_time was buggy,
00536         * or something, since duplicate id's actually happened. Or something
00537         * like that.  I think this is because init_from_time kept returning
00538         * the same values too many times in a row.  So we'll do some 'block
00539         * chaining', and feed in the old guid as new random data.
00540         *
00541         * Anyway, I think the whole fact that I saw a bunch of duplicate 
00542         * id's at one point, but can't reproduce the bug is rather alarming.
00543         * Something must be broken somewhere, and merely adding more salt
00544         * is just hiding the problem, not fixing it.
00545         */
00546   init_from_int (433781*counter);
00547   init_from_buff (guid->data, GUID_DATA_SIZE);
00548 
00549   if (counter == 0)
00550   {
00551     FILE *fp;
00552 
00553     fp = g_fopen ("/dev/urandom", "r");
00554     if (fp == NULL)
00555       return;
00556 
00557     init_from_stream(fp, 32);
00558 
00559     fclose(fp);
00560 
00561     counter = GUID_PERIOD;
00562   }
00563 
00564   counter--;
00565 }

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

00569 {
00570   GUID guid;
00571 
00572   guid_new (&guid);
00573 
00574   return guid;
00575 }

const GUID* guid_null ( void   ) 

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

Definition at line 151 of file guid.c.

00152 {
00153   static int null_inited = 0;
00154   static GUID null_guid;
00155 
00156   if (!null_inited) {
00157       int i;
00158 
00159       for (i = 0; i < GUID_DATA_SIZE; i++)
00160           null_guid.data[i] = '\0';
00161 
00162       null_inited = 1;
00163   }
00164 
00165   return &null_guid;
00166 }

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

00508 {
00509 #ifndef HAVE_GLIB29
00510         guid_memchunk_shutdown();
00511 #endif
00512 }

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

00637 {
00638 #ifdef G_THREADS_ENABLED
00639   static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT;
00640   gchar *string;
00641 
00642   string = g_static_private_get (&guid_buffer_key);
00643   if (string == NULL) {
00644     string = malloc(GUID_ENCODING_LENGTH+1);
00645     g_static_private_set (&guid_buffer_key, string, g_free);
00646   }
00647 #else
00648   static char string[64];
00649 #endif
00650 
00651   encode_md5_data(guid->data, string);
00652   string[GUID_ENCODING_LENGTH] = '\0';
00653 
00654   return string;
00655 }

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 Jul 3 05:07:21 2008 for GnuCash by  doxygen 1.5.2