Remove definition of builtin function
[platform/upstream/db4.git] / fileops / fop_basic.c
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2001-2009 Oracle.  All rights reserved.
5  *
6  * $Id$
7  */
8
9 #include "db_config.h"
10
11 #include "db_int.h"
12 #include "dbinc/db_page.h"
13 #include "dbinc/fop.h"
14 #include "dbinc/log.h"
15 #include "dbinc/mp.h"
16 #include "dbinc/txn.h"
17 #include "dbinc/db_am.h"
18
19 /*
20  * The transactional guarantees Berkeley DB provides for file
21  * system level operations (database physical file create, delete,
22  * rename) are based on our understanding of current file system
23  * semantics; a system that does not provide these semantics and
24  * guarantees could be in danger.
25  *
26  * First, as in standard database changes, fsync and fdatasync must
27  * work: when applied to the log file, the records written into the
28  * log must be transferred to stable storage.
29  *
30  * Second, it must not be possible for the log file to be removed
31  * without previous file system level operations being flushed to
32  * stable storage.  Berkeley DB applications write log records
33  * describing file system operations into the log, then perform the
34  * file system operation, then commit the enclosing transaction
35  * (which flushes the log file to stable storage).  Subsequently,
36  * a database environment checkpoint may make it possible for the
37  * application to remove the log file containing the record of the
38  * file system operation.  DB's transactional guarantees for file
39  * system operations require the log file removal not succeed until
40  * all previous filesystem operations have been flushed to stable
41  * storage.  In other words, the flush of the log file, or the
42  * removal of the log file, must block until all previous
43  * filesystem operations have been flushed to stable storage.  This
44  * semantic is not, as far as we know, required by any existing
45  * standards document, but we have never seen a filesystem where
46  * it does not apply.
47  */
48
49 /*
50  * __fop_create --
51  * Create a (transactionally protected) file system object.  This is used
52  * to create DB files now, potentially blobs, queue extents and anything
53  * else you wish to store in a file system object.
54  *
55  * PUBLIC: int __fop_create __P((ENV *, DB_TXN *,
56  * PUBLIC:     DB_FH **, const char *, const char **, APPNAME, int, u_int32_t));
57  */
58 int
59 __fop_create(env, txn, fhpp, name, dirp, appname, mode, flags)
60         ENV *env;
61         DB_TXN *txn;
62         DB_FH **fhpp;
63         const char *name, **dirp;
64         APPNAME appname;
65         int mode;
66         u_int32_t flags;
67 {
68         DBT data, dirdata;
69         DB_FH *fhp;
70         DB_LSN lsn;
71         int ret;
72         char *real_name;
73
74         real_name = NULL;
75         fhp = NULL;
76
77         if ((ret = __db_appname(env, appname, name, dirp, &real_name)) != 0)
78                 return (ret);
79
80         if (mode == 0)
81                 mode = DB_MODE_600;
82
83         if (DBENV_LOGGING(env)
84 #if !defined(DEBUG_WOP)
85             && txn != NULL
86 #endif
87             ) {
88                 DB_INIT_DBT(data, name, strlen(name) + 1);
89                 if (dirp != NULL && *dirp != NULL)
90                         DB_INIT_DBT(dirdata, *dirp, strlen(*dirp) + 1);
91                 else
92                         memset(&dirdata, 0, sizeof(dirdata));
93                 if ((ret = __fop_create_log(env, txn, &lsn,
94                     flags | DB_FLUSH,
95                     &data, &dirdata, (u_int32_t)appname, (u_int32_t)mode)) != 0)
96                         goto err;
97         }
98
99         DB_ENV_TEST_RECOVERY(env, DB_TEST_POSTLOG, ret, name);
100
101         if (fhpp == NULL)
102                 fhpp = &fhp;
103         ret = __os_open(
104             env, real_name, 0, DB_OSO_CREATE | DB_OSO_EXCL, mode, fhpp);
105
106 err:
107 DB_TEST_RECOVERY_LABEL
108         if (fhpp == &fhp && fhp != NULL)
109                 (void)__os_closehandle(env, fhp);
110         if (real_name != NULL)
111                 __os_free(env, real_name);
112         return (ret);
113 }
114
115 /*
116  * __fop_remove --
117  *      Remove a file system object.
118  *
119  * PUBLIC: int __fop_remove __P((ENV *, DB_TXN *,
120  * PUBLIC:     u_int8_t *, const char *, const char **, APPNAME, u_int32_t));
121  */
122 int
123 __fop_remove(env, txn, fileid, name, dirp, appname, flags)
124         ENV *env;
125         DB_TXN *txn;
126         u_int8_t *fileid;
127         const char *name, **dirp;
128         APPNAME appname;
129         u_int32_t flags;
130 {
131         DBT fdbt, ndbt;
132         DB_LSN lsn;
133         char *real_name;
134         int ret;
135
136         real_name = NULL;
137
138         if ((ret = __db_appname(env, appname, name, dirp, &real_name)) != 0)
139                 goto err;
140
141         if (!IS_REAL_TXN(txn)) {
142                 if (fileid != NULL && (ret = __memp_nameop(
143                     env, fileid, NULL, real_name, NULL, 0)) != 0)
144                         goto err;
145         } else {
146                 if (DBENV_LOGGING(env)
147 #if !defined(DEBUG_WOP)
148                     && txn != NULL
149 #endif
150                 ) {
151                         memset(&fdbt, 0, sizeof(ndbt));
152                         fdbt.data = fileid;
153                         fdbt.size = fileid == NULL ? 0 : DB_FILE_ID_LEN;
154                         DB_INIT_DBT(ndbt, name, strlen(name) + 1);
155                         if ((ret = __fop_remove_log(env, txn, &lsn,
156                             flags, &ndbt, &fdbt, (u_int32_t)appname)) != 0)
157                                 goto err;
158                 }
159                 ret = __txn_remevent(env, txn, real_name, fileid, 0);
160         }
161
162 err:    if (real_name != NULL)
163                 __os_free(env, real_name);
164         return (ret);
165 }
166
167 /*
168  * __fop_write
169  *
170  * Write "size" bytes from "buf" to file "name" beginning at offset "off."
171  * If the file is open, supply a handle in fhp.  Istmp indicate if this is
172  * an operation that needs to be undone in the face of failure (i.e., if
173  * this is a write to a temporary file, we're simply going to remove the
174  * file, so don't worry about undoing the write).
175  *
176  * Currently, we *only* use this with istmp true.  If we need more general
177  * handling, then we'll have to zero out regions on abort (and possibly
178  * log the before image of the data in the log record).
179  *
180  * PUBLIC: int __fop_write __P((ENV *, DB_TXN *,
181  * PUBLIC:     const char *, const char *, APPNAME, DB_FH *, u_int32_t,
182  * PUBLIC:     db_pgno_t, u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t));
183  */
184 int
185 __fop_write(env, txn,
186     name, dirname, appname, fhp, pgsize, pageno, off, buf, size, istmp, flags)
187         ENV *env;
188         DB_TXN *txn;
189         const char *name, *dirname;
190         APPNAME appname;
191         DB_FH *fhp;
192         u_int32_t pgsize;
193         db_pgno_t pageno;
194         u_int32_t off;
195         void *buf;
196         u_int32_t size, istmp, flags;
197 {
198         DBT data, namedbt, dirdbt;
199         DB_LSN lsn;
200         size_t nbytes;
201         int local_open, ret, t_ret;
202         char *real_name;
203
204         DB_ASSERT(env, istmp != 0);
205
206         ret = local_open = 0;
207         real_name = NULL;
208
209         if (DBENV_LOGGING(env)
210 #if !defined(DEBUG_WOP)
211             && txn != NULL
212 #endif
213             ) {
214                 memset(&data, 0, sizeof(data));
215                 data.data = buf;
216                 data.size = size;
217                 DB_INIT_DBT(namedbt, name, strlen(name) + 1);
218                 if (dirname != NULL)
219                         DB_INIT_DBT(dirdbt, dirname, strlen(dirname) + 1);
220                 else
221                         memset(&dirdbt, 0, sizeof(dirdbt));
222                 if ((ret = __fop_write_log(env, txn,
223                     &lsn, flags, &namedbt, &dirdbt, (u_int32_t)appname,
224                     pgsize, pageno, off, &data, istmp)) != 0)
225                         goto err;
226         }
227
228         if (fhp == NULL) {
229                 /* File isn't open; we need to reopen it. */
230                 if ((ret = __db_appname(env,
231                     appname, name, &dirname, &real_name)) != 0)
232                         return (ret);
233
234                 if ((ret = __os_open(env, real_name, 0, 0, 0, &fhp)) != 0)
235                         goto err;
236                 local_open = 1;
237         }
238
239         /* Seek to offset. */
240         if ((ret = __os_seek(env, fhp, pageno, pgsize, off)) != 0)
241                 goto err;
242
243         /* Now do the write. */
244         if ((ret = __os_write(env, fhp, buf, size, &nbytes)) != 0)
245                 goto err;
246
247 err:    if (local_open &&
248             (t_ret = __os_closehandle(env, fhp)) != 0 && ret == 0)
249                         ret = t_ret;
250
251         if (real_name != NULL)
252                 __os_free(env, real_name);
253         return (ret);
254 }
255
256 /*
257  * __fop_rename --
258  *      Change a file's name.
259  *
260  * PUBLIC: int __fop_rename __P((ENV *, DB_TXN *, const char *, const char *,
261  * PUBLIC:      const char **, u_int8_t *, APPNAME, int, u_int32_t));
262  */
263 int
264 __fop_rename(env, txn, oldname, newname, dirp, fid, appname, with_undo, flags)
265         ENV *env;
266         DB_TXN *txn;
267         const char *oldname;
268         const char *newname;
269         const char **dirp;
270         u_int8_t *fid;
271         APPNAME appname;
272         int with_undo;
273         u_int32_t flags;
274 {
275         DBT fiddbt, dir, new, old;
276         DB_LSN lsn;
277         int ret;
278         char *n, *o;
279
280         o = n = NULL;
281         if ((ret = __db_appname(env, appname, oldname, dirp, &o)) != 0)
282                 goto err;
283         if ((ret = __db_appname(env, appname, newname, dirp, &n)) != 0)
284                 goto err;
285
286         if (DBENV_LOGGING(env)
287 #if !defined(DEBUG_WOP)
288             && txn != NULL
289 #endif
290             ) {
291                 DB_INIT_DBT(old, oldname, strlen(oldname) + 1);
292                 DB_INIT_DBT(new, newname, strlen(newname) + 1);
293                 if (dirp != NULL && *dirp != NULL)
294                         DB_INIT_DBT(dir, *dirp, strlen(*dirp) + 1);
295                 else
296                         memset(&dir, 0, sizeof(dir));
297                 memset(&fiddbt, 0, sizeof(fiddbt));
298                 fiddbt.data = fid;
299                 fiddbt.size = DB_FILE_ID_LEN;
300                 if (with_undo)
301                         ret = __fop_rename_log(env,
302                             txn, &lsn, flags | DB_FLUSH,
303                             &old, &new, &dir, &fiddbt, (u_int32_t)appname);
304                 else
305                         ret = __fop_rename_noundo_log(env,
306                             txn, &lsn, flags | DB_FLUSH,
307                             &old, &new, &dir, &fiddbt, (u_int32_t)appname);
308                 if (ret != 0)
309                         goto err;
310         }
311
312         ret = __memp_nameop(env, fid, newname, o, n, 0);
313
314 err:    if (o != NULL)
315                 __os_free(env, o);
316         if (n != NULL)
317                 __os_free(env, n);
318         return (ret);
319 }