1 | /*- |
---|
2 | * See the file LICENSE for redistribution information. |
---|
3 | * |
---|
4 | * Copyright (c) 1998-2002 |
---|
5 | * Sleepycat Software. All rights reserved. |
---|
6 | */ |
---|
7 | |
---|
8 | #include "db_config.h" |
---|
9 | |
---|
10 | #ifndef lint |
---|
11 | static const char revid[] = "Id: os_handle.c,v 11.30 2002/07/12 18:56:54 bostic Exp "; |
---|
12 | #endif /* not lint */ |
---|
13 | |
---|
14 | #ifndef NO_SYSTEM_INCLUDES |
---|
15 | #include <sys/types.h> |
---|
16 | |
---|
17 | #include <fcntl.h> |
---|
18 | #include <string.h> |
---|
19 | #include <unistd.h> |
---|
20 | #endif |
---|
21 | |
---|
22 | #include "db_int.h" |
---|
23 | |
---|
24 | /* |
---|
25 | * __os_openhandle -- |
---|
26 | * Open a file, using POSIX 1003.1 open flags. |
---|
27 | * |
---|
28 | * PUBLIC: int __os_openhandle __P((DB_ENV *, const char *, int, int, DB_FH *)); |
---|
29 | */ |
---|
30 | int |
---|
31 | __os_openhandle(dbenv, name, flags, mode, fhp) |
---|
32 | DB_ENV *dbenv; |
---|
33 | const char *name; |
---|
34 | int flags, mode; |
---|
35 | DB_FH *fhp; |
---|
36 | { |
---|
37 | int ret, nrepeat; |
---|
38 | |
---|
39 | memset(fhp, 0, sizeof(*fhp)); |
---|
40 | fhp->handle = INVALID_HANDLE_VALUE; |
---|
41 | |
---|
42 | /* If the application specified an interface, use it. */ |
---|
43 | if (DB_GLOBAL(j_open) != NULL) { |
---|
44 | if ((fhp->fd = DB_GLOBAL(j_open)(name, flags, mode)) == -1) |
---|
45 | return (__os_get_errno()); |
---|
46 | F_SET(fhp, DB_FH_VALID); |
---|
47 | return (0); |
---|
48 | } |
---|
49 | |
---|
50 | for (nrepeat = 1; nrepeat < 4; ++nrepeat) { |
---|
51 | ret = 0; |
---|
52 | fhp->fd = open(name, flags, mode); |
---|
53 | |
---|
54 | if (fhp->fd == -1) { |
---|
55 | /* |
---|
56 | * If it's a "temporary" error, we retry up to 3 times, |
---|
57 | * waiting up to 12 seconds. While it's not a problem |
---|
58 | * if we can't open a database, an inability to open a |
---|
59 | * log file is cause for serious dismay. |
---|
60 | */ |
---|
61 | ret = __os_get_errno(); |
---|
62 | if (ret == ENFILE || ret == EMFILE || ret == ENOSPC) { |
---|
63 | (void)__os_sleep(dbenv, nrepeat * 2, 0); |
---|
64 | continue; |
---|
65 | } |
---|
66 | |
---|
67 | /* |
---|
68 | * If it was an EINTR it's reasonable to retry |
---|
69 | * immediately, and arbitrarily often. |
---|
70 | */ |
---|
71 | if (ret == EINTR) { |
---|
72 | --nrepeat; |
---|
73 | continue; |
---|
74 | } |
---|
75 | } else { |
---|
76 | F_SET(fhp, DB_FH_VALID); |
---|
77 | } |
---|
78 | break; |
---|
79 | } |
---|
80 | |
---|
81 | return (ret); |
---|
82 | } |
---|
83 | |
---|
84 | /* |
---|
85 | * __os_closehandle -- |
---|
86 | * Close a file. |
---|
87 | * |
---|
88 | * PUBLIC: int __os_closehandle __P((DB_ENV *, DB_FH *)); |
---|
89 | */ |
---|
90 | int |
---|
91 | __os_closehandle(dbenv, fhp) |
---|
92 | DB_ENV *dbenv; |
---|
93 | DB_FH *fhp; |
---|
94 | { |
---|
95 | BOOL success; |
---|
96 | int ret; |
---|
97 | |
---|
98 | COMPQUIET(dbenv, NULL); |
---|
99 | /* Don't close file descriptors that were never opened. */ |
---|
100 | DB_ASSERT(F_ISSET(fhp, DB_FH_VALID) && |
---|
101 | ((fhp->fd != -1) || (fhp->handle != INVALID_HANDLE_VALUE))); |
---|
102 | |
---|
103 | ret = 0; |
---|
104 | |
---|
105 | do { |
---|
106 | if (DB_GLOBAL(j_close) != NULL) |
---|
107 | success = (DB_GLOBAL(j_close)(fhp->fd) == 0); |
---|
108 | else if (fhp->handle != INVALID_HANDLE_VALUE) { |
---|
109 | success = CloseHandle(fhp->handle); |
---|
110 | if (!success) |
---|
111 | __os_set_errno(__os_win32_errno()); |
---|
112 | } |
---|
113 | else |
---|
114 | success = (close(fhp->fd) == 0); |
---|
115 | } while (!success && (ret = __os_get_errno()) == EINTR); |
---|
116 | |
---|
117 | /* |
---|
118 | * Smash the POSIX file descriptor -- it's never tested, but we want |
---|
119 | * to catch any mistakes. |
---|
120 | */ |
---|
121 | fhp->fd = -1; |
---|
122 | fhp->handle = INVALID_HANDLE_VALUE; |
---|
123 | F_CLR(fhp, DB_FH_VALID); |
---|
124 | |
---|
125 | return (ret); |
---|
126 | } |
---|