Sophie

Sophie

distrib > Mandriva > current > x86_64 > by-pkgid > f55d1abfaaf6723462aacad8a1db97a8 > files > 2

db2-2.4.14-23mdv2010.1.src.rpm

--- db2/os/os_fid.c.db_fileid-64bit-fix	1998-06-09 11:04:45.000000000 -0400
+++ db2/os/os_fid.c	2002-11-23 03:56:38.000000000 -0500
@@ -17,12 +17,17 @@ static const char sccsid[] = "@(#)os_fid
 
 #include <errno.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
 #include <time.h>
 #endif
 
 #include "db_int.h"
 #include "common_ext.h"
 
+#define	SERIAL_INIT	0
+static u_int32_t fid_serial = SERIAL_INIT;
+
 /*
  * __db_fileid --
  *	Return a unique identifier for a file.
@@ -38,39 +43,85 @@ __db_fileid(dbenv, fname, timestamp, fid
 {
 	struct stat sb;
 	size_t i;
-	time_t now;
+ 	int ret;
+ 	u_int32_t tmp;
 	u_int8_t *p;
 
 	/* Clear the buffer. */
 	memset(fidp, 0, DB_FILE_ID_LEN);
 
-	/* Check for the unthinkable. */
-	if (sizeof(sb.st_ino) +
-	    sizeof(sb.st_dev) + sizeof(time_t) > DB_FILE_ID_LEN)
-		return (EINVAL);
-
-	/* On UNIX, use a dev/inode pair. */
 	if (stat(fname, &sb)) {
 		__db_err(dbenv, "%s: %s", fname, strerror(errno));
 		return (errno);
 	}
 
 	/*
-	 * Use the inode first and in reverse order, hopefully putting the
-	 * distinguishing information early in the string.
+	 * Initialize/increment the serial number we use to help avoid
+	 * fileid collisions.  Note that we don't bother with locking;
+	 * it's unpleasant to do from down in here, and if we race on
+	 * this no real harm will be done, since the finished fileid
+	 * has so many other components.
+	 *
+	 * We increment by 100000 on each call as a simple way of
+	 * randomizing;  simply incrementing seems potentially less useful
+	 * if pids are also simply incremented, since this is process-local
+	 * and we may be one of a set of processes starting up.  100000
+	 * pushes us out of pid space on most platforms, and has few
+	 * interesting properties in base 2.
+	 */
+	if (fid_serial == SERIAL_INIT)
+		fid_serial = (u_int32_t)getpid();
+	else
+		fid_serial += 100000;
+
+	/*
+	 * !!!
+	 * Nothing is ever big enough -- on Sparc V9, st_ino, st_dev and the
+	 * time_t types are all 8 bytes.  As DB_FILE_ID_LEN is only 20 bytes,
+	 * we convert to a (potentially) smaller fixed-size type and use it.
+	 *
+	 * We don't worry about byte sexing or the actual variable sizes.
+	 *
+	 * When this routine is called from the DB access methods, it's only
+	 * called once -- whatever ID is generated when a database is created
+	 * is stored in the database file's metadata, and that is what is
+	 * saved in the mpool region's information to uniquely identify the
+	 * file.
+	 *
+	 * When called from the mpool layer this routine will be called each
+	 * time a new thread of control wants to share the file, which makes
+	 * things tougher.  As far as byte sexing goes, since the mpool region
+	 * lives on a single host, there's no issue of that -- the entire
+	 * region is byte sex dependent.  As far as variable sizes go, we make
+	 * the simplifying assumption that 32-bit and 64-bit processes will
+	 * get the same 32-bit values if we truncate any returned 64-bit value
+	 * to a 32-bit value.  When we're called from the mpool layer, though,
+	 * we need to be careful not to include anything that isn't
+	 * reproducible for a given file, such as the timestamp or serial
+	 * number.
 	 */
-	for (p = (u_int8_t *)&sb.st_ino +
-	    sizeof(sb.st_ino), i = 0; i < sizeof(sb.st_ino); ++i)
-		*fidp++ = *--p;
-	for (p = (u_int8_t *)&sb.st_dev +
-	    sizeof(sb.st_dev), i = 0; i < sizeof(sb.st_dev); ++i)
-		*fidp++ = *--p;
+	tmp = (u_int32_t)sb.st_ino;
+	for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
+		*fidp++ = *p++;
+
+	tmp = (u_int32_t)sb.st_dev;
+	for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
+		*fidp++ = *p++;
 
 	if (timestamp) {
-		(void)time(&now);
-		for (p = (u_int8_t *)&now +
-		    sizeof(now), i = 0; i < sizeof(now); ++i)
-			*fidp++ = *--p;
+		/*
+		 * We want the number of seconds, not the high-order 0 bits,
+		 * so convert the returned time_t to a (potentially) smaller
+		 * fixed-size type.
+		 */
+		tmp = (u_int32_t)time(NULL);
+		for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
+			*fidp++ = *p++;
+
+		for (p = (u_int8_t *)&fid_serial, i = sizeof(u_int32_t);
+		    i > 0; --i)
+			*fidp++ = *p++;
 	}
+
 	return (0);
 }