tdb/common/open.c

ソースコードを見る。

関数

static unsigned int default_tdb_hash (TDB_DATA *key)
static int tdb_new_database (struct tdb_context *tdb, int hash_size)
static int tdb_already_open (dev_t device, ino_t ino)
tdb_contexttdb_open (const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode)
static void null_log_fn (struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt,...) PRINTF_ATTRIBUTE(3
tdb_contexttdb_open_ex (const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, const struct tdb_logging_context *log_ctx, tdb_hash_func hash_fn)
void tdb_set_max_dead (struct tdb_context *tdb, int max_dead)
int tdb_close (struct tdb_context *tdb)
 Close a database.
void tdb_set_logging_function (struct tdb_context *tdb, const struct tdb_logging_context *log_ctx)
void * tdb_get_logging_private (struct tdb_context *tdb)
int tdb_reopen (struct tdb_context *tdb)
int tdb_reopen_all (int parent_longlived)

変数

static struct tdb_contexttdbs = NULL


関数

static unsigned int default_tdb_hash ( TDB_DATA key  )  [static]

open.c36 行で定義されています。

参照先 TDB_DATA::dptrTDB_DATA::dsize.

参照元 tdb_open_ex().

00037 {
00038         u32 value;      /* Used to compute the hash value.  */
00039         u32   i;        /* Used to cycle through random values. */
00040 
00041         /* Set the initial value from the key size. */
00042         for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
00043                 value = (value + (key->dptr[i] << (i*5 % 24)));
00044 
00045         return (1103515243 * value + 12345);  
00046 }

static int tdb_new_database ( struct tdb_context tdb,
int  hash_size 
) [static]

open.c50 行で定義されています。

参照先 errnotdb_context::fdtdb_context::flagstdb_header::hash_sizetdb_context::headertdb_header::magic_foodtdb_context::map_ptrtdb_context::map_sizesizetdbTDB_ERR_OOMtdb_header::version.

参照元 tdb_open_ex().

00051 {
00052         struct tdb_header *newdb;
00053         size_t size;
00054         int ret = -1;
00055         ssize_t written;
00056 
00057         /* We make it up in memory, then write it out if not internal */
00058         size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t);
00059         if (!(newdb = (struct tdb_header *)calloc(size, 1)))
00060                 return TDB_ERRCODE(TDB_ERR_OOM, -1);
00061 
00062         /* Fill in the header */
00063         newdb->version = TDB_VERSION;
00064         newdb->hash_size = hash_size;
00065         if (tdb->flags & TDB_INTERNAL) {
00066                 tdb->map_size = size;
00067                 tdb->map_ptr = (char *)newdb;
00068                 memcpy(&tdb->header, newdb, sizeof(tdb->header));
00069                 /* Convert the `ondisk' version if asked. */
00070                 CONVERT(*newdb);
00071                 return 0;
00072         }
00073         if (lseek(tdb->fd, 0, SEEK_SET) == -1)
00074                 goto fail;
00075 
00076         if (ftruncate(tdb->fd, 0) == -1)
00077                 goto fail;
00078 
00079         /* This creates an endian-converted header, as if read from disk */
00080         CONVERT(*newdb);
00081         memcpy(&tdb->header, newdb, sizeof(tdb->header));
00082         /* Don't endian-convert the magic food! */
00083         memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
00084         /* we still have "ret == -1" here */
00085         written = write(tdb->fd, newdb, size);
00086         if (written == size) {
00087                 ret = 0;
00088         } else if (written != -1) {
00089                 /* call write once again, this usually should return -1 and
00090                  * set errno appropriately */
00091                 size -= written;
00092                 written = write(tdb->fd, newdb+written, size);
00093                 if (written == size) {
00094                         ret = 0;
00095                 } else if (written >= 0) {
00096                         /* a second incomplete write - we give up.
00097                          * guessing the errno... */
00098                         errno = ENOSPC;
00099                 }
00100         }
00101 
00102   fail:
00103         SAFE_FREE(newdb);
00104         return ret;
00105 }

static int tdb_already_open ( dev_t  device,
ino_t  ino 
) [static]

open.c109 行で定義されています。

参照先 tdb_context::devicetdb_context::inodetdb_context::nexttdbs.

参照元 tdb_open_ex().

00111 {
00112         struct tdb_context *i;
00113         
00114         for (i = tdbs; i; i = i->next) {
00115                 if (i->device == device && i->inode == ino) {
00116                         return 1;
00117                 }
00118         }
00119 
00120         return 0;
00121 }

struct tdb_context* tdb_open ( const char *  name,
int  hash_size,
int  tdb_flags,
int  open_flags,
mode_t  mode 
)

open.c133 行で定義されています。

参照先 tdb_open_ex().

参照元 backup_tdb()create_tdb()dump_tdb()hash_a_service()main()move_rec()open_tdb()py_tdb_open()smb_share_mode_db_open()tdb_validate_freelist()torture_mangle()verify_tdb().

00135 {
00136         return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL);
00137 }

static void static void null_log_fn ( struct tdb_context tdb,
enum tdb_debug_level  level,
const char *  fmt,
  ... 
) [static]

open.c141 行で定義されています。

参照元 tdb_open_ex().

00142 {
00143 }

struct tdb_context* tdb_open_ex ( const char *  name,
int  hash_size,
int  tdb_flags,
int  open_flags,
mode_t  mode,
const struct tdb_logging_context log_ctx,
tdb_hash_func  hash_fn 
)

open.c146 行で定義されています。

参照先 default_tdb_hash()errnotdb_logging_context::log_fnnull_log_fn()strdup()strerror()tdbtdb_already_open()tdb_convert()TDB_DEBUG_ERRORTDB_DEBUG_FATALTDB_DEBUG_WARNINGtdb_io_init()tdb_mmap()tdb_munmap()tdb_new_database()tdb_transaction_recover()tdbs.

参照元 main()mangle_hash_init()reset_stat_cache()tdb_open()tdb_open_log().

00150 {
00151         struct tdb_context *tdb;
00152         struct stat st;
00153         int rev = 0, locked = 0;
00154         unsigned char *vp;
00155         u32 vertest;
00156 
00157         if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
00158                 /* Can't log this */
00159                 errno = ENOMEM;
00160                 goto fail;
00161         }
00162         tdb_io_init(tdb);
00163         tdb->fd = -1;
00164         tdb->name = NULL;
00165         tdb->map_ptr = NULL;
00166         tdb->flags = tdb_flags;
00167         tdb->open_flags = open_flags;
00168         if (log_ctx) {
00169                 tdb->log = *log_ctx;
00170         } else {
00171                 tdb->log.log_fn = null_log_fn;
00172                 tdb->log.log_private = NULL;
00173         }
00174         tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
00175 
00176         /* cache the page size */
00177         tdb->page_size = getpagesize();
00178         if (tdb->page_size <= 0) {
00179                 tdb->page_size = 0x2000;
00180         }
00181 
00182         if ((open_flags & O_ACCMODE) == O_WRONLY) {
00183                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n",
00184                          name));
00185                 errno = EINVAL;
00186                 goto fail;
00187         }
00188         
00189         if (hash_size == 0)
00190                 hash_size = DEFAULT_HASH_SIZE;
00191         if ((open_flags & O_ACCMODE) == O_RDONLY) {
00192                 tdb->read_only = 1;
00193                 /* read only databases don't do locking or clear if first */
00194                 tdb->flags |= TDB_NOLOCK;
00195                 tdb->flags &= ~TDB_CLEAR_IF_FIRST;
00196         }
00197 
00198         /* internal databases don't mmap or lock, and start off cleared */
00199         if (tdb->flags & TDB_INTERNAL) {
00200                 tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
00201                 tdb->flags &= ~TDB_CLEAR_IF_FIRST;
00202                 if (tdb_new_database(tdb, hash_size) != 0) {
00203                         TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!"));
00204                         goto fail;
00205                 }
00206                 goto internal;
00207         }
00208 
00209         if ((tdb->fd = open(name, open_flags, mode)) == -1) {
00210                 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n",
00211                          name, strerror(errno)));
00212                 goto fail;      /* errno set by open(2) */
00213         }
00214 
00215         /* ensure there is only one process initialising at once */
00216         if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
00217                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n",
00218                          name, strerror(errno)));
00219                 goto fail;      /* errno set by tdb_brlock */
00220         }
00221 
00222         /* we need to zero database if we are the only one with it open */
00223         if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
00224             (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) {
00225                 open_flags |= O_CREAT;
00226                 if (ftruncate(tdb->fd, 0) == -1) {
00227                         TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
00228                                  "failed to truncate %s: %s\n",
00229                                  name, strerror(errno)));
00230                         goto fail; /* errno set by ftruncate */
00231                 }
00232         }
00233 
00234         errno = 0;
00235         if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
00236             || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
00237             || (tdb->header.version != TDB_VERSION
00238                 && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) {
00239                 /* its not a valid database - possibly initialise it */
00240                 if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) {
00241                         if (errno == 0) {
00242                                 errno = EIO; /* ie bad format or something */
00243                         }
00244                         goto fail;
00245                 }
00246                 rev = (tdb->flags & TDB_CONVERT);
00247         }
00248         vp = (unsigned char *)&tdb->header.version;
00249         vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) |
00250                   (((u32)vp[2]) << 8) | (u32)vp[3];
00251         tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
00252         if (!rev)
00253                 tdb->flags &= ~TDB_CONVERT;
00254         else {
00255                 tdb->flags |= TDB_CONVERT;
00256                 tdb_convert(&tdb->header, sizeof(tdb->header));
00257         }
00258         if (fstat(tdb->fd, &st) == -1)
00259                 goto fail;
00260 
00261         if (tdb->header.rwlocks != 0) {
00262                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n"));
00263                 goto fail;
00264         }
00265 
00266         /* Is it already in the open list?  If so, fail. */
00267         if (tdb_already_open(st.st_dev, st.st_ino)) {
00268                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
00269                          "%s (%d,%d) is already open in this process\n",
00270                          name, (int)st.st_dev, (int)st.st_ino));
00271                 errno = EBUSY;
00272                 goto fail;
00273         }
00274 
00275         if (!(tdb->name = (char *)strdup(name))) {
00276                 errno = ENOMEM;
00277                 goto fail;
00278         }
00279 
00280         tdb->map_size = st.st_size;
00281         tdb->device = st.st_dev;
00282         tdb->inode = st.st_ino;
00283         tdb->max_dead_records = 0;
00284         tdb_mmap(tdb);
00285         if (locked) {
00286                 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) {
00287                         TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
00288                                  "failed to take ACTIVE_LOCK on %s: %s\n",
00289                                  name, strerror(errno)));
00290                         goto fail;
00291                 }
00292 
00293         }
00294 
00295         /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if
00296            we didn't get the initial exclusive lock as we need to let all other
00297            users know we're using it. */
00298 
00299         if (tdb_flags & TDB_CLEAR_IF_FIRST) {
00300                 /* leave this lock in place to indicate it's in use */
00301                 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)
00302                         goto fail;
00303         }
00304 
00305         /* if needed, run recovery */
00306         if (tdb_transaction_recover(tdb) == -1) {
00307                 goto fail;
00308         }
00309 
00310  internal:
00311         /* Internal (memory-only) databases skip all the code above to
00312          * do with disk files, and resume here by releasing their
00313          * global lock and hooking into the active list. */
00314         if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1)
00315                 goto fail;
00316         tdb->next = tdbs;
00317         tdbs = tdb;
00318         return tdb;
00319 
00320  fail:
00321         { int save_errno = errno;
00322 
00323         if (!tdb)
00324                 return NULL;
00325         
00326         if (tdb->map_ptr) {
00327                 if (tdb->flags & TDB_INTERNAL)
00328                         SAFE_FREE(tdb->map_ptr);
00329                 else
00330                         tdb_munmap(tdb);
00331         }
00332         SAFE_FREE(tdb->name);
00333         if (tdb->fd != -1)
00334                 if (close(tdb->fd) != 0)
00335                         TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n"));
00336         SAFE_FREE(tdb);
00337         errno = save_errno;
00338         return NULL;
00339         }
00340 }

void tdb_set_max_dead ( struct tdb_context tdb,
int  max_dead 
)

open.c346 行で定義されています。

参照先 tdb_context::max_dead_recordstdb.

参照元 brl_init()locking_init()message_init().

00347 {
00348         tdb->max_dead_records = max_dead;
00349 }

int tdb_close ( struct tdb_context tdb  ) 

Close a database.

戻り値:
-1 for error; 0 for success.

open.c356 行で定義されています。

参照先 tdb_context::fdtdb_context::flagstdb_context::lockrecstdb_context::map_ptrtdb_context::nametdb_context::nexttdbtdb_munmap()tdb_transaction_cancel()tdbstdb_context::transaction.

参照元 _reg_perfcount_get_counter_data()_reg_perfcount_init_data_block_perf()backup_tdb()brl_shutdown()close_all_print_db()create_tdb()do_daemon_stack_trace()do_winbind_offline()do_winbind_online()elog_close_tdb()gencache_shutdown()idmap_cache_destructor()idmap_tdb_convert()idmap_tdb_open_db()idmap_tdb_tdb_close()initialize_winbindd_cache()lang_tdb_init()locking_end()login_cache_shutdown()main()move_rec()net_idmap_dump()net_status_sessions()net_status_shares()net_status_shares_parseable()netsamlogon_cache_shutdown()netsamlogon_clear_cached_user()nt_printing_init()open_schannel_session_store()open_tdb()posix_locking_end()py_tdb_close()receive_unexpected()reg_perfcount_get_base_index()reg_perfcount_get_counter_help()reg_perfcount_get_counter_names()reg_perfcount_get_perf_data_block()regdb_close()reset_stat_cache()secrets_restore_schannel_session_info()secrets_store_schannel_session_info()send_message()send_repl_message()send_sync_message()smb_share_mode_db_close()status_page()tdb_hnd_dealloc()tdb_reopen()tdb_validate_freelist()tdb_wrap_destructor()tdbsam_close()tdbsam_new_rid()tdbsam_open()verify_tdb()wcache_flush_cache().

00357 {
00358         struct tdb_context **i;
00359         int ret = 0;
00360 
00361         if (tdb->transaction) {
00362                 tdb_transaction_cancel(tdb);
00363         }
00364 
00365         if (tdb->map_ptr) {
00366                 if (tdb->flags & TDB_INTERNAL)
00367                         SAFE_FREE(tdb->map_ptr);
00368                 else
00369                         tdb_munmap(tdb);
00370         }
00371         SAFE_FREE(tdb->name);
00372         if (tdb->fd != -1)
00373                 ret = close(tdb->fd);
00374         SAFE_FREE(tdb->lockrecs);
00375 
00376         /* Remove from contexts list */
00377         for (i = &tdbs; *i; i = &(*i)->next) {
00378                 if (*i == tdb) {
00379                         *i = tdb->next;
00380                         break;
00381                 }
00382         }
00383 
00384         memset(tdb, 0, sizeof(*tdb));
00385         SAFE_FREE(tdb);
00386 
00387         return ret;
00388 }

void tdb_set_logging_function ( struct tdb_context tdb,
const struct tdb_logging_context log_ctx 
)

open.c391 行で定義されています。

参照先 tdb_context::logtdb.

00393 {
00394         tdb->log = *log_ctx;
00395 }

void* tdb_get_logging_private ( struct tdb_context tdb  ) 

open.c397 行で定義されています。

参照先 tdb_context::logtdb_logging_context::log_privatetdb.

00398 {
00399         return tdb->log.log_private;
00400 }

int tdb_reopen ( struct tdb_context tdb  ) 

open.c404 行で定義されています。

参照先 tdb_lock_type::counttdb_context::deviceerrnotdb_context::fdtdb_context::flagstdb_context::global_locktdb_context::inodetdb_context::methodstdb_context::nametdb_context::num_lockstdb_context::open_flagsstrerror()tdbtdb_methods::tdb_brlocktdb_close()TDB_DEBUG_ERRORTDB_DEBUG_FATALtdb_mmap()tdb_munmap()tdb_context::transaction.

参照元 tdb_reopen_all()wins_write_database().

00405 {
00406         struct stat st;
00407 
00408         if (tdb->flags & TDB_INTERNAL) {
00409                 return 0; /* Nothing to do. */
00410         }
00411 
00412         if (tdb->num_locks != 0 || tdb->global_lock.count) {
00413                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n"));
00414                 goto fail;
00415         }
00416 
00417         if (tdb->transaction != 0) {
00418                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n"));
00419                 goto fail;
00420         }
00421 
00422         if (tdb_munmap(tdb) != 0) {
00423                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
00424                 goto fail;
00425         }
00426         if (close(tdb->fd) != 0)
00427                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n"));
00428         tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
00429         if (tdb->fd == -1) {
00430                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno)));
00431                 goto fail;
00432         }
00433         if ((tdb->flags & TDB_CLEAR_IF_FIRST) && 
00434             (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) {
00435                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
00436                 goto fail;
00437         }
00438         if (fstat(tdb->fd, &st) != 0) {
00439                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
00440                 goto fail;
00441         }
00442         if (st.st_ino != tdb->inode || st.st_dev != tdb->device) {
00443                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n"));
00444                 goto fail;
00445         }
00446         tdb_mmap(tdb);
00447 
00448         return 0;
00449 
00450 fail:
00451         tdb_close(tdb);
00452         return -1;
00453 }

int tdb_reopen_all ( int  parent_longlived  ) 

open.c456 行で定義されています。

参照先 tdb_context::flagstdb_context::nexttdbtdb_reopen()tdbs.

参照元 addrec_db()fork_child_dc_connect()fork_domain_child()open_sockets_smbd().

00457 {
00458         struct tdb_context *tdb;
00459 
00460         for (tdb=tdbs; tdb; tdb = tdb->next) {
00461                 /*
00462                  * If the parent is longlived (ie. a
00463                  * parent daemon architecture), we know
00464                  * it will keep it's active lock on a
00465                  * tdb opened with CLEAR_IF_FIRST. Thus
00466                  * for child processes we don't have to
00467                  * add an active lock. This is essential
00468                  * to improve performance on systems that
00469                  * keep POSIX locks as a non-scalable data
00470                  * structure in the kernel.
00471                  */
00472                 if (parent_longlived) {
00473                         /* Ensure no clear-if-first. */
00474                         tdb->flags &= ~TDB_CLEAR_IF_FIRST;
00475                 }
00476 
00477                 if (tdb_reopen(tdb) != 0)
00478                         return -1;
00479         }
00480 
00481         return 0;
00482 }


変数

struct tdb_context* tdbs = NULL [static]

open.c32 行で定義されています。

参照元 tdb_already_open()tdb_close()tdb_open_ex()tdb_reopen_all().


Sambaに対してSat Aug 29 21:24:27 2009に生成されました。  doxygen 1.4.7