Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

fop_basic.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2001-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: fop_basic.c,v 12.8 2005/10/12 17:52:16 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <string.h>
00014 #include <sys/types.h>
00015 #endif
00016 
00017 #include "db_int.h"
00018 #include "dbinc/db_page.h"
00019 #include "dbinc/db_shash.h"
00020 #include "dbinc/fop.h"
00021 #include "dbinc/log.h"
00022 #include "dbinc/mp.h"
00023 #include "dbinc/txn.h"
00024 #include "dbinc/db_am.h"
00025 
00026 /*
00027  * The transactional guarantees Berkeley DB provides for file
00028  * system level operations (database physical file create, delete,
00029  * rename) are based on our understanding of current file system
00030  * semantics; a system that does not provide these semantics and
00031  * guarantees could be in danger.
00032  *
00033  * First, as in standard database changes, fsync and fdatasync must
00034  * work: when applied to the log file, the records written into the
00035  * log must be transferred to stable storage.
00036  *
00037  * Second, it must not be possible for the log file to be removed
00038  * without previous file system level operations being flushed to
00039  * stable storage.  Berkeley DB applications write log records
00040  * describing file system operations into the log, then perform the
00041  * file system operation, then commit the enclosing transaction
00042  * (which flushes the log file to stable storage).  Subsequently,
00043  * a database environment checkpoint may make it possible for the
00044  * application to remove the log file containing the record of the
00045  * file system operation.  DB's transactional guarantees for file
00046  * system operations require the log file removal not succeed until
00047  * all previous filesystem operations have been flushed to stable
00048  * storage.  In other words, the flush of the log file, or the
00049  * removal of the log file, must block until all previous
00050  * filesystem operations have been flushed to stable storage.  This
00051  * semantic is not, as far as we know, required by any existing
00052  * standards document, but we have never seen a filesystem where
00053  * it does not apply.
00054  */
00055 
00056 /*
00057  * __fop_create --
00058  * Create a (transactionally protected) file system object.  This is used
00059  * to create DB files now, potentially blobs, queue extents and anything
00060  * else you wish to store in a file system object.
00061  *
00062  * PUBLIC: int __fop_create __P((DB_ENV *,
00063  * PUBLIC:     DB_TXN *, DB_FH **, const char *, APPNAME, int, u_int32_t));
00064  */
00065 int
00066 __fop_create(dbenv, txn, fhpp, name, appname, mode, flags)
00067         DB_ENV *dbenv;
00068         DB_TXN *txn;
00069         DB_FH **fhpp;
00070         const char *name;
00071         APPNAME appname;
00072         int mode;
00073         u_int32_t flags;
00074 {
00075         DB_FH *fhp;
00076         DB_LSN lsn;
00077         DBT data;
00078         int ret;
00079         char *real_name;
00080 
00081         real_name = NULL;
00082         fhp = NULL;
00083 
00084         if ((ret =
00085             __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0)
00086                 return (ret);
00087 
00088         if (mode == 0)
00089                 mode = __db_omode(OWNER_RW);
00090 
00091         if (DBENV_LOGGING(dbenv)) {
00092                 memset(&data, 0, sizeof(data));
00093                 data.data = (void *)name;
00094                 data.size = (u_int32_t)strlen(name) + 1;
00095                 if ((ret = __fop_create_log(dbenv, txn, &lsn,
00096                     flags | DB_FLUSH,
00097                     &data, (u_int32_t)appname, (u_int32_t)mode)) != 0)
00098                         goto err;
00099         }
00100 
00101         DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_POSTLOG, ret, name);
00102 
00103         if (fhpp == NULL)
00104                 fhpp = &fhp;
00105         ret = __os_open(
00106             dbenv, real_name, DB_OSO_CREATE | DB_OSO_EXCL, mode, fhpp);
00107 
00108 err:
00109 DB_TEST_RECOVERY_LABEL
00110         if (fhpp == &fhp && fhp != NULL)
00111                 (void)__os_closehandle(dbenv, fhp);
00112         if (real_name != NULL)
00113                 __os_free(dbenv, real_name);
00114         return (ret);
00115 }
00116 
00117 /*
00118  * __fop_remove --
00119  *      Remove a file system object.
00120  *
00121  * PUBLIC: int __fop_remove __P((DB_ENV *,
00122  * PUBLIC:     DB_TXN *, u_int8_t *, const char *, APPNAME, u_int32_t));
00123  */
00124 int
00125 __fop_remove(dbenv, txn, fileid, name, appname, flags)
00126         DB_ENV *dbenv;
00127         DB_TXN *txn;
00128         u_int8_t *fileid;
00129         const char *name;
00130         APPNAME appname;
00131         u_int32_t flags;
00132 {
00133         DB_LSN lsn;
00134         DBT fdbt, ndbt;
00135         char *real_name;
00136         int ret;
00137 
00138         real_name = NULL;
00139 
00140         if ((ret =
00141             __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0)
00142                 goto err;
00143 
00144         if (txn == NULL) {
00145                 if (fileid != NULL && (ret = __memp_nameop(
00146                     dbenv, fileid, NULL, real_name, NULL, 0)) != 0)
00147                         goto err;
00148         } else {
00149                 if (DBENV_LOGGING(dbenv)) {
00150                         memset(&fdbt, 0, sizeof(ndbt));
00151                         fdbt.data = fileid;
00152                         fdbt.size = fileid == NULL ? 0 : DB_FILE_ID_LEN;
00153                         memset(&ndbt, 0, sizeof(ndbt));
00154                         ndbt.data = (void *)name;
00155                         ndbt.size = (u_int32_t)strlen(name) + 1;
00156                         if ((ret = __fop_remove_log(dbenv, txn, &lsn,
00157                             flags, &ndbt, &fdbt, (u_int32_t)appname)) != 0)
00158                                 goto err;
00159                 }
00160                 ret = __txn_remevent(dbenv, txn, real_name, fileid, 0);
00161         }
00162 
00163 err:    if (real_name != NULL)
00164                 __os_free(dbenv, real_name);
00165         return (ret);
00166 }
00167 
00168 /*
00169  * __fop_write
00170  *
00171  * Write "size" bytes from "buf" to file "name" beginning at offset "off."
00172  * If the file is open, supply a handle in fhp.  Istmp indicate if this is
00173  * an operation that needs to be undone in the face of failure (i.e., if
00174  * this is a write to a temporary file, we're simply going to remove the
00175  * file, so don't worry about undoing the write).
00176  *
00177  * Currently, we *only* use this with istmp true.  If we need more general
00178  * handling, then we'll have to zero out regions on abort (and possibly
00179  * log the before image of the data in the log record).
00180  *
00181  * PUBLIC: int __fop_write __P((DB_ENV *,
00182  * PUBLIC:     DB_TXN *, const char *, APPNAME, DB_FH *, u_int32_t, db_pgno_t,
00183  * PUBLIC:     u_int32_t, u_int8_t *, u_int32_t, u_int32_t, u_int32_t));
00184  */
00185 int
00186 __fop_write(dbenv,
00187     txn, name, appname, fhp, pgsize, pageno, off, buf, size, istmp, flags)
00188         DB_ENV *dbenv;
00189         DB_TXN *txn;
00190         const char *name;
00191         APPNAME appname;
00192         DB_FH *fhp;
00193         u_int32_t pgsize;
00194         db_pgno_t pageno;
00195         u_int32_t off;
00196         u_int8_t *buf;
00197         u_int32_t size, istmp, flags;
00198 {
00199         DB_LSN lsn;
00200         DBT data, namedbt;
00201         size_t nbytes;
00202         int local_open, ret, t_ret;
00203         char *real_name;
00204 
00205         DB_ASSERT(istmp != 0);
00206 
00207         ret = local_open = 0;
00208         real_name = NULL;
00209 
00210         if ((ret =
00211             __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0)
00212                 return (ret);
00213 
00214         if (DBENV_LOGGING(dbenv)) {
00215                 memset(&data, 0, sizeof(data));
00216                 data.data = buf;
00217                 data.size = size;
00218                 memset(&namedbt, 0, sizeof(namedbt));
00219                 namedbt.data = (void *)name;
00220                 namedbt.size = (u_int32_t)strlen(name) + 1;
00221                 if ((ret = __fop_write_log(dbenv, txn,
00222                     &lsn, flags, &namedbt, (u_int32_t)appname,
00223                     pgsize, pageno, off, &data, istmp)) != 0)
00224                         goto err;
00225         }
00226 
00227         if (fhp == NULL) {
00228                 /* File isn't open; we need to reopen it. */
00229                 if ((ret = __os_open(dbenv, real_name, 0, 0, &fhp)) != 0)
00230                         goto err;
00231                 local_open = 1;
00232         }
00233 
00234         /* Seek to offset. */
00235         if ((ret = __os_seek(dbenv,
00236             fhp, pgsize, pageno, off, 0, DB_OS_SEEK_SET)) != 0)
00237                 goto err;
00238 
00239         /* Now do the write. */
00240         if ((ret = __os_write(dbenv, fhp, buf, size, &nbytes)) != 0)
00241                 goto err;
00242 
00243 err:    if (local_open &&
00244             (t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
00245                         ret = t_ret;
00246 
00247         if (real_name != NULL)
00248                 __os_free(dbenv, real_name);
00249         return (ret);
00250 }
00251 
00252 /*
00253  * __fop_rename --
00254  *      Change a file's name.
00255  *
00256  * PUBLIC: int __fop_rename __P((DB_ENV *, DB_TXN *,
00257  * PUBLIC:      const char *, const char *, u_int8_t *, APPNAME, u_int32_t));
00258  */
00259 int
00260 __fop_rename(dbenv, txn, oldname, newname, fid, appname, flags)
00261         DB_ENV *dbenv;
00262         DB_TXN *txn;
00263         const char *oldname;
00264         const char *newname;
00265         u_int8_t *fid;
00266         APPNAME appname;
00267         u_int32_t flags;
00268 {
00269         DB_LSN lsn;
00270         DBT fiddbt, new, old;
00271         int ret;
00272         char *n, *o;
00273 
00274         o = n = NULL;
00275         if ((ret = __db_appname(dbenv, appname, oldname, 0, NULL, &o)) != 0)
00276                 goto err;
00277         if ((ret = __db_appname(dbenv, appname, newname, 0, NULL, &n)) != 0)
00278                 goto err;
00279 
00280         if (DBENV_LOGGING(dbenv)) {
00281                 memset(&old, 0, sizeof(old));
00282                 memset(&new, 0, sizeof(new));
00283                 memset(&fiddbt, 0, sizeof(fiddbt));
00284                 old.data = (void *)oldname;
00285                 old.size = (u_int32_t)strlen(oldname) + 1;
00286                 new.data = (void *)newname;
00287                 new.size = (u_int32_t)strlen(newname) + 1;
00288                 fiddbt.data = fid;
00289                 fiddbt.size = DB_FILE_ID_LEN;
00290                 if ((ret = __fop_rename_log(dbenv, txn, &lsn, flags | DB_FLUSH,
00291                     &old, &new, &fiddbt, (u_int32_t)appname)) != 0)
00292                         goto err;
00293         }
00294 
00295         ret = __memp_nameop(dbenv, fid, newname, o, n, 0);
00296 
00297 err:    if (o != NULL)
00298                 __os_free(dbenv, o);
00299         if (n != NULL)
00300                 __os_free(dbenv, n);
00301         return (ret);
00302 }

Generated on Sun Dec 25 12:14:28 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2