/*创建一个connection evict cache*/ int __wt_cache_create(WT_SESSION_IMPL* session, const char* cfg[]) { WT_CACHE *cache; WT_CONNECTION_IMPL *conn; WT_DECL_RET; conn = S2C(session); WT_RET(__wt_calloc_one(session, &conn->cache)); cache = conn->cache; /*对cache进行配置*/ WT_RET(__wt_cache_config(session, 0, cfg)); if (cache->eviction_target >= cache->eviction_trigger) WT_ERR_MSG(session, EINVAL, "eviction target must be lower than the eviction trigger"); /*创建evict cond信号量*/ WT_ERR(__wt_cond_alloc(session, "cache eviction server", 0, &cache->evict_cond)); WT_ERR(__wt_cond_alloc(session, "eviction waiters", 0, &cache->evict_waiter_cond)); WT_ERR(__wt_spin_init(session, &cache->evict_lock, "cache eviction")); WT_ERR(__wt_spin_init(session, &cache->evict_walk_lock, "cache walk")); /* Allocate the LRU eviction queue. */ cache->evict_slots = WT_EVICT_WALK_BASE + WT_EVICT_WALK_INCR; WT_ERR(__wt_calloc_def(session, cache->evict_slots, &cache->evict)); /*初始化cache stat统计模块*/ __wt_cache_stats_update(session); return 0; err: WT_RET(__wt_cache_destroy(session)); return ret; }
/* * __wt_logmgr_create -- * Initialize the log subsystem (before running recovery). */ int __wt_logmgr_create(WT_SESSION_IMPL *session, const char *cfg[]) { WT_CONNECTION_IMPL *conn; WT_LOG *log; bool run; conn = S2C(session); /* Handle configuration. */ WT_RET(__logmgr_config(session, cfg, &run, false)); /* If logging is not configured, we're done. */ if (!run) return (0); FLD_SET(conn->log_flags, WT_CONN_LOG_ENABLED); /* * Logging is on, allocate the WT_LOG structure and open the log file. */ WT_RET(__wt_calloc_one(session, &conn->log)); log = conn->log; WT_RET(__wt_spin_init(session, &log->log_lock, "log")); WT_RET(__wt_spin_init(session, &log->log_slot_lock, "log slot")); WT_RET(__wt_spin_init(session, &log->log_sync_lock, "log sync")); WT_RET(__wt_spin_init(session, &log->log_writelsn_lock, "log write LSN")); WT_RET(__wt_rwlock_alloc(session, &log->log_archive_lock, "log archive lock")); if (FLD_ISSET(conn->direct_io, WT_FILE_TYPE_LOG)) log->allocsize = WT_MAX((uint32_t)conn->buffer_alignment, WT_LOG_ALIGN); else log->allocsize = WT_LOG_ALIGN; WT_INIT_LSN(&log->alloc_lsn); WT_INIT_LSN(&log->ckpt_lsn); WT_INIT_LSN(&log->first_lsn); WT_INIT_LSN(&log->sync_lsn); /* * We only use file numbers for directory sync, so this needs to * initialized to zero. */ WT_ZERO_LSN(&log->sync_dir_lsn); WT_INIT_LSN(&log->trunc_lsn); WT_INIT_LSN(&log->write_lsn); WT_INIT_LSN(&log->write_start_lsn); log->fileid = 0; WT_RET(__wt_cond_alloc( session, "log sync", false, &log->log_sync_cond)); WT_RET(__wt_cond_alloc( session, "log write", false, &log->log_write_cond)); WT_RET(__wt_log_open(session)); WT_RET(__wt_log_slot_init(session)); return (0); }
/* * __wt_cache_create -- * Create the underlying cache. */ int __wt_cache_create(WT_SESSION_IMPL *session, const char *cfg[]) { WT_CACHE *cache; WT_CONNECTION_IMPL *conn; WT_DECL_RET; conn = S2C(session); WT_ASSERT(session, conn->cache == NULL); WT_RET(__wt_calloc_one(session, &conn->cache)); cache = conn->cache; /* Use a common routine for run-time configuration options. */ WT_RET(__wt_cache_config(session, false, cfg)); /* * The lowest possible page read-generation has a special meaning, it * marks a page for forcible eviction; don't let it happen by accident. */ cache->read_gen = WT_READGEN_START_VALUE; /* * The target size must be lower than the trigger size or we will never * get any work done. */ if (cache->eviction_target >= cache->eviction_trigger) WT_ERR_MSG(session, EINVAL, "eviction target must be lower than the eviction trigger"); WT_ERR(__wt_cond_auto_alloc(session, "cache eviction server", false, 10000, WT_MILLION, &cache->evict_cond)); WT_ERR(__wt_cond_alloc(session, "eviction waiters", false, &cache->evict_waiter_cond)); WT_ERR(__wt_spin_init(session, &cache->evict_lock, "cache eviction")); WT_ERR(__wt_spin_init(session, &cache->evict_walk_lock, "cache walk")); /* Allocate the LRU eviction queue. */ cache->evict_slots = WT_EVICT_WALK_BASE + WT_EVICT_WALK_INCR; WT_ERR(__wt_calloc_def(session, cache->evict_slots, &cache->evict_queue)); /* * We get/set some values in the cache statistics (rather than have * two copies), configure them. */ __wt_cache_stats_update(session); return (0); err: WT_RET(__wt_cache_destroy(session)); return (ret); }
/* * __wt_global_once -- * Global initialization, run once. */ static void __wt_global_once(void) { WT_DECL_RET; if ((ret = __system_is_little_endian()) != 0) { __wt_pthread_once_failed = ret; return; } if ((ret = __wt_spin_init(NULL, &__wt_process.spinlock, "global")) != 0) { __wt_pthread_once_failed = ret; return; } __wt_cksum_init(); TAILQ_INIT(&__wt_process.connqh); #ifdef HAVE_DIAGNOSTIC /* Load debugging code the compiler might optimize out. */ (void)__wt_breakpoint(); #endif }
/* * __wt_global_once -- * Global initialization, run once. */ static void __wt_global_once(void) { WT_DECL_RET; if ((ret = __system_is_little_endian()) != 0) { __wt_pthread_once_failed = ret; return; } if ((ret = __wt_spin_init(NULL, &__wt_process.spinlock, "global")) != 0) { __wt_pthread_once_failed = ret; return; } __wt_cksum_init(); TAILQ_INIT(&__wt_process.connqh); #ifdef HAVE_DIAGNOSTIC /* Verify the pre-computed metadata hash. */ WT_ASSERT(NULL, WT_METAFILE_NAME_HASH == __wt_hash_city64(WT_METAFILE_URI, strlen(WT_METAFILE_URI))); /* Load debugging code the compiler might optimize out. */ (void)__wt_breakpoint(); #endif }
/* * __wt_txn_global_init -- * Initialize the global transaction state. */ int __wt_txn_global_init(WT_SESSION_IMPL *session, const char *cfg[]) { WT_CONNECTION_IMPL *conn; WT_TXN_GLOBAL *txn_global; WT_TXN_STATE *s; u_int i; WT_UNUSED(cfg); conn = S2C(session); txn_global = &conn->txn_global; txn_global->current = txn_global->last_running = txn_global->oldest_id = WT_TXN_FIRST; WT_RET(__wt_spin_init(session, &txn_global->id_lock, "transaction id lock")); WT_RET(__wt_rwlock_alloc(session, &txn_global->nsnap_rwlock, "named snapshot lock")); txn_global->nsnap_oldest_id = WT_TXN_NONE; TAILQ_INIT(&txn_global->nsnaph); WT_RET(__wt_calloc_def( session, conn->session_size, &txn_global->states)); WT_CACHE_LINE_ALIGNMENT_VERIFY(session, txn_global->states); for (i = 0, s = txn_global->states; i < conn->session_size; i++, s++) s->id = s->snap_min = WT_TXN_NONE; return (0); }
/* * __wt_cache_create -- * Create the underlying cache. */ int __wt_cache_create(WT_SESSION_IMPL *session, const char *cfg[]) { WT_CACHE *cache; WT_CONNECTION_IMPL *conn; WT_DECL_RET; conn = S2C(session); WT_ASSERT(session, conn->cache == NULL); WT_RET(__wt_calloc_one(session, &conn->cache)); cache = conn->cache; /* Use a common routine for run-time configuration options. */ WT_RET(__wt_cache_config(session, 0, cfg)); /* * The target size must be lower than the trigger size or we will never * get any work done. */ if (cache->eviction_target >= cache->eviction_trigger) WT_ERR_MSG(session, EINVAL, "eviction target must be lower than the eviction trigger"); WT_ERR(__wt_cond_alloc(session, "cache eviction server", 0, &cache->evict_cond)); WT_ERR(__wt_cond_alloc(session, "eviction waiters", 0, &cache->evict_waiter_cond)); WT_ERR(__wt_spin_init(session, &cache->evict_lock, "cache eviction")); WT_ERR(__wt_spin_init(session, &cache->evict_walk_lock, "cache walk")); /* Allocate the LRU eviction queue. */ cache->evict_slots = WT_EVICT_WALK_BASE + WT_EVICT_WALK_INCR; WT_ERR(__wt_calloc_def(session, cache->evict_slots, &cache->evict)); /* * We get/set some values in the cache statistics (rather than have * two copies), configure them. */ __wt_cache_stats_update(session); return (0); err: WT_RET(__wt_cache_destroy(session)); return (ret); }
static void __wt_pthread_once(void) { __wt_spin_init(NULL, &__wt_process.spinlock); TAILQ_INIT(&__wt_process.connqh); #ifdef HAVE_DIAGNOSTIC /* Load debugging code the compiler might optimize out. */ (void)__wt_breakpoint(); #endif }
/* * __wt_connection_init -- * Structure initialization for a just-created WT_CONNECTION_IMPL handle. */ int __wt_connection_init(WT_CONNECTION_IMPL *conn) { WT_SESSION_IMPL *session; session = conn->default_session; TAILQ_INIT(&conn->dhqh); /* Data handle list */ TAILQ_INIT(&conn->dlhqh); /* Library list */ TAILQ_INIT(&conn->dsrcqh); /* Data source list */ TAILQ_INIT(&conn->fhqh); /* File list */ TAILQ_INIT(&conn->collqh); /* Collator list */ TAILQ_INIT(&conn->compqh); /* Compressor list */ TAILQ_INIT(&conn->lsmqh); /* WT_LSM_TREE list */ /* Configuration. */ WT_RET(__wt_conn_config_init(session)); /* Statistics. */ __wt_stat_init_connection_stats(&conn->stats); /* Locks. */ __wt_spin_init(session, &conn->api_lock); __wt_spin_init(session, &conn->checkpoint_lock); __wt_spin_init(session, &conn->fh_lock); __wt_spin_init(session, &conn->hot_backup_lock); __wt_spin_init(session, &conn->schema_lock); __wt_spin_init(session, &conn->serial_lock); /* * Block manager. * XXX * If there's ever a second block manager, we'll want to make this * more opaque, but for now this is simpler. */ __wt_spin_init(session, &conn->block_lock); TAILQ_INIT(&conn->blockqh); /* Block manager list */ return (0); }
/* * __wt_txn_global_init -- * Initialize the global transaction state. */ int __wt_txn_global_init(WT_SESSION_IMPL *session, const char *cfg[]) { WT_CONNECTION_IMPL *conn; WT_TXN_GLOBAL *txn_global; WT_TXN_STATE *s; u_int i; WT_UNUSED(cfg); conn = S2C(session); txn_global = &conn->txn_global; txn_global->current = txn_global->last_running = txn_global->metadata_pinned = txn_global->oldest_id = WT_TXN_FIRST; WT_RET(__wt_spin_init( session, &txn_global->id_lock, "transaction id lock")); WT_RET(__wt_rwlock_init(session, &txn_global->rwlock)); WT_RET(__wt_rwlock_init(session, &txn_global->visibility_rwlock)); WT_RET(__wt_rwlock_init(session, &txn_global->commit_timestamp_rwlock)); TAILQ_INIT(&txn_global->commit_timestamph); WT_RET(__wt_rwlock_init(session, &txn_global->read_timestamp_rwlock)); TAILQ_INIT(&txn_global->read_timestamph); WT_RET(__wt_rwlock_init(session, &txn_global->nsnap_rwlock)); txn_global->nsnap_oldest_id = WT_TXN_NONE; TAILQ_INIT(&txn_global->nsnaph); WT_RET(__wt_calloc_def( session, conn->session_size, &txn_global->states)); for (i = 0, s = txn_global->states; i < conn->session_size; i++, s++) s->id = s->metadata_pinned = s->pinned_id = WT_TXN_NONE; return (0); }
/* * __global_once -- * Global initialization, run once. */ static void __global_once(void) { WT_DECL_RET; if ((ret = __wt_spin_init(NULL, &__wt_process.spinlock, "global")) != 0) { __wt_pthread_once_failed = ret; return; } TAILQ_INIT(&__wt_process.connqh); #if defined(HAVE_PAGE_VERSION_TS) __wt_process.page_version_ts = true; #else __wt_process.page_version_ts = false; #endif __wt_process.checksum = wiredtiger_crc32c_func(); __global_calibrate_ticks(); }
/* * __wt_cache_create -- * Create the underlying cache. */ int __wt_cache_create(WT_SESSION_IMPL *session, const char *cfg[]) { WT_CACHE *cache; WT_CONNECTION_IMPL *conn; WT_DECL_RET; int i; conn = S2C(session); WT_ASSERT(session, conn->cache == NULL); WT_RET(__wt_calloc_one(session, &conn->cache)); cache = conn->cache; /* Use a common routine for run-time configuration options. */ WT_RET(__wt_cache_config(session, false, cfg)); /* * The lowest possible page read-generation has a special meaning, it * marks a page for forcible eviction; don't let it happen by accident. */ cache->read_gen = WT_READGEN_START_VALUE; /* * The target size must be lower than the trigger size or we will never * get any work done. */ if (cache->eviction_target >= cache->eviction_trigger) WT_ERR_MSG(session, EINVAL, "eviction target must be lower than the eviction trigger"); WT_ERR(__wt_cond_auto_alloc(session, "cache eviction server", false, 10000, WT_MILLION, &cache->evict_cond)); WT_ERR(__wt_spin_init(session, &cache->evict_pass_lock, "evict pass")); WT_ERR(__wt_spin_init(session, &cache->evict_queue_lock, "cache eviction queue")); WT_ERR(__wt_spin_init(session, &cache->evict_walk_lock, "cache walk")); if ((ret = __wt_open_internal_session(conn, "evict pass", false, WT_SESSION_NO_DATA_HANDLES, &cache->walk_session)) != 0) WT_ERR_MSG(NULL, ret, "Failed to create session for eviction walks"); /* Allocate the LRU eviction queue. */ cache->evict_slots = WT_EVICT_WALK_BASE + WT_EVICT_WALK_INCR; for (i = 0; i < WT_EVICT_QUEUE_MAX; ++i) { WT_ERR(__wt_calloc_def(session, cache->evict_slots, &cache->evict_queues[i].evict_queue)); WT_ERR(__wt_spin_init(session, &cache->evict_queues[i].evict_lock, "cache eviction")); } /* Ensure there are always non-NULL queues. */ cache->evict_current_queue = cache->evict_fill_queue = &cache->evict_queues[0]; cache->evict_other_queue = &cache->evict_queues[1]; cache->evict_urgent_queue = &cache->evict_queues[WT_EVICT_URGENT_QUEUE]; /* * We get/set some values in the cache statistics (rather than have * two copies), configure them. */ __wt_cache_stats_update(session); return (0); err: WT_RET(__wt_cache_destroy(session)); return (ret); }
/* * __wt_connection_init -- * Structure initialization for a just-created WT_CONNECTION_IMPL handle. */ int __wt_connection_init(WT_CONNECTION_IMPL *conn) { WT_SESSION_IMPL *session; u_int i; session = conn->default_session; for (i = 0; i < WT_HASH_ARRAY_SIZE; i++) { SLIST_INIT(&conn->dhhash[i]); /* Data handle hash lists */ SLIST_INIT(&conn->fhhash[i]); /* File handle hash lists */ } SLIST_INIT(&conn->dhlh); /* Data handle list */ TAILQ_INIT(&conn->dlhqh); /* Library list */ TAILQ_INIT(&conn->dsrcqh); /* Data source list */ SLIST_INIT(&conn->fhlh); /* File list */ TAILQ_INIT(&conn->collqh); /* Collator list */ TAILQ_INIT(&conn->compqh); /* Compressor list */ TAILQ_INIT(&conn->extractorqh); /* Extractor list */ TAILQ_INIT(&conn->lsmqh); /* WT_LSM_TREE list */ /* Setup the LSM work queues. */ TAILQ_INIT(&conn->lsm_manager.switchqh); TAILQ_INIT(&conn->lsm_manager.appqh); TAILQ_INIT(&conn->lsm_manager.managerqh); /* Configuration. */ WT_RET(__wt_conn_config_init(session)); /* Statistics. */ __wt_stat_init_connection_stats(&conn->stats); /* Locks. */ WT_RET(__wt_spin_init(session, &conn->api_lock, "api")); WT_RET(__wt_spin_init(session, &conn->checkpoint_lock, "checkpoint")); WT_RET(__wt_spin_init(session, &conn->dhandle_lock, "data handle")); WT_RET(__wt_spin_init(session, &conn->fh_lock, "file list")); WT_RET(__wt_spin_init(session, &conn->hot_backup_lock, "hot backup")); WT_RET(__wt_spin_init(session, &conn->reconfig_lock, "reconfigure")); WT_RET(__wt_spin_init(session, &conn->schema_lock, "schema")); WT_RET(__wt_spin_init(session, &conn->table_lock, "table creation")); WT_RET(__wt_calloc_def(session, WT_PAGE_LOCKS(conn), &conn->page_lock)); for (i = 0; i < WT_PAGE_LOCKS(conn); ++i) WT_RET( __wt_spin_init(session, &conn->page_lock[i], "btree page")); /* Setup the spin locks for the LSM manager queues. */ WT_RET(__wt_spin_init(session, &conn->lsm_manager.app_lock, "LSM application queue lock")); WT_RET(__wt_spin_init(session, &conn->lsm_manager.manager_lock, "LSM manager queue lock")); WT_RET(__wt_spin_init( session, &conn->lsm_manager.switch_lock, "LSM switch queue lock")); WT_RET(__wt_cond_alloc( session, "LSM worker cond", 0, &conn->lsm_manager.work_cond)); /* * Generation numbers. * * Start split generations at one. Threads publish this generation * number before examining tree structures, and zero when they leave. * We need to distinguish between threads that are in a tree before the * first split has happened, and threads that are not in a tree. */ conn->split_gen = 1; /* * Block manager. * XXX * If there's ever a second block manager, we'll want to make this * more opaque, but for now this is simpler. */ WT_RET(__wt_spin_init(session, &conn->block_lock, "block manager")); for (i = 0; i < WT_HASH_ARRAY_SIZE; i++) SLIST_INIT(&conn->blockhash[i]);/* Block handle hash lists */ SLIST_INIT(&conn->blocklh); /* Block manager list */ return (0); }
/* * __wt_connection_init -- * Structure initialization for a just-created WT_CONNECTION_IMPL handle. */ int __wt_connection_init(WT_CONNECTION_IMPL *conn) { WT_SESSION_IMPL *session; u_int i; session = conn->default_session; for (i = 0; i < WT_HASH_ARRAY_SIZE; i++) { TAILQ_INIT(&conn->dhhash[i]); /* Data handle hash lists */ TAILQ_INIT(&conn->fhhash[i]); /* File handle hash lists */ } TAILQ_INIT(&conn->dhqh); /* Data handle list */ TAILQ_INIT(&conn->dlhqh); /* Library list */ TAILQ_INIT(&conn->dsrcqh); /* Data source list */ TAILQ_INIT(&conn->fhqh); /* File list */ TAILQ_INIT(&conn->collqh); /* Collator list */ TAILQ_INIT(&conn->compqh); /* Compressor list */ TAILQ_INIT(&conn->encryptqh); /* Encryptor list */ TAILQ_INIT(&conn->extractorqh); /* Extractor list */ TAILQ_INIT(&conn->lsmqh); /* WT_LSM_TREE list */ /* Setup the LSM work queues. */ TAILQ_INIT(&conn->lsm_manager.switchqh); TAILQ_INIT(&conn->lsm_manager.appqh); TAILQ_INIT(&conn->lsm_manager.managerqh); /* Random numbers. */ __wt_random_init(&session->rnd); /* Configuration. */ WT_RET(__wt_conn_config_init(session)); /* Statistics. */ WT_RET(__wt_stat_connection_init(session, conn)); /* Spinlocks. */ WT_RET(__wt_spin_init(session, &conn->api_lock, "api")); WT_SPIN_INIT_TRACKED(session, &conn->checkpoint_lock, checkpoint); WT_SPIN_INIT_TRACKED(session, &conn->dhandle_lock, handle_list); WT_RET(__wt_spin_init(session, &conn->encryptor_lock, "encryptor")); WT_RET(__wt_spin_init(session, &conn->fh_lock, "file list")); WT_RET(__wt_spin_init(session, &conn->las_lock, "lookaside table")); WT_SPIN_INIT_TRACKED(session, &conn->metadata_lock, metadata); WT_RET(__wt_spin_init(session, &conn->reconfig_lock, "reconfigure")); WT_SPIN_INIT_TRACKED(session, &conn->schema_lock, schema); WT_SPIN_INIT_TRACKED(session, &conn->table_lock, table); WT_RET(__wt_spin_init(session, &conn->turtle_lock, "turtle file")); /* Read-write locks */ WT_RET(__wt_rwlock_alloc( session, &conn->hot_backup_lock, "hot backup")); WT_RET(__wt_calloc_def(session, WT_PAGE_LOCKS, &conn->page_lock)); WT_CACHE_LINE_ALIGNMENT_VERIFY(session, conn->page_lock); for (i = 0; i < WT_PAGE_LOCKS; ++i) WT_RET( __wt_spin_init(session, &conn->page_lock[i], "btree page")); /* Setup the spin locks for the LSM manager queues. */ WT_RET(__wt_spin_init(session, &conn->lsm_manager.app_lock, "LSM application queue lock")); WT_RET(__wt_spin_init(session, &conn->lsm_manager.manager_lock, "LSM manager queue lock")); WT_RET(__wt_spin_init( session, &conn->lsm_manager.switch_lock, "LSM switch queue lock")); WT_RET(__wt_cond_alloc( session, "LSM worker cond", false, &conn->lsm_manager.work_cond)); /* * Generation numbers. * * Start split generations at one. Threads publish this generation * number before examining tree structures, and zero when they leave. * We need to distinguish between threads that are in a tree before the * first split has happened, and threads that are not in a tree. */ conn->split_gen = 1; /* * Block manager. * XXX * If there's ever a second block manager, we'll want to make this * more opaque, but for now this is simpler. */ WT_RET(__wt_spin_init(session, &conn->block_lock, "block manager")); for (i = 0; i < WT_HASH_ARRAY_SIZE; i++) TAILQ_INIT(&conn->blockhash[i]);/* Block handle hash lists */ TAILQ_INIT(&conn->blockqh); /* Block manager list */ return (0); }
/* * __wt_conn_optrack_setup -- * Set up operation logging. */ int __wt_conn_optrack_setup(WT_SESSION_IMPL *session, const char *cfg[], bool reconfig) { WT_CONFIG_ITEM cval; WT_CONNECTION_IMPL *conn; WT_DECL_ITEM(buf); WT_DECL_RET; conn = S2C(session); /* Once an operation tracking path has been set it can't be changed. */ if (!reconfig) { WT_RET(__wt_config_gets(session, cfg, "operation_tracking.path", &cval)); WT_RET(__wt_strndup(session, cval.str, cval.len, &conn->optrack_path)); } WT_RET(__wt_config_gets(session, cfg, "operation_tracking.enabled", &cval)); if (cval.val == 0) { if (F_ISSET(conn, WT_CONN_OPTRACK)) { WT_RET(__wt_conn_optrack_teardown(session, reconfig)); F_CLR(conn, WT_CONN_OPTRACK); } return (0); } if (F_ISSET(conn, WT_CONN_READONLY)) /* Operation tracking isn't supported in read-only mode */ WT_RET_MSG(session, EINVAL, "Operation tracking is incompatible with read only " "configuration."); if (F_ISSET(conn, WT_CONN_OPTRACK)) /* Already enabled, nothing else to do */ return (0); /* * Operation tracking files will include the ID of the creating process * in their name, so we can distinguish between log files created by * different WiredTiger processes in the same directory. We cache the * process id for future use. */ conn->optrack_pid = __wt_process_id(); /* * Open the file in the same directory that will hold a map of * translations between function names and function IDs. If the file * exists, remove it. */ WT_RET(__wt_scr_alloc(session, 0, &buf)); WT_ERR(__wt_filename_construct(session, conn->optrack_path, "optrack-map", conn->optrack_pid, UINT32_MAX, buf)); WT_ERR(__wt_open(session, (const char *)buf->data, WT_FS_OPEN_FILE_TYPE_REGULAR, WT_FS_OPEN_CREATE, &conn->optrack_map_fh)); WT_ERR(__wt_spin_init(session, &conn->optrack_map_spinlock, "optrack map spinlock")); WT_ERR(__wt_malloc(session, WT_OPTRACK_BUFSIZE, &conn->dummy_session.optrack_buf)); /* Set operation tracking on */ F_SET(conn, WT_CONN_OPTRACK); err: __wt_scr_free(session, &buf); return (ret); }
/* * __wt_block_open -- * Open a block handle. */ int __wt_block_open(WT_SESSION_IMPL *session, const char *filename, const char *cfg[], int forced_salvage, int readonly, uint32_t allocsize, WT_BLOCK **blockp) { WT_BLOCK *block; WT_CONFIG_ITEM cval; WT_CONNECTION_IMPL *conn; WT_DECL_RET; WT_TRET(__wt_verbose(session, WT_VERB_BLOCK, "open: %s", filename)); conn = S2C(session); *blockp = NULL; __wt_spin_lock(session, &conn->block_lock); TAILQ_FOREACH(block, &conn->blockqh, q) if (strcmp(filename, block->name) == 0) { ++block->ref; *blockp = block; __wt_spin_unlock(session, &conn->block_lock); return (0); } /* Basic structure allocation, initialization. */ WT_ERR(__wt_calloc_def(session, 1, &block)); block->ref = 1; TAILQ_INSERT_HEAD(&conn->blockqh, block, q); WT_ERR(__wt_strdup(session, filename, &block->name)); block->allocsize = allocsize; WT_ERR(__wt_config_gets(session, cfg, "block_allocation", &cval)); block->allocfirst = WT_STRING_MATCH("first", cval.str, cval.len) ? 1 : 0; /* Configuration: optional OS buffer cache maximum size. */ WT_ERR(__wt_config_gets(session, cfg, "os_cache_max", &cval)); block->os_cache_max = (size_t)cval.val; #ifdef HAVE_POSIX_FADVISE if (conn->direct_io && block->os_cache_max) WT_ERR_MSG(session, EINVAL, "os_cache_max not supported in combination with direct_io"); #else if (block->os_cache_max) WT_ERR_MSG(session, EINVAL, "os_cache_max not supported if posix_fadvise not " "available"); #endif /* Configuration: optional immediate write scheduling flag. */ WT_ERR(__wt_config_gets(session, cfg, "os_cache_dirty_max", &cval)); block->os_cache_dirty_max = (size_t)cval.val; #ifdef HAVE_SYNC_FILE_RANGE if (conn->direct_io && block->os_cache_dirty_max) WT_ERR_MSG(session, EINVAL, "os_cache_dirty_max not supported in combination with " "direct_io"); #else if (block->os_cache_dirty_max) { /* * Ignore any setting if it is not supported. */ block->os_cache_dirty_max = 0; WT_ERR(__wt_verbose(session, WT_VERB_BLOCK, "os_cache_dirty_max ignored when sync_file_range not " "available")); } #endif /* Open the underlying file handle. */ WT_ERR(__wt_open(session, filename, 0, 0, readonly ? WT_FILE_TYPE_CHECKPOINT : WT_FILE_TYPE_DATA, &block->fh)); /* Initialize the live checkpoint's lock. */ WT_ERR(__wt_spin_init(session, &block->live_lock, "block manager")); /* * Read the description information from the first block. * * Salvage is a special case: if we're forcing the salvage, we don't * look at anything, including the description information. */ if (!forced_salvage) WT_ERR(__desc_read(session, block)); *blockp = block; __wt_spin_unlock(session, &conn->block_lock); return (0); err: WT_TRET(__block_destroy(session, block)); __wt_spin_unlock(session, &conn->block_lock); return (ret); }
/* * __wt_connection_init -- * Structure initialization for a just-created WT_CONNECTION_IMPL handle. */ int __wt_connection_init(WT_CONNECTION_IMPL *conn) { WT_SESSION_IMPL *session; u_int i; session = conn->default_session; for (i = 0; i < WT_HASH_ARRAY_SIZE; i++) { TAILQ_INIT(&conn->dhhash[i]); /* Data handle hash lists */ TAILQ_INIT(&conn->fhhash[i]); /* File handle hash lists */ } TAILQ_INIT(&conn->dhqh); /* Data handle list */ TAILQ_INIT(&conn->dlhqh); /* Library list */ TAILQ_INIT(&conn->dsrcqh); /* Data source list */ TAILQ_INIT(&conn->fhqh); /* File list */ TAILQ_INIT(&conn->collqh); /* Collator list */ TAILQ_INIT(&conn->compqh); /* Compressor list */ TAILQ_INIT(&conn->encryptqh); /* Encryptor list */ TAILQ_INIT(&conn->extractorqh); /* Extractor list */ TAILQ_INIT(&conn->lsmqh); /* WT_LSM_TREE list */ /* Setup the LSM work queues. */ TAILQ_INIT(&conn->lsm_manager.switchqh); TAILQ_INIT(&conn->lsm_manager.appqh); TAILQ_INIT(&conn->lsm_manager.managerqh); /* Random numbers. */ __wt_random_init(&session->rnd); /* Configuration. */ WT_RET(__wt_conn_config_init(session)); /* Statistics. */ WT_RET(__wt_stat_connection_init(session, conn)); /* Spinlocks. */ WT_RET(__wt_spin_init(session, &conn->api_lock, "api")); WT_SPIN_INIT_TRACKED(session, &conn->checkpoint_lock, checkpoint); WT_RET(__wt_spin_init(session, &conn->encryptor_lock, "encryptor")); WT_RET(__wt_spin_init(session, &conn->fh_lock, "file list")); WT_SPIN_INIT_TRACKED(session, &conn->metadata_lock, metadata); WT_RET(__wt_spin_init(session, &conn->reconfig_lock, "reconfigure")); WT_SPIN_INIT_SESSION_TRACKED(session, &conn->schema_lock, schema); WT_RET(__wt_spin_init(session, &conn->turtle_lock, "turtle file")); /* Read-write locks */ WT_RWLOCK_INIT_SESSION_TRACKED(session, &conn->dhandle_lock, dhandle); WT_RET(__wt_rwlock_init(session, &conn->hot_backup_lock)); WT_RWLOCK_INIT_TRACKED(session, &conn->table_lock, table); /* Setup the spin locks for the LSM manager queues. */ WT_RET(__wt_spin_init(session, &conn->lsm_manager.app_lock, "LSM application queue lock")); WT_RET(__wt_spin_init(session, &conn->lsm_manager.manager_lock, "LSM manager queue lock")); WT_RET(__wt_spin_init( session, &conn->lsm_manager.switch_lock, "LSM switch queue lock")); WT_RET(__wt_cond_alloc( session, "LSM worker cond", &conn->lsm_manager.work_cond)); /* Initialize the generation manager. */ __wt_gen_init(session); /* * Block manager. * XXX * If there's ever a second block manager, we'll want to make this * more opaque, but for now this is simpler. */ WT_RET(__wt_spin_init(session, &conn->block_lock, "block manager")); for (i = 0; i < WT_HASH_ARRAY_SIZE; i++) TAILQ_INIT(&conn->blockhash[i]);/* Block handle hash lists */ TAILQ_INIT(&conn->blockqh); /* Block manager list */ return (0); }
/* * __conn_dhandle_get -- * Allocate a new data handle, lock it exclusively, and return it linked * into the connection's list. */ static int __conn_dhandle_get(WT_SESSION_IMPL *session, const char *name, const char *ckpt, uint32_t flags) { WT_BTREE *btree; WT_CONNECTION_IMPL *conn; WT_DATA_HANDLE *dhandle; WT_DECL_RET; uint32_t bucket; conn = S2C(session); /* * We have the handle lock, check whether we can find the handle we * are looking for. If we do, and we can lock it in the state we * want, this session will take ownership and we are done. */ ret = __wt_conn_dhandle_find(session, name, ckpt, flags); if (ret == 0) { dhandle = session->dhandle; WT_RET(__conn_dhandle_open_lock(session, dhandle, flags)); return (0); } WT_RET_NOTFOUND_OK(ret); /* * If no handle was found, allocate the data handle and a btree handle, * then initialize the data handle. Exclusively lock the data handle * before inserting it in the list. */ WT_RET(__wt_calloc_one(session, &dhandle)); WT_ERR(__wt_rwlock_alloc(session, &dhandle->rwlock, "data handle")); dhandle->name_hash = __wt_hash_city64(name, strlen(name)); WT_ERR(__wt_strdup(session, name, &dhandle->name)); if (ckpt != NULL) WT_ERR(__wt_strdup(session, ckpt, &dhandle->checkpoint)); WT_ERR(__wt_calloc_one(session, &btree)); dhandle->handle = btree; btree->dhandle = dhandle; WT_ERR(__wt_spin_init( session, &dhandle->close_lock, "data handle close")); F_SET(dhandle, WT_DHANDLE_EXCLUSIVE); WT_ERR(__wt_writelock(session, dhandle->rwlock)); /* * Prepend the handle to the connection list, assuming we're likely to * need new files again soon, until they are cached by all sessions. * Find the right hash bucket to insert into as well. */ WT_ASSERT(session, F_ISSET(session, WT_SESSION_HANDLE_LIST_LOCKED)); bucket = dhandle->name_hash % WT_HASH_ARRAY_SIZE; WT_CONN_DHANDLE_INSERT(conn, dhandle, bucket); session->dhandle = dhandle; return (0); err: WT_TRET(__wt_rwlock_destroy(session, &dhandle->rwlock)); __wt_free(session, dhandle->name); __wt_free(session, dhandle->checkpoint); __wt_free(session, dhandle->handle); /* btree free */ __wt_spin_destroy(session, &dhandle->close_lock); __wt_overwrite_and_free(session, dhandle); return (ret); }