From ade47b572da1659c95b4d06f297f0d87b0a20d0d Mon Sep 17 00:00:00 2001 From: Alex Gorrod Date: Fri, 9 May 2014 15:57:54 +1000 Subject: Make statistics log server reconfigurable. --- dist/api_data.py | 90 ++++++++++++++++++++++----------------------- dist/flags.py | 1 + src/config/config_def.c | 22 ++++++----- src/conn/conn_api.c | 3 +- src/conn/conn_stat.c | 64 +++++++++++++++++++++++++------- src/include/flags.h | 17 +++++---- src/include/wiredtiger.in | 23 +++++++++++- test/suite/test_reconfig.py | 14 +++++++ 8 files changed, 156 insertions(+), 78 deletions(-) diff --git a/dist/api_data.py b/dist/api_data.py index 0ab23c97829..325fcf28620 100644 --- a/dist/api_data.py +++ b/dist/api_data.py @@ -311,6 +311,10 @@ connection_runtime_config = [ requests''', min='1', max='20'), # !!! Must match WT_ASYNC_MAX_WORKERS ]), + Config('cache_size', '100MB', r''' + maximum heap memory to allocate for the cache. A database should + configure either a cache_size or a shared_cache not both''', + min='1MB', max='10TB'), Config('checkpoint', '', r''' periodically checkpoint the database''', type='category', subconfig=[ @@ -321,28 +325,6 @@ connection_runtime_config = [ above 0 configures periodic checkpoints''', min='0', max='100000'), ]), - Config('shared_cache', '', r''' - shared cache configuration options. A database should configure - either a cache_size or a shared_cache not both''', - type='category', subconfig=[ - Config('chunk', '10MB', r''' - the granularity that a shared cache is redistributed''', - min='1MB', max='10TB'), - Config('reserve', '0', r''' - amount of cache this database is guaranteed to have - available from the shared cache. This setting is per - database. Defaults to the chunk size''', type='int'), - Config('name', '', r''' - name of a cache that is shared between databases'''), - Config('size', '500MB', r''' - maximum memory to allocate for the shared cache. Setting - this will update the value if one is already set''', - min='1MB', max='10TB') - ]), - Config('cache_size', '100MB', r''' - maximum heap memory to allocate for the cache. A database should - configure either a cache_size or a shared_cache not both''', - min='1MB', max='10TB'), Config('error_prefix', '', r''' prefix string for error messages'''), Config('eviction_dirty_target', '80', r''' @@ -361,6 +343,24 @@ connection_runtime_config = [ Config('eviction_workers', '0', r''' additional threads to help evict pages from cache''', min=0, max=20), + Config('shared_cache', '', r''' + shared cache configuration options. A database should configure + either a cache_size or a shared_cache not both''', + type='category', subconfig=[ + Config('chunk', '10MB', r''' + the granularity that a shared cache is redistributed''', + min='1MB', max='10TB'), + Config('reserve', '0', r''' + amount of cache this database is guaranteed to have + available from the shared cache. This setting is per + database. Defaults to the chunk size''', type='int'), + Config('name', '', r''' + name of a cache that is shared between databases'''), + Config('size', '500MB', r''' + maximum memory to allocate for the shared cache. Setting + this will update the value if one is already set''', + min='1MB', max='10TB') + ]), Config('statistics', 'none', r''' Maintain database statistics, which may impact performance. Choosing "all" maintains all statistics regardless of cost, @@ -375,6 +375,29 @@ connection_runtime_config = [ are logged using the \c statistics_log configuration. See @ref statistics for more information''', type='list', choices=['all', 'fast', 'none', 'clear']), + Config('statistics_log', '', r''' + log any statistics the database is configured to maintain, + to a file. See @ref statistics for more information''', + type='category', subconfig=[ + Config('path', '"WiredTigerStat.%d.%H"', r''' + the pathname to a file into which the log records are written, + may contain ISO C standard strftime conversion specifications. + If the value is not an absolute path name, the file is created + relative to the database home'''), + Config('sources', '', r''' + if non-empty, include statistics for the list of data source + URIs, if they are open at the time of the statistics logging. + The list may include URIs matching a single data source + ("table:mytable"), or a URI matching all data sources of a + particular type ("table:")''', + type='list'), + Config('timestamp', '"%b %d %H:%M:%S"', r''' + a timestamp prepended to each log record, may contain strftime + conversion specifications'''), + Config('wait', '0', r''' + seconds to wait between each write of the log records''', + min='0', max='100000'), + ]), Config('verbose', '', r''' enable messages for various events. Only available if WiredTiger is configured with --enable-verbose. Options are given as a @@ -723,29 +746,6 @@ methods = { maximum expected number of sessions (including server threads)''', min='1'), - Config('statistics_log', '', r''' - log any statistics the database is configured to maintain, - to a file. See @ref statistics for more information''', - type='category', subconfig=[ - Config('path', '"WiredTigerStat.%d.%H"', r''' - the pathname to a file into which the log records are written, - may contain ISO C standard strftime conversion specifications. - If the value is not an absolute path name, the file is created - relative to the database home'''), - Config('sources', '', r''' - if non-empty, include statistics for the list of data source - URIs, if they are open at the time of the statistics logging. - The list may include URIs matching a single data source - ("table:mytable"), or a URI matching all data sources of a - particular type ("table:")''', - type='list'), - Config('timestamp', '"%b %d %H:%M:%S"', r''' - a timestamp prepended to each log record, may contain strftime - conversion specifications'''), - Config('wait', '0', r''' - seconds to wait between each write of the log records''', - min='1', max='100000'), - ]), Config('transaction_sync', 'fsync', r''' how to sync log records when the transaction commits''', choices=['dsync', 'fsync', 'none']), diff --git a/dist/flags.py b/dist/flags.py index 462d6f90875..89313928748 100644 --- a/dist/flags.py +++ b/dist/flags.py @@ -90,6 +90,7 @@ flags = { 'CONN_PANIC', 'CONN_SERVER_RUN', 'CONN_SERVER_CHECKPOINT', + 'CONN_SERVER_STATISTICS', ], 'session' : [ 'SESSION_INTERNAL', diff --git a/src/config/config_def.c b/src/config/config_def.c index 3eaf3e5f199..6bb7378a70f 100644 --- a/src/config/config_def.c +++ b/src/config/config_def.c @@ -57,6 +57,14 @@ static const WT_CONFIG_CHECK confchk_shared_cache_subconfigs[] = { { NULL, NULL, NULL, NULL } }; +static const WT_CONFIG_CHECK confchk_statistics_log_subconfigs[] = { + { "path", "string", NULL, NULL }, + { "sources", "list", NULL, NULL }, + { "timestamp", "string", NULL, NULL }, + { "wait", "int", "min=0,max=100000", NULL }, + { NULL, NULL, NULL, NULL } +}; + static const WT_CONFIG_CHECK confchk_connection_reconfigure[] = { { "async", "category", NULL, confchk_async_subconfigs}, { "cache_size", "int", "min=1MB,max=10TB", NULL}, @@ -72,6 +80,8 @@ static const WT_CONFIG_CHECK confchk_connection_reconfigure[] = { { "statistics", "list", "choices=[\"all\",\"fast\",\"none\",\"clear\"]", NULL}, + { "statistics_log", "category", NULL, + confchk_statistics_log_subconfigs}, { "verbose", "list", "choices=[\"api\",\"block\",\"checkpoint\",\"compact\",\"evict\"" ",\"evictserver\",\"fileops\",\"log\",\"lsm\",\"metadata\"," @@ -261,14 +271,6 @@ static const WT_CONFIG_CHECK confchk_log_subconfigs[] = { { NULL, NULL, NULL, NULL } }; -static const WT_CONFIG_CHECK confchk_statistics_log_subconfigs[] = { - { "path", "string", NULL, NULL }, - { "sources", "list", NULL, NULL }, - { "timestamp", "string", NULL, NULL }, - { "wait", "int", "min=1,max=100000", NULL }, - { NULL, NULL, NULL, NULL } -}; - static const WT_CONFIG_CHECK confchk_wiredtiger_open[] = { { "async", "category", NULL, confchk_async_subconfigs}, { "buffer_alignment", "int", "min=-1,max=1MB", NULL}, @@ -357,7 +359,9 @@ static const WT_CONFIG_ENTRY config_entries[] = { "checkpoint=(name=\"WiredTigerCheckpoint\",wait=0),error_prefix=," "eviction_dirty_target=80,eviction_target=80,eviction_trigger=95," "eviction_workers=0,shared_cache=(chunk=10MB,name=,reserve=0," - "size=500MB),statistics=none,verbose=", + "size=500MB),statistics=none," + "statistics_log=(path=\"WiredTigerStat.%d.%H\",sources=," + "timestamp=\"%b %d %H:%M:%S\",wait=0),verbose=", confchk_connection_reconfigure }, { "cursor.close", diff --git a/src/conn/conn_api.c b/src/conn/conn_api.c index 1459aa08170..172b6c3eb7d 100644 --- a/src/conn/conn_api.c +++ b/src/conn/conn_api.c @@ -606,7 +606,8 @@ __conn_reconfigure(WT_CONNECTION *wt_conn, const char *config) WT_ERR(__conn_statistics_config(session, raw_cfg)); WT_ERR(__wt_conn_verbose_config(session, raw_cfg)); - WT_ERR(__wt_checkpoint_server_create(conn, raw_cfg)); + WT_ERR(__wt_checkpoint_server_create(conn, cfg)); + WT_ERR(__wt_statlog_create(conn, cfg)); /* Wake up the cache pool server so any changes are noticed. */ if (F_ISSET(conn, WT_CONN_CACHE_POOL)) diff --git a/src/conn/conn_stat.c b/src/conn/conn_stat.c index aa84ef28c1d..cb4c03ac329 100644 --- a/src/conn/conn_stat.c +++ b/src/conn/conn_stat.c @@ -56,8 +56,8 @@ __statlog_config(WT_SESSION_IMPL *session, const char **cfg, int *runp) *runp = 1; conn->stat_usecs = (long)cval.val * 1000000; - WT_RET(__wt_config_gets(session, cfg, "statistics_log.sources", &cval)); - WT_RET(__wt_config_subinit(session, &objectconf, &cval)); + ret = (__wt_config_gets(session, cfg, "statistics_log.sources", &cval)); + ret = (__wt_config_subinit(session, &objectconf, &cval)); for (cnt = 0; (ret = __wt_config_next(&objectconf, &k, &v)) == 0; ++cnt) ; WT_RET_NOTFOUND_OK(ret); @@ -267,7 +267,8 @@ __statlog_server(void *arg) WT_ERR(__wt_buf_init(session, &path, strlen(conn->stat_path) + 128)); WT_ERR(__wt_buf_init(session, &tmp, strlen(conn->stat_path) + 128)); - while (F_ISSET(conn, WT_CONN_SERVER_RUN)) { + while (F_ISSET(conn, WT_CONN_SERVER_RUN) && + F_ISSET(conn, WT_CONN_SERVER_STATISTICS)) { /* * If statistics are turned off, wait until it's time to output * statistics and check again. @@ -357,28 +358,25 @@ err: __wt_err(session, ret, "statistics log server error"); } /* - * __wt_statlog_create -- + * __statlog_start -- * Start the statistics server thread. */ -int -__wt_statlog_create(WT_CONNECTION_IMPL *conn, const char *cfg[]) +static int +__statlog_start(WT_CONNECTION_IMPL *conn) { WT_SESSION_IMPL *session; - int run; - - session = conn->default_session; - - /* Handle configuration. */ - WT_RET(__statlog_config(session, cfg, &run)); - /* If not configured, we're done. */ - if (!run) + /* Nothing to do if the server is already running. */ + if (conn->stat_session != NULL) return (0); + F_SET(conn, WT_CONN_SERVER_STATISTICS); /* The statistics log server gets its own session. */ WT_RET(__wt_open_session(conn, 1, NULL, NULL, &conn->stat_session)); conn->stat_session->name = "statlog-server"; + session = conn->stat_session; + WT_RET(__wt_cond_alloc( session, "statistics log server", 0, &conn->stat_cond)); @@ -399,6 +397,33 @@ __wt_statlog_create(WT_CONNECTION_IMPL *conn, const char *cfg[]) return (0); } +/* + * __wt_statlog_create -- + * Start the statistics server thread. + */ +int +__wt_statlog_create(WT_CONNECTION_IMPL *conn, const char *cfg[]) +{ + WT_SESSION_IMPL *session; + int start; + + session = conn->default_session; + + /* + * Stop any server that is already running. This means that each time + * reconfigure is called we'll bounce the server even if there are no + * configuration changes - but that makes our lives easier. + */ + if (conn->stat_session != NULL) + WT_RET(__wt_statlog_destroy(conn)); + + WT_RET_NOTFOUND_OK(__statlog_config(session, cfg, &start)); + if (start) + WT_RET(__statlog_start(conn)); + + return (0); +} + /* * __wt_statlog_destroy -- * Destroy the statistics server thread. @@ -413,6 +438,7 @@ __wt_statlog_destroy(WT_CONNECTION_IMPL *conn) session = conn->default_session; + F_CLR(conn, WT_CONN_SERVER_STATISTICS); if (conn->stat_tid_set) { WT_TRET(__wt_cond_signal(session, conn->stat_cond)); WT_TRET(__wt_thread_join(session, conn->stat_tid)); @@ -434,5 +460,15 @@ __wt_statlog_destroy(WT_CONNECTION_IMPL *conn) WT_TRET(wt_session->close(wt_session, NULL)); } + /* Clear connection settings so reconfigure is reliable. */ + conn->stat_session = NULL; + conn->stat_tid_set = 0; + conn->stat_format = NULL; + conn->stat_fp = NULL; + conn->stat_path = NULL; + conn->stat_sources = NULL; + conn->stat_stamp = NULL; + conn->stat_usecs = 0; + return (ret); } diff --git a/src/include/flags.h b/src/include/flags.h index 28a0678f1be..4e5a5c28a2d 100644 --- a/src/include/flags.h +++ b/src/include/flags.h @@ -3,14 +3,15 @@ * flags section: BEGIN */ #define WT_CACHE_POOL_RUN 0x00000001 -#define WT_CONN_CACHE_POOL 0x00000080 -#define WT_CONN_CKPT_SYNC 0x00000040 -#define WT_CONN_EVICTION_RUN 0x00000020 -#define WT_CONN_LEAK_MEMORY 0x00000010 -#define WT_CONN_LSM_MERGE 0x00000008 -#define WT_CONN_PANIC 0x00000004 -#define WT_CONN_SERVER_CHECKPOINT 0x00000002 -#define WT_CONN_SERVER_RUN 0x00000001 +#define WT_CONN_CACHE_POOL 0x00000100 +#define WT_CONN_CKPT_SYNC 0x00000080 +#define WT_CONN_EVICTION_RUN 0x00000040 +#define WT_CONN_LEAK_MEMORY 0x00000020 +#define WT_CONN_LSM_MERGE 0x00000010 +#define WT_CONN_PANIC 0x00000008 +#define WT_CONN_SERVER_CHECKPOINT 0x00000004 +#define WT_CONN_SERVER_RUN 0x00000002 +#define WT_CONN_SERVER_STATISTICS 0x00000001 #define WT_EVICTION_LOCKED 0x00000004 #define WT_FILE_TYPE_CHECKPOINT 0x00000004 #define WT_FILE_TYPE_DATA 0x00000002 diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in index 698e4f8e60b..9834f438d2a 100644 --- a/src/include/wiredtiger.in +++ b/src/include/wiredtiger.in @@ -1605,6 +1605,27 @@ struct __wt_connection { * configuration. See @ref statistics for more information., a list\, * with values chosen from the following options: \c "all"\, \c "fast"\, * \c "none"\, \c "clear"; default \c none.} + * @config{statistics_log = (, log any statistics the database is + * configured to maintain\, to a file. See @ref statistics for more + * information., a set of related configuration options defined below.} + * @config{    path, the pathname to a file into + * which the log records are written\, may contain ISO C standard + * strftime conversion specifications. If the value is not an absolute + * path name\, the file is created relative to the database home., a + * string; default \c "WiredTigerStat.%d.%H".} + * @config{    sources, if non-empty\, include + * statistics for the list of data source URIs\, if they are open at the + * time of the statistics logging. The list may include URIs matching a + * single data source ("table:mytable")\, or a URI matching all data + * sources of a particular type ("table:")., a list of strings; default + * empty.} + * @config{    timestamp, a timestamp + * prepended to each log record\, may contain strftime conversion + * specifications., a string; default \c "%b %d %H:%M:%S".} + * @config{    wait, seconds to wait between each + * write of the log records., an integer between 0 and 100000; default + * \c 0.} + * @config{ ),,} * @config{verbose, enable messages for various events. Only available * if WiredTiger is configured with --enable-verbose. Options are given * as a list\, such as "verbose=[evictserver\,read]"., a @@ -1943,7 +1964,7 @@ struct __wt_connection { * record\, may contain strftime conversion specifications., a string; default * \c "%b %d %H:%M:%S".} * @config{    wait, seconds to wait - * between each write of the log records., an integer between 1 and 100000; + * between each write of the log records., an integer between 0 and 100000; * default \c 0.} * @config{ ),,} * @config{transaction_sync, how to sync log records when the transaction diff --git a/test/suite/test_reconfig.py b/test/suite/test_reconfig.py index be824748713..f865fe9f56f 100644 --- a/test/suite/test_reconfig.py +++ b/test/suite/test_reconfig.py @@ -45,5 +45,19 @@ class test_reconfig(wttest.WiredTigerTestCase): self.conn.reconfigure("checkpoint=(wait=0,name=hi)") self.conn.reconfigure("checkpoint=(wait=5,name=hi)") + def test_reconfig_stat_log(self): + self.conn.reconfigure("statistics=[all],statistics_log=(wait=0)") + self.conn.reconfigure("statistics_log=(wait=0)") + self.conn.reconfigure("statistics_log=(wait=2)") + self.conn.reconfigure("statistics_log=(wait=0)") + self.conn.reconfigure("statistics_log=(wait=2,sources=[lsm:])") + self.conn.reconfigure("statistics_log=(wait=0)") + self.conn.reconfigure("statistics_log=(wait=2,timestamp=\"t%b %d\")") + self.conn.reconfigure("statistics_log=(wait=0)") + self.conn.reconfigure("statistics_log=(wait=2,path=\"wts.%d.%H\")") + self.conn.reconfigure("statistics_log=(wait=0)") + self.conn.reconfigure( + "statistics_log=(wait=2,sources=[lsm:],timestamp=\"%b\")") + if __name__ == '__main__': wttest.run() -- cgit v1.2.1