typedef struct tdb_context TDB_CONTEXT |
typedef int(*) tdb_traverse_func(struct tdb_context *, TDB_DATA, TDB_DATA, void *) |
typedef void(*) tdb_log_func(struct tdb_context *, enum tdb_debug_level, const char *,...) PRINTF_ATTRIBUTE(3 |
typedef void(*) typedef unsigned int(*) tdb_hash_func(TDB_DATA *key) |
enum TDB_ERROR |
TDB_SUCCESS | |
TDB_ERR_CORRUPT | |
TDB_ERR_IO | |
TDB_ERR_LOCK | |
TDB_ERR_OOM | |
TDB_ERR_EXISTS | |
TDB_ERR_NOLOCK | |
TDB_ERR_LOCK_TIMEOUT | |
TDB_ERR_NOEXIST | |
TDB_ERR_EINVAL | |
TDB_ERR_RDONLY |
00054 {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, 00055 TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, 00056 TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY};
enum tdb_debug_level |
struct tdb_context* tdb_open | ( | const char * | name, | |
int | hash_size, | |||
int | tdb_flags, | |||
int | open_flags, | |||
mode_t | mode | |||
) |
参照先 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 }
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 | |||
) |
参照先 default_tdb_hash()・errno・tdb_logging_context::log_fn・null_log_fn()・strdup()・strerror()・tdb・tdb_already_open()・tdb_convert()・TDB_DEBUG_ERROR・TDB_DEBUG_FATAL・TDB_DEBUG_WARNING・tdb_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 | |||
) |
参照先 tdb_context::max_dead_records・tdb.
参照元 brl_init()・locking_init()・message_init().
00347 { 00348 tdb->max_dead_records = max_dead; 00349 }
int tdb_reopen | ( | struct tdb_context * | tdb | ) |
参照先 tdb_lock_type::count・tdb_context::device・errno・tdb_context::fd・tdb_context::flags・tdb_context::global_lock・tdb_context::inode・tdb_context::methods・tdb_context::name・tdb_context::num_locks・tdb_context::open_flags・strerror()・tdb・tdb_methods::tdb_brlock・tdb_close()・TDB_DEBUG_ERROR・TDB_DEBUG_FATAL・tdb_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 | ) |
参照先 tdb_context::flags・tdb_context::next・tdb・tdb_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 }
void tdb_set_logging_function | ( | struct tdb_context * | tdb, | |
const struct tdb_logging_context * | log_ctx | |||
) |
enum TDB_ERROR tdb_error | ( | struct tdb_context * | tdb | ) |
const char* tdb_errorstr | ( | struct tdb_context * | tdb | ) |
参照先 tdb_errname::ecode・tdb_context::ecode・emap・tdb_errname::estring・tdb.
参照元 claim_connection()・count_current_connections()・count_fn()・idmap_tdb_remove_mapping()・idmap_tdb_set_mapping()・info_tdb()・initialize_winbindd_cache()・net_enum_pipes()・register_message_flags()・tdb_ass_subscript()・tdb_delete_samacct_only()・tdb_update_ridrec_only()・tdb_update_samacct_only()・tdbsam_delete_sam_account()・tdbsam_getsampwnam()・tdbsam_getsampwrid()・upgrade_to_version_3()・yield_connection().
00051 { 00052 u32 i; 00053 for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) 00054 if (tdb->ecode == emap[i].ecode) 00055 return emap[i].estring; 00056 return "Invalid error code"; 00057 }
TDB_DATA tdb_fetch | ( | struct tdb_context * | tdb, | |
TDB_DATA | key | |||
) |
参照先 TDB_DATA::dptr・tdb_context::hash_fn・tdb・tdb_alloc_read()・tdb_find_lock_hash()・tdb_null・tdb_unlock().
参照元 _reg_perfcount_assemble_global()・_reg_perfcount_get_64()・_reg_perfcount_get_counter_data()・_reg_perfcount_get_counter_info()・_reg_perfcount_get_instance_info()・_reg_perfcount_get_numinst()・_reg_perfcount_multi_sz_from_tdb()・add_aliasmem()・add_fd_to_close_entry()・addrec_db()・brl_get_locks_internal()・cache_retrieve_response()・compare_db()・decrement_windows_lock_ref_count()・delete_printer_driver()・dump_tdb()・enum_group_mapping()・find_name_on_wins_subnet()・first_record()・gencache_get()・gencache_iterate()・get_a_printer_2()・get_a_printer_driver_3()・get_eventlog_record()・get_group_map_from_gid()・get_group_map_from_ntname()・get_group_map_from_sid()・get_jobs_changed_data()・get_ntforms()・get_posix_pending_close_entries()・get_privileges()・get_queue_status()・get_share_mode_lock()・get_stored_queue_info()・get_updating_pid()・get_windows_lock_ref_count()・group_map_remove()・idmap_cache_map_id()・idmap_cache_map_sid()・idmap_tdb_id_to_sid()・idmap_tdb_remove_mapping()・idmap_tdb_set_mapping()・idmap_tdb_sid_to_id()・increment_windows_lock_ref_count()・lang_msg()・login_cache_read()・make_way_for_eventlogs()・message_send_pid_internal()・messages_pending_for_pid()・move_rec()・netsamlogon_cache_get()・next_record()・one_alias_membership()・pjob_store()・pjobid_to_rap()・print_job_find()・print_queue_status()・rap_jobid_delete()・rap_to_pjobid()・reduce_windows_lock_ref_count()・reg_perfcount_get_base_index()・register_message_flags()・remove_from_jobs_changed()・retrieve_all_messages()・secrets_fetch()・session_yield()・set_driver_init_2()・show_tdb()・smb_change_share_mode_entry()・smb_create_share_mode_entry_ex()・smb_delete_share_mode_entry()・smb_get_share_mode_entries()・tdb_append()・tdb_fetch_bystring()・tdb_fetch_int32_byblob()・tdb_fetch_uint32_byblob()・tdb_hnd_subscript()・tdbsam_convert()・tdbsam_getsampwent()・tdbsam_getsampwnam()・tdbsam_getsampwrid()・upgrade_to_version_3()・wcache_cached_creds_exist()・wcache_fetch_raw()・wcache_remove_oldest_cached_creds().
00145 { 00146 tdb_off_t rec_ptr; 00147 struct list_struct rec; 00148 TDB_DATA ret; 00149 u32 hash; 00150 00151 /* find which hash bucket it is in */ 00152 hash = tdb->hash_fn(&key); 00153 if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) 00154 return tdb_null; 00155 00156 ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, 00157 rec.data_len); 00158 ret.dsize = rec.data_len; 00159 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); 00160 return ret; 00161 }
int tdb_parse_record | ( | struct tdb_context * | tdb, | |
TDB_DATA | key, | |||
int(*)(TDB_DATA key, TDB_DATA data, void *private_data) | parser, | |||
void * | private_data | |||
) |
参照先 tdb_context::hash_fn・tdb・TDB_ERR_NOEXIST・tdb_find_lock_hash()・tdb_parse_data()・tdb_unlock().
参照元 get_delete_on_close_flag().
00183 { 00184 tdb_off_t rec_ptr; 00185 struct list_struct rec; 00186 int ret; 00187 u32 hash; 00188 00189 /* find which hash bucket it is in */ 00190 hash = tdb->hash_fn(&key); 00191 00192 if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) { 00193 return TDB_ERRCODE(TDB_ERR_NOEXIST, 0); 00194 } 00195 00196 ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len, 00197 rec.data_len, parser, private_data); 00198 00199 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); 00200 00201 return ret; 00202 }
int tdb_delete | ( | struct tdb_context * | tdb, | |
TDB_DATA | key | |||
) |
参照先 tdb_context::hash_fn・tdb・tdb_delete_hash().
参照元 addrec_db()・byte_range_lock_destructor()・cache_cleanup_response()・cache_store_response()・convert_fn()・count_fn()・cull_traverse()・del_a_printer()・del_aliasmem()・del_driver_init()・delete_a_form()・delete_close_entries()・delete_pipe_opendb()・delete_printer_driver()・delete_tdb()・delete_windows_lock_ref_count()・do_delete_fn()・gencache_del()・gencache_get()・group_map_remove()・idmap_cache_del()・idmap_cache_map_id()・idmap_cache_map_sid()・idmap_tdb_remove_mapping()・idmap_tdb_set_mapping()・login_cache_delentry()・merge_test()・message_notify()・netsamlogon_cache_get()・netsamlogon_clear_cached_user()・normalize_printers_fn()・pjob_delete()・rap_jobid_delete()・remove_name_from_wins_namelist()・sec_desc_upg_fn()・secrets_delete()・session_claim()・session_yield()・set_updating_pid()・share_mode_lock_destructor()・smb_delete_share_mode_entry()・tdb_ass_subscript()・tdb_delete_bystring()・tdb_delete_samacct_only()・tdb_trans_delete()・tdb_traverse_delete_fn()・tdbsam_delete_sam_account()・traverse_fn()・traverse_fn_cleanup()・upgrade_to_version_3()・wcache_delete()・wcache_remove_oldest_cached_creds()・yield_connection().
00375 { 00376 u32 hash = tdb->hash_fn(&key); 00377 return tdb_delete_hash(tdb, key, hash); 00378 }
int tdb_store | ( | struct tdb_context * | tdb, | |
TDB_DATA | key, | |||
TDB_DATA | dbuf, | |||
int | flag | |||
) |
参照先 list_struct::data_len・TDB_DATA::dptr・TDB_DATA::dsize・tdb_context::ecode・list_struct::full_hash・tdb_context::hash_fn・list_struct::key_len・list_struct::magic・list_struct::next・tdb_context::read_only・tdb・tdb_allocate()・tdb_delete_hash()・TDB_ERR_EXISTS・TDB_ERR_NOEXIST・TDB_ERR_OOM・TDB_ERR_RDONLY・tdb_exists_hash()・tdb_find_dead()・tdb_increment_seqnum()・tdb_lock()・tdb_ofs_read()・tdb_ofs_write()・tdb_purge_dead()・tdb_rec_write()・TDB_SUCCESS・tdb_unlock()・tdb_update_hash()・tdb_context::traverse_read.
参照元 add_a_printer_driver_3()・add_aliasmem()・add_fd_to_close_entry()・add_mapping_entry()・addrec_db()・byte_range_lock_destructor()・cache_store_response()・centry_end()・claim_connection()・convert_fn()・copy_fn()・decrement_windows_lock_ref_count()・del_aliasmem()・gencache_set()・idmap_cache_set()・idmap_cache_set_negative_id()・idmap_cache_set_negative_sid()・idmap_tdb_set_mapping()・increment_windows_lock_ref_count()・insert_tdb()・load_msg()・login_cache_write()・merge_test()・message_send_pid_internal()・move_rec()・normalize_printers_fn()・pjob_store()・pjobid_to_rap()・print_queue_update_internal()・reduce_windows_lock_ref_count()・regdb_store_keys_internal()・register_message_flags()・remove_from_jobs_changed()・retrieve_all_messages()・seen_insert()・session_claim()・set_privileges()・set_updating_pid()・share_mode_lock_destructor()・smb_change_share_mode_entry()・smb_create_share_mode_entry_ex()・smb_delete_share_mode_entry()・store_or_replace_wins_namerec()・store_pipe_opendb()・store_queue_struct()・store_tdb()・tdb_append()・tdb_ass_subscript()・tdb_store_bystring()・tdb_store_int32_byblob()・tdb_store_uint32_byblob()・tdb_trans_store()・tdb_update_ridrec_only()・tdb_update_samacct_only()・tdbsam_convert()・traverse_fn()・unexpected_packet()・update_a_printer_2()・update_driver_init_2()・upgrade_to_version_3()・write_eventlog_tdb()・write_ntforms().
00415 { 00416 struct list_struct rec; 00417 u32 hash; 00418 tdb_off_t rec_ptr; 00419 char *p = NULL; 00420 int ret = -1; 00421 00422 if (tdb->read_only || tdb->traverse_read) { 00423 tdb->ecode = TDB_ERR_RDONLY; 00424 return -1; 00425 } 00426 00427 /* find which hash bucket it is in */ 00428 hash = tdb->hash_fn(&key); 00429 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) 00430 return -1; 00431 00432 /* check for it existing, on insert. */ 00433 if (flag == TDB_INSERT) { 00434 if (tdb_exists_hash(tdb, key, hash)) { 00435 tdb->ecode = TDB_ERR_EXISTS; 00436 goto fail; 00437 } 00438 } else { 00439 /* first try in-place update, on modify or replace. */ 00440 if (tdb_update_hash(tdb, key, hash, dbuf) == 0) { 00441 goto done; 00442 } 00443 if (tdb->ecode == TDB_ERR_NOEXIST && 00444 flag == TDB_MODIFY) { 00445 /* if the record doesn't exist and we are in TDB_MODIFY mode then 00446 we should fail the store */ 00447 goto fail; 00448 } 00449 } 00450 /* reset the error code potentially set by the tdb_update() */ 00451 tdb->ecode = TDB_SUCCESS; 00452 00453 /* delete any existing record - if it doesn't exist we don't 00454 care. Doing this first reduces fragmentation, and avoids 00455 coalescing with `allocated' block before it's updated. */ 00456 if (flag != TDB_INSERT) 00457 tdb_delete_hash(tdb, key, hash); 00458 00459 /* Copy key+value *before* allocating free space in case malloc 00460 fails and we are left with a dead spot in the tdb. */ 00461 00462 if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) { 00463 tdb->ecode = TDB_ERR_OOM; 00464 goto fail; 00465 } 00466 00467 memcpy(p, key.dptr, key.dsize); 00468 if (dbuf.dsize) 00469 memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize); 00470 00471 if (tdb->max_dead_records != 0) { 00472 /* 00473 * Allow for some dead records per hash chain, look if we can 00474 * find one that can hold the new record. We need enough space 00475 * for key, data and tailer. If we find one, we don't have to 00476 * consult the central freelist. 00477 */ 00478 rec_ptr = tdb_find_dead( 00479 tdb, hash, &rec, 00480 key.dsize + dbuf.dsize + sizeof(tdb_off_t)); 00481 00482 if (rec_ptr != 0) { 00483 rec.key_len = key.dsize; 00484 rec.data_len = dbuf.dsize; 00485 rec.full_hash = hash; 00486 rec.magic = TDB_MAGIC; 00487 if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 00488 || tdb->methods->tdb_write( 00489 tdb, rec_ptr + sizeof(rec), 00490 p, key.dsize + dbuf.dsize) == -1) { 00491 goto fail; 00492 } 00493 goto done; 00494 } 00495 } 00496 00497 /* 00498 * We have to allocate some space from the freelist, so this means we 00499 * have to lock it. Use the chance to purge all the DEAD records from 00500 * the hash chain under the freelist lock. 00501 */ 00502 00503 if (tdb_lock(tdb, -1, F_WRLCK) == -1) { 00504 goto fail; 00505 } 00506 00507 if ((tdb->max_dead_records != 0) 00508 && (tdb_purge_dead(tdb, hash) == -1)) { 00509 tdb_unlock(tdb, -1, F_WRLCK); 00510 goto fail; 00511 } 00512 00513 /* we have to allocate some space */ 00514 rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec); 00515 00516 tdb_unlock(tdb, -1, F_WRLCK); 00517 00518 if (rec_ptr == 0) { 00519 goto fail; 00520 } 00521 00522 /* Read hash top into next ptr */ 00523 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) 00524 goto fail; 00525 00526 rec.key_len = key.dsize; 00527 rec.data_len = dbuf.dsize; 00528 rec.full_hash = hash; 00529 rec.magic = TDB_MAGIC; 00530 00531 /* write out and point the top of the hash chain at it */ 00532 if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 00533 || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 00534 || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { 00535 /* Need to tdb_unallocate() here */ 00536 goto fail; 00537 } 00538 00539 done: 00540 ret = 0; 00541 fail: 00542 if (ret == 0) { 00543 tdb_increment_seqnum(tdb); 00544 } 00545 00546 SAFE_FREE(p); 00547 tdb_unlock(tdb, BUCKET(hash), F_WRLCK); 00548 return ret; 00549 }
int tdb_append | ( | struct tdb_context * | tdb, | |
TDB_DATA | key, | |||
TDB_DATA | new_dbuf | |||
) |
参照先 TDB_DATA::dptr・TDB_DATA::dsize・tdb_context::ecode・failed・tdb_context::hash_fn・tdb・TDB_ERR_OOM・tdb_fetch()・tdb_lock()・tdb_store()・tdb_unlock().
参照元 add_to_jobs_changed()・addrec_db()・message_send_pid_internal().
00554 { 00555 u32 hash; 00556 TDB_DATA dbuf; 00557 int ret = -1; 00558 00559 /* find which hash bucket it is in */ 00560 hash = tdb->hash_fn(&key); 00561 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) 00562 return -1; 00563 00564 dbuf = tdb_fetch(tdb, key); 00565 00566 if (dbuf.dptr == NULL) { 00567 dbuf.dptr = (char *)malloc(new_dbuf.dsize); 00568 } else { 00569 char *new_dptr = (char *)realloc(dbuf.dptr, 00570 dbuf.dsize + new_dbuf.dsize); 00571 if (new_dptr == NULL) { 00572 free(dbuf.dptr); 00573 } 00574 dbuf.dptr = new_dptr; 00575 } 00576 00577 if (dbuf.dptr == NULL) { 00578 tdb->ecode = TDB_ERR_OOM; 00579 goto failed; 00580 } 00581 00582 memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize); 00583 dbuf.dsize += new_dbuf.dsize; 00584 00585 ret = tdb_store(tdb, key, dbuf, 0); 00586 00587 failed: 00588 tdb_unlock(tdb, BUCKET(hash), F_WRLCK); 00589 SAFE_FREE(dbuf.dptr); 00590 return ret; 00591 }
int tdb_close | ( | struct tdb_context * | tdb | ) |
Close a database.
参照先 tdb_context::fd・tdb_context::flags・tdb_context::lockrecs・tdb_context::map_ptr・tdb_context::name・tdb_context::next・tdb・tdb_munmap()・tdb_transaction_cancel()・tdbs・tdb_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 }
TDB_DATA tdb_firstkey | ( | struct tdb_context * | tdb | ) |
traverse.c の 255 行で定義されています。
参照先 TDB_DATA::dptr・TDB_DATA::dsize・tdb_traverse_lock::hash・list_struct::key_len・tdb_traverse_lock::lock_rw・tdb_traverse_lock::off・tdb・tdb_alloc_read()・TDB_DEBUG_FATAL・tdb_next_lock()・tdb_null・tdb_unlock()・tdb_unlock_record()・tdb_context::travlocks.
参照元 compare_db()・enum_group_mapping()・first_record()・get_group_map_from_gid()・get_group_map_from_ntname()・get_ntdrivers()・get_ntforms()・py_tdb_hnd_first_key()・tdb_search_keys()・tdbsam_convert()・upgrade_to_version_3().
00256 { 00257 TDB_DATA key; 00258 struct list_struct rec; 00259 00260 /* release any old lock */ 00261 if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) 00262 return tdb_null; 00263 tdb->travlocks.off = tdb->travlocks.hash = 0; 00264 tdb->travlocks.lock_rw = F_RDLCK; 00265 00266 /* Grab first record: locks chain and returned record. */ 00267 if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) 00268 return tdb_null; 00269 /* now read the key */ 00270 key.dsize = rec.key_len; 00271 key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); 00272 00273 /* Unlock the hash chain of the record we just read. */ 00274 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) 00275 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n")); 00276 return key; 00277 }
TDB_DATA tdb_nextkey | ( | struct tdb_context * | tdb, | |
TDB_DATA | key | |||
) |
traverse.c の 280 行で定義されています。
参照先 TDB_DATA::dptr・TDB_DATA::dsize・errno・list_struct::full_hash・tdb_traverse_lock::hash・tdb_context::hash_fn・list_struct::key_len・tdb_traverse_lock::lock_rw・tdb_traverse_lock::off・strerror()・tdb・tdb_alloc_read()・TDB_DEBUG_FATAL・tdb_find_lock_hash()・tdb_lock()・tdb_lock_record()・tdb_next_lock()・tdb_null・tdb_rec_read()・tdb_unlock()・tdb_unlock_record()・tdb_context::travlocks.
参照元 compare_db()・enum_group_mapping()・get_group_map_from_gid()・get_group_map_from_ntname()・get_ntdrivers()・get_ntforms()・next_record()・py_tdb_hnd_next_key()・tdb_search_keys()・tdbsam_convert()・upgrade_to_version_3().
00281 { 00282 u32 oldhash; 00283 TDB_DATA key = tdb_null; 00284 struct list_struct rec; 00285 char *k = NULL; 00286 00287 /* Is locked key the old key? If so, traverse will be reliable. */ 00288 if (tdb->travlocks.off) { 00289 if (tdb_lock(tdb,tdb->travlocks.hash,tdb->travlocks.lock_rw)) 00290 return tdb_null; 00291 if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1 00292 || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), 00293 rec.key_len)) 00294 || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { 00295 /* No, it wasn't: unlock it and start from scratch */ 00296 if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) { 00297 SAFE_FREE(k); 00298 return tdb_null; 00299 } 00300 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) { 00301 SAFE_FREE(k); 00302 return tdb_null; 00303 } 00304 tdb->travlocks.off = 0; 00305 } 00306 00307 SAFE_FREE(k); 00308 } 00309 00310 if (!tdb->travlocks.off) { 00311 /* No previous element: do normal find, and lock record */ 00312 tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), tdb->travlocks.lock_rw, &rec); 00313 if (!tdb->travlocks.off) 00314 return tdb_null; 00315 tdb->travlocks.hash = BUCKET(rec.full_hash); 00316 if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) { 00317 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); 00318 return tdb_null; 00319 } 00320 } 00321 oldhash = tdb->travlocks.hash; 00322 00323 /* Grab next record: locks chain and returned record, 00324 unlocks old record */ 00325 if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { 00326 key.dsize = rec.key_len; 00327 key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), 00328 key.dsize); 00329 /* Unlock the chain of this new record */ 00330 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) 00331 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); 00332 } 00333 /* Unlock the chain of old record */ 00334 if (tdb_unlock(tdb, BUCKET(oldhash), tdb->travlocks.lock_rw) != 0) 00335 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); 00336 return key; 00337 }
int tdb_traverse | ( | struct tdb_context * | tdb, | |
tdb_traverse_func | fn, | |||
void * | ||||
) |
traverse.c の 230 行で定義されています。
参照先 tdb_context::ecode・tdb_context::methods・tdb_context::read_only・tdb・tdb_methods::tdb_brlock・TDB_DEBUG_ERROR・TDB_ERR_LOCK・tdb_traverse_internal()・tdb_traverse_read()・tdb_context::traverse_read.
参照元 addrec_db()・backup_tdb()・brl_forall()・clear_unexpected()・count_current_connections()・do_command()・do_daemon_stack_trace()・dump_tdb()・dump_wins_subnet_namelist()・elog_tdb_size()・enum_aliasmem()・fetch_all_active_wins_1b_names()・idmap_tdb_convert()・idmap_tdb_dump_data()・info_tdb()・init_group_mapping()・initiate_wins_processing()・load_msg()・main()・message_send_all()・net_enum_pipes()・net_idmap_dump()・net_status_sessions()・net_status_shares()・net_status_shares_parseable()・print_backend_init()・print_queue_update_internal()・privilege_enumerate_accounts()・py_tdb_hnd_keys()・py_tdb_hnd_traverse()・receive_unexpected()・session_traverse()・share_info_db_init()・share_mode_forall()・status_page()・sysjob_to_jobid()・tdb_hnd_length()・tdbsam_setsampwent()・update_c_setprinter()・upgrade_to_version_4()・upgrade_to_version_5()・verify_tdb()・wcache_count_cached_creds()・wcache_flush_cache()・wcache_invalidate_cache()・wcache_remove_oldest_cached_creds()・wins_write_database().
00232 { 00233 struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK }; 00234 int ret; 00235 00236 if (tdb->read_only || tdb->traverse_read) { 00237 return tdb_traverse_read(tdb, fn, private_data); 00238 } 00239 00240 if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { 00241 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_traverse: failed to get transaction lock\n")); 00242 tdb->ecode = TDB_ERR_LOCK; 00243 return -1; 00244 } 00245 00246 ret = tdb_traverse_internal(tdb, fn, private_data, &tl); 00247 00248 tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); 00249 00250 return ret; 00251 }
int tdb_traverse_read | ( | struct tdb_context * | tdb, | |
tdb_traverse_func | fn, | |||
void * | ||||
) |
traverse.c の 203 行で定義されています。
参照先 tdb_context::ecode・tdb_context::methods・tdb・tdb_methods::tdb_brlock・TDB_DEBUG_ERROR・TDB_ERR_LOCK・tdb_traverse_internal()・tdb_context::traverse_read.
参照元 addrec_db()・main()・tdb_traverse().
00205 { 00206 struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK }; 00207 int ret; 00208 00209 /* we need to get a read lock on the transaction lock here to 00210 cope with the lock ordering semantics of solaris10 */ 00211 if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1) { 00212 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_traverse_read: failed to get transaction lock\n")); 00213 tdb->ecode = TDB_ERR_LOCK; 00214 return -1; 00215 } 00216 00217 tdb->traverse_read++; 00218 ret = tdb_traverse_internal(tdb, fn, private_data, &tl); 00219 tdb->traverse_read--; 00220 00221 tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); 00222 00223 return ret; 00224 }
int tdb_exists | ( | struct tdb_context * | tdb, | |
TDB_DATA | key | |||
) |
参照先 tdb_context::hash_fn・tdb・tdb_exists_hash().
参照元 print_job_exists()・py_tdb_hnd_has_key().
00221 { 00222 u32 hash = tdb->hash_fn(&key); 00223 return tdb_exists_hash(tdb, key, hash); 00224 }
int tdb_lockall | ( | struct tdb_context * | tdb | ) |
参照先 _tdb_lockall()・tdb.
参照元 backup_tdb()・load_msg()・py_tdb_hnd_lock_all().
00337 { 00338 return _tdb_lockall(tdb, F_WRLCK); 00339 }
int tdb_unlockall | ( | struct tdb_context * | tdb | ) |
参照先 _tdb_unlockall()・tdb.
参照元 load_msg()・py_tdb_hnd_unlock_all().
00343 { 00344 return _tdb_unlockall(tdb, F_WRLCK); 00345 }
int tdb_lockall_read | ( | struct tdb_context * | tdb | ) |
int tdb_unlockall_read | ( | struct tdb_context * | tdb | ) |
const char* tdb_name | ( | struct tdb_context * | tdb | ) |
int tdb_fd | ( | struct tdb_context * | tdb | ) |
tdb_log_func tdb_log_fn | ( | struct tdb_context * | tdb | ) |
void* tdb_get_logging_private | ( | struct tdb_context * | tdb | ) |
参照先 tdb_context::log・tdb_logging_context::log_private・tdb.
00398 { 00399 return tdb->log.log_private; 00400 }
int tdb_transaction_start | ( | struct tdb_context * | tdb | ) |
transaction.c の 384 行で定義されています。
参照先 tdb_lock_type::count・tdb_context::ecode・tdb_context::flags・tdb_context::global_lock・tdb_transaction::hash_heads・tdb_header::hash_size・tdb_context::header・tdb_transaction::io_methods・tdb_context::map_size・tdb_context::methods・tdb_transaction::nesting・tdb_traverse_lock::next・tdb_context::num_locks・tdb_transaction::old_map_size・tdb_context::read_only・tdb・tdb_brlock()・TDB_DEBUG_ERROR・TDB_DEBUG_FATAL・TDB_DEBUG_TRACE・TDB_ERR_EINVAL・TDB_ERR_IO・TDB_ERR_LOCK・TDB_ERR_OOM・tdb_methods::tdb_oob・tdb_methods::tdb_read・tdb_context::transaction・transaction_methods・transaction_write()・tdb_context::traverse_read・tdb_context::travlocks.
参照元 addrec_db()・init_registry_data()・tdb_trans_delete()・tdb_trans_store().
00385 { 00386 /* some sanity checks */ 00387 if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) { 00388 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n")); 00389 tdb->ecode = TDB_ERR_EINVAL; 00390 return -1; 00391 } 00392 00393 /* cope with nested tdb_transaction_start() calls */ 00394 if (tdb->transaction != NULL) { 00395 tdb->transaction->nesting++; 00396 TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n", 00397 tdb->transaction->nesting)); 00398 return 0; 00399 } 00400 00401 if (tdb->num_locks != 0 || tdb->global_lock.count) { 00402 /* the caller must not have any locks when starting a 00403 transaction as otherwise we'll be screwed by lack 00404 of nested locks in posix */ 00405 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction with locks held\n")); 00406 tdb->ecode = TDB_ERR_LOCK; 00407 return -1; 00408 } 00409 00410 if (tdb->travlocks.next != NULL) { 00411 /* you cannot use transactions inside a traverse (although you can use 00412 traverse inside a transaction) as otherwise you can end up with 00413 deadlock */ 00414 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction within a traverse\n")); 00415 tdb->ecode = TDB_ERR_LOCK; 00416 return -1; 00417 } 00418 00419 tdb->transaction = (struct tdb_transaction *) 00420 calloc(sizeof(struct tdb_transaction), 1); 00421 if (tdb->transaction == NULL) { 00422 tdb->ecode = TDB_ERR_OOM; 00423 return -1; 00424 } 00425 00426 /* get the transaction write lock. This is a blocking lock. As 00427 discussed with Volker, there are a number of ways we could 00428 make this async, which we will probably do in the future */ 00429 if (tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { 00430 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get transaction lock\n")); 00431 tdb->ecode = TDB_ERR_LOCK; 00432 SAFE_FREE(tdb->transaction); 00433 return -1; 00434 } 00435 00436 /* get a read lock from the freelist to the end of file. This 00437 is upgraded to a write lock during the commit */ 00438 if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) { 00439 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n")); 00440 tdb->ecode = TDB_ERR_LOCK; 00441 goto fail; 00442 } 00443 00444 /* setup a copy of the hash table heads so the hash scan in 00445 traverse can be fast */ 00446 tdb->transaction->hash_heads = (u32 *) 00447 calloc(tdb->header.hash_size+1, sizeof(u32)); 00448 if (tdb->transaction->hash_heads == NULL) { 00449 tdb->ecode = TDB_ERR_OOM; 00450 goto fail; 00451 } 00452 if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads, 00453 TDB_HASHTABLE_SIZE(tdb), 0) != 0) { 00454 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to read hash heads\n")); 00455 tdb->ecode = TDB_ERR_IO; 00456 goto fail; 00457 } 00458 00459 /* make sure we know about any file expansions already done by 00460 anyone else */ 00461 tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); 00462 tdb->transaction->old_map_size = tdb->map_size; 00463 00464 /* finally hook the io methods, replacing them with 00465 transaction specific methods */ 00466 tdb->transaction->io_methods = tdb->methods; 00467 tdb->methods = &transaction_methods; 00468 00469 /* by calling this transaction write here, we ensure that we don't grow the 00470 transaction linked list due to hash table updates */ 00471 if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads, 00472 TDB_HASHTABLE_SIZE(tdb)) != 0) { 00473 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n")); 00474 tdb->ecode = TDB_ERR_IO; 00475 goto fail; 00476 } 00477 00478 return 0; 00479 00480 fail: 00481 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); 00482 tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); 00483 SAFE_FREE(tdb->transaction->hash_heads); 00484 SAFE_FREE(tdb->transaction); 00485 return -1; 00486 }
int tdb_transaction_commit | ( | struct tdb_context * | tdb | ) |
transaction.c の 783 行で定義されています。
参照先 tdb_lock_type::count・tdb_transaction_el::data・tdb_context::ecode・tdb_transaction::elements・tdb_context::flags・tdb_context::global_lock・tdb_transaction::io_methods・tdb_transaction_el::length・tdb_context::map_size・tdb_context::methods・methods・tdb_context::name・tdb_transaction::nesting・tdb_transaction_el::next・tdb_context::num_locks・tdb_transaction_el::offset・tdb_transaction::old_map_size・tdb・tdb_brlock()・tdb_brlock_upgrade()・TDB_DEBUG_ERROR・TDB_DEBUG_FATAL・TDB_ERR_IO・TDB_ERR_LOCK・tdb_transaction_cancel()・tdb_transaction_recover()・tdb_context::transaction・tdb_transaction::transaction_error・transaction_setup_recovery()・transaction_sync().
参照元 addrec_db()・init_registry_data()・tdb_trans_delete()・tdb_trans_store().
00784 { 00785 const struct tdb_methods *methods; 00786 tdb_off_t magic_offset = 0; 00787 u32 zero = 0; 00788 00789 if (tdb->transaction == NULL) { 00790 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n")); 00791 return -1; 00792 } 00793 00794 if (tdb->transaction->transaction_error) { 00795 tdb->ecode = TDB_ERR_IO; 00796 tdb_transaction_cancel(tdb); 00797 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n")); 00798 return -1; 00799 } 00800 00801 if (tdb->transaction->nesting != 0) { 00802 tdb->transaction->nesting--; 00803 return 0; 00804 } 00805 00806 /* check for a null transaction */ 00807 if (tdb->transaction->elements == NULL) { 00808 tdb_transaction_cancel(tdb); 00809 return 0; 00810 } 00811 00812 methods = tdb->transaction->io_methods; 00813 00814 /* if there are any locks pending then the caller has not 00815 nested their locks properly, so fail the transaction */ 00816 if (tdb->num_locks || tdb->global_lock.count) { 00817 tdb->ecode = TDB_ERR_LOCK; 00818 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: locks pending on commit\n")); 00819 tdb_transaction_cancel(tdb); 00820 return -1; 00821 } 00822 00823 /* upgrade the main transaction lock region to a write lock */ 00824 if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) { 00825 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to upgrade hash locks\n")); 00826 tdb->ecode = TDB_ERR_LOCK; 00827 tdb_transaction_cancel(tdb); 00828 return -1; 00829 } 00830 00831 /* get the global lock - this prevents new users attaching to the database 00832 during the commit */ 00833 if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { 00834 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: failed to get global lock\n")); 00835 tdb->ecode = TDB_ERR_LOCK; 00836 tdb_transaction_cancel(tdb); 00837 return -1; 00838 } 00839 00840 if (!(tdb->flags & TDB_NOSYNC)) { 00841 /* write the recovery data to the end of the file */ 00842 if (transaction_setup_recovery(tdb, &magic_offset) == -1) { 00843 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to setup recovery data\n")); 00844 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); 00845 tdb_transaction_cancel(tdb); 00846 return -1; 00847 } 00848 } 00849 00850 /* expand the file to the new size if needed */ 00851 if (tdb->map_size != tdb->transaction->old_map_size) { 00852 if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, 00853 tdb->map_size - 00854 tdb->transaction->old_map_size) == -1) { 00855 tdb->ecode = TDB_ERR_IO; 00856 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n")); 00857 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); 00858 tdb_transaction_cancel(tdb); 00859 return -1; 00860 } 00861 tdb->map_size = tdb->transaction->old_map_size; 00862 methods->tdb_oob(tdb, tdb->map_size + 1, 1); 00863 } 00864 00865 /* perform all the writes */ 00866 while (tdb->transaction->elements) { 00867 struct tdb_transaction_el *el = tdb->transaction->elements; 00868 00869 if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) { 00870 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n")); 00871 00872 /* we've overwritten part of the data and 00873 possibly expanded the file, so we need to 00874 run the crash recovery code */ 00875 tdb->methods = methods; 00876 tdb_transaction_recover(tdb); 00877 00878 tdb_transaction_cancel(tdb); 00879 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); 00880 00881 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n")); 00882 return -1; 00883 } 00884 tdb->transaction->elements = el->next; 00885 free(el->data); 00886 free(el); 00887 } 00888 00889 if (!(tdb->flags & TDB_NOSYNC)) { 00890 /* ensure the new data is on disk */ 00891 if (transaction_sync(tdb, 0, tdb->map_size) == -1) { 00892 return -1; 00893 } 00894 00895 /* remove the recovery marker */ 00896 if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) { 00897 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to remove recovery magic\n")); 00898 return -1; 00899 } 00900 00901 /* ensure the recovery marker has been removed on disk */ 00902 if (transaction_sync(tdb, magic_offset, 4) == -1) { 00903 return -1; 00904 } 00905 } 00906 00907 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); 00908 00909 /* 00910 TODO: maybe write to some dummy hdr field, or write to magic 00911 offset without mmap, before the last sync, instead of the 00912 utime() call 00913 */ 00914 00915 /* on some systems (like Linux 2.6.x) changes via mmap/msync 00916 don't change the mtime of the file, this means the file may 00917 not be backed up (as tdb rounding to block sizes means that 00918 file size changes are quite rare too). The following forces 00919 mtime changes when a transaction completes */ 00920 #ifdef HAVE_UTIME 00921 utime(tdb->name, NULL); 00922 #endif 00923 00924 /* use a transaction cancel to free memory and remove the 00925 transaction locks */ 00926 tdb_transaction_cancel(tdb); 00927 return 0; 00928 }
int tdb_transaction_cancel | ( | struct tdb_context * | tdb | ) |
transaction.c の 492 行で定義されています。
参照先 tdb_lock_type::count・tdb_transaction_el::data・tdb_transaction::elements・tdb_context::global_lock・tdb_transaction::hash_heads・tdb_header::hash_size・tdb_context::header・tdb_transaction::io_methods・tdb_lock_type::list・tdb_context::lockrecs・tdb_context::map_size・tdb_context::methods・tdb_transaction::nesting・tdb_transaction_el::next・tdb_context::num_lockrecs・tdb_context::num_locks・tdb_transaction::old_map_size・tdb・tdb_brlock()・TDB_DEBUG_ERROR・tdb_context::transaction・tdb_transaction::transaction_error.
参照元 addrec_db()・init_registry_data()・tdb_close()・tdb_trans_delete()・tdb_trans_store()・tdb_transaction_commit().
00493 { 00494 if (tdb->transaction == NULL) { 00495 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n")); 00496 return -1; 00497 } 00498 00499 if (tdb->transaction->nesting != 0) { 00500 tdb->transaction->transaction_error = 1; 00501 tdb->transaction->nesting--; 00502 return 0; 00503 } 00504 00505 tdb->map_size = tdb->transaction->old_map_size; 00506 00507 /* free all the transaction elements */ 00508 while (tdb->transaction->elements) { 00509 struct tdb_transaction_el *el = tdb->transaction->elements; 00510 tdb->transaction->elements = el->next; 00511 free(el->data); 00512 free(el); 00513 } 00514 00515 /* remove any global lock created during the transaction */ 00516 if (tdb->global_lock.count != 0) { 00517 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size); 00518 tdb->global_lock.count = 0; 00519 } 00520 00521 /* remove any locks created during the transaction */ 00522 if (tdb->num_locks != 0) { 00523 int i; 00524 for (i=0;i<tdb->num_lockrecs;i++) { 00525 tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list, 00526 F_UNLCK,F_SETLKW, 0, 1); 00527 } 00528 tdb->num_locks = 0; 00529 tdb->num_lockrecs = 0; 00530 SAFE_FREE(tdb->lockrecs); 00531 } 00532 00533 /* restore the normal io methods */ 00534 tdb->methods = tdb->transaction->io_methods; 00535 00536 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); 00537 tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); 00538 SAFE_FREE(tdb->transaction->hash_heads); 00539 SAFE_FREE(tdb->transaction); 00540 00541 return 0; 00542 }
int tdb_transaction_recover | ( | struct tdb_context * | tdb | ) |
transaction.c の 936 行で定義されています。
参照先 tdb_transaction_el::data・tdb_context::ecode・tdb_context::fd・len・list_struct::magic・tdb_context::map_size・tdb_context::methods・tdb_context::read_only・tdb・tdb_convert()・TDB_DEBUG_FATAL・TDB_DEBUG_TRACE・TDB_ERR_CORRUPT・TDB_ERR_IO・TDB_ERR_OOM・tdb_mmap()・tdb_munmap()・tdb_ofs_read()・tdb_ofs_write()・tdb_methods::tdb_read・tdb_methods::tdb_write・transaction_sync().
参照元 tdb_open_ex()・tdb_transaction_commit().
00937 { 00938 tdb_off_t recovery_head, recovery_eof; 00939 unsigned char *data, *p; 00940 u32 zero = 0; 00941 struct list_struct rec; 00942 00943 /* find the recovery area */ 00944 if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { 00945 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery head\n")); 00946 tdb->ecode = TDB_ERR_IO; 00947 return -1; 00948 } 00949 00950 if (recovery_head == 0) { 00951 /* we have never allocated a recovery record */ 00952 return 0; 00953 } 00954 00955 /* read the recovery record */ 00956 if (tdb->methods->tdb_read(tdb, recovery_head, &rec, 00957 sizeof(rec), DOCONV()) == -1) { 00958 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n")); 00959 tdb->ecode = TDB_ERR_IO; 00960 return -1; 00961 } 00962 00963 if (rec.magic != TDB_RECOVERY_MAGIC) { 00964 /* there is no valid recovery data */ 00965 return 0; 00966 } 00967 00968 if (tdb->read_only) { 00969 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: attempt to recover read only database\n")); 00970 tdb->ecode = TDB_ERR_CORRUPT; 00971 return -1; 00972 } 00973 00974 recovery_eof = rec.key_len; 00975 00976 data = (unsigned char *)malloc(rec.data_len); 00977 if (data == NULL) { 00978 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n")); 00979 tdb->ecode = TDB_ERR_OOM; 00980 return -1; 00981 } 00982 00983 /* read the full recovery data */ 00984 if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data, 00985 rec.data_len, 0) == -1) { 00986 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n")); 00987 tdb->ecode = TDB_ERR_IO; 00988 return -1; 00989 } 00990 00991 /* recover the file data */ 00992 p = data; 00993 while (p+8 < data + rec.data_len) { 00994 u32 ofs, len; 00995 if (DOCONV()) { 00996 tdb_convert(p, 8); 00997 } 00998 memcpy(&ofs, p, 4); 00999 memcpy(&len, p+4, 4); 01000 01001 if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) { 01002 free(data); 01003 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs)); 01004 tdb->ecode = TDB_ERR_IO; 01005 return -1; 01006 } 01007 p += 8 + len; 01008 } 01009 01010 free(data); 01011 01012 if (transaction_sync(tdb, 0, tdb->map_size) == -1) { 01013 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync recovery\n")); 01014 tdb->ecode = TDB_ERR_IO; 01015 return -1; 01016 } 01017 01018 /* if the recovery area is after the recovered eof then remove it */ 01019 if (recovery_eof <= recovery_head) { 01020 if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) { 01021 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n")); 01022 tdb->ecode = TDB_ERR_IO; 01023 return -1; 01024 } 01025 } 01026 01027 /* remove the recovery magic */ 01028 if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic), 01029 &zero) == -1) { 01030 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n")); 01031 tdb->ecode = TDB_ERR_IO; 01032 return -1; 01033 } 01034 01035 /* reduce the file size to the old size */ 01036 tdb_munmap(tdb); 01037 if (ftruncate(tdb->fd, recovery_eof) != 0) { 01038 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n")); 01039 tdb->ecode = TDB_ERR_IO; 01040 return -1; 01041 } 01042 tdb->map_size = recovery_eof; 01043 tdb_mmap(tdb); 01044 01045 if (transaction_sync(tdb, 0, recovery_eof) == -1) { 01046 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync2 recovery\n")); 01047 tdb->ecode = TDB_ERR_IO; 01048 return -1; 01049 } 01050 01051 TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n", 01052 recovery_eof)); 01053 01054 /* all done */ 01055 return 0; 01056 }
int tdb_get_seqnum | ( | struct tdb_context * | tdb | ) |
参照先 tdb・tdb_ofs_read().
参照元 notify_init()・notify_load().
00634 { 00635 tdb_off_t seqnum=0; 00636 00637 tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); 00638 return seqnum; 00639 }
int tdb_hash_size | ( | struct tdb_context * | tdb | ) |
size_t tdb_map_size | ( | struct tdb_context * | tdb | ) |
int tdb_get_flags | ( | struct tdb_context * | tdb | ) |
int tdb_chainlock | ( | struct tdb_context * | tdb, | |
TDB_DATA | key | |||
) |
参照先 tdb_context::hash_fn・tdb・tdb_lock().
参照元 addrec_db()・brl_get_locks_internal()・get_share_mode_lock()・idmap_tdb_remove_mapping()・idmap_tdb_set_mapping()・message_send_pid_internal()・py_tdb_hnd_chainlock()・retrieve_all_messages()・smb_lock_share_mode_entry()・tdb_chainlock_with_timeout_internal()・tdb_lock_bystring().
int tdb_chainunlock | ( | struct tdb_context * | tdb, | |
TDB_DATA | key | |||
) |
参照先 tdb_context::hash_fn・tdb・tdb_unlock().
参照元 addrec_db()・byte_range_lock_destructor()・idmap_tdb_remove_mapping()・idmap_tdb_set_mapping()・message_send_pid_internal()・py_tdb_hnd_chainunlock()・remove_from_jobs_changed()・retrieve_all_messages()・share_mode_lock_destructor()・smb_unlock_share_mode_entry()・tdb_unlock_bystring().
00367 { 00368 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); 00369 }
int tdb_chainlock_read | ( | struct tdb_context * | tdb, | |
TDB_DATA | key | |||
) |
int tdb_chainunlock_read | ( | struct tdb_context * | tdb, | |
TDB_DATA | key | |||
) |
参照先 tdb_context::hash_fn・tdb・tdb_unlock().
参照元 tdb_read_unlock_bystring().
00377 { 00378 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); 00379 }
void tdb_setalarm_sigptr | ( | struct tdb_context * | tdb, | |
volatile sig_atomic_t * | sigptr | |||
) |
参照先 tdb_context::interrupt_sig_ptr・tdb.
参照元 tdb_chainlock_with_timeout_internal().
00032 { 00033 tdb->interrupt_sig_ptr = ptr; 00034 }
void tdb_dump_all | ( | struct tdb_context * | tdb | ) |
参照先 tdb_header::hash_size・tdb_context::header・printf()・tdb・tdb_dump_chain().
参照元 do_command().
00085 { 00086 int i; 00087 for (i=0;i<tdb->header.hash_size;i++) { 00088 tdb_dump_chain(tdb, i); 00089 } 00090 printf("freelist:\n"); 00091 tdb_dump_chain(tdb, -1); 00092 }
int tdb_printfreelist | ( | struct tdb_context * | tdb | ) |
参照先 tdb_context::methods・printf()・tdb・tdb_lock()・tdb_ofs_read()・tdb_methods::tdb_read・tdb_unlock().
参照元 do_command().
00095 { 00096 int ret; 00097 long total_free = 0; 00098 tdb_off_t offset, rec_ptr; 00099 struct list_struct rec; 00100 00101 if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) 00102 return ret; 00103 00104 offset = FREELIST_TOP; 00105 00106 /* read in the freelist top */ 00107 if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) { 00108 tdb_unlock(tdb, -1, F_WRLCK); 00109 return 0; 00110 } 00111 00112 printf("freelist top=[0x%08x]\n", rec_ptr ); 00113 while (rec_ptr) { 00114 if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, 00115 sizeof(rec), DOCONV()) == -1) { 00116 tdb_unlock(tdb, -1, F_WRLCK); 00117 return -1; 00118 } 00119 00120 if (rec.magic != TDB_FREE_MAGIC) { 00121 printf("bad magic 0x%08x in free list\n", rec.magic); 00122 tdb_unlock(tdb, -1, F_WRLCK); 00123 return -1; 00124 } 00125 00126 printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", 00127 rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); 00128 total_free += rec.rec_len; 00129 00130 /* move to the next record */ 00131 rec_ptr = rec.next; 00132 } 00133 printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, 00134 (int)total_free); 00135 00136 return tdb_unlock(tdb, -1, F_WRLCK); 00137 }
int tdb_validate_freelist | ( | struct tdb_context * | tdb, | |
int * | pnum_entries | |||
) |
freelistcheck.c の 47 行で定義されています。
参照先 tdb_header::hash_size・tdb_context::header・last_ptr・list_struct::next・rec_free_read()・seen_insert()・tdb・tdb_close()・TDB_ERR_CORRUPT・tdb_lock()・tdb_ofs_read()・tdb_open()・tdb_unlock().
参照元 main().
00048 { 00049 struct tdb_context *mem_tdb = NULL; 00050 struct list_struct rec; 00051 tdb_off_t rec_ptr, last_ptr; 00052 int ret = -1; 00053 00054 *pnum_entries = 0; 00055 00056 mem_tdb = tdb_open("flval", tdb->header.hash_size, 00057 TDB_INTERNAL, O_RDWR, 0600); 00058 if (!mem_tdb) { 00059 return -1; 00060 } 00061 00062 if (tdb_lock(tdb, -1, F_WRLCK) == -1) { 00063 tdb_close(mem_tdb); 00064 return 0; 00065 } 00066 00067 last_ptr = FREELIST_TOP; 00068 00069 /* Store the FREELIST_TOP record. */ 00070 if (seen_insert(mem_tdb, last_ptr) == -1) { 00071 ret = TDB_ERRCODE(TDB_ERR_CORRUPT, -1); 00072 goto fail; 00073 } 00074 00075 /* read in the freelist top */ 00076 if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) { 00077 goto fail; 00078 } 00079 00080 while (rec_ptr) { 00081 00082 /* If we can't store this record (we've seen it 00083 before) then the free list has a loop and must 00084 be corrupt. */ 00085 00086 if (seen_insert(mem_tdb, rec_ptr)) { 00087 ret = TDB_ERRCODE(TDB_ERR_CORRUPT, -1); 00088 goto fail; 00089 } 00090 00091 if (rec_free_read(tdb, rec_ptr, &rec) == -1) { 00092 goto fail; 00093 } 00094 00095 /* move to the next record */ 00096 last_ptr = rec_ptr; 00097 rec_ptr = rec.next; 00098 *pnum_entries += 1; 00099 } 00100 00101 ret = 0; 00102 00103 fail: 00104 00105 tdb_close(mem_tdb); 00106 tdb_unlock(tdb, -1, F_WRLCK); 00107 return ret; 00108 }