~ubuntu-branches/ubuntu/edgy/rpm/edgy

« back to all changes in this revision

Viewing changes to db/os_win32/os_fid.c

  • Committer: Bazaar Package Importer
  • Author(s): Joey Hess
  • Date: 2002-01-22 20:56:57 UTC
  • Revision ID: james.westby@ubuntu.com-20020122205657-l74j50mr9z8ofcl5
Tags: upstream-4.0.3
ImportĀ upstreamĀ versionĀ 4.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * See the file LICENSE for redistribution information.
 
3
 *
 
4
 * Copyright (c) 1996-2001
 
5
 *      Sleepycat Software.  All rights reserved.
 
6
 */
 
7
 
 
8
#include "db_config.h"
 
9
 
 
10
#ifndef lint
 
11
static const char revid[] = "$Id: os_fid.c,v 11.8 2001/01/25 18:23:00 bostic Exp $";
 
12
#endif /* not lint */
 
13
 
 
14
#include "db_int.h"
 
15
 
 
16
#define SERIAL_INIT     0
 
17
static u_int32_t fid_serial = SERIAL_INIT;
 
18
 
 
19
/*
 
20
 * __os_fileid --
 
21
 *      Return a unique identifier for a file.
 
22
 */
 
23
int
 
24
__os_fileid(dbenv, fname, unique_okay, fidp)
 
25
        DB_ENV *dbenv;
 
26
        const char *fname;
 
27
        int unique_okay;
 
28
        u_int8_t *fidp;
 
29
{
 
30
        size_t i;
 
31
        u_int32_t tmp;
 
32
        u_int8_t *p;
 
33
        int ret;
 
34
 
 
35
        /*
 
36
         * The documentation for GetFileInformationByHandle() states that the
 
37
         * inode-type numbers are not constant between processes.  Actually,
 
38
         * they are, they're the NTFS MFT indexes.  So, this works on NTFS,
 
39
         * but perhaps not on other platforms, and perhaps not over a network.
 
40
         * Can't think of a better solution right now.
 
41
         */
 
42
        DB_FH fh;
 
43
        HANDLE handle;
 
44
        BY_HANDLE_FILE_INFORMATION fi;
 
45
        BOOL retval = FALSE;
 
46
 
 
47
        /* Clear the buffer. */
 
48
        memset(fidp, 0, DB_FILE_ID_LEN);
 
49
 
 
50
        /*
 
51
         * Initialize/increment the serial number we use to help avoid
 
52
         * fileid collisions.  Note that we don't bother with locking;
 
53
         * it's unpleasant to do from down in here, and if we race on
 
54
         * this no real harm will be done, since the finished fileid
 
55
         * has so many other components.
 
56
         *
 
57
         * We increment by 100000 on each call as a simple way of
 
58
         * randomizing;  simply incrementing seems potentially less useful
 
59
         * if pids are also simply incremented, since this is process-local
 
60
         * and we may be one of a set of processes starting up.  100000
 
61
         * pushes us out of pid space on most platforms, and has few
 
62
         * interesting properties in base 2.
 
63
         */
 
64
        if (fid_serial == SERIAL_INIT)
 
65
                fid_serial = (u_int32_t)getpid();
 
66
        else
 
67
                fid_serial += 100000;
 
68
 
 
69
        /*
 
70
         * First we open the file, because we're not given a handle to it.
 
71
         * If we can't open it, we're in trouble.
 
72
         */
 
73
        if ((ret = __os_open(dbenv, fname, DB_OSO_RDONLY, _S_IREAD, &fh)) != 0)
 
74
                return (ret);
 
75
 
 
76
        /* File open, get its info */
 
77
        handle = (HANDLE)_get_osfhandle(fh.fd);
 
78
        if (handle == INVALID_HANDLE_VALUE)
 
79
                ret = __os_win32_errno();
 
80
        else
 
81
                if ((retval = GetFileInformationByHandle(handle, &fi)) == FALSE)
 
82
                        ret = __os_win32_errno();
 
83
        __os_closehandle(&fh);
 
84
 
 
85
        if (handle == INVALID_HANDLE_VALUE || retval == FALSE)
 
86
                return (ret);
 
87
 
 
88
        /*
 
89
         * We want the three 32-bit words which tell us the volume ID and
 
90
         * the file ID.  We make a crude attempt to copy the bytes over to
 
91
         * the callers buffer.
 
92
         *
 
93
         * We don't worry about byte sexing or the actual variable sizes.
 
94
         *
 
95
         * When this routine is called from the DB access methods, it's only
 
96
         * called once -- whatever ID is generated when a database is created
 
97
         * is stored in the database file's metadata, and that is what is
 
98
         * saved in the mpool region's information to uniquely identify the
 
99
         * file.
 
100
         *
 
101
         * When called from the mpool layer this routine will be called each
 
102
         * time a new thread of control wants to share the file, which makes
 
103
         * things tougher.  As far as byte sexing goes, since the mpool region
 
104
         * lives on a single host, there's no issue of that -- the entire
 
105
         * region is byte sex dependent.  As far as variable sizes go, we make
 
106
         * the simplifying assumption that 32-bit and 64-bit processes will
 
107
         * get the same 32-bit values if we truncate any returned 64-bit value
 
108
         * to a 32-bit value.
 
109
         */
 
110
        tmp = (u_int32_t)fi.nFileIndexLow;
 
111
        for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
 
112
                *fidp++ = *p++;
 
113
        tmp = (u_int32_t)fi.nFileIndexHigh;
 
114
        for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
 
115
                *fidp++ = *p++;
 
116
        if (unique_okay) {
 
117
                /*
 
118
                 * Use the system time to try to get a unique value
 
119
                 * within this process.  A millisecond counter
 
120
                 * overflows 32 bits in about 49 days.  So we use 8
 
121
                 * bytes, and don't bother with the volume ID, which
 
122
                 * is not very useful for our purposes.
 
123
                 */
 
124
                SYSTEMTIME st;
 
125
 
 
126
                GetSystemTime(&st);
 
127
                tmp = (st.wYear - 1900) * 12 + (st.wMonth - 1);
 
128
                for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
 
129
                        *fidp++ = *p++;
 
130
                tmp = ((((st.wDay - 1) * 24 + st.wHour) * 60 +
 
131
                        st.wMinute) * 60 + st.wSecond) * 1000 +
 
132
                        st.wMilliseconds;
 
133
                for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
 
134
                        *fidp++ = *p++;
 
135
                for (p = (u_int8_t *)&fid_serial, i = sizeof(u_int32_t);
 
136
                    i > 0; --i)
 
137
                        *fidp++ = *p++;
 
138
        } else {
 
139
                tmp = (u_int32_t)fi.dwVolumeSerialNumber;
 
140
                for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
 
141
                        *fidp++ = *p++;
 
142
        }
 
143
 
 
144
        return (0);
 
145
}