os_fid.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:4k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: os_fid.c,v 11.14 2002/08/26 14:37:38 margo Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #if TIME_WITH_SYS_TIME
  15. #include <sys/time.h>
  16. #include <time.h>
  17. #else
  18. #if HAVE_SYS_TIME_H
  19. #include <sys/time.h>
  20. #else
  21. #include <time.h>
  22. #endif
  23. #endif
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #endif
  28. #include "db_int.h"
  29. #define SERIAL_INIT 0
  30. static u_int32_t fid_serial = SERIAL_INIT;
  31. /*
  32.  * __os_fileid --
  33.  * Return a unique identifier for a file.  The structure
  34.  * of a fileid is: ino(4) dev(4) time(4) pid(4) extra(4).
  35.  * For real files, which have a backing inode and device, the first
  36.  * 16 bytes are filled in and the extra bytes are left 0.  For
  37.  * temporary files, the inode and device fields are left blank and
  38.  * the extra four bytes are filled in with a random value.
  39.  *
  40.  * PUBLIC: int __os_fileid __P((DB_ENV *, const char *, int, u_int8_t *));
  41.  */
  42. int
  43. __os_fileid(dbenv, fname, unique_okay, fidp)
  44. DB_ENV *dbenv;
  45. const char *fname;
  46. int unique_okay;
  47. u_int8_t *fidp;
  48. {
  49. struct stat sb;
  50. size_t i;
  51. int ret;
  52. u_int32_t tmp;
  53. u_int8_t *p;
  54. /* Clear the buffer. */
  55. memset(fidp, 0, DB_FILE_ID_LEN);
  56. /* On POSIX/UNIX, use a dev/inode pair. */
  57. retry:
  58. #ifdef HAVE_VXWORKS
  59. if (stat((char *)fname, &sb) != 0) {
  60. #else
  61. if (stat(fname, &sb) != 0) {
  62. #endif
  63. if ((ret = __os_get_errno()) == EINTR)
  64. goto retry;
  65. __db_err(dbenv, "%s: %s", fname, strerror(ret));
  66. return (ret);
  67. }
  68. /*
  69.  * Initialize/increment the serial number we use to help avoid
  70.  * fileid collisions.  Note that we don't bother with locking;
  71.  * it's unpleasant to do from down in here, and if we race on
  72.  * this no real harm will be done, since the finished fileid
  73.  * has so many other components.
  74.  *
  75.  * We increment by 100000 on each call as a simple way of
  76.  * randomizing;  simply incrementing seems potentially less useful
  77.  * if pids are also simply incremented, since this is process-local
  78.  * and we may be one of a set of processes starting up.  100000
  79.  * pushes us out of pid space on most platforms, and has few
  80.  * interesting properties in base 2.
  81.  */
  82. if (fid_serial == SERIAL_INIT)
  83. __os_id(&fid_serial);
  84. else
  85. fid_serial += 100000;
  86. /*
  87.  * !!!
  88.  * Nothing is ever big enough -- on Sparc V9, st_ino, st_dev and the
  89.  * time_t types are all 8 bytes.  As DB_FILE_ID_LEN is only 20 bytes,
  90.  * we convert to a (potentially) smaller fixed-size type and use it.
  91.  *
  92.  * We don't worry about byte sexing or the actual variable sizes.
  93.  *
  94.  * When this routine is called from the DB access methods, it's only
  95.  * called once -- whatever ID is generated when a database is created
  96.  * is stored in the database file's metadata, and that is what is
  97.  * saved in the mpool region's information to uniquely identify the
  98.  * file.
  99.  *
  100.  * When called from the mpool layer this routine will be called each
  101.  * time a new thread of control wants to share the file, which makes
  102.  * things tougher.  As far as byte sexing goes, since the mpool region
  103.  * lives on a single host, there's no issue of that -- the entire
  104.  * region is byte sex dependent.  As far as variable sizes go, we make
  105.  * the simplifying assumption that 32-bit and 64-bit processes will
  106.  * get the same 32-bit values if we truncate any returned 64-bit value
  107.  * to a 32-bit value.  When we're called from the mpool layer, though,
  108.  * we need to be careful not to include anything that isn't
  109.  * reproducible for a given file, such as the timestamp or serial
  110.  * number.
  111.  */
  112. tmp = (u_int32_t)sb.st_ino;
  113. for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
  114. *fidp++ = *p++;
  115. tmp = (u_int32_t)sb.st_dev;
  116. for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
  117. *fidp++ = *p++;
  118. if (unique_okay) {
  119. /*
  120.  * We want the number of seconds, not the high-order 0 bits,
  121.  * so convert the returned time_t to a (potentially) smaller
  122.  * fixed-size type.
  123.  */
  124. tmp = (u_int32_t)time(NULL);
  125. for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
  126. *fidp++ = *p++;
  127. for (p = (u_int8_t *)&fid_serial, i = sizeof(u_int32_t);
  128.     i > 0; --i)
  129. *fidp++ = *p++;
  130. }
  131. return (0);
  132. }