/*创建一个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_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_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); }
/* * __wt_connection_close -- * Close a connection handle. */ int __wt_connection_close(WT_CONNECTION_IMPL *conn) { WT_CONNECTION *wt_conn; WT_DECL_RET; WT_DLH *dlh; WT_SESSION_IMPL *s, *session; WT_TXN_GLOBAL *txn_global; u_int i; wt_conn = &conn->iface; txn_global = &conn->txn_global; session = conn->default_session; /* * We're shutting down. Make sure everything gets freed. * * It's possible that the eviction server is in the middle of a long * operation, with a transaction ID pinned. In that case, we will loop * here until the transaction ID is released, when the oldest * transaction ID will catch up with the current ID. */ for (;;) { WT_TRET(__wt_txn_update_oldest(session, WT_TXN_OLDEST_STRICT | WT_TXN_OLDEST_WAIT)); if (txn_global->oldest_id == txn_global->current) break; __wt_yield(); } /* Clear any pending async ops. */ WT_TRET(__wt_async_flush(session)); /* * Shut down server threads other than the eviction server, which is * needed later to close btree handles. Some of these threads access * btree handles, so take care in ordering shutdown to make sure they * exit before files are closed. */ F_CLR(conn, WT_CONN_SERVER_RUN); WT_TRET(__wt_async_destroy(session)); WT_TRET(__wt_lsm_manager_destroy(session)); WT_TRET(__wt_sweep_destroy(session)); F_SET(conn, WT_CONN_CLOSING); WT_TRET(__wt_checkpoint_server_destroy(session)); WT_TRET(__wt_statlog_destroy(session, true)); WT_TRET(__wt_evict_destroy(session)); /* Shut down the lookaside table, after all eviction is complete. */ WT_TRET(__wt_las_destroy(session)); /* Close open data handles. */ WT_TRET(__wt_conn_dhandle_discard(session)); /* Shut down metadata tracking, required before creating tables. */ WT_TRET(__wt_meta_track_destroy(session)); /* * Now that all data handles are closed, tell logging that a checkpoint * has completed then shut down the log manager (only after closing * data handles). The call to destroy the log manager is outside the * conditional because we allocate the log path so that printlog can * run without running logging or recovery. */ if (FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED) && FLD_ISSET(conn->log_flags, WT_CONN_LOG_RECOVER_DONE)) WT_TRET(__wt_txn_checkpoint_log( session, true, WT_TXN_LOG_CKPT_STOP, NULL)); F_CLR(conn, WT_CONN_LOG_SERVER_RUN); WT_TRET(__wt_logmgr_destroy(session)); /* Free memory for collators, compressors, data sources. */ WT_TRET(__wt_conn_remove_collator(session)); WT_TRET(__wt_conn_remove_compressor(session)); WT_TRET(__wt_conn_remove_data_source(session)); WT_TRET(__wt_conn_remove_encryptor(session)); WT_TRET(__wt_conn_remove_extractor(session)); /* Disconnect from shared cache - must be before cache destroy. */ WT_TRET(__wt_conn_cache_pool_destroy(session)); /* Discard the cache. */ WT_TRET(__wt_cache_destroy(session)); /* Discard transaction state. */ WT_TRET(__wt_txn_global_destroy(session)); /* Close extensions, first calling any unload entry point. */ while ((dlh = TAILQ_FIRST(&conn->dlhqh)) != NULL) { TAILQ_REMOVE(&conn->dlhqh, dlh, q); if (dlh->terminate != NULL) WT_TRET(dlh->terminate(wt_conn)); WT_TRET(__wt_dlclose(session, dlh)); } /* Close the lock file, opening up the database to other connections. */ if (conn->lock_fh != NULL) WT_TRET(__wt_close(session, &conn->lock_fh)); /* Close any file handles left open. */ WT_TRET(__wt_close_connection_close(session)); /* * Close the internal (default) session, and switch back to the dummy * session in case of any error messages from the remaining operations * while destroying the connection handle. */ if (session != &conn->dummy_session) { WT_TRET(session->iface.close(&session->iface, NULL)); session = conn->default_session = &conn->dummy_session; } /* * The session's split stash isn't discarded during normal session close * because it may persist past the life of the session. Discard it now. */ if ((s = conn->sessions) != NULL) for (i = 0; i < conn->session_size; ++s, ++i) __wt_split_stash_discard_all(session, s); /* * The session's hazard pointer memory isn't discarded during normal * session close because access to it isn't serialized. Discard it * now. */ if ((s = conn->sessions) != NULL) for (i = 0; i < conn->session_size; ++s, ++i) { /* * If hash arrays were allocated, free them now. */ __wt_free(session, s->dhhash); __wt_free(session, s->tablehash); __wt_free(session, s->hazard); } /* Destroy the handle. */ WT_TRET(__wt_connection_destroy(conn)); return (ret); }
/* * __wt_connection_close -- * Close a connection handle. */ int __wt_connection_close(WT_CONNECTION_IMPL *conn) { WT_CONNECTION *wt_conn; WT_DECL_RET; WT_DLH *dlh; WT_SESSION_IMPL *s, *session; u_int i; wt_conn = &conn->iface; session = conn->default_session; /* Shut down transactions (wait for in-flight operations to complete. */ WT_TRET(__wt_txn_global_shutdown(session)); /* Shut down the subsystems, ensuring workers see the state change. */ F_SET(conn, WT_CONN_CLOSING); WT_FULL_BARRIER(); /* * Clear any pending async operations and shut down the async worker * threads and system before closing LSM. */ WT_TRET(__wt_async_flush(session)); WT_TRET(__wt_async_destroy(session)); /* * Shut down server threads other than the eviction server, which is * needed later to close btree handles. Some of these threads access * btree handles, so take care in ordering shutdown to make sure they * exit before files are closed. */ WT_TRET(__wt_lsm_manager_destroy(session)); /* * Once the async and LSM threads exit, we shouldn't be opening any * more files. */ F_SET(conn, WT_CONN_CLOSING_NO_MORE_OPENS); WT_FULL_BARRIER(); WT_TRET(__wt_checkpoint_server_destroy(session)); WT_TRET(__wt_statlog_destroy(session, true)); WT_TRET(__wt_sweep_destroy(session)); /* The eviction server is shut down last. */ WT_TRET(__wt_evict_destroy(session)); /* Shut down the lookaside table, after all eviction is complete. */ WT_TRET(__wt_las_destroy(session)); /* Close open data handles. */ WT_TRET(__wt_conn_dhandle_discard(session)); /* Shut down metadata tracking. */ WT_TRET(__wt_meta_track_destroy(session)); /* * Now that all data handles are closed, tell logging that a checkpoint * has completed then shut down the log manager (only after closing * data handles). The call to destroy the log manager is outside the * conditional because we allocate the log path so that printlog can * run without running logging or recovery. */ if (FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED) && FLD_ISSET(conn->log_flags, WT_CONN_LOG_RECOVER_DONE)) WT_TRET(__wt_txn_checkpoint_log( session, true, WT_TXN_LOG_CKPT_STOP, NULL)); WT_TRET(__wt_logmgr_destroy(session)); /* Free memory for collators, compressors, data sources. */ WT_TRET(__wt_conn_remove_collator(session)); WT_TRET(__wt_conn_remove_compressor(session)); WT_TRET(__wt_conn_remove_data_source(session)); WT_TRET(__wt_conn_remove_encryptor(session)); WT_TRET(__wt_conn_remove_extractor(session)); /* Disconnect from shared cache - must be before cache destroy. */ WT_TRET(__wt_conn_cache_pool_destroy(session)); /* Discard the cache. */ WT_TRET(__wt_cache_destroy(session)); /* Discard transaction state. */ __wt_txn_global_destroy(session); /* Close the lock file, opening up the database to other connections. */ if (conn->lock_fh != NULL) WT_TRET(__wt_close(session, &conn->lock_fh)); /* Close any file handles left open. */ WT_TRET(__wt_close_connection_close(session)); /* * Close the internal (default) session, and switch back to the dummy * session in case of any error messages from the remaining operations * while destroying the connection handle. */ if (session != &conn->dummy_session) { WT_TRET(session->iface.close(&session->iface, NULL)); session = conn->default_session = &conn->dummy_session; } /* * The session split stash, hazard information and handle arrays aren't * discarded during normal session close, they persist past the life of * the session. Discard them now. */ if (!F_ISSET(conn, WT_CONN_LEAK_MEMORY)) if ((s = conn->sessions) != NULL) for (i = 0; i < conn->session_size; ++s, ++i) { __wt_free(session, s->dhhash); __wt_stash_discard_all(session, s); __wt_free(session, s->hazard); } /* Destroy the file-system configuration. */ if (conn->file_system != NULL && conn->file_system->terminate != NULL) WT_TRET(conn->file_system->terminate( conn->file_system, (WT_SESSION *)session)); /* Close extensions, first calling any unload entry point. */ while ((dlh = TAILQ_FIRST(&conn->dlhqh)) != NULL) { TAILQ_REMOVE(&conn->dlhqh, dlh, q); if (dlh->terminate != NULL) WT_TRET(dlh->terminate(wt_conn)); WT_TRET(__wt_dlclose(session, dlh)); } /* Destroy the handle. */ __wt_connection_destroy(conn); return (ret); }
/* * __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); }