Compare commits

...

90 Commits

Author SHA1 Message Date
Michael Cahill
dddca65606 WT-2802 Copy values during commit before releasing snapshot. (#2917)
(cherry picked from commit 8f3e5f31da)
2016-07-29 16:35:37 +10:00
Michael Cahill
2969c02ab9 WT-2798 Fix data consistency bug with table creates during a checkpoint. (#2910)
When logging is disabled, a create operation (and potentially other
metadata updates) could write partially completed checkpoint metadata,
leaving on-disk files inconsistent until the checkpoint completes.

(cherry picked from commit 7e1a47dd45)
2016-07-29 16:19:02 +10:00
Keith Bostic
82323cf72f WT-2760 Fix a bug in backup related to directory sync. Change the filesystem API to make durable the default (#2867)
Change the default remove/rename calls to flush the enclosing directory.

Simplify the pluggable file system API by replacing the directory-sync method
with "durable" boolean argument to the remove, rename and open-file methods.

* Add "durable" arguments to relevant functions so that each remove or rename
call specifies its durability requirements.

* Switch the  WT_FILE_SYSTEM::fs_open_file type enum from WT_OPEN_FILE_TYPE,
with WT_OPEN_XXX names, to the WT_FS_OPEN_FILE_TYPE, with WT_FS_OPEN_XXX
names.

Switch the  WT_FILE_SYSTEM::fs_open_file flags from WT_OPEN_XXX names to
WT_FS_OPEN_XXX names.

* Replace the "bool durable" argument to WT_FILE_SYSTEM.fs_remove and
WT_FILE_SYSTEM.fs_rename with a "uint32_t flags" argument, and the
WT_FS_DURABLE flag.

* Remove a stray bracket.

(cherry picked from commit 11f018322c)
2016-07-29 16:18:32 +10:00
Keith Bostic
859c8eda1e WT-2730 Btree can incorrectly match key slots on new pages (#2848)
This problem can occur for both row and column store.

The WT_CURSOR_BTREE.rip_saved field potentially has the same problem
as the cip_saved field, initializing it on point-searches is wrong,
it should be initialized as a cursor moves to a new page.

* Clear cip_saved and rip_saved when starting to iterate from a search
position.  This wasn't necessary before because we cleared them in
__cursor_pos_clear(), but I removed that code.

In summary, we now clear them in the iteration code, both when starting
an iteration and when switching to a new page. That's correct because
they have nothing to do with searches so the clear doesn't belong in
__cursor_pos_clear(), and we have to do the clear when switching to a
new page regardless, __cursor_pos_clear() isn't called when switching
to a new page.

(cherry picked from commit 1b6a9220c3)
2016-07-29 16:13:37 +10:00
Keith Bostic
24cd107c1d WT-2730 column-store incorrectly matches key slots on new pages (#2847)
Reset the column-store saved slot information on each new page, otherwise
it's possible for it to match the last page we were traversing.
(cherry picked from commit 51a4e1593d)
2016-07-29 16:13:30 +10:00
David Hows
3dc8860451 WT-2711 Remove posix expanded strftime values and use older C89 values (#2865)
* WT-2711 Remove posix expanded strftime values and use older C89 values

* Fix issues with s_string

* Add a comment so nobody rewrites the strftime format and reintroduces the bug.

* Fix strings sort order.

(cherry picked from commit 1c67c4e0f0)
2016-07-29 16:12:45 +10:00
Keith Bostic
9383fc98ee WT-2711 Change statistics log configuration options (#2857)
If there's no server running, discard any configuration information so
we don't leak memory during reconfiguration.
(cherry picked from commit e001657e5c)
2016-07-29 16:12:29 +10:00
Keith Bostic
307e63aac7 WT-2711 Change statistics log configuration options (#2834)
No longer support setting the statistics_log path in WT_CONNECTION::reconfigure.
No longer support setting a custom name for statistics files, only allow a destination directory.
Be more explicit about which logging configuration options are allowed in WT_CONNECTION::reconfigure.

The aim of these changes is to avoid situations where applications that embed WiredTiger allow their users to overwrite unexpected files on a file system.

This potentially requires an upgrade step for applications that were specifying a non-standard file name component for statistics log file names, it's not backward compatible.
(cherry picked from commit 9cc5d0f4b1)
2016-07-29 16:12:16 +10:00
Michael Cahill
6f81f19793 SERVER-24971 Don't cache buffers after application eviction. (#2869)
(cherry picked from commit f98ecc9d7c)
2016-07-29 16:08:16 +10:00
Alex Gorrod
848e5f5c0b Merge branch 'mongodb-3.4' into mongodb-3.2
Choosing the content of the 3.4 branch, rather than manually
resolving merge conflicts.
2016-07-26 11:11:27 +10:00
sueloverso
8b7110bfac WT-2706 Fix lost log writes when switching files (#2803)
Fix a path that incorrectly returning success from log_write without writing a log record.

(cherry picked from commit 36d657ccc6)
2016-07-07 08:49:56 +10:00
Michael Cahill
f4954f6592 WT-2729 Focus eviction on the largest trees in cache (mongodb-3.2). (#2833)
Randomize visits to trees that use a tiny fraction of the cache.

Eviction optimizations.

Now that we are queuing more entries (potentially), make sure enough of
them become candidates.  Previously, a skewed distribution of read
generations could mean that only 10% of queue entries were considered.

Improve the efficiency of sorting the queue by calculating the score
once when pages are added to the queue.

Take care to bound the maximum eviction slot.
2016-06-28 14:58:58 +10:00
Keith Bostic
dd2a33849a WT-2708 split child-update race with reconciliation/eviction (#2835)
(cherry picked from commit 521270d54c)

When splitting the root page and updating the child's WT_REF.addr, reconciliation/eviction can race with us, updating WT_REF.addr after our read and before our update. The update is necessary because the child's
address points into the page being split: if the address changes, then it can no longer point into the page being split and the update is no longer necessary.
2016-06-28 14:17:30 +10:00
Michael Cahill
a63e21b838 SERVER-24580 Add more eviction stats to track efficiency. (#2830)
(cherry picked from commit 1f4aaa4490)
2016-06-23 17:36:28 +10:00
sueloverso
30e49acc90 WT-2696 Wait if we find an unbuffered flag without the size set yet. (#2794)
* Modify recovery test to use multiple threads to reproduce this issue.

(cherry picked from commit 0d4c83daf7)
2016-06-23 17:30:02 +10:00
Keith Bostic
063dbdfe45 WT-2672 handle system calls that don't set errno (#2765)
Define system call success as a 0 return, and split error handling into two parts: if the call returns -1, use errno, otherwise expect the failing return to be an error value.

Replace calls to remove with unlink, so we know errno will be set.  Do the best we can with rename, there's no easy workaround.

POSIX requires posix_madvise return an errno value, but some OS versions return a -1/errno pair instead (at least FreeBSD and OS X). I don't care about retrying posix_madvise calls on failure, but since WT_SYSCALL_RETRY includes the necessary error handling magic, wrap the posix_madvise calls in WT_SYSCALL_RETRY.

(cherry picked from commit ced588aecd)
2016-06-23 17:16:06 +10:00
Michael Cahill
9ee39b8aea SERVER-24580 Fix backport. 2016-06-23 16:29:47 +10:00
Michael Cahill
d68800d0e9 SERVER-24580 Update oldest txn ID with "strict, nowait" flags. (#2829)
Add more options for callers when updating the oldest ID to control how much they care about the ID being updated.
(cherry picked from commit 116e41e5e1)
2016-06-23 16:03:26 +10:00
Michael Cahill
ded2149b2c SERVER-24580 Enhance eviction when application threads are contributing (#2806)
When the cache hits eviction triggers, all application threads can
hammer the eviction queue lock, starving each other and server threads.

Also, noticed with the same workload, the eviction server doesn't need
to force updates to the oldest ID (which can starve the eviction server
thread if there are hundreds of application threads getting snapshots).
It is sufficient to update it lazily.

* Clear the eviction walk if we don't find any candidates.

Otherwise, we are keeping a page pinned in what might be an idle file,
and tying up a hazard pointer that could prevent eviction from an active
file (since the eviction server tracks how many hazard pointers it is
using to avoid going over the limit).

(cherry picked from commit 7f9d7aecea)
2016-06-23 16:03:04 +10:00
Michael Cahill
0f36f40c37 WT-2702 Block operations when the cache is 100% full. (#2798)
(cherry picked from commit ac14731a59)
2016-06-23 16:02:46 +10:00
David Hows
a6a64e986b WT-2646 Add checkpoint_wait configuration option to drop (#2768)
* Default checkpoint_wait is true. This change is useful because it means concurrent create/drop calls don't generate EBUSY returns.
* Mark lock_wait and checkpoint_wait as undoc

(cherry picked from commit 4b48ad6fb7)
2016-06-02 16:12:21 +10:00
David Hows
234b68b116 WT-2613 Add WT_UNUSED to a variable to fix Windows compilation. (#2717)
(cherry picked from commit 7deb9c213b)
2016-06-01 12:47:25 +10:00
Michael Cahill
5d215904c3 SERVER-24306 Fix stall in log_flush switching to new files. (#2761)
* SERVER-24306 Fix stall in log_flush switching to new files.

* Pass boolean false rather than 0.

(cherry picked from commit b89aaece7b)
2016-06-01 12:44:46 +10:00
Michael Cahill
18879587af WT-2629 Make the stack non-executable with GCC only. (#2742)
(cherry picked from commit f6f86961a4)
2016-06-01 12:41:58 +10:00
Michael Cahill
6bfcb1ca5b WT-2629 Don't make stacks executable in assembly source. (#2739)
(cherry picked from commit 0f7ae730d9)
2016-06-01 12:41:48 +10:00
Alex Gorrod
71c0588a77 Merge pull request #2677 from wiredtiger/wt-2560-spin
WT-2560 Spin on transaction locks.
(cherry picked from commit f498d8c1c1)
2016-06-01 10:48:12 +10:00
Michael Cahill
58765850aa Merge pull request #2660 from wiredtiger/wt-2560
WT-2560 Use a rwlock to protect transaction state, don't spin.
Conflicted on a whitespace cleanup.

(cherry picked from commit 76e286c7ba)
2016-06-01 10:46:47 +10:00
Keith Bostic
30d327f810 Merge pull request #2664 from wiredtiger/wt-2559
WT-2559 Open a local log file handle for sync.
(cherry picked from commit 6b3553003f)
2016-06-01 10:40:38 +10:00
Michael Cahill
88b898e7cb Merge pull request #2670 from wiredtiger/wt-2566
WT-2566 Lock/unlock operations should imply memory barriers.
(cherry picked from commit 05cfbc26c2)
2016-04-20 17:04:16 +10:00
Alex Gorrod
7ea2631de2 Merge branch 'mongodb-3.4' into mongodb-3.2 2016-04-08 16:48:45 +10:00
Michael Cahill
039fe06082 Merge branch 'mongodb-3.4' into mongodb-3.2 2016-04-07 17:29:23 +10:00
Michael Cahill
43e885a0f9 Merge branch 'mongodb-3.4' into mongodb-3.2 2016-03-25 08:19:12 +11:00
Michael Cahill
5cdd3e320c Merge branch 'mongodb-3.2.3' into mongodb-3.2 2016-02-18 14:00:00 +11:00
Michael Cahill
563b7823f7 Merge pull request #2495 from wiredtiger/wt-2397
WT-2397: Cursor traversal from end of the tree skips records.
(cherry picked from commit d915631b)

Manually resolved conflicts from pull request 2478.
2016-02-17 17:30:39 +11:00
Michael Cahill
5e3a56f0ab Merge pull request #2498 from wiredtiger/server-22676
SERVER-22676 Don't check duplicated create calls for matching configurations
(cherry picked from commit 98d6ce255d)
2016-02-17 17:17:20 +11:00
Michael Cahill
bc929dbcf1 Merge branch 'mongodb-3.4' into mongodb-3.2 2016-02-11 12:05:59 +11:00
Michael Cahill
07966a492a Fixup for merge vs backport. 2016-01-28 12:18:13 +11:00
Michael Cahill
67e412d4c5 Merge branch 'develop' into mongodb-3.2 2016-01-28 09:30:32 +11:00
Alex Gorrod
3c2ad56b50 Merge pull request #2415 from wiredtiger/wt-2307-fix
(cherry picked from commit 12aaeb6)

WT-2307: Fix for cursor iteration bug when pages are splitting
2015-12-29 05:42:26 +11:00
Alex Gorrod
b1768d0d9f Revert "Merge pull request #2394 from wiredtiger/SERVER-21887-sample"
The change wasn't ready for back port into 3.2.1

This reverts commit 21b5f9951e.
2015-12-22 08:15:10 +00:00
Alex Gorrod
2893117baa Revert "WT-2291: error: comparison of array 'ins->next' not equal to a null"
The change isn't ready for back port into 3.2.1

This reverts commit 4380cec93d.
2015-12-22 08:14:38 +00:00
Keith Bostic
4380cec93d WT-2291: error: comparison of array 'ins->next' not equal to a null
pointer is always true [-Werror,-Wtautological-pointer-compare]
2015-12-17 10:48:19 +11:00
Alex Gorrod
21b5f9951e Merge pull request #2394 from wiredtiger/SERVER-21887-sample
WT-2291: fix for sampling in newly created trees.
2015-12-17 10:47:55 +11:00
Keith Bostic
decd9166cc __wt_ref_info() and __ref_is_lef() no longer need a WT_SESSION_IMPL
argument, remove it.
2015-12-16 15:54:52 +11:00
Keith Bostic
d835a0c0a8 gcc47 with [-Werror=maybe-uninitialized] reports we can end up with type
uninitialized in __ref_is_leaf() (based on a call to __wt_ref_info()).
It's not really possible because the path where type isn't set is a path
where we panic because the WT_ADDR structure has an impossible type.

We already ignore the __wt_ref_info() error return in one path, and
there are only two paths that care about the returned type; remove the
error check from __wt_ref_info() and set type to 0 in the failing case
(the same value we use when there's no WT_REF addr to check), the code
that calls this function already checks addr on return.

This simplifies __ref_is_leaf() slightly, it now returns a boolean
instead of an error code with a boolean pointer argument.
2015-12-16 15:29:31 +11:00
Keith Bostic
48e1343e40 Merge pull request #2363 from wiredtiger/WT-2262
WT-2262 Have random sampling walk the tree so it isn't biased in skewed trees.
2015-12-16 15:29:13 +11:00
Michael Cahill
eb838c7f12 Merge pull request #2361 from wiredtiger/wt-2260-dont-evict-internal
WT-2260 Avoid adding internal pages to the eviction queue.
2015-12-16 15:28:52 +11:00
Alex Gorrod
a6957512a4 Merge pull request #2358 from wiredtiger/wt-2258-preload-directio 2015-12-16 15:28:11 +11:00
Michael Cahill
197eef00fd Merge branch 'develop' into mongodb-3.2 2015-12-02 22:58:11 +11:00
Michael Cahill
7a4f3259b4 Merge branch 'develop' into mongodb-3.2 2015-12-01 17:12:04 +11:00
Michael Cahill
8326df6b76 Merge branch 'develop' into mongodb-3.2 2015-11-30 15:02:38 +11:00
Keith Bostic
b65381f64c Merge branch 'develop' into mongodb-3.2 2015-11-24 11:29:41 -05:00
Michael Cahill
0019262fed Merge branch 'develop' into mongodb-3.2 2015-11-24 21:59:04 +11:00
Keith Bostic
4d72349b8a Merge branch 'develop' into mongodb-3.2 2015-11-23 09:00:49 -05:00
Michael Cahill
4898aa408f Merge branch 'develop' into mongodb-3.2 2015-11-20 16:58:33 +11:00
Michael Cahill
9d375e3416 Merge branch 'develop' into mongodb-3.2 2015-11-19 17:18:28 +11:00
Michael Cahill
d9ec1ff8ec Merge branch 'develop' into mongodb-3.2 2015-11-11 16:27:42 +11:00
Keith Bostic
465dca8b46 Merge branch 'develop' into mongodb-3.2 2015-11-03 10:33:14 -05:00
Alex Gorrod
f95877af13 Merge branch 'develop' into mongodb-3.2 2015-11-03 22:18:00 +11:00
Alex Gorrod
62c1a7aa36 Merge branch 'develop' into mongodb-3.2 2015-11-02 03:59:53 +00:00
Michael Cahill
0dc3f20df6 Merge branch 'develop' into mongodb-3.2 2015-11-02 11:43:14 +11:00
Michael Cahill
0537648e03 Merge branch 'develop' into mongodb-3.2 2015-10-09 17:07:24 +11:00
Alex Gorrod
3c856645c8 Merge branch 'develop' into mongodb-3.2 2015-09-30 15:01:57 +10:00
Michael Cahill
10208e8284 Merge branch 'develop' into mongodb-3.2 2015-09-25 15:00:04 +10:00
Michael Cahill
16e3e48d98 Merge branch 'develop' into mongodb-3.2 2015-09-18 12:56:14 +10:00
Michael Cahill
5205bb1f0f Merge branch 'develop' into mongodb-3.2 2015-09-11 16:23:01 +10:00
Michael Cahill
dca63120b7 Merge branch 'develop' into mongodb-3.2 2015-09-11 12:21:49 +10:00
sueloverso
0cccab30c0 WT-2064 Don't spin indefinitely waiting for the handle list lock in eviction
Merge pull request #2155 from wiredtiger/WT-2064

(cherry picked from commit 66757f7247)
2015-08-28 11:48:29 +10:00
Alex Gorrod
578a856c19 Merge pull request #2156 from wiredtiger/WT-2066
WT-2066 - Update the oldest transaction ID from eviction
(cherry picked from commit 8f42f02d3c)
2015-08-28 11:47:56 +10:00
Alex Gorrod
a85c5cda41 Merge pull request #2152 from wiredtiger/WT-2062
WT-2062 Try harder to make progress on in-memory splits
(cherry picked from commit 3e0c7bfa3a)
2015-08-28 11:47:30 +10:00
Michael Cahill
6da2dc175b Merge commit '12044d22cce1a79804254ac9c80b1120701bd7c8' into mongodb-3.2 2015-08-28 11:45:48 +10:00
Michael Cahill
7ffa315e39 Merge branch 'develop' into mongodb-3.2 2015-08-18 10:25:36 +10:00
Michael Cahill
26d1ad271f Merge branch 'develop' into mongodb-3.2 2015-08-12 20:36:04 +10:00
Alex Gorrod
fdedd3621c Merge branch 'develop' into mongodb-3.2 2015-07-23 15:53:52 +10:00
Alex Gorrod
4187f419f8 Merge branch 'develop' into mongodb-3.2 2015-07-23 15:50:57 +10:00
Michael Cahill
42823c9682 Merge branch 'develop' into mongodb-3.2 2015-07-17 22:19:04 +10:00
Alex Gorrod
fbaf1cf4f5 Merge branch 'develop' into mongodb-3.2 2015-06-26 05:09:48 +00:00
Alex Gorrod
3d845c98cb Merge branch 'develop' into mongodb-3.2 2015-06-10 18:54:48 +00:00
Michael Cahill
1d2fe8a145 Merge branch 'develop' into mongodb-3.2 2015-06-09 01:26:55 +10:00
Alex Gorrod
bdaaaec87d Merge branch 'develop' into mongodb-3.2 2015-05-29 00:19:26 +00:00
Michael Cahill
35cc116acd Merge branch 'develop' into mongodb-3.2 2015-05-18 15:02:56 +10:00
Alex Gorrod
cbe0fad3e9 Merge branch 'develop' into mongodb-3.2 2015-05-15 06:07:13 +00:00
Michael Cahill
4f9aa1c548 Merge branch 'develop' into mongodb-3.2 2015-05-08 14:19:20 +10:00
Michael Cahill
1f44c05f91 Merge branch 'develop' into mongodb-3.2 2015-04-27 17:43:11 +10:00
Michael Cahill
e31aa8cf29 Merge branch 'develop' into mongodb-3.2 2015-04-27 17:23:58 +10:00
Michael Cahill
c90bc747e1 Merge branch 'develop' into mongodb-3.2 2015-04-24 17:17:50 +10:00
Alex Gorrod
2c1b7aa80b Update MongoDB changelog with latest merge commits. 2015-04-23 17:28:27 +10:00
Alex Gorrod
41762ae13c Merge branch 'develop' into mongodb-3.2 2015-04-23 17:25:06 +10:00
Alex Gorrod
f7691f63a6 Add long version of commit log to NEWS.MONGODB 2015-04-23 17:21:01 +10:00
Alex Gorrod
9be5497753 Add in MongoDB changelog from 3.0 2015-04-23 11:43:19 +10:00
49 changed files with 854 additions and 644 deletions

View File

@@ -129,7 +129,8 @@ cycle_idle_tables(void *arg)
* Drop the table. Keep retrying on EBUSY failure - it is an
* expected return when checkpoints are happening.
*/
while ((ret = session->drop(session, uri, "force")) == EBUSY)
while ((ret = session->drop(
session, uri, "force,checkpoint_wait=false")) == EBUSY)
__wt_sleep(1, 0);
if (ret != 0 && ret != EBUSY) {

View File

@@ -0,0 +1,20 @@
# Check create and drop behavior concurrent with checkpoints (WT-2798).
# Setup a multiple tables and a cache size large enough that checkpoints can
# take a long time.
conn_config="cache_size=8GB,log=(enabled=false),checkpoint=(wait=30)"
table_config="leaf_page_max=4k,internal_page_max=16k,type=file"
icount=10000000
table_count=100
table_count_idle=100
# Turn on create/drop of idle tables, but don't worry if individual operations
# take a long time.
idle_table_cycle=120
populate_threads=5
checkpoint_threads=0
report_interval=5
# 100 million
random_range=10000000
run_time=300
# Setup a workload that dirties a lot of the cache
threads=((count=2,reads=1),(count=2,inserts=1),(count=2,updates=1))
value_sz=500

174
dist/api_data.py vendored
View File

@@ -420,40 +420,6 @@ connection_runtime_config = [
interval in seconds at which to check for files that are
inactive and close them''', min=1, max=100000),
]),
Config('log', '', r'''
enable logging. Enabling logging uses three sessions from the
configured session_max''',
type='category', subconfig=[
Config('archive', 'true', r'''
automatically archive unneeded log files''',
type='boolean'),
Config('compressor', 'none', r'''
configure a compressor for log records. Permitted values are
\c "none" or custom compression engine name created with
WT_CONNECTION::add_compressor. If WiredTiger has builtin support
for \c "snappy", \c "lz4" or \c "zlib" compression, these names
are also available. See @ref compression for more information'''),
Config('enabled', 'false', r'''
enable logging subsystem''',
type='boolean'),
Config('file_max', '100MB', r'''
the maximum size of log files''',
min='100KB', max='2GB'),
Config('path', '"."', r'''
the path to a directory into which the log files are written.
If the value is not an absolute path name, the files are created
relative to the database home'''),
Config('prealloc', 'true', r'''
pre-allocate log files.''',
type='boolean'),
Config('recover', 'on', r'''
run recovery or error if recovery needs to run after an
unclean shutdown.''',
choices=['error','on']),
Config('zero_fill', 'false', r'''
manually write zeroes into log files''',
type='boolean'),
]),
Config('lsm_manager', '', r'''
configure database wide options for LSM tree management. The LSM
manager is started automatically the first time an LSM tree is opened.
@@ -525,38 +491,6 @@ 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. Enabling
the statistics log server uses a session from the configured
session_max''',
type='category', subconfig=[
Config('json', 'false', r'''
encode statistics in JSON format''',
type='boolean'),
Config('on_close', 'false', r'''log statistics on database close''',
type='boolean'),
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, when \c json is configured, defaults
to \c "%FT%Y.000Z"'''),
Config('wait', '0', r'''
seconds to wait between each write of the log records; setting
this value above 0 configures statistics logging''',
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
@@ -590,13 +524,113 @@ connection_runtime_config = [
'write']),
]
# wiredtiger_open and WT_CONNECTION.reconfigure log configurations.
log_configuration_common = [
Config('archive', 'true', r'''
automatically archive unneeded log files''',
type='boolean'),
Config('prealloc', 'true', r'''
pre-allocate log files.''',
type='boolean'),
Config('zero_fill', 'false', r'''
manually write zeroes into log files''',
type='boolean')
]
connection_reconfigure_log_configuration = [
Config('log', '', r'''
enable logging. Enabling logging uses three sessions from the
configured session_max''',
type='category', subconfig=
log_configuration_common)
]
wiredtiger_open_log_configuration = [
Config('log', '', r'''
enable logging. Enabling logging uses three sessions from the
configured session_max''',
type='category', subconfig=
log_configuration_common + [
Config('enabled', 'false', r'''
enable logging subsystem''',
type='boolean'),
Config('compressor', 'none', r'''
configure a compressor for log records. Permitted values are
\c "none" or custom compression engine name created with
WT_CONNECTION::add_compressor. If WiredTiger has builtin support
for \c "snappy", \c "lz4" or \c "zlib" compression, these names
are also available. See @ref compression for more information'''),
Config('file_max', '100MB', r'''
the maximum size of log files''',
min='100KB', max='2GB'),
Config('path', '"."', r'''
the name of a directory into which log files are written. The
directory must already exist. If the value is not an absolute
path, the path is relative to the database home (see @ref
absolute_path for more information)'''),
Config('recover', 'on', r'''
run recovery or error if recovery needs to run after an
unclean shutdown''',
choices=['error','on'])
]),
]
# wiredtiger_open and WT_CONNECTION.reconfigure statistics log configurations.
statistics_log_configuration_common = [
Config('json', 'false', r'''
encode statistics in JSON format''',
type='boolean'),
Config('on_close', 'false', r'''log statistics on database close''',
type='boolean'),
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, when \c json is configured, defaults
to \c "%FT%Y.000Z"'''),
Config('wait', '0', r'''
seconds to wait between each write of the log records; setting
this value above 0 configures statistics logging''',
min='0', max='100000'),
]
connection_reconfigure_statistics_log_configuration = [
Config('statistics_log', '', r'''
log any statistics the database is configured to maintain,
to a file. See @ref statistics for more information. Enabling
the statistics log server uses a session from the configured
session_max''',
type='category', subconfig=
statistics_log_configuration_common)
]
wiredtiger_open_statistics_log_configuration = [
Config('statistics_log', '', r'''
log any statistics the database is configured to maintain,
to a file. See @ref statistics for more information. Enabling
the statistics log server uses a session from the configured
session_max''',
type='category', subconfig=
statistics_log_configuration_common + [
Config('path', '"."', r'''
the name of a directory into which statistics files are written.
The directory must already exist. If the value is not an absolute
path, the path is relative to the database home (see @ref
absolute_path for more information)''')
])
]
session_config = [
Config('isolation', 'read-committed', r'''
the default isolation level for operations in this session''',
choices=['read-uncommitted', 'read-committed', 'snapshot']),
]
wiredtiger_open_common = connection_runtime_config + [
wiredtiger_open_common =\
connection_runtime_config +\
wiredtiger_open_log_configuration +\
wiredtiger_open_statistics_log_configuration + [
Config('buffer_alignment', '-1', r'''
in-memory alignment (in bytes) for buffers used for I/O. The
default value of -1 indicates a platform-specific alignment value
@@ -1084,7 +1118,11 @@ methods = {
don't free memory during close''',
type='boolean'),
]),
'WT_CONNECTION.reconfigure' : Method(connection_runtime_config),
'WT_CONNECTION.reconfigure' : Method(
connection_reconfigure_log_configuration +\
connection_reconfigure_statistics_log_configuration +\
connection_runtime_config
),
'WT_CONNECTION.set_file_system' : Method([]),
'WT_CONNECTION.load_extension' : Method([

7
dist/s_string.ok vendored
View File

@@ -86,6 +86,7 @@ DbEnv
Decrement
Decrypt
DeleteFileA
EACCES
EAGAIN
EB
EBUSY
@@ -117,6 +118,7 @@ FLv
FNV
FORALL
FOREACH
FS
FULLFSYNC
FindClose
FindFirstFile
@@ -326,6 +328,7 @@ UID
UIDs
UINT
ULINE
UNC
URI
URIs
UTF
@@ -528,6 +531,7 @@ cust
customp
cv
cxa
dT
data's
database's
datalen
@@ -557,6 +561,7 @@ dequeued
der
dereference
desc
designator
dest
destSize
dev
@@ -1065,6 +1070,7 @@ tV
tablename
tcbench
td
tempdir
testutil
th
tid
@@ -1091,6 +1097,7 @@ txn
txnc
txnid
txnmin
txt
typedef
uB
uS

View File

@@ -1160,34 +1160,27 @@ main(void)
if (ret == 0)
(void)conn->close(conn, NULL);
#ifdef MIGHT_NOT_RUN
/*
* Don't run this code, statistics logging doesn't yet support tables.
*/
/*! [Statistics logging with a table] */
ret = wiredtiger_open(home, NULL,
"create, statistics_log=("
"sources=(\"lsm:table1\",\"lsm:table2\"), wait=5)",
"sources=(\"table:table1\",\"table:table2\"), wait=5)",
&conn);
/*! [Statistics logging with a table] */
if (ret == 0)
(void)conn->close(conn, NULL);
/*! [Statistics logging with all tables] */
ret = wiredtiger_open(home, NULL,
"create, statistics_log=(sources=(\"lsm:\"), wait=5)",
&conn);
/*! [Statistics logging with all tables] */
if (ret == 0)
(void)conn->close(conn, NULL);
#ifdef MIGHT_NOT_RUN
/*
* This example code gets run, and a non-existent log file path might
* cause the open to fail. The documentation requires code snippets,
* use #ifdef's to avoid running it.
* Don't run this code, statistics logging doesn't yet support indexes.
*/
/*! [Statistics logging with path] */
/*! [Statistics logging with a source type] */
ret = wiredtiger_open(home, NULL,
"create,"
"statistics_log=(wait=120,path=/log/log.%m.%d.%y)", &conn);
/*! [Statistics logging with path] */
"create, statistics_log=(sources=(\"index:\"), wait=5)",
&conn);
/*! [Statistics logging with a source type] */
if (ret == 0)
(void)conn->close(conn, NULL);

View File

@@ -118,18 +118,17 @@ int demo_file_system_create(WT_CONNECTION *, WT_CONFIG_ARG *);
/*
* Forward function declarations for file system API implementation
*/
static int demo_fs_open(WT_FILE_SYSTEM *,
WT_SESSION *, const char *, WT_OPEN_FILE_TYPE, uint32_t, WT_FILE_HANDLE **);
static int demo_fs_open(WT_FILE_SYSTEM *, WT_SESSION *,
const char *, WT_FS_OPEN_FILE_TYPE, uint32_t, WT_FILE_HANDLE **);
static int demo_fs_directory_list(WT_FILE_SYSTEM *, WT_SESSION *,
const char *, const char *, char ***, uint32_t *);
static int demo_fs_directory_list_free(
WT_FILE_SYSTEM *, WT_SESSION *, char **, uint32_t);
static int demo_fs_directory_sync(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *directory);
static int demo_fs_exist(WT_FILE_SYSTEM *, WT_SESSION *, const char *, bool *);
static int demo_fs_remove(WT_FILE_SYSTEM *, WT_SESSION *, const char *);
static int demo_fs_remove(
WT_FILE_SYSTEM *, WT_SESSION *, const char *, uint32_t);
static int demo_fs_rename(
WT_FILE_SYSTEM *, WT_SESSION *, const char *, const char *);
WT_FILE_SYSTEM *, WT_SESSION *, const char *, const char *, uint32_t);
static int demo_fs_size(
WT_FILE_SYSTEM *, WT_SESSION *, const char *, wt_off_t *);
static int demo_fs_terminate(WT_FILE_SYSTEM *, WT_SESSION *);
@@ -255,7 +254,6 @@ demo_file_system_create(WT_CONNECTION *conn, WT_CONFIG_ARG *config)
/* Initialize the in-memory jump table. */
file_system->fs_directory_list = demo_fs_directory_list;
file_system->fs_directory_list_free = demo_fs_directory_list_free;
file_system->fs_directory_sync = demo_fs_directory_sync;
file_system->fs_exist = demo_fs_exist;
file_system->fs_open_file = demo_fs_open;
file_system->fs_remove = demo_fs_remove;
@@ -282,7 +280,7 @@ err: free(demo_fs);
*/
static int
demo_fs_open(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags,
const char *name, WT_FS_OPEN_FILE_TYPE file_type, uint32_t flags,
WT_FILE_HANDLE **file_handlep)
{
DEMO_FILE_HANDLE *demo_fh;
@@ -468,21 +466,6 @@ demo_fs_directory_list_free(WT_FILE_SYSTEM *file_system,
return (0);
}
/*
* demo_fs_directory_sync --
* Directory sync for our demo file system, which is a no-op.
*/
static int
demo_fs_directory_sync(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *directory)
{
(void)file_system; /* Unused */
(void)session; /* Unused */
(void)directory; /* Unused */
return (0);
}
/*
* demo_fs_exist --
* Return if the file exists.
@@ -507,13 +490,15 @@ demo_fs_exist(WT_FILE_SYSTEM *file_system,
* POSIX remove.
*/
static int
demo_fs_remove(
WT_FILE_SYSTEM *file_system, WT_SESSION *session, const char *name)
demo_fs_remove(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *name, uint32_t flags)
{
DEMO_FILE_SYSTEM *demo_fs;
DEMO_FILE_HANDLE *demo_fh;
int ret = 0;
(void)flags; /* Unused */
demo_fs = (DEMO_FILE_SYSTEM *)file_system;
ret = ENOENT;
@@ -531,13 +516,15 @@ demo_fs_remove(
*/
static int
demo_fs_rename(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *from, const char *to)
WT_SESSION *session, const char *from, const char *to, uint32_t flags)
{
DEMO_FILE_HANDLE *demo_fh;
DEMO_FILE_SYSTEM *demo_fs;
char *copy;
int ret = 0;
(void)flags; /* Unused */
demo_fs = (DEMO_FILE_SYSTEM *)file_system;
LOCK_FILE_SYSTEM(session, demo_fs);

View File

@@ -988,6 +988,10 @@ allExample()
/*! [Statistics logging] */
conn.close(null);
if (false) { // MIGHT_NOT_RUN
/*
* Don't run this code, statistics logging doesn't yet support tables.
*/
/*! [Statistics logging with a table] */
conn = wiredtiger.open(home,
"create," +
@@ -995,23 +999,13 @@ allExample()
/*! [Statistics logging with a table] */
conn.close(null);
/*! [Statistics logging with all tables] */
conn = wiredtiger.open(home,
"create,statistics_log=(sources=(\"table:\"))");
/*! [Statistics logging with all tables] */
conn.close(null);
if (false) { // MIGHT_NOT_RUN
/*
* This example code gets run, and a non-existent log file path might
* cause the open to fail. The documentation requires code snippets,
* use if (false) to avoid running it.
* Don't run this code, statistics logging doesn't yet support indexes.
*/
/*! [Statistics logging with path] */
/*! [Statistics logging with a source type] */
conn = wiredtiger.open(home,
"create," +
"statistics_log=(wait=120,path=/log/log.%m.%d.%y)");
/*! [Statistics logging with path] */
"create,statistics_log=(sources=(\"index:\"))");
/*! [Statistics logging with a source type] */
conn.close(null);
/*

View File

@@ -15,9 +15,10 @@ static int __desc_read(WT_SESSION_IMPL *, WT_BLOCK *);
* Drop a file.
*/
int
__wt_block_manager_drop(WT_SESSION_IMPL *session, const char *filename)
__wt_block_manager_drop(
WT_SESSION_IMPL *session, const char *filename, bool durable)
{
return (__wt_remove_if_exists(session, filename));
return (__wt_remove_if_exists(session, filename, durable));
}
/*
@@ -43,8 +44,9 @@ __wt_block_manager_create(
* in our space. Move any existing files out of the way and complain.
*/
for (;;) {
if ((ret = __wt_open(session, filename, WT_OPEN_FILE_TYPE_DATA,
WT_OPEN_CREATE | WT_OPEN_EXCLUSIVE, &fh)) == 0)
if ((ret = __wt_open(session, filename,
WT_FS_OPEN_FILE_TYPE_DATA, WT_FS_OPEN_CREATE |
WT_FS_OPEN_DURABLE | WT_FS_OPEN_EXCLUSIVE, &fh)) == 0)
break;
WT_ERR_TEST(ret != EEXIST, ret);
@@ -56,7 +58,7 @@ __wt_block_manager_create(
WT_ERR(__wt_fs_exist(session, tmp->data, &exists));
if (!exists) {
WT_ERR(__wt_fs_rename(
session, filename, tmp->data));
session, filename, tmp->data, false));
WT_ERR(__wt_msg(session,
"unexpected file %s found, renamed to %s",
filename, (const char *)tmp->data));
@@ -77,16 +79,9 @@ __wt_block_manager_create(
/* Close the file handle. */
WT_TRET(__wt_close(session, &fh));
/*
* Some filesystems require that we sync the directory to be confident
* that the file will appear.
*/
if (ret == 0)
WT_TRET(__wt_fs_directory_sync(session, filename));
/* Undo any create on error. */
if (ret != 0)
WT_TRET(__wt_fs_remove(session, filename));
WT_TRET(__wt_fs_remove(session, filename, false));
err: __wt_scr_free(session, &tmp);
@@ -207,11 +202,11 @@ __wt_block_open(WT_SESSION_IMPL *session,
*/
flags = 0;
if (readonly && FLD_ISSET(conn->direct_io, WT_DIRECT_IO_CHECKPOINT))
LF_SET(WT_OPEN_DIRECTIO);
LF_SET(WT_FS_OPEN_DIRECTIO);
if (!readonly && FLD_ISSET(conn->direct_io, WT_DIRECT_IO_DATA))
LF_SET(WT_OPEN_DIRECTIO);
LF_SET(WT_FS_OPEN_DIRECTIO);
WT_ERR(__wt_open(
session, filename, WT_OPEN_FILE_TYPE_DATA, flags, &block->fh));
session, filename, WT_FS_OPEN_FILE_TYPE_DATA, flags, &block->fh));
/* Set the file's size. */
WT_ERR(__wt_filesize(session, block->fh, &block->size));

View File

@@ -183,6 +183,7 @@ __cursor_var_next(WT_CURSOR_BTREE *cbt, bool newpage)
if (cbt->last_standard_recno == 0)
return (WT_NOTFOUND);
__cursor_set_recno(cbt, cbt->ref->ref_recno);
cbt->cip_saved = NULL;
goto new_page;
}
@@ -301,12 +302,13 @@ __cursor_row_next(WT_CURSOR_BTREE *cbt, bool newpage)
* WT_INSERT_HEAD[0], and so on. This means WT_INSERT lists are
* odd-numbered slots, and WT_ROW array slots are even-numbered slots.
*
* New page configuration.
* Initialize for each new page.
*/
if (newpage) {
cbt->ins_head = WT_ROW_INSERT_SMALLEST(page);
cbt->ins = WT_SKIP_FIRST(cbt->ins_head);
cbt->row_iteration_slot = 1;
cbt->rip_saved = NULL;
goto new_insert;
}
@@ -517,11 +519,13 @@ __wt_btcur_iterate_setup(WT_CURSOR_BTREE *cbt)
*/
F_SET(cbt, WT_CBT_ITERATE_NEXT | WT_CBT_ITERATE_PREV);
/*
* Clear the count of deleted items on the page.
*/
/* Clear the count of deleted items on the page. */
cbt->page_deleted_count = 0;
/* Clear saved iteration cursor position information. */
cbt->cip_saved = NULL;
cbt->rip_saved = NULL;
/*
* If we don't have a search page, then we're done, we're starting at
* the beginning or end of the tree, not as a result of a search.

View File

@@ -329,6 +329,7 @@ __cursor_var_prev(WT_CURSOR_BTREE *cbt, bool newpage)
if (cbt->last_standard_recno == 0)
return (WT_NOTFOUND);
__cursor_set_recno(cbt, cbt->last_standard_recno);
cbt->cip_saved = NULL;
goto new_page;
}
@@ -447,7 +448,7 @@ __cursor_row_prev(WT_CURSOR_BTREE *cbt, bool newpage)
* WT_INSERT_HEAD[0], and so on. This means WT_INSERT lists are
* odd-numbered slots, and WT_ROW array slots are even-numbered slots.
*
* New page configuration.
* Initialize for each new page.
*/
if (newpage) {
/*
@@ -464,6 +465,7 @@ __cursor_row_prev(WT_CURSOR_BTREE *cbt, bool newpage)
WT_ROW_INSERT_SLOT(page, page->pg_row_entries - 1);
cbt->ins = WT_SKIP_LAST(cbt->ins_head);
cbt->row_iteration_slot = page->pg_row_entries * 2 + 1;
cbt->rip_saved = NULL;
goto new_insert;
}

View File

@@ -157,7 +157,8 @@ __huffman_confchk_file(WT_SESSION_IMPL *session,
/* Check the file exists. */
WT_RET(__wt_strndup(session, v->str + len, v->len - len, &fname));
WT_ERR(__wt_fopen(session, fname, WT_OPEN_FIXED, WT_STREAM_READ, &fs));
WT_ERR(__wt_fopen(
session, fname, WT_FS_OPEN_FIXED, WT_STREAM_READ, &fs));
/* Optionally return the file handle. */
if (fsp == NULL)

View File

@@ -67,16 +67,9 @@ static const WT_CONFIG_CHECK
};
static const WT_CONFIG_CHECK
confchk_wiredtiger_open_log_subconfigs[] = {
confchk_WT_CONNECTION_reconfigure_log_subconfigs[] = {
{ "archive", "boolean", NULL, NULL, NULL, 0 },
{ "compressor", "string", NULL, NULL, NULL, 0 },
{ "enabled", "boolean", NULL, NULL, NULL, 0 },
{ "file_max", "int", NULL, "min=100KB,max=2GB", NULL, 0 },
{ "path", "string", NULL, NULL, NULL, 0 },
{ "prealloc", "boolean", NULL, NULL, NULL, 0 },
{ "recover", "string",
NULL, "choices=[\"error\",\"on\"]",
NULL, 0 },
{ "zero_fill", "boolean", NULL, NULL, NULL, 0 },
{ NULL, NULL, NULL, NULL, NULL, 0 }
};
@@ -99,10 +92,9 @@ static const WT_CONFIG_CHECK
};
static const WT_CONFIG_CHECK
confchk_wiredtiger_open_statistics_log_subconfigs[] = {
confchk_WT_CONNECTION_reconfigure_statistics_log_subconfigs[] = {
{ "json", "boolean", NULL, NULL, NULL, 0 },
{ "on_close", "boolean", NULL, NULL, NULL, 0 },
{ "path", "string", NULL, NULL, NULL, 0 },
{ "sources", "list", NULL, NULL, NULL, 0 },
{ "timestamp", "string", NULL, NULL, NULL, 0 },
{ "wait", "int", NULL, "min=0,max=100000", NULL, 0 },
@@ -135,7 +127,7 @@ static const WT_CONFIG_CHECK confchk_WT_CONNECTION_reconfigure[] = {
confchk_wiredtiger_open_file_manager_subconfigs, 3 },
{ "log", "category",
NULL, NULL,
confchk_wiredtiger_open_log_subconfigs, 8 },
confchk_WT_CONNECTION_reconfigure_log_subconfigs, 3 },
{ "lsm_manager", "category",
NULL, NULL,
confchk_wiredtiger_open_lsm_manager_subconfigs, 2 },
@@ -148,7 +140,7 @@ static const WT_CONFIG_CHECK confchk_WT_CONNECTION_reconfigure[] = {
NULL, 0 },
{ "statistics_log", "category",
NULL, NULL,
confchk_wiredtiger_open_statistics_log_subconfigs, 6 },
confchk_WT_CONNECTION_reconfigure_statistics_log_subconfigs, 5 },
{ "verbose", "list",
NULL, "choices=[\"api\",\"block\",\"checkpoint\",\"compact\","
"\"evict\",\"evictserver\",\"fileops\",\"handleops\",\"log\","
@@ -607,6 +599,32 @@ static const WT_CONFIG_CHECK
{ NULL, NULL, NULL, NULL, NULL, 0 }
};
static const WT_CONFIG_CHECK
confchk_wiredtiger_open_log_subconfigs[] = {
{ "archive", "boolean", NULL, NULL, NULL, 0 },
{ "compressor", "string", NULL, NULL, NULL, 0 },
{ "enabled", "boolean", NULL, NULL, NULL, 0 },
{ "file_max", "int", NULL, "min=100KB,max=2GB", NULL, 0 },
{ "path", "string", NULL, NULL, NULL, 0 },
{ "prealloc", "boolean", NULL, NULL, NULL, 0 },
{ "recover", "string",
NULL, "choices=[\"error\",\"on\"]",
NULL, 0 },
{ "zero_fill", "boolean", NULL, NULL, NULL, 0 },
{ NULL, NULL, NULL, NULL, NULL, 0 }
};
static const WT_CONFIG_CHECK
confchk_wiredtiger_open_statistics_log_subconfigs[] = {
{ "json", "boolean", NULL, NULL, NULL, 0 },
{ "on_close", "boolean", NULL, NULL, NULL, 0 },
{ "path", "string", NULL, NULL, NULL, 0 },
{ "sources", "list", NULL, NULL, NULL, 0 },
{ "timestamp", "string", NULL, NULL, NULL, 0 },
{ "wait", "int", NULL, "min=0,max=100000", NULL, 0 },
{ NULL, NULL, NULL, NULL, NULL, 0 }
};
static const WT_CONFIG_CHECK
confchk_wiredtiger_open_transaction_sync_subconfigs[] = {
{ "enabled", "boolean", NULL, NULL, NULL, 0 },
@@ -975,12 +993,10 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"eviction=(threads_max=1,threads_min=1),eviction_dirty_target=80,"
"eviction_dirty_trigger=95,eviction_target=80,eviction_trigger=95"
",file_manager=(close_handle_minimum=250,close_idle_time=30,"
"close_scan_interval=10),log=(archive=,compressor=,enabled=0,"
"file_max=100MB,path=\".\",prealloc=,recover=on,zero_fill=0),"
"close_scan_interval=10),log=(archive=,prealloc=,zero_fill=0),"
"lsm_manager=(merge=,worker_thread_max=4),lsm_merge=,"
"shared_cache=(chunk=10MB,name=,quota=0,reserve=0,size=500MB),"
"statistics=none,statistics_log=(json=0,on_close=0,"
"path=\"WiredTigerStat.%d.%H\",sources=,"
"statistics=none,statistics_log=(json=0,on_close=0,sources=,"
"timestamp=\"%b %d %H:%M:%S\",wait=0),verbose=",
confchk_WT_CONNECTION_reconfigure, 18
},
@@ -1181,11 +1197,10 @@ static const WT_CONFIG_ENTRY config_entries[] = {
",worker_thread_max=4),lsm_merge=,mmap=,multiprocess=0,readonly=0"
",session_max=100,session_scratch_max=2MB,"
"shared_cache=(chunk=10MB,name=,quota=0,reserve=0,size=500MB),"
"statistics=none,statistics_log=(json=0,on_close=0,"
"path=\"WiredTigerStat.%d.%H\",sources=,"
"timestamp=\"%b %d %H:%M:%S\",wait=0),transaction_sync=(enabled=0"
",method=fsync),use_environment=,use_environment_priv=0,verbose=,"
"write_through=",
"statistics=none,statistics_log=(json=0,on_close=0,path=\".\","
"sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
"transaction_sync=(enabled=0,method=fsync),use_environment=,"
"use_environment_priv=0,verbose=,write_through=",
confchk_wiredtiger_open, 38
},
{ "wiredtiger_open_all",
@@ -1203,11 +1218,11 @@ static const WT_CONFIG_ENTRY config_entries[] = {
",worker_thread_max=4),lsm_merge=,mmap=,multiprocess=0,readonly=0"
",session_max=100,session_scratch_max=2MB,"
"shared_cache=(chunk=10MB,name=,quota=0,reserve=0,size=500MB),"
"statistics=none,statistics_log=(json=0,on_close=0,"
"path=\"WiredTigerStat.%d.%H\",sources=,"
"timestamp=\"%b %d %H:%M:%S\",wait=0),transaction_sync=(enabled=0"
",method=fsync),use_environment=,use_environment_priv=0,verbose=,"
"version=(major=0,minor=0),write_through=",
"statistics=none,statistics_log=(json=0,on_close=0,path=\".\","
"sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
"transaction_sync=(enabled=0,method=fsync),use_environment=,"
"use_environment_priv=0,verbose=,version=(major=0,minor=0),"
"write_through=",
confchk_wiredtiger_open_all, 39
},
{ "wiredtiger_open_basecfg",
@@ -1224,10 +1239,9 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"worker_thread_max=4),lsm_merge=,mmap=,multiprocess=0,readonly=0,"
"session_max=100,session_scratch_max=2MB,shared_cache=(chunk=10MB"
",name=,quota=0,reserve=0,size=500MB),statistics=none,"
"statistics_log=(json=0,on_close=0,path=\"WiredTigerStat.%d.%H\","
"sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
"transaction_sync=(enabled=0,method=fsync),verbose=,"
"version=(major=0,minor=0),write_through=",
"statistics_log=(json=0,on_close=0,path=\".\",sources=,"
"timestamp=\"%b %d %H:%M:%S\",wait=0),transaction_sync=(enabled=0"
",method=fsync),verbose=,version=(major=0,minor=0),write_through=",
confchk_wiredtiger_open_basecfg, 33
},
{ "wiredtiger_open_usercfg",
@@ -1244,10 +1258,9 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"worker_thread_max=4),lsm_merge=,mmap=,multiprocess=0,readonly=0,"
"session_max=100,session_scratch_max=2MB,shared_cache=(chunk=10MB"
",name=,quota=0,reserve=0,size=500MB),statistics=none,"
"statistics_log=(json=0,on_close=0,path=\"WiredTigerStat.%d.%H\","
"sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
"transaction_sync=(enabled=0,method=fsync),verbose=,"
"write_through=",
"statistics_log=(json=0,on_close=0,path=\".\",sources=,"
"timestamp=\"%b %d %H:%M:%S\",wait=0),transaction_sync=(enabled=0"
",method=fsync),verbose=,write_through=",
confchk_wiredtiger_open_usercfg, 32
},
{ NULL, NULL, NULL, 0 }

View File

@@ -1217,7 +1217,8 @@ __conn_config_file(WT_SESSION_IMPL *session,
return (0);
/* Open the configuration file. */
WT_RET(__wt_open(session, filename, WT_OPEN_FILE_TYPE_REGULAR, 0, &fh));
WT_RET(__wt_open(
session, filename, WT_FS_OPEN_FILE_TYPE_REGULAR, 0, &fh));
WT_ERR(__wt_filesize(session, fh, &size));
if (size == 0)
goto err;
@@ -1510,8 +1511,8 @@ __conn_single(WT_SESSION_IMPL *session, const char *cfg[])
exist = false;
if (!is_create)
WT_ERR(__wt_fs_exist(session, WT_WIREDTIGER, &exist));
ret = __wt_open(session, WT_SINGLETHREAD, WT_OPEN_FILE_TYPE_REGULAR,
is_create || exist ? WT_OPEN_CREATE : 0, &conn->lock_fh);
ret = __wt_open(session, WT_SINGLETHREAD, WT_FS_OPEN_FILE_TYPE_REGULAR,
is_create || exist ? WT_FS_OPEN_CREATE : 0, &conn->lock_fh);
/*
* If this is a read-only connection and we cannot grab the lock
@@ -1563,7 +1564,8 @@ __conn_single(WT_SESSION_IMPL *session, const char *cfg[])
/* We own the lock file, optionally create the WiredTiger file. */
ret = __wt_open(session, WT_WIREDTIGER,
WT_OPEN_FILE_TYPE_REGULAR, is_create ? WT_OPEN_CREATE : 0, &fh);
WT_FS_OPEN_FILE_TYPE_REGULAR, is_create ? WT_FS_OPEN_CREATE : 0,
&fh);
/*
* If we're read-only, check for handled errors. Even if able to open
@@ -1784,7 +1786,7 @@ __conn_write_base_config(WT_SESSION_IMPL *session, const char *cfg[])
* runs. This doesn't matter for correctness, it's just cleaning up
* random files.
*/
WT_RET(__wt_remove_if_exists(session, WT_BASECONFIG_SET));
WT_RET(__wt_remove_if_exists(session, WT_BASECONFIG_SET, false));
/*
* The base configuration file is only written if creating the database,
@@ -1809,7 +1811,7 @@ __conn_write_base_config(WT_SESSION_IMPL *session, const char *cfg[])
return (0);
WT_RET(__wt_fopen(session, WT_BASECONFIG_SET,
WT_OPEN_CREATE | WT_OPEN_EXCLUSIVE, WT_STREAM_WRITE, &fs));
WT_FS_OPEN_CREATE | WT_FS_OPEN_EXCLUSIVE, WT_STREAM_WRITE, &fs));
WT_ERR(__wt_fprintf(session, fs, "%s\n\n",
"# Do not modify this file.\n"
@@ -1870,7 +1872,8 @@ __conn_write_base_config(WT_SESSION_IMPL *session, const char *cfg[])
if (0) {
/* Close open file handle, remove any temporary file. */
err: WT_TRET(__wt_fclose(session, &fs));
WT_TRET(__wt_remove_if_exists(session, WT_BASECONFIG_SET));
WT_TRET(
__wt_remove_if_exists(session, WT_BASECONFIG_SET, false));
}
__wt_free(session, base_config);

View File

@@ -23,37 +23,16 @@ __ckpt_server_config(WT_SESSION_IMPL *session, const char **cfg, bool *startp)
WT_DECL_RET;
char *p;
*startp = false;
conn = S2C(session);
/*
* The checkpoint configuration requires a wait time and/or a log
* size -- if one is not set, we're not running at all.
* Checkpoints based on log size also require logging be enabled.
*/
WT_RET(__wt_config_gets(session, cfg, "checkpoint.wait", &cval));
conn->ckpt_usecs = (uint64_t)cval.val * WT_MILLION;
WT_RET(__wt_config_gets(session, cfg, "checkpoint.log_size", &cval));
conn->ckpt_logsize = (wt_off_t)cval.val;
/* Checkpoints are incompatible with in-memory configuration */
if (conn->ckpt_usecs != 0 || conn->ckpt_logsize != 0) {
WT_RET(__wt_config_gets(session, cfg, "in_memory", &cval));
if (cval.val != 0)
WT_RET_MSG(session, EINVAL,
"In memory configuration incompatible with "
"checkpoints");
}
__wt_log_written_reset(session);
if ((conn->ckpt_usecs == 0 && conn->ckpt_logsize == 0) ||
(conn->ckpt_logsize && conn->ckpt_usecs == 0 &&
!FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED))) {
*startp = false;
return (0);
}
*startp = true;
/*
* The application can specify a checkpoint name, which we ignore if
* it's our default.
@@ -72,6 +51,26 @@ __ckpt_server_config(WT_SESSION_IMPL *session, const char **cfg, bool *startp)
conn->ckpt_config = p;
}
/*
* The checkpoint configuration requires a wait time and/or a log size,
* if neither is set, we're not running at all. Checkpoints based on log
* size also require logging be enabled.
*/
if (conn->ckpt_usecs != 0 ||
(conn->ckpt_logsize != 0 &&
FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED))) {
/* Checkpoints are incompatible with in-memory configuration */
WT_ERR(__wt_config_gets(session, cfg, "in_memory", &cval));
if (cval.val != 0)
WT_ERR_MSG(session, EINVAL,
"checkpoint configuration incompatible with "
"in-memory configuration");
__wt_log_written_reset(session);
*startp = true;
}
err: __wt_scr_free(session, &tmp);
return (ret);
}
@@ -179,7 +178,16 @@ __wt_checkpoint_server_create(WT_SESSION_IMPL *session, const char *cfg[])
conn = S2C(session);
start = false;
/* If there is already a server running, shut it down. */
/*
* 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. This makes our life easier as the underlying
* configuration routine doesn't have to worry about freeing objects
* in the connection structure (it's guaranteed to always start with a
* blank slate), and we don't have to worry about races where a running
* server is reading configuration information that we're updating, and
* it's not expected that reconfiguration will happen a lot.
*/
if (conn->ckpt_session != NULL)
WT_RET(__wt_checkpoint_server_destroy(session));

View File

@@ -51,6 +51,25 @@ __logmgr_config(
WT_CONNECTION_IMPL *conn;
bool enabled;
/*
* A note on reconfiguration: the standard "is this configuration string
* allowed" checks should fail if reconfiguration has invalid strings,
* for example, "log=(enabled)", or "statistics_log=(path=XXX)", because
* the connection reconfiguration method doesn't allow those strings.
* Additionally, the base configuration values during reconfiguration
* are the currently configured values (so we don't revert to default
* values when repeatedly reconfiguring), and configuration processing
* of a currently set value should not change the currently set value.
*
* In this code path, log server reconfiguration does not stop/restart
* the log server, so there's no point in re-evaluating configuration
* strings that cannot be reconfigured, risking bugs in configuration
* setup, and depending on evaluation of currently set values to always
* result in the currently set value. Skip tests for any configuration
* strings which don't make sense during reconfiguration, but don't
* worry about error reporting because it should never happen.
*/
conn = S2C(session);
WT_RET(__wt_config_gets(session, cfg, "log.enabled", &cval));
@@ -62,6 +81,8 @@ __logmgr_config(
*
* If it is off and the user it turning it on, or it is on
* and the user is turning it off, return an error.
*
* See above: should never happen.
*/
if (reconfig &&
((enabled && !FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED)) ||
@@ -83,6 +104,8 @@ __logmgr_config(
* Setup a log path and compression even if logging is disabled in case
* we are going to print a log. Only do this on creation. Once a
* compressor or log path are set they cannot be changed.
*
* See above: should never happen.
*/
if (!reconfig) {
conn->log_compressor = NULL;
@@ -95,6 +118,7 @@ __logmgr_config(
WT_RET(__wt_strndup(
session, cval.str, cval.len, &conn->log_path));
}
/* We are done if logging isn't enabled. */
if (!*runp)
return (0);
@@ -103,13 +127,14 @@ __logmgr_config(
if (cval.val != 0)
FLD_SET(conn->log_flags, WT_CONN_LOG_ARCHIVE);
/*
* The file size cannot be reconfigured. The amount of memory allocated
* to the log slots may be based on the log file size at creation and we
* don't want to re-allocate that memory while running.
*
* See above: should never happen.
*/
if (!reconfig) {
/*
* Ignore if the user tries to change the file size. The
* amount of memory allocated to the log slots may be based
* on the log file size at creation and we don't want to
* re-allocate that memory while running.
*/
WT_RET(__wt_config_gets(session, cfg, "log.file_max", &cval));
conn->log_file_max = (wt_off_t)cval.val;
WT_STAT_FAST_CONN_SET(session,
@@ -125,12 +150,17 @@ __logmgr_config(
conn->log_prealloc = 1;
/*
* Note that it is meaningless to reconfigure this value during
* runtime. It only matters on create before recovery runs.
* Note it's meaningless to reconfigure this value during runtime, it
* only matters on create before recovery runs.
*
* See above: should never happen.
*/
WT_RET(__wt_config_gets_def(session, cfg, "log.recover", 0, &cval));
if (cval.len != 0 && WT_STRING_MATCH("error", cval.str, cval.len))
FLD_SET(conn->log_flags, WT_CONN_LOG_RECOVER_ERR);
if (!reconfig) {
WT_RET(__wt_config_gets_def(
session, cfg, "log.recover", 0, &cval));
if (WT_STRING_MATCH("error", cval.str, cval.len))
FLD_SET(conn->log_flags, WT_CONN_LOG_RECOVER_ERR);
}
WT_RET(__wt_config_gets(session, cfg, "log.zero_fill", &cval));
if (cval.val != 0) {

View File

@@ -35,6 +35,31 @@ __stat_sources_free(WT_SESSION_IMPL *session, char ***sources)
}
}
/*
* __stat_config_discard --
* Discard all statistics-log configuration.
*/
static int
__stat_config_discard(WT_SESSION_IMPL *session)
{
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
conn = S2C(session);
/*
* Discard all statistics-log configuration information, called when
* reconfiguring or destroying the statistics logging setup,
*/
__wt_free(session, conn->stat_format);
ret = __wt_fclose(session, &conn->stat_fs);
__wt_free(session, conn->stat_path);
__stat_sources_free(session, &conn->stat_sources);
conn->stat_stamp = NULL;
conn->stat_usecs = 0;
return (ret);
}
/*
* __wt_conn_stat_init --
* Initialize the per-connection statistics.
@@ -73,20 +98,37 @@ __statlog_config(WT_SESSION_IMPL *session, const char **cfg, bool *runp)
WT_CONFIG objectconf;
WT_CONFIG_ITEM cval, k, v;
WT_CONNECTION_IMPL *conn;
WT_DECL_ITEM(tmp);
WT_DECL_RET;
int cnt;
char **sources;
/*
* A note on reconfiguration: the standard "is this configuration string
* allowed" checks should fail if reconfiguration has invalid strings,
* for example, "log=(enabled)", or "statistics_log=(path=XXX)", because
* the connection reconfiguration method doesn't allow those strings.
* Additionally, the base configuration values during reconfiguration
* are the currently configured values (so we don't revert to default
* values when repeatedly reconfiguring), and configuration processing
* of a currently set value should not change the currently set value.
*
* In this code path, a previous statistics log server reconfiguration
* may have stopped the server (and we're about to restart it). Because
* stopping the server discarded the configured information stored in
* the connection structure, we have to re-evaluate all configuration
* values, reconfiguration can't skip any of them.
*/
conn = S2C(session);
sources = NULL;
WT_RET(__wt_config_gets(session, cfg, "statistics_log.wait", &cval));
/* Only start the server if wait time is non-zero */
WT_RET(__wt_config_gets(session, cfg, "statistics_log.wait", &cval));
*runp = cval.val != 0;
conn->stat_usecs = (uint64_t)cval.val * WT_MILLION;
WT_RET(__wt_config_gets(
session, cfg, "statistics_log.json", &cval));
WT_RET(__wt_config_gets(session, cfg, "statistics_log.json", &cval));
if (cval.val != 0)
FLD_SET(conn->stat_flags, WT_CONN_STAT_JSON);
@@ -96,24 +138,30 @@ __statlog_config(WT_SESSION_IMPL *session, const char **cfg, bool *runp)
FLD_SET(conn->stat_flags, WT_CONN_STAT_ON_CLOSE);
/*
* Statistics logging configuration requires either a wait time or an
* on-close setting.
* We don't allow the log path to be reconfigured for security reasons.
* (Applications passing input strings directly to reconfigure would
* expose themselves to a potential security problem, the utility of
* reconfiguring a statistics log path isn't worth the security risk.)
*
* See above for the details, but during reconfiguration we're loading
* the path value from the saved configuration information, and it's
* required during reconfiguration because we potentially stopped and
* are restarting, the server.
*/
if (!*runp && !FLD_ISSET(conn->stat_flags, WT_CONN_STAT_ON_CLOSE))
return (0);
WT_RET(__wt_config_gets(session, cfg, "statistics_log.path", &cval));
WT_ERR(__wt_scr_alloc(session, 0, &tmp));
WT_ERR(__wt_buf_fmt(session,
tmp, "%.*s/%s", (int)cval.len, cval.str, WT_STATLOG_FILENAME));
WT_ERR(__wt_filename(session, tmp->data, &conn->stat_path));
/*
* If any statistics logging is done, this must not be a read-only
* connection.
*/
WT_RET(__wt_config_gets(session, cfg, "statistics_log.sources", &cval));
WT_RET(__wt_config_subinit(session, &objectconf, &cval));
WT_ERR(__wt_config_gets(session, cfg, "statistics_log.sources", &cval));
WT_ERR(__wt_config_subinit(session, &objectconf, &cval));
for (cnt = 0; (ret = __wt_config_next(&objectconf, &k, &v)) == 0; ++cnt)
;
WT_RET_NOTFOUND_OK(ret);
WT_ERR_NOTFOUND_OK(ret);
if (cnt != 0) {
WT_RET(__wt_calloc_def(session, cnt + 1, &sources));
WT_RET(__wt_config_subinit(session, &objectconf, &cval));
WT_ERR(__wt_calloc_def(session, cnt + 1, &sources));
WT_ERR(__wt_config_subinit(session, &objectconf, &cval));
for (cnt = 0;
(ret = __wt_config_next(&objectconf, &k, &v)) == 0; ++cnt) {
/*
@@ -138,29 +186,37 @@ __statlog_config(WT_SESSION_IMPL *session, const char **cfg, bool *runp)
sources = NULL;
}
WT_ERR(__wt_config_gets(session, cfg, "statistics_log.path", &cval));
WT_ERR(__wt_nfilename(session, cval.str, cval.len, &conn->stat_path));
/*
* When using JSON format, use the same timestamp format as MongoDB by
* default.
* default. This requires caution: the user might have set the timestamp
* in a previous reconfigure call and we don't want to override that, so
* compare the retrieved value with the default value to decide if we
* should use the JSON default.
*
* (This still implies if the user explicitly sets the timestamp to the
* default value, then sets the JSON flag in a separate reconfigure
* call, or vice-versa, we will incorrectly switch to the JSON default
* timestamp. But there's no way to detect that, and this is all a low
* probability path.)
*
* !!!
* Don't rewrite in the compressed "%FT%T.000Z" form, MSVC13 segfaults.
*/
if (FLD_ISSET(conn->stat_flags, WT_CONN_STAT_JSON)) {
ret = __wt_config_gets(
session, &cfg[1], "statistics_log.timestamp", &cval);
if (ret == WT_NOTFOUND)
WT_ERR(__wt_strdup(
session, "%FT%T.000Z", &conn->stat_format));
WT_ERR_NOTFOUND_OK(ret);
}
if (conn->stat_format == NULL) {
WT_ERR(__wt_config_gets(
session, cfg, "statistics_log.timestamp", &cval));
#define WT_TIMESTAMP_DEFAULT "%b %d %H:%M:%S"
#define WT_TIMESTAMP_JSON_DEFAULT "%Y-%m-%dT%H:%M:%S.000Z"
WT_ERR(__wt_config_gets(
session, cfg, "statistics_log.timestamp", &cval));
if (FLD_ISSET(conn->stat_flags, WT_CONN_STAT_JSON) &&
WT_STRING_MATCH(WT_TIMESTAMP_DEFAULT, cval.str, cval.len))
WT_ERR(__wt_strdup(
session, WT_TIMESTAMP_JSON_DEFAULT, &conn->stat_format));
else
WT_ERR(__wt_strndup(
session, cval.str, cval.len, &conn->stat_format));
}
err: __stat_sources_free(session, &sources);
__wt_scr_free(session, &tmp);
return (ret);
}
@@ -373,7 +429,7 @@ __statlog_log_one(WT_SESSION_IMPL *session, WT_ITEM *path, WT_ITEM *tmp)
if (path != NULL)
(void)strcpy(path->mem, tmp->mem);
WT_RET(__wt_fopen(session, tmp->mem,
WT_OPEN_CREATE | WT_OPEN_FIXED, WT_STREAM_APPEND,
WT_FS_OPEN_CREATE | WT_FS_OPEN_FIXED, WT_STREAM_APPEND,
&log_stream));
}
conn->stat_fs = log_stream;
@@ -538,14 +594,23 @@ __wt_statlog_create(WT_SESSION_IMPL *session, const char *cfg[])
bool start;
conn = S2C(session);
start = false;
/*
* 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.
* configuration changes. This makes our life easier as the underlying
* configuration routine doesn't have to worry about freeing objects
* in the connection structure (it's guaranteed to always start with a
* blank slate), and we don't have to worry about races where a running
* server is reading configuration information that we're updating, and
* it's not expected that reconfiguration will happen a lot.
*
* If there's no server running, discard any configuration information
* so we don't leak memory during reconfiguration.
*/
if (conn->stat_session != NULL)
if (conn->stat_session == NULL)
WT_RET(__stat_config_discard(session));
else
WT_RET(__wt_statlog_destroy(session, false));
WT_RET(__statlog_config(session, cfg, &start));
@@ -568,38 +633,28 @@ __wt_statlog_destroy(WT_SESSION_IMPL *session, bool is_close)
conn = S2C(session);
/* Stop the server thread. */
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));
conn->stat_tid_set = false;
}
WT_TRET(__wt_cond_destroy(session, &conn->stat_cond));
/* Log a set of statistics on shutdown if configured. */
if (is_close)
WT_TRET(__wt_statlog_log_one(session));
WT_TRET(__wt_cond_destroy(session, &conn->stat_cond));
__stat_sources_free(session, &conn->stat_sources);
__wt_free(session, conn->stat_path);
__wt_free(session, conn->stat_format);
/* Discard all configuration information. */
WT_TRET(__stat_config_discard(session));
/* Close the server thread's session. */
if (conn->stat_session != NULL) {
wt_session = &conn->stat_session->iface;
WT_TRET(wt_session->close(wt_session, NULL));
conn->stat_session = NULL;
}
/* Clear connection settings so reconfigure is reliable. */
conn->stat_session = NULL;
conn->stat_tid_set = false;
conn->stat_format = NULL;
WT_TRET(__wt_fclose(session, &conn->stat_fs));
conn->stat_path = NULL;
conn->stat_sources = NULL;
conn->stat_stamp = NULL;
conn->stat_usecs = 0;
return (ret);
}

View File

@@ -235,7 +235,7 @@ __backup_start(
* doesn't confuse restarting in the source database.
*/
WT_ERR(__wt_fopen(session, WT_BACKUP_TMP,
WT_OPEN_CREATE, WT_STREAM_WRITE, &cb->bfs));
WT_FS_OPEN_CREATE, WT_STREAM_WRITE, &cb->bfs));
/*
* If a list of targets was specified, work our way through them.
* Else, generate a list of all database objects.
@@ -261,7 +261,7 @@ __backup_start(
*/
dest = WT_INCREMENTAL_BACKUP;
WT_ERR(__wt_fopen(session, WT_INCREMENTAL_SRC,
WT_OPEN_CREATE, WT_STREAM_WRITE, &srcfs));
WT_FS_OPEN_CREATE, WT_STREAM_WRITE, &srcfs));
WT_ERR(__backup_list_append(
session, cb, WT_INCREMENTAL_BACKUP));
} else {
@@ -287,7 +287,7 @@ err: /* Close the hot backup file. */
WT_TRET(__backup_stop(session));
} else {
WT_ASSERT(session, dest != NULL);
WT_TRET(__wt_fs_rename(session, WT_BACKUP_TMP, dest));
WT_TRET(__wt_fs_rename(session, WT_BACKUP_TMP, dest, false));
}
return (ret);
@@ -443,10 +443,10 @@ __wt_backup_file_remove(WT_SESSION_IMPL *session)
* always know we were a source directory while there's any chance of
* an incremental backup file existing.
*/
WT_TRET(__wt_remove_if_exists(session, WT_BACKUP_TMP));
WT_TRET(__wt_remove_if_exists(session, WT_INCREMENTAL_BACKUP));
WT_TRET(__wt_remove_if_exists(session, WT_INCREMENTAL_SRC));
WT_TRET(__wt_remove_if_exists(session, WT_METADATA_BACKUP));
WT_TRET(__wt_remove_if_exists(session, WT_BACKUP_TMP, true));
WT_TRET(__wt_remove_if_exists(session, WT_INCREMENTAL_BACKUP, true));
WT_TRET(__wt_remove_if_exists(session, WT_INCREMENTAL_SRC, true));
WT_TRET(__wt_remove_if_exists(session, WT_METADATA_BACKUP, true));
return (ret);
}

View File

@@ -2,10 +2,23 @@
@section directory_permissions Database directory permissions
All WiredTiger files are stored in the database home directory, and the
WiredTiger database directory should have its permissions set to ensure
database objects are not accessible to users without appropriate
permissions. See @ref home for more information.
By default, WiredTiger files are stored beneath the database home directory.
The WiredTiger database directory should have its permissions set to ensure
database objects are not accessible to users without appropriate permissions.
See @ref home for more information.
@section absolute_path Absolute paths
WiredTiger prepends the name of the database home to file names which
do not appear to be absolute paths. (The absolute path test is
simplistic, matching a leading slash character on POSIX systems or a
leading alphabetic character and colon on Windows.) No file path
sanitization or validation is done by WiredTiger, for example, file
paths may match universal naming conventions (UNC), or include \c "../"
(dot dot slash) components.
Applications are responsible for validating user-supplied file paths as
necessary to prevent directory traversal attacks.
@section file_permissions File permissions

View File

@@ -80,6 +80,7 @@ SCons
Seward's
SiH
TXT
UNC
URIs
WILLNEED
WiredTiger
@@ -368,6 +369,7 @@ php
png
posix
pre
prepends
primary's
printf
printlog
@@ -411,6 +413,7 @@ runtime
rwlock
sHQ
sHq
sanitization
scalable
scanf
schemas

View File

@@ -90,11 +90,20 @@ cursor.
@section statistics_log Statistics logging
WiredTiger will optionally log database statistics into a file when the
WiredTiger will optionally log database statistics into files when the
the ::wiredtiger_open \c statistics_log configuration is set.
The resulting statistics can be displayed using the \c wtstats visualization
tool. For more information, see @ref_single wtstats.
The log files are named \c WiredTiger.%%d.%%H, where \c %%d is replaced
with the day of the month as a decimal number (01-31), and \c %%H
is replaced by the hour (24-hour clock) as a decimal number (00-23).
Each log file contains the statistics for the hour specified in its name.
The location of the log files may be changed with the \c statistics_log.path
configuration string.
The resulting statistics can be displayed and interactively examined
using the \c wtstats visualization tool. For more information, see
@ref_single wtstats.
The following example logs statistics every 30 seconds:
@@ -120,7 +129,7 @@ Statistics for all underlying data sources of a particular type may be
included by adding a partial data source URI to the \c statistics_log
configuration string:
@snippet ex_all.c Statistics logging with all tables
@snippet ex_all.c Statistics logging with a source type
When database statistics are logged, the database home will be the first
space-separated entry for each record in the log file. For example:
@@ -151,23 +160,9 @@ currently open in the database, nor will any statistics requiring the
traversal of a tree (as if the \c statistics_fast configuration string
were set).
The location of the log files may be changed with the \c statistics_log.path
configuration string. The \c path value value may contain ISO C90 standard
strftime conversion specifications. WiredTiger will not create non-existent
directories in the path, they must exist before ::wiredtiger_open is called.
The following example logs statistics into files named with the month,
day and year:
@snippet ex_all.c Statistics logging with path
A Python script that parses the default logging output and uses the
<a href="http://www.gnuplot.info/">gnuplot</a>, utility to generate
Portable Network Graphics (PNG) format graphs is included in the
WiredTiger distribution in the file \c tools/statlog.py.
@m_if{c}
To interactively examine statistics results, see @ref wtstats.
@m_endif
*/

View File

@@ -1,5 +1,16 @@
/*! @page upgrading Upgrading WiredTiger applications
@section version_281 Upgrading to Version 2.8.1
<dl>
<dt>Statistics logging path</dt>
<dd>
The statistics logging path configuration has been simplified to be only a
path to a directory, and the file name component of the path may no longer
be specified. Applications depending on the ability to set statistics log
file names will require modifications.
</dd>
</dl><hr>
@section version_280 Upgrading to Version 2.8.0
<dl>
<dt>LSM metadata</dt>
@@ -55,7 +66,6 @@ The WiredTiger public API used to define a structure that could encapsulate
log sequence numbers. That structure is no longer exposed publicly.
</dd>
<dt>
</dl><hr>
@section version_270 Upgrading to Version 2.7.0

View File

@@ -145,6 +145,18 @@ done: if (((inmem_split && ret == 0) || (forced_eviction && ret == EBUSY)) &&
WT_TRET(__wt_evict_server_wake(session));
}
/*
* When application threads perform eviction, we don't want to cache
* reconciliation structures.
*/
if (!F_ISSET(session, WT_SESSION_INTERNAL)) {
if (session->block_manager_cleanup != NULL)
WT_TRET(session->block_manager_cleanup(session));
if (session->reconcile_cleanup != NULL)
WT_TRET(session->reconcile_cleanup(session));
}
return (ret);
}
/*

View File

@@ -314,6 +314,7 @@ struct __wt_connection_impl {
uint32_t evict_workers; /* Number of eviction workers */
WT_EVICT_WORKER *evict_workctx; /* Eviction worker context */
#define WT_STATLOG_FILENAME "WiredTigerStat.%d.%H"
WT_SESSION_IMPL *stat_session; /* Statistics log session */
wt_thread_t stat_tid; /* Statistics log thread */
bool stat_tid_set; /* Statistics log thread set */

View File

@@ -38,9 +38,6 @@ __cursor_pos_clear(WT_CURSOR_BTREE *cbt)
cbt->ins_head = NULL;
cbt->ins_stack[0] = NULL;
cbt->cip_saved = NULL;
cbt->rip_saved = NULL;
F_CLR(cbt, WT_CBT_POSITION_MASK);
}

View File

@@ -44,7 +44,7 @@ extern void __wt_block_extlist_free(WT_SESSION_IMPL *session, WT_EXTLIST *el);
extern int __wt_block_map(WT_SESSION_IMPL *session, WT_BLOCK *block, void *mapped_regionp, size_t *lengthp, void *mapped_cookiep);
extern int __wt_block_unmap(WT_SESSION_IMPL *session, WT_BLOCK *block, void *mapped_region, size_t length, void *mapped_cookie);
extern int __wt_block_manager_open(WT_SESSION_IMPL *session, const char *filename, const char *cfg[], bool forced_salvage, bool readonly, uint32_t allocsize, WT_BM **bmp);
extern int __wt_block_manager_drop(WT_SESSION_IMPL *session, const char *filename);
extern int __wt_block_manager_drop( WT_SESSION_IMPL *session, const char *filename, bool durable);
extern int __wt_block_manager_create( WT_SESSION_IMPL *session, const char *filename, uint32_t allocsize);
extern void __wt_block_configure_first_fit(WT_BLOCK *block, bool on);
extern int __wt_block_open(WT_SESSION_IMPL *session, const char *filename, const char *cfg[], bool forced_salvage, bool readonly, uint32_t allocsize, WT_BLOCK **blockp);
@@ -485,8 +485,7 @@ extern int __wt_turtle_read(WT_SESSION_IMPL *session, const char *key, char **va
extern int __wt_turtle_update(WT_SESSION_IMPL *session, const char *key, const char *value);
extern int __wt_filename(WT_SESSION_IMPL *session, const char *name, char **path);
extern int __wt_nfilename( WT_SESSION_IMPL *session, const char *name, size_t namelen, char **path);
extern int __wt_remove_if_exists(WT_SESSION_IMPL *session, const char *name);
extern int __wt_rename_and_sync_directory( WT_SESSION_IMPL *session, const char *from, const char *to);
extern int __wt_remove_if_exists(WT_SESSION_IMPL *session, const char *name, bool durable);
extern int __wt_copy_and_sync(WT_SESSION *wt_session, const char *from, const char *to);
extern void __wt_abort(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((noreturn));
extern int __wt_calloc(WT_SESSION_IMPL *session, size_t number, size_t size, void *retp);
@@ -500,7 +499,7 @@ extern int __wt_errno(void);
extern const char *__wt_strerror(WT_SESSION_IMPL *session, int error, char *errbuf, size_t errlen);
extern int __wt_ext_map_windows_error( WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, uint32_t windows_error);
extern bool __wt_handle_is_open(WT_SESSION_IMPL *session, const char *name);
extern int __wt_open(WT_SESSION_IMPL *session, const char *name, WT_OPEN_FILE_TYPE file_type, u_int flags, WT_FH **fhp);
extern int __wt_open(WT_SESSION_IMPL *session, const char *name, WT_FS_OPEN_FILE_TYPE file_type, u_int flags, WT_FH **fhp);
extern int __wt_close(WT_SESSION_IMPL *session, WT_FH **fhp);
extern int __wt_close_connection_close(WT_SESSION_IMPL *session);
extern int __wt_os_inmemory(WT_SESSION_IMPL *session);

View File

@@ -8,7 +8,7 @@
/*
* __wt_fs_directory_list --
* Get a list of files from a directory.
* Return a list of files from a directory.
*/
static inline int
__wt_fs_directory_list(WT_SESSION_IMPL *session,
@@ -60,61 +60,6 @@ __wt_fs_directory_list_free(
return (ret);
}
/*
* __wt_fs_directory_sync --
* Flush a directory to ensure file creation is durable.
*/
static inline int
__wt_fs_directory_sync(WT_SESSION_IMPL *session, const char *name)
{
WT_DECL_RET;
WT_FILE_SYSTEM *file_system;
WT_SESSION *wt_session;
char *copy, *dir;
WT_ASSERT(session, !F_ISSET(S2C(session), WT_CONN_READONLY));
WT_RET(__wt_verbose(
session, WT_VERB_FILEOPS, "%s: directory-sync", name));
/*
* POSIX 1003.1 does not require that fsync of a file handle ensures the
* entry in the directory containing the file has also reached disk (and
* there are historic Linux filesystems requiring it). If the underlying
* filesystem method is set, do an explicit fsync on a file descriptor
* for the directory to be sure.
*
* directory-sync is not a required call, no method means the call isn't
* needed.
*/
file_system = S2C(session)->file_system;
if (file_system->fs_directory_sync == NULL)
return (0);
copy = NULL;
if (name == NULL || strchr(name, '/') == NULL)
name = S2C(session)->home;
else {
/*
* File name construction should not return a path without any
* slash separator, but caution isn't unreasonable.
*/
WT_RET(__wt_filename(session, name, &copy));
if ((dir = strrchr(copy, '/')) == NULL)
name = S2C(session)->home;
else {
dir[1] = '\0';
name = copy;
}
}
wt_session = (WT_SESSION *)session;
ret = file_system->fs_directory_sync(file_system, wt_session, name);
__wt_free(session, copy);
return (ret);
}
/*
* __wt_fs_exist --
* Return if the file exists.
@@ -141,10 +86,10 @@ __wt_fs_exist(WT_SESSION_IMPL *session, const char *name, bool *existp)
/*
* __wt_fs_remove --
* POSIX remove.
* Remove the file.
*/
static inline int
__wt_fs_remove(WT_SESSION_IMPL *session, const char *name)
__wt_fs_remove(WT_SESSION_IMPL *session, const char *name, bool durable)
{
WT_DECL_RET;
WT_FILE_SYSTEM *file_system;
@@ -169,7 +114,8 @@ __wt_fs_remove(WT_SESSION_IMPL *session, const char *name)
file_system = S2C(session)->file_system;
wt_session = (WT_SESSION *)session;
ret = file_system->fs_remove(file_system, wt_session, path);
ret = file_system->fs_remove(
file_system, wt_session, path, durable ? WT_FS_DURABLE : 0);
__wt_free(session, path);
return (ret);
@@ -177,10 +123,11 @@ __wt_fs_remove(WT_SESSION_IMPL *session, const char *name)
/*
* __wt_fs_rename --
* POSIX rename.
* Rename the file.
*/
static inline int
__wt_fs_rename(WT_SESSION_IMPL *session, const char *from, const char *to)
__wt_fs_rename(
WT_SESSION_IMPL *session, const char *from, const char *to, bool durable)
{
WT_DECL_RET;
WT_FILE_SYSTEM *file_system;
@@ -211,8 +158,8 @@ __wt_fs_rename(WT_SESSION_IMPL *session, const char *from, const char *to)
file_system = S2C(session)->file_system;
wt_session = (WT_SESSION *)session;
ret = file_system->fs_rename(
file_system, wt_session, from_path, to_path);
ret = file_system->fs_rename(file_system,
wt_session, from_path, to_path, durable ? WT_FS_DURABLE : 0);
err: __wt_free(session, from_path);
__wt_free(session, to_path);
@@ -221,7 +168,7 @@ err: __wt_free(session, from_path);
/*
* __wt_fs_size --
* Get the size of a file in bytes, by file name.
* Return the size of a file in bytes, by file name.
*/
static inline int
__wt_fs_size(WT_SESSION_IMPL *session, const char *name, wt_off_t *sizep)

View File

@@ -93,5 +93,5 @@ __wt_sync_and_rename(WT_SESSION_IMPL *session,
WT_TRET(__wt_fclose(session, &fstr));
WT_RET(ret);
return (__wt_rename_and_sync_directory(session, from, to));
return (__wt_fs_rename(session, from, to, true));
}

View File

@@ -98,6 +98,7 @@ struct __wt_txn_global {
volatile uint32_t checkpoint_id; /* Checkpoint's session ID */
volatile uint64_t checkpoint_gen;
volatile uint64_t checkpoint_pinned;
volatile uint64_t checkpoint_txnid; /* Checkpoint's txn ID */
/* Named snapshot state. */
WT_RWLOCK *nsnap_rwlock;

View File

@@ -1836,25 +1836,8 @@ struct __wt_connection {
* configuration options defined below.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;archive, automatically archive
* unneeded log files., a boolean flag; default \c true.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;compressor, configure a compressor
* for log records. Permitted values are \c "none" or custom
* compression engine name created with WT_CONNECTION::add_compressor.
* If WiredTiger has builtin support for \c "snappy"\, \c "lz4" or \c
* "zlib" compression\, these names are also available. See @ref
* compression for more information., a string; default \c none.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;enabled, enable logging subsystem., a
* boolean flag; default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;file_max, the maximum size of log
* files., an integer between 100KB and 2GB; default \c 100MB.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;path, the path to a directory into
* which the log files are written. If the value is not an absolute
* path name\, the files are created relative to the database home., a
* string; default \c ".".}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;prealloc,
* pre-allocate log files., a boolean flag; default \c true.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;recover, run recovery or error if
* recovery needs to run after an unclean shutdown., a string\, chosen
* from the following options: \c "error"\, \c "on"; default \c on.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;prealloc, pre-allocate log files., a
* boolean flag; default \c true.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;zero_fill, manually write zeroes into
* log files., a boolean flag; default \c false.}
* @config{ ),,}
@@ -1914,11 +1897,6 @@ struct __wt_connection {
* statistics in JSON format., a boolean flag; default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;on_close, log statistics on database
* close., a boolean flag; default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;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{&nbsp;&nbsp;&nbsp;&nbsp;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
@@ -2343,9 +2321,10 @@ struct __wt_connection {
* subsystem., a boolean flag; default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;file_max, the maximum size of log files., an
* integer between 100KB and 2GB; default \c 100MB.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;path, the path to a directory into which the
* log files are written. If the value is not an absolute path name\, the files
* are created relative to the database home., a string; default \c ".".}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;path, the name of a directory into which log
* files are written. The directory must already exist. If the value is not an
* absolute path\, the path is relative to the database home (see @ref
* absolute_path for more information)., a string; default \c ".".}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;prealloc, pre-allocate log files., a boolean
* flag; default \c true.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;recover, run recovery
@@ -2415,16 +2394,15 @@ struct __wt_connection {
* boolean flag; default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;on_close,
* log statistics on database close., a boolean flag; default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;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{&nbsp;&nbsp;&nbsp;&nbsp;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{&nbsp;&nbsp;&nbsp;&nbsp;path, the name of a directory into which
* statistics files are written. The directory must already exist. If the
* value is not an absolute path\, the path is relative to the database home
* (see @ref absolute_path for more information)., a string; default \c ".".}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;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{&nbsp;&nbsp;&nbsp;&nbsp;timestamp, a timestamp prepended to each log
* record\, may contain strftime conversion specifications\, when \c json is
* configured\, defaults to \c "%FT%Y.000Z"., a string; default \c "%b %d
@@ -3701,24 +3679,34 @@ struct __wt_extractor {
#if !defined(SWIG)
/*! WT_FILE_SYSTEM::open_file file types */
typedef enum {
WT_OPEN_FILE_TYPE_CHECKPOINT, /*!< open a data file checkpoint */
WT_OPEN_FILE_TYPE_DATA, /*!< open a data file */
WT_OPEN_FILE_TYPE_DIRECTORY, /*!< open a directory */
WT_OPEN_FILE_TYPE_LOG, /*!< open a log file */
WT_OPEN_FILE_TYPE_REGULAR /*!< open a regular file */
} WT_OPEN_FILE_TYPE;
WT_FS_OPEN_FILE_TYPE_CHECKPOINT,/*!< open a data file checkpoint */
WT_FS_OPEN_FILE_TYPE_DATA, /*!< open a data file */
WT_FS_OPEN_FILE_TYPE_DIRECTORY, /*!< open a directory */
WT_FS_OPEN_FILE_TYPE_LOG, /*!< open a log file */
WT_FS_OPEN_FILE_TYPE_REGULAR /*!< open a regular file */
} WT_FS_OPEN_FILE_TYPE;
/*! WT_FILE_SYSTEM::open_file flags: create if does not exist */
#define WT_OPEN_CREATE 0x001
#define WT_FS_OPEN_CREATE 0x001
/*! WT_FILE_SYSTEM::open_file flags: direct I/O requested */
#define WT_OPEN_DIRECTIO 0x002
/*! WT_FILE_SYSTEM::open_file flags: error if exclusive use not available */
#define WT_OPEN_EXCLUSIVE 0x004
#define WT_FS_OPEN_DIRECTIO 0x002
/*! WT_FILE_SYSTEM::open_file flags: file creation must be durable */
#define WT_FS_OPEN_DURABLE 0x004
/*!
* WT_FILE_SYSTEM::open_file flags: return EBUSY if exclusive use not available
*/
#define WT_FS_OPEN_EXCLUSIVE 0x008
#ifndef DOXYGEN
#define WT_OPEN_FIXED 0x008 /* Path not home relative (internal) */
#define WT_FS_OPEN_FIXED 0x010 /* Path not home relative (internal) */
#endif
/*! WT_FILE_SYSTEM::open_file flags: open is read-only */
#define WT_OPEN_READONLY 0x010
#define WT_FS_OPEN_READONLY 0x020
/*!
* WT_FILE_SYSTEM::remove or WT_FILE_SYSTEM::rename flags: the remove or rename
* operation must be durable
*/
#define WT_FS_DURABLE 0x001
/*!
* The interface implemented by applications to provide a custom file system
@@ -3767,23 +3755,6 @@ struct __wt_file_system {
int (*fs_directory_list_free)(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, char **dirlist, uint32_t count);
/*!
* Flush the named directory.
*
* This method is not required for readonly file systems or file systems
* where it is not necessary to flush a file's directory to ensure the
* durability of file system operations, and should be set to NULL when
* not required by the file system.
*
* @errors
*
* @param file_system the WT_FILE_SYSTEM
* @param session the current WiredTiger session
* @param directory the name of the directory
*/
int (*fs_directory_sync)(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *directory);
/*!
* Return if the named file system object exists.
*
@@ -3800,6 +3771,16 @@ struct __wt_file_system {
/*!
* Open a handle for a named file system object
*
* The method should return ENOENT if the file is not being created and
* does not exist.
*
* The method should return EACCES if the file cannot be opened in the
* requested mode (for example, a file opened for writing in a readonly
* file system).
*
* The method should return EBUSY if ::WT_FS_OPEN_EXCLUSIVE is set and
* the file is in use.
*
* @errors
*
* @param file_system the WT_FILE_SYSTEM
@@ -3809,8 +3790,8 @@ struct __wt_file_system {
* The file type is provided to allow optimization for different file
* access patterns.
* @param flags flags indicating how to open the file, one or more of
* ::WT_OPEN_CREATE, ::WT_OPEN_DIRECTIO, ::WT_OPEN_EXCLUSIVE or
* ::WT_OPEN_READONLY.
* ::WT_FS_OPEN_CREATE, ::WT_FS_OPEN_DIRECTIO, ::WT_FS_OPEN_DURABLE,
* ::WT_FS_OPEN_EXCLUSIVE or ::WT_FS_OPEN_READONLY.
* @param[out] file_handlep the handle to the newly opened file. File
* system implementations must allocate memory for the handle and
* the WT_FILE_HANDLE::name field, and fill in the WT_FILE_HANDLE::
@@ -3819,7 +3800,7 @@ struct __wt_file_system {
* their own structure as a superset of a WT_FILE_HANDLE:: structure.
*/
int (*fs_open_file)(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags,
const char *name, WT_FS_OPEN_FILE_TYPE file_type, uint32_t flags,
WT_FILE_HANDLE **file_handlep);
/*!
@@ -3833,9 +3814,11 @@ struct __wt_file_system {
* @param file_system the WT_FILE_SYSTEM
* @param session the current WiredTiger session
* @param name the name of the file system object
* @param durable if the operation requires durability
* @param flags 0 or ::WT_FS_DURABLE
*/
int (*fs_remove)(
WT_FILE_SYSTEM *file_system, WT_SESSION *session, const char *name);
int (*fs_remove)(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *name, uint32_t flags);
/*!
* Rename a named file system object
@@ -3849,9 +3832,10 @@ struct __wt_file_system {
* @param session the current WiredTiger session
* @param from the original name of the object
* @param to the new name for the object
* @param flags 0 or ::WT_FS_DURABLE
*/
int (*fs_rename)(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *from, const char *to);
int (*fs_rename)(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
const char *from, const char *to, uint32_t flags);
/*!
* Return the size of a named file system object

View File

@@ -683,7 +683,7 @@ __log_openfile(WT_SESSION_IMPL *session,
WT_LOG_DESC *desc;
WT_LOG_RECORD *logrec;
uint32_t allocsize;
u_int flags;
u_int wtopen_flags;
conn = S2C(session);
log = conn->log;
@@ -695,13 +695,13 @@ __log_openfile(WT_SESSION_IMPL *session,
WT_ERR(__log_filename(session, id, file_prefix, buf));
WT_ERR(__wt_verbose(session, WT_VERB_LOG,
"opening log %s", (const char *)buf->data));
flags = 0;
wtopen_flags = 0;
if (ok_create)
LF_SET(WT_OPEN_CREATE);
FLD_SET(wtopen_flags, WT_FS_OPEN_CREATE);
if (FLD_ISSET(conn->direct_io, WT_DIRECT_IO_LOG))
LF_SET(WT_OPEN_DIRECTIO);
FLD_SET(wtopen_flags, WT_FS_OPEN_DIRECTIO);
WT_ERR(__wt_open(
session, buf->data, WT_OPEN_FILE_TYPE_LOG, flags, fhp));
session, buf->data, WT_FS_OPEN_FILE_TYPE_LOG, wtopen_flags, fhp));
/*
* If we are not creating the log file but opening it for reading,
@@ -773,7 +773,7 @@ __log_alloc_prealloc(WT_SESSION_IMPL *session, uint32_t to_num)
* All file setup, writing the header and pre-allocation was done
* before. We only need to rename it.
*/
WT_ERR(__wt_fs_rename(session, from_path->data, to_path->data));
WT_ERR(__wt_fs_rename(session, from_path->data, to_path->data, false));
err: __wt_scr_free(session, &from_path);
__wt_scr_free(session, &to_path);
@@ -1058,7 +1058,7 @@ __wt_log_allocfile(
/*
* Rename it into place and make it available.
*/
WT_ERR(__wt_fs_rename(session, from_path->data, to_path->data));
WT_ERR(__wt_fs_rename(session, from_path->data, to_path->data, false));
err: __wt_scr_free(session, &from_path);
__wt_scr_free(session, &to_path);
@@ -1081,7 +1081,7 @@ __wt_log_remove(WT_SESSION_IMPL *session,
WT_ERR(__log_filename(session, lognum, file_prefix, path));
WT_ERR(__wt_verbose(session, WT_VERB_LOG,
"log_remove: remove log %s", (char *)path->data));
WT_ERR(__wt_fs_remove(session, path->data));
WT_ERR(__wt_fs_remove(session, path->data, false));
err: __wt_scr_free(session, &path);
return (ret);
}
@@ -1117,7 +1117,7 @@ __wt_log_open(WT_SESSION_IMPL *session)
WT_RET(__wt_verbose(session, WT_VERB_LOG,
"log_open: open fh to directory %s", conn->log_path));
WT_RET(__wt_open(session, conn->log_path,
WT_OPEN_FILE_TYPE_DIRECTORY, 0, &log->log_dir_fh));
WT_FS_OPEN_FILE_TYPE_DIRECTORY, 0, &log->log_dir_fh));
}
if (!F_ISSET(conn, WT_CONN_READONLY)) {

View File

@@ -219,13 +219,20 @@ __clsm_enter(WT_CURSOR_LSM *clsm, bool reset, bool update)
* transaction ID in each chunk: any transaction ID
* that overlaps with our snapshot is a potential
* conflict.
*
* Note that the global snap_min is correct here: it
* tracks concurrent transactions excluding special
* transactions such as checkpoint (which we can't
* conflict with because checkpoint only writes the
* metadata, which is not an LSM tree).
*/
clsm->nupdates = 1;
if (txn->isolation == WT_ISO_SNAPSHOT &&
F_ISSET(clsm, WT_CLSM_OPEN_SNAPSHOT)) {
WT_ASSERT(session,
F_ISSET(txn, WT_TXN_HAS_SNAPSHOT));
snap_min = txn->snap_min;
snap_min =
WT_SESSION_TXN_STATE(session)->snap_min;
for (switch_txnp =
&clsm->switch_txn[clsm->nchunks - 2];
clsm->nupdates < clsm->nchunks;

View File

@@ -526,7 +526,7 @@ __lsm_drop_file(WT_SESSION_IMPL *session, const char *uri)
ret = __wt_schema_drop(session, uri, drop_cfg));
if (ret == 0)
ret = __wt_fs_remove(session, uri + strlen("file:"));
ret = __wt_fs_remove(session, uri + strlen("file:"), false);
WT_RET(__wt_verbose(session, WT_VERB_LSM, "Dropped %s", uri));
if (ret == EBUSY || ret == ENOENT)

View File

@@ -141,7 +141,8 @@ __meta_track_apply(WT_SESSION_IMPL *session, WT_META_TRACK *trk)
ret = bm->checkpoint_resolve(bm, session));
break;
case WT_ST_DROP_COMMIT:
if ((ret = __wt_block_manager_drop(session, trk->a)) != 0)
if ((ret =
__wt_block_manager_drop(session, trk->a, false)) != 0)
__wt_err(session, ret,
"metadata remove dropped file %s", trk->a);
break;
@@ -188,13 +189,15 @@ __meta_track_unroll(WT_SESSION_IMPL *session, WT_META_TRACK *trk)
* For removes, b is NULL.
*/
if (trk->a != NULL && trk->b != NULL &&
(ret = __wt_rename_and_sync_directory(session,
trk->b + strlen("file:"), trk->a + strlen("file:"))) != 0)
(ret = __wt_fs_rename(session,
trk->b + strlen("file:"), trk->a + strlen("file:"),
true)) != 0)
__wt_err(session, ret,
"metadata unroll rename %s to %s", trk->b, trk->a);
if (trk->a == NULL && (ret =
__wt_fs_remove(session, trk->b + strlen("file:"))) != 0)
if (trk->a == NULL &&
(ret = __wt_fs_remove(session,
trk->b + strlen("file:"), false)) != 0)
__wt_err(session, ret,
"metadata unroll create %s", trk->b);

View File

@@ -158,7 +158,7 @@ __wt_turtle_init(WT_SESSION_IMPL *session)
* Discard any turtle setup file left-over from previous runs. This
* doesn't matter for correctness, it's just cleaning up random files.
*/
WT_RET(__wt_remove_if_exists(session, WT_METADATA_TURTLE_SET));
WT_RET(__wt_remove_if_exists(session, WT_METADATA_TURTLE_SET, false));
/*
* We could die after creating the turtle file and before creating the
@@ -197,9 +197,10 @@ __wt_turtle_init(WT_SESSION_IMPL *session)
"Both %s and %s exist; recreating metadata from "
"backup",
WT_METADATA_TURTLE, WT_METADATA_BACKUP));
WT_RET(__wt_remove_if_exists(session, WT_METAFILE));
WT_RET(
__wt_remove_if_exists(session, WT_METAFILE, false));
WT_RET(__wt_remove_if_exists(
session, WT_METADATA_TURTLE));
session, WT_METADATA_TURTLE, false));
load = true;
}
} else
@@ -305,7 +306,7 @@ __wt_turtle_update(WT_SESSION_IMPL *session, const char *key, const char *value)
* every time.
*/
WT_RET(__wt_fopen(session, WT_METADATA_TURTLE_SET,
WT_OPEN_CREATE | WT_OPEN_EXCLUSIVE, WT_STREAM_WRITE, &fs));
WT_FS_OPEN_CREATE | WT_FS_OPEN_EXCLUSIVE, WT_STREAM_WRITE, &fs));
version = wiredtiger_version(&vmajor, &vminor, &vpatch);
WT_ERR(__wt_fprintf(session, fs,
@@ -320,7 +321,7 @@ __wt_turtle_update(WT_SESSION_IMPL *session, const char *key, const char *value)
/* Close any file handle left open, remove any temporary file. */
err: WT_TRET(__wt_fclose(session, &fs));
WT_TRET(__wt_remove_if_exists(session, WT_METADATA_TURTLE_SET));
WT_TRET(__wt_remove_if_exists(session, WT_METADATA_TURTLE_SET, false));
return (ret);
}

View File

@@ -56,54 +56,16 @@ __wt_nfilename(
* Remove a file if it exists.
*/
int
__wt_remove_if_exists(WT_SESSION_IMPL *session, const char *name)
__wt_remove_if_exists(WT_SESSION_IMPL *session, const char *name, bool durable)
{
bool exist;
WT_RET(__wt_fs_exist(session, name, &exist));
if (exist)
WT_RET(__wt_fs_remove(session, name));
WT_RET(__wt_fs_remove(session, name, durable));
return (0);
}
/*
* __wt_rename_and_sync_directory --
* Rename a file and sync the enclosing directory.
*/
int
__wt_rename_and_sync_directory(
WT_SESSION_IMPL *session, const char *from, const char *to)
{
const char *fp, *tp;
bool same_directory;
/* Rename the source file to the target. */
WT_RET(__wt_fs_rename(session, from, to));
/*
* Flush the backing directory to guarantee the rename. My reading of
* POSIX 1003.1 is there's no guarantee flushing only one of the from
* or to directories, or flushing a common parent, is sufficient, and
* even if POSIX were to make that guarantee, existing filesystems are
* known to not provide the guarantee or only provide the guarantee
* with specific mount options. Flush both of the from/to directories
* until it's a performance problem.
*/
WT_RET(__wt_fs_directory_sync(session, from));
/*
* In almost all cases, we're going to be renaming files in the same
* directory, we can at least fast-path that.
*/
fp = strrchr(from, '/');
tp = strrchr(to, '/');
same_directory = (fp == NULL && tp == NULL) ||
(fp != NULL && tp != NULL &&
fp - from == tp - to && memcmp(from, to, (size_t)(fp - from)) == 0);
return (same_directory ? 0 : __wt_fs_directory_sync(session, to));
}
/*
* __wt_copy_and_sync --
* Copy a file safely; here to support the wt utility.
@@ -134,13 +96,13 @@ __wt_copy_and_sync(WT_SESSION *wt_session, const char *from, const char *to)
WT_ERR(__wt_scr_alloc(session, 0, &tmp));
WT_ERR(__wt_buf_fmt(session, tmp, "%s.copy", to));
WT_ERR(__wt_remove_if_exists(session, to));
WT_ERR(__wt_remove_if_exists(session, tmp->data));
WT_ERR(__wt_remove_if_exists(session, to, false));
WT_ERR(__wt_remove_if_exists(session, tmp->data, false));
/* Open the from and temporary file handles. */
WT_ERR(__wt_open(session, from, WT_OPEN_FILE_TYPE_REGULAR, 0, &ffh));
WT_ERR(__wt_open(session, tmp->data, WT_OPEN_FILE_TYPE_REGULAR,
WT_OPEN_CREATE | WT_OPEN_EXCLUSIVE, &tfh));
WT_ERR(__wt_open(session, from, WT_FS_OPEN_FILE_TYPE_REGULAR, 0, &ffh));
WT_ERR(__wt_open(session, tmp->data, WT_FS_OPEN_FILE_TYPE_REGULAR,
WT_FS_OPEN_CREATE | WT_FS_OPEN_EXCLUSIVE, &tfh));
/*
* Allocate a copy buffer. Don't use a scratch buffer, this thing is
@@ -162,7 +124,7 @@ __wt_copy_and_sync(WT_SESSION *wt_session, const char *from, const char *to)
WT_ERR(__wt_fsync(session, tfh, true));
WT_ERR(__wt_close(session, &tfh));
ret = __wt_rename_and_sync_directory(session, tmp->data, to);
ret = __wt_fs_rename(session, tmp->data, to, true);
err: WT_TRET(__wt_close(session, &ffh));
WT_TRET(__wt_close(session, &tfh));

View File

@@ -150,19 +150,19 @@ __open_verbose(
*/
switch (file_type) {
case WT_OPEN_FILE_TYPE_CHECKPOINT:
case WT_FS_OPEN_FILE_TYPE_CHECKPOINT:
file_type_tag = "checkpoint";
break;
case WT_OPEN_FILE_TYPE_DATA:
case WT_FS_OPEN_FILE_TYPE_DATA:
file_type_tag = "data";
break;
case WT_OPEN_FILE_TYPE_DIRECTORY:
case WT_FS_OPEN_FILE_TYPE_DIRECTORY:
file_type_tag = "directory";
break;
case WT_OPEN_FILE_TYPE_LOG:
case WT_FS_OPEN_FILE_TYPE_LOG:
file_type_tag = "log";
break;
case WT_OPEN_FILE_TYPE_REGULAR:
case WT_FS_OPEN_FILE_TYPE_REGULAR:
file_type_tag = "regular";
break;
default:
@@ -172,18 +172,18 @@ __open_verbose(
WT_RET(__wt_scr_alloc(session, 0, &tmp));
sep = " (";
#define WT_OPEN_VERBOSE_FLAG(f, name) \
#define WT_FS_OPEN_VERBOSE_FLAG(f, name) \
if (LF_ISSET(f)) { \
WT_ERR(__wt_buf_catfmt( \
session, tmp, "%s%s", sep, name)); \
sep = ", "; \
}
WT_OPEN_VERBOSE_FLAG(WT_OPEN_CREATE, "create");
WT_OPEN_VERBOSE_FLAG(WT_OPEN_DIRECTIO, "direct-IO");
WT_OPEN_VERBOSE_FLAG(WT_OPEN_EXCLUSIVE, "exclusive");
WT_OPEN_VERBOSE_FLAG(WT_OPEN_FIXED, "fixed");
WT_OPEN_VERBOSE_FLAG(WT_OPEN_READONLY, "readonly");
WT_FS_OPEN_VERBOSE_FLAG(WT_FS_OPEN_CREATE, "create");
WT_FS_OPEN_VERBOSE_FLAG(WT_FS_OPEN_DIRECTIO, "direct-IO");
WT_FS_OPEN_VERBOSE_FLAG(WT_FS_OPEN_EXCLUSIVE, "exclusive");
WT_FS_OPEN_VERBOSE_FLAG(WT_FS_OPEN_FIXED, "fixed");
WT_FS_OPEN_VERBOSE_FLAG(WT_FS_OPEN_READONLY, "readonly");
if (tmp->size != 0)
WT_ERR(__wt_buf_catfmt(session, tmp, ")"));
@@ -209,7 +209,7 @@ err: __wt_scr_free(session, &tmp);
*/
int
__wt_open(WT_SESSION_IMPL *session,
const char *name, WT_OPEN_FILE_TYPE file_type, u_int flags, WT_FH **fhp)
const char *name, WT_FS_OPEN_FILE_TYPE file_type, u_int flags, WT_FH **fhp)
{
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
@@ -247,12 +247,12 @@ __wt_open(WT_SESSION_IMPL *session,
if (F_ISSET(conn, WT_CONN_READONLY)) {
lock_file = strcmp(name, WT_SINGLETHREAD) == 0;
if (!lock_file)
LF_SET(WT_OPEN_READONLY);
WT_ASSERT(session, lock_file || !LF_ISSET(WT_OPEN_CREATE));
LF_SET(WT_FS_OPEN_READONLY);
WT_ASSERT(session, lock_file || !LF_ISSET(WT_FS_OPEN_CREATE));
}
/* Create the path to the file. */
if (!LF_ISSET(WT_OPEN_FIXED))
if (!LF_ISSET(WT_FS_OPEN_FIXED))
WT_ERR(__wt_filename(session, name, &path));
/* Call the underlying open function. */
@@ -261,7 +261,7 @@ __wt_open(WT_SESSION_IMPL *session,
open_called = true;
WT_ERR(__fhandle_method_finalize(
session, fh->handle, LF_ISSET(WT_OPEN_READONLY)));
session, fh->handle, LF_ISSET(WT_FS_OPEN_READONLY)));
/*
* Repeat the check for a match: if there's no match, link our newly

View File

@@ -188,14 +188,16 @@ __im_fs_exist(WT_FILE_SYSTEM *file_system,
* POSIX remove.
*/
static int
__im_fs_remove(
WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name)
__im_fs_remove(WT_FILE_SYSTEM *file_system,
WT_SESSION *wt_session, const char *name, uint32_t flags)
{
WT_DECL_RET;
WT_FILE_HANDLE_INMEM *im_fh;
WT_FILE_SYSTEM_INMEM *im_fs;
WT_SESSION_IMPL *session;
WT_UNUSED(flags);
im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
session = (WT_SESSION_IMPL *)wt_session;
@@ -215,7 +217,7 @@ __im_fs_remove(
*/
static int
__im_fs_rename(WT_FILE_SYSTEM *file_system,
WT_SESSION *wt_session, const char *from, const char *to)
WT_SESSION *wt_session, const char *from, const char *to, uint32_t flags)
{
WT_DECL_RET;
WT_FILE_HANDLE_INMEM *im_fh;
@@ -224,6 +226,8 @@ __im_fs_rename(WT_FILE_SYSTEM *file_system,
uint64_t bucket;
char *copy;
WT_UNUSED(flags);
im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
session = (WT_SESSION_IMPL *)wt_session;
@@ -463,7 +467,7 @@ err: __wt_spin_unlock(session, &im_fs->lock);
*/
static int
__im_file_open(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags,
const char *name, WT_FS_OPEN_FILE_TYPE file_type, uint32_t flags,
WT_FILE_HANDLE **file_handlep)
{
WT_DECL_RET;

View File

@@ -187,7 +187,7 @@ __wt_fopen(WT_SESSION_IMPL *session,
fstr = NULL;
WT_RET(__wt_open(
session, name, WT_OPEN_FILE_TYPE_REGULAR, open_flags, &fh));
session, name, WT_FS_OPEN_FILE_TYPE_REGULAR, open_flags, &fh));
WT_ERR(__wt_calloc_one(session, &fstr));
fstr->fh = fh;

View File

@@ -30,7 +30,7 @@
/*
* __posix_sync --
* Underlying support function to flush a file handle.
* Underlying support function to flush a file descriptor.
*/
static int
__posix_sync(
@@ -77,33 +77,42 @@ __posix_sync(
#ifdef __linux__
/*
* __posix_directory_sync --
* Flush a directory to ensure file creation is durable.
* Flush a directory to ensure file creation, remove or rename is durable.
*/
static int
__posix_directory_sync(
WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *path)
__posix_directory_sync(WT_SESSION_IMPL *session, const char *path)
{
WT_DECL_ITEM(tmp);
WT_DECL_RET;
WT_SESSION_IMPL *session;
int fd, tret;
char *dir;
WT_UNUSED(file_system);
WT_RET(__wt_scr_alloc(session, 0, &tmp));
WT_ERR(__wt_buf_setstr(session, tmp, path));
session = (WT_SESSION_IMPL *)wt_session;
/*
* This layer should never see a path that doesn't include a trailing
* path separator, this code asserts that fact.
*/
dir = tmp->mem;
strrchr(dir, '/')[1] = '\0';
fd = -1; /* -Wconditional-uninitialized */
WT_SYSCALL_RETRY((
(fd = open(path, O_RDONLY, 0444)) == -1 ? -1 : 0), ret);
(fd = open(dir, O_RDONLY, 0444)) == -1 ? -1 : 0), ret);
if (ret != 0)
WT_RET_MSG(session, ret, "%s: directory-sync: open", path);
WT_ERR_MSG(session, ret, "%s: directory-sync: open", dir);
ret = __posix_sync(session, fd, path, "directory-sync");
ret = __posix_sync(session, fd, dir, "directory-sync");
WT_SYSCALL(close(fd), tret);
if (tret != 0) {
__wt_err(session, tret, "%s: directory-sync: close", path);
__wt_err(session, tret, "%s: directory-sync: close", dir);
if (ret == 0)
ret = tret;
}
err: __wt_scr_free(session, &tmp);
return (ret);
}
#endif
@@ -141,8 +150,8 @@ __posix_fs_exist(WT_FILE_SYSTEM *file_system,
* Remove a file.
*/
static int
__posix_fs_remove(
WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name)
__posix_fs_remove(WT_FILE_SYSTEM *file_system,
WT_SESSION *wt_session, const char *name, uint32_t flags)
{
WT_DECL_RET;
WT_SESSION_IMPL *session;
@@ -159,9 +168,17 @@ __posix_fs_remove(
* using unlink may be marginally safer.
*/
WT_SYSCALL(unlink(name), ret);
if (ret == 0)
if (ret != 0)
WT_RET_MSG(session, ret, "%s: file-remove: unlink", name);
if (!LF_ISSET(WT_FS_DURABLE))
return (0);
WT_RET_MSG(session, ret, "%s: file-remove: unlink", name);
#ifdef __linux__
/* Flush the backing directory to guarantee the remove. */
WT_RET (__posix_directory_sync(session, name));
#endif
return (0);
}
/*
@@ -170,7 +187,7 @@ __posix_fs_remove(
*/
static int
__posix_fs_rename(WT_FILE_SYSTEM *file_system,
WT_SESSION *wt_session, const char *from, const char *to)
WT_SESSION *wt_session, const char *from, const char *to, uint32_t flags)
{
WT_DECL_RET;
WT_SESSION_IMPL *session;
@@ -187,9 +204,43 @@ __posix_fs_rename(WT_FILE_SYSTEM *file_system,
* return (if errno is 0), but we've done the best we can.
*/
WT_SYSCALL(rename(from, to) != 0 ? -1 : 0, ret);
if (ret == 0)
if (ret != 0)
WT_RET_MSG(
session, ret, "%s to %s: file-rename: rename", from, to);
if (!LF_ISSET(WT_FS_DURABLE))
return (0);
WT_RET_MSG(session, ret, "%s to %s: file-rename: rename", from, to);
#ifdef __linux__
/*
* Flush the backing directory to guarantee the rename. My reading of
* POSIX 1003.1 is there's no guarantee flushing only one of the from
* or to directories, or flushing a common parent, is sufficient, and
* even if POSIX were to make that guarantee, existing filesystems are
* known to not provide the guarantee or only provide the guarantee
* with specific mount options. Flush both of the from/to directories
* until it's a performance problem.
*/
WT_RET(__posix_directory_sync(session, from));
/*
* In almost all cases, we're going to be renaming files in the same
* directory, we can at least fast-path that.
*/
{
bool same_directory;
const char *fp, *tp;
fp = strrchr(from, '/');
tp = strrchr(to, '/');
same_directory = (fp == NULL && tp == NULL) ||
(fp != NULL && tp != NULL &&
fp - from == tp - to && memcmp(from, to, (size_t)(fp - from)) == 0);
if (!same_directory)
WT_RET(__posix_directory_sync(session, to));
}
#endif
return (0);
}
/*
@@ -513,7 +564,7 @@ __posix_open_file_cloexec(WT_SESSION_IMPL *session, int fd, const char *name)
*/
static int
__posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags,
const char *name, WT_FS_OPEN_FILE_TYPE file_type, uint32_t flags,
WT_FILE_HANDLE **file_handlep)
{
WT_CONNECTION_IMPL *conn;
@@ -536,7 +587,7 @@ __posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
/* Set up error handling. */
pfh->fd = -1;
if (file_type == WT_OPEN_FILE_TYPE_DIRECTORY) {
if (file_type == WT_FS_OPEN_FILE_TYPE_DIRECTORY) {
f = O_RDONLY;
#ifdef O_CLOEXEC
/*
@@ -554,10 +605,10 @@ __posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
goto directory_open;
}
f = LF_ISSET(WT_OPEN_READONLY) ? O_RDONLY : O_RDWR;
if (LF_ISSET(WT_OPEN_CREATE)) {
f = LF_ISSET(WT_FS_OPEN_READONLY) ? O_RDONLY : O_RDWR;
if (LF_ISSET(WT_FS_OPEN_CREATE)) {
f |= O_CREAT;
if (LF_ISSET(WT_OPEN_EXCLUSIVE))
if (LF_ISSET(WT_FS_OPEN_EXCLUSIVE))
f |= O_EXCL;
mode = 0666;
} else
@@ -577,7 +628,7 @@ __posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
#endif
#ifdef O_DIRECT
/* Direct I/O. */
if (LF_ISSET(WT_OPEN_DIRECTIO)) {
if (LF_ISSET(WT_FS_OPEN_DIRECTIO)) {
f |= O_DIRECT;
pfh->direct_io = true;
} else
@@ -585,11 +636,11 @@ __posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
#endif
#ifdef O_NOATIME
/* Avoid updating metadata for read-only workloads. */
if (file_type == WT_OPEN_FILE_TYPE_DATA)
if (file_type == WT_FS_OPEN_FILE_TYPE_DATA)
f |= O_NOATIME;
#endif
if (file_type == WT_OPEN_FILE_TYPE_LOG &&
if (file_type == WT_FS_OPEN_FILE_TYPE_LOG &&
FLD_ISSET(conn->txn_logsync, WT_LOG_DSYNC)) {
#ifdef O_DSYNC
f |= O_DSYNC;
@@ -601,6 +652,7 @@ __posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
#endif
}
/* Create/Open the file. */
WT_SYSCALL_RETRY(((pfh->fd = open(name, f, mode)) == -1 ? -1 : 0), ret);
if (ret != 0)
WT_ERR_MSG(session, ret,
@@ -608,6 +660,16 @@ __posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
"%s: handle-open: open: failed with direct I/O configured, "
"some filesystem types do not support direct I/O" :
"%s: handle-open: open", name);
#ifdef __linux__
/*
* Durability: some filesystems require a directory sync to be confident
* the file will appear.
*/
if (LF_ISSET(WT_FS_OPEN_DURABLE))
WT_ERR(__posix_directory_sync(session, name));
#endif
WT_ERR(__posix_open_file_cloexec(session, pfh->fd, name));
#if defined(HAVE_POSIX_FADVISE)
@@ -616,7 +678,7 @@ __posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
* Ignore fadvise when doing direct I/O, the kernel cache isn't
* interesting.
*/
if (!pfh->direct_io && file_type == WT_OPEN_FILE_TYPE_DATA) {
if (!pfh->direct_io && file_type == WT_FS_OPEN_FILE_TYPE_DATA) {
WT_SYSCALL(
posix_fadvise(pfh->fd, 0, 0, POSIX_FADV_RANDOM), ret);
if (ret != 0)
@@ -705,9 +767,6 @@ __wt_os_posix(WT_SESSION_IMPL *session)
/* Initialize the POSIX jump table. */
file_system->fs_directory_list = __wt_posix_directory_list;
file_system->fs_directory_list_free = __wt_posix_directory_list_free;
#ifdef __linux__
file_system->fs_directory_sync = __posix_directory_sync;
#endif
file_system->fs_exist = __posix_fs_exist;
file_system->fs_open_file = __posix_open_file;
file_system->fs_remove = __posix_fs_remove;

View File

@@ -36,13 +36,14 @@ __win_fs_exist(WT_FILE_SYSTEM *file_system,
* Remove a file.
*/
static int
__win_fs_remove(
WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name)
__win_fs_remove(WT_FILE_SYSTEM *file_system,
WT_SESSION *wt_session, const char *name, uint32_t flags)
{
DWORD windows_error;
WT_SESSION_IMPL *session;
WT_UNUSED(file_system);
WT_UNUSED(flags);
session = (WT_SESSION_IMPL *)wt_session;
@@ -62,12 +63,13 @@ __win_fs_remove(
*/
static int
__win_fs_rename(WT_FILE_SYSTEM *file_system,
WT_SESSION *wt_session, const char *from, const char *to)
WT_SESSION *wt_session, const char *from, const char *to, uint32_t flags)
{
DWORD windows_error;
WT_SESSION_IMPL *session;
WT_UNUSED(file_system);
WT_UNUSED(flags);
session = (WT_SESSION_IMPL *)wt_session;
@@ -426,7 +428,7 @@ __win_file_write(WT_FILE_HANDLE *file_handle,
*/
static int
__win_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags,
const char *name, WT_FS_OPEN_FILE_TYPE file_type, uint32_t flags,
WT_FILE_HANDLE **file_handlep)
{
DWORD dwCreationDisposition, windows_error;
@@ -458,11 +460,11 @@ __win_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
* require that functionality: create an empty WT_FH structure with
* invalid handles.
*/
if (file_type == WT_OPEN_FILE_TYPE_DIRECTORY)
if (file_type == WT_FS_OPEN_FILE_TYPE_DIRECTORY)
goto directory_open;
desired_access = GENERIC_READ;
if (!LF_ISSET(WT_OPEN_READONLY))
if (!LF_ISSET(WT_FS_OPEN_READONLY))
desired_access |= GENERIC_WRITE;
/*
@@ -476,15 +478,15 @@ __win_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
f = FILE_ATTRIBUTE_NORMAL;
dwCreationDisposition = 0;
if (LF_ISSET(WT_OPEN_CREATE)) {
if (LF_ISSET(WT_FS_OPEN_CREATE)) {
dwCreationDisposition = CREATE_NEW;
if (LF_ISSET(WT_OPEN_EXCLUSIVE))
if (LF_ISSET(WT_FS_OPEN_EXCLUSIVE))
dwCreationDisposition = CREATE_ALWAYS;
} else
dwCreationDisposition = OPEN_EXISTING;
/* Direct I/O. */
if (LF_ISSET(WT_OPEN_DIRECTIO)) {
if (LF_ISSET(WT_FS_OPEN_DIRECTIO)) {
f |= FILE_FLAG_NO_BUFFERING;
win_fh->direct_io = true;
}
@@ -493,19 +495,19 @@ __win_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
if (FLD_ISSET(conn->write_through, file_type))
f |= FILE_FLAG_WRITE_THROUGH;
if (file_type == WT_OPEN_FILE_TYPE_LOG &&
if (file_type == WT_FS_OPEN_FILE_TYPE_LOG &&
FLD_ISSET(conn->txn_logsync, WT_LOG_DSYNC))
f |= FILE_FLAG_WRITE_THROUGH;
/* Disable read-ahead on trees: it slows down random read workloads. */
if (file_type == WT_OPEN_FILE_TYPE_DATA)
if (file_type == WT_FS_OPEN_FILE_TYPE_DATA)
f |= FILE_FLAG_RANDOM_ACCESS;
win_fh->filehandle = CreateFileA(name, desired_access,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, dwCreationDisposition, f, NULL);
if (win_fh->filehandle == INVALID_HANDLE_VALUE) {
if (LF_ISSET(WT_OPEN_CREATE) &&
if (LF_ISSET(WT_FS_OPEN_CREATE) &&
GetLastError() == ERROR_FILE_EXISTS)
win_fh->filehandle = CreateFileA(name, desired_access,
FILE_SHARE_READ | FILE_SHARE_WRITE,
@@ -528,7 +530,7 @@ __win_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
* concurrently with reads on the file. Writes would also move the file
* pointer.
*/
if (!LF_ISSET(WT_OPEN_READONLY)) {
if (!LF_ISSET(WT_FS_OPEN_READONLY)) {
win_fh->filehandle_secondary = CreateFileA(name, desired_access,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, f, NULL);

View File

@@ -16,8 +16,30 @@ bool
__wt_absolute_path(const char *path)
{
/*
* Check for a drive name (for example, "D:"), allow both forward and
* backward slashes.
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247
*
* For Windows API functions that manipulate files, file names can often
* be relative to the current directory, while some APIs require a fully
* qualified path. A file name is relative to the current directory if
* it does not begin with one of the following:
*
* -- A UNC name of any format, which always start with two backslash
* characters ("\\").
* -- A disk designator with a backslash, for example "C:\" or "d:\".
* -- A single backslash, for example, "\directory" or "\file.txt". This
* is also referred to as an absolute path.
*
* If a file name begins with only a disk designator but not the
* backslash after the colon, it is interpreted as a relative path to
* the current directory on the drive with the specified letter. Note
* that the current directory may or may not be the root directory
* depending on what it was set to during the most recent "change
* directory" operation on that disk.
*
* -- "C:tmp.txt" refers to a file named "tmp.txt" in the current
* directory on drive C.
* -- "C:tempdir\tmp.txt" refers to a file in a subdirectory to the
* current directory on drive C.
*/
if (strlen(path) >= 3 && __wt_isalpha(path[0]) && path[1] == ':')
path += 2;

View File

@@ -1135,8 +1135,18 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r,
*/
if (!skipped &&
(F_ISSET(btree, WT_BTREE_LOOKASIDE) ||
__wt_txn_visible_all(session, max_txn)))
__wt_txn_visible_all(session, max_txn))) {
/*
* The checkpoint transaction is special. Make sure we never
* write (metadata) updates from a checkpoint in a concurrent
* session.
*/
WT_ASSERT(session, *updp == NULL ||
(txnid = (*updp)->txnid) == WT_TXN_NONE ||
txnid != S2C(session)->txn_global.checkpoint_txnid ||
WT_SESSION_IS_CHECKPOINT(session));
return (0);
}
/*
* In some cases, there had better not be skipped updates or updates not

View File

@@ -64,7 +64,7 @@ __rename_file(
WT_ERR(__wt_metadata_insert(session, newuri, oldvalue));
/* Rename the underlying file. */
WT_ERR(__wt_fs_rename(session, filename, newfile));
WT_ERR(__wt_fs_rename(session, filename, newfile, false));
if (WT_META_TRACKING(session))
WT_ERR(__wt_meta_track_fileop(session, uri, newuri));

View File

@@ -66,6 +66,11 @@ __wt_session_copy_values(WT_SESSION_IMPL *session)
TAILQ_FOREACH(cursor, &session->cursors, q)
if (F_ISSET(cursor, WT_CURSTD_VALUE_INT)) {
/* We have to do this with a transaction ID pinned. */
WT_ASSERT(session,
WT_SESSION_TXN_STATE(session)->snap_min !=
WT_TXN_NONE);
F_CLR(cursor, WT_CURSTD_VALUE_INT);
WT_RET(__wt_buf_set(session, &cursor->value,
cursor->value.data, cursor->value.size));

View File

@@ -124,6 +124,7 @@ __wt_txn_get_snapshot(WT_SESSION_IMPL *session)
txn = &session->txn;
txn_global = &conn->txn_global;
txn_state = WT_SESSION_TXN_STATE(session);
n = 0;
/*
* Spin waiting for the lock: the sleeps in our blocking readlock
@@ -137,20 +138,26 @@ __wt_txn_get_snapshot(WT_SESSION_IMPL *session)
current_id = snap_min = txn_global->current;
prev_oldest_id = txn_global->oldest_id;
/*
* Include the checkpoint transaction, if one is running: we should
* ignore any uncommitted changes the checkpoint has written to the
* metadata. We don't have to keep the checkpoint's changes pinned so
* don't including it in the published snap_min.
*/
if ((id = txn_global->checkpoint_txnid) != WT_TXN_NONE)
txn->snapshot[n++] = id;
/* For pure read-only workloads, avoid scanning. */
if (prev_oldest_id == current_id) {
txn_state->snap_min = current_id;
__txn_sort_snapshot(session, 0, current_id);
/* Check that the oldest ID has not moved in the meantime. */
WT_ASSERT(session, prev_oldest_id == txn_global->oldest_id);
WT_RET(__wt_readunlock(session, txn_global->scan_rwlock));
return (0);
goto done;
}
/* Walk the array of concurrent transactions. */
WT_ORDERED_READ(session_cnt, conn->session_cnt);
for (i = n = 0, s = txn_global->states; i < session_cnt; i++, s++) {
for (i = 0, s = txn_global->states; i < session_cnt; i++, s++) {
/*
* Build our snapshot of any concurrent transaction IDs.
*
@@ -178,8 +185,7 @@ __wt_txn_get_snapshot(WT_SESSION_IMPL *session)
WT_ASSERT(session, prev_oldest_id == txn_global->oldest_id);
txn_state->snap_min = snap_min;
WT_RET(__wt_readunlock(session, txn_global->scan_rwlock));
done: WT_RET(__wt_readunlock(session, txn_global->scan_rwlock));
__txn_sort_snapshot(session, n, current_id);
return (0);
}
@@ -433,18 +439,22 @@ __wt_txn_release(WT_SESSION_IMPL *session)
WT_TXN_STATE *txn_state;
txn = &session->txn;
WT_ASSERT(session, txn->mod_count == 0);
txn->notify = NULL;
txn_global = &S2C(session)->txn_global;
txn_state = WT_SESSION_TXN_STATE(session);
WT_ASSERT(session, txn->mod_count == 0);
txn->notify = NULL;
/* Clear the transaction's ID from the global table. */
if (WT_SESSION_IS_CHECKPOINT(session)) {
WT_ASSERT(session, txn_state->id == WT_TXN_NONE);
txn->id = WT_TXN_NONE;
txn->id = txn_global->checkpoint_txnid = WT_TXN_NONE;
/* Clear the global checkpoint transaction IDs. */
/*
* Be extra careful to cleanup everything for checkpoints: once
* the global checkpoint ID is cleared, we can no longer tell
* if this session is doing a checkpoint.
*/
txn_global->checkpoint_id = 0;
txn_global->checkpoint_pinned = WT_TXN_NONE;
} else if (F_ISSET(txn, WT_TXN_HAS_ID)) {
@@ -540,6 +550,16 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
WT_TRET(txn->notify->notify(txn->notify,
(WT_SESSION *)session, txn->id, 1));
/*
* We are about to release the snapshot: copy values into any
* positioned cursors so they don't point to updates that could be
* freed once we don't have a snapshot.
*/
if (session->ncursors > 0) {
WT_DIAGNOSTIC_YIELD;
WT_RET(__wt_session_copy_values(session));
}
/* If we are logging, write a commit log record. */
if (ret == 0 && txn->mod_count > 0 &&
FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED) &&
@@ -569,14 +589,6 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
__wt_txn_op_free(session, op);
txn->mod_count = 0;
/*
* We are about to release the snapshot: copy values into any
* positioned cursors so they don't point to updates that could be
* freed once we don't have a transaction ID pinned.
*/
if (session->ncursors > 0)
WT_RET(__wt_session_copy_values(session));
__wt_txn_release(session);
return (0);
}

View File

@@ -475,21 +475,22 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
WT_ERR(__wt_txn_id_check(session));
/*
* Save the checkpoint session ID. We never do checkpoints in the
* default session (with id zero).
* Save the checkpoint session ID.
*
* We never do checkpoints in the default session (with id zero).
*/
WT_ASSERT(session, session->id != 0 && txn_global->checkpoint_id == 0);
txn_global->checkpoint_id = session->id;
txn_global->checkpoint_pinned =
WT_MIN(txn_state->id, txn_state->snap_min);
/*
* We're about to clear the checkpoint transaction from the global
* state table so the oldest ID can move forward. Make sure everything
* we've done above is scheduled.
* Remove the checkpoint transaction from the global table.
*
* This allows ordinary visibility checks to move forward because
* checkpoints often take a long time and only write to the metadata.
*/
WT_FULL_BARRIER();
WT_ERR(__wt_writelock(session, txn_global->scan_rwlock));
txn_global->checkpoint_txnid = txn->id;
txn_global->checkpoint_pinned = WT_MIN(txn->id, txn->snap_min);
/*
* Sanity check that the oldest ID hasn't moved on before we have
@@ -507,6 +508,7 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
* details).
*/
txn_state->id = txn_state->snap_min = WT_TXN_NONE;
WT_ERR(__wt_writeunlock(session, txn_global->scan_rwlock));
/* Tell logging that we have started a database checkpoint. */
if (full && logging)

View File

@@ -95,19 +95,24 @@ class test_reconfig01(wttest.WiredTigerTestCase):
self.conn.reconfigure("checkpoint=(wait=0,name=hi)")
self.conn.reconfigure("checkpoint=(wait=5,name=hi)")
def test_reconfig_stat_log(self):
# Statistics logging: reconfigure the things we can reconfigure.
def test_reconfig_statistics_log_ok(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=2,json=true)")
self.conn.reconfigure("statistics_log=(wait=0)")
self.conn.reconfigure("statistics_log=(wait=2,on_close=true)")
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\")")
# Statistics logging: reconfigure the things we can't reconfigure.
def test_reconfig_statistics_log_fail(self):
msg = '/unknown configuration key/'
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.conn.reconfigure("log=(path=foo)"), msg)
def test_file_manager(self):
self.conn.reconfigure("file_manager=(close_scan_interval=3)")

View File

@@ -41,24 +41,29 @@ class test_reconfig02(wttest.WiredTigerTestCase):
self.conn_config = self.init_config
return wttest.WiredTigerTestCase.setUpConnectionOpen(self, dir)
# Call reconfigure for zero filling a file. There is nothing
# we can actually look for to confirm it did anything.
# Also changing the log file size is a no-op, but should not fail.
# Logging: reconfigure the things we can reconfigure.
def test_reconfig02_simple(self):
self.conn.reconfigure("log=(zero_fill=true)")
self.conn.reconfigure("log=(file_max=1MB)")
self.conn.reconfigure("log=(archive=false)")
self.conn.reconfigure("log=(prealloc=false)")
self.conn.reconfigure("log=(zero_fill=false)")
# Test that we get an error if we try to turn logging off.
self.conn.reconfigure("log=(archive=true)")
self.conn.reconfigure("log=(prealloc=true)")
self.conn.reconfigure("log=(zero_fill=true)")
# Logging: reconfigure the things we can't reconfigure.
def test_reconfig02_disable(self):
msg = 'Invalid argument'
gotException = False
try:
self.conn.reconfigure("log=(enabled=false)")
except wiredtiger.WiredTigerError as e:
gotException = True
self.pr('got exception: ' + str(e))
self.assertTrue(str(e).find(msg) >= 0)
self.assertTrue(gotException)
msg = '/unknown configuration key/'
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.conn.reconfigure("log=(enabled=true)"), msg)
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.conn.reconfigure("log=(compressor=foo)"), msg)
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.conn.reconfigure("log=(file_max=1MB)"), msg)
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.conn.reconfigure("log=(path=foo)"), msg)
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.conn.reconfigure("log=(recovery=true)"), msg)
# Logging starts on, but prealloc is off. Verify it is off.
# Reconfigure it on and run again, making sure that log files

View File

@@ -51,9 +51,10 @@ class test_stat_log01(wttest.WiredTigerTestCase):
None, "create,statistics=(fast),statistics_log=(wait=1)")
# Wait for the default interval, to ensure stats have been written.
time.sleep(2)
self.check_stats_file("WiredTigerStat")
self.check_stats_file(".")
def test_stats_log_name(self):
os.mkdir("foo")
self.conn = self.wiredtiger_open(
None, "create,statistics=(fast),statistics_log=(wait=1,path=foo)")
# Wait for the default interval, to ensure stats have been written.
@@ -66,21 +67,18 @@ class test_stat_log01(wttest.WiredTigerTestCase):
# Wait for the default interval, to ensure stats have been written.
time.sleep(2)
self.close_conn()
self.check_stats_file("WiredTigerStat")
self.check_stats_file(".")
def test_stats_log_on_close(self):
self.conn = self.wiredtiger_open(None,
"create,statistics=(fast),statistics_log=(on_close=true)")
# Close the connection to ensure the statistics get generated.
self.close_conn()
self.check_stats_file("WiredTigerStat")
self.check_stats_file(".")
def check_stats_file(self, filename):
if filename == "WiredTigerStat":
files = glob.glob(filename + '.[0-9]*')
self.assertTrue(files)
else:
self.assertTrue(os.path.isfile(filename))
def check_stats_file(self, dir):
files = glob.glob(dir + '/' + 'WiredTigerStat.[0-9]*')
self.assertTrue(files)
if __name__ == '__main__':
wttest.run()